key.c 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125
  1. /* Keyboard support routines.
  2. Copyright (C) 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
  3. 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
  4. Written by: 1994, 1995 Miguel de Icaza.
  5. 1994, 1995 Janne Kukonlehto.
  6. 1995 Jakub Jelinek.
  7. 1997 Norbert Warmuth
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
  19. /** \file key.c
  20. * \brief Source: keyboard support routines
  21. */
  22. #include <config.h>
  23. #include <ctype.h>
  24. #include <errno.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <sys/time.h>
  29. #include <sys/types.h>
  30. #include <unistd.h>
  31. #include "lib/global.h"
  32. #include "lib/strutil.h" /* str_casecmp */
  33. #include "lib/vfs/vfs.h"
  34. #include "tty.h"
  35. #include "tty-internal.h" /* mouse_enabled */
  36. #include "mouse.h"
  37. #include "key.h"
  38. #include "win.h" /* xterm_flag */
  39. #include "lib/widget.h" /* mc_refresh() */
  40. #ifdef HAVE_TEXTMODE_X11_SUPPORT
  41. #include "x11conn.h"
  42. #endif
  43. #ifdef __linux__
  44. #if defined(__GLIBC__) && (__GLIBC__ < 2)
  45. #include <linux/termios.h> /* TIOCLINUX */
  46. #else
  47. #include <termios.h>
  48. #endif
  49. #include <sys/ioctl.h>
  50. #endif /* __linux__ */
  51. #ifdef __CYGWIN__
  52. #include <termios.h>
  53. #include <sys/ioctl.h>
  54. #endif /* __CYGWIN__ */
  55. #ifdef __QNXNTO__
  56. #include <dlfcn.h>
  57. #include <Ph.h>
  58. #include <sys/dcmd_chr.h>
  59. #endif /* __QNXNTO__ */
  60. /*** global variables ****************************************************************************/
  61. /* If true, use + and \ keys normally and select/unselect do if M-+ / M-\.
  62. and M-- and keypad + / - */
  63. int alternate_plus_minus = 0;
  64. int mou_auto_repeat = 100;
  65. int double_click_speed = 250;
  66. int old_esc_mode = 0;
  67. int use_8th_bit_as_meta = 0;
  68. /* This table is a mapping between names and the constants we use
  69. * We use this to allow users to define alternate definitions for
  70. * certain keys that may be missing from the terminal database
  71. */
  72. const key_code_name_t key_name_conv_tab[] = {
  73. /* KEY_F(0) is not here, since we are mapping it to f10, so there is no reason
  74. to define f0 as well. Also, it makes Learn keys a bunch of problems :( */
  75. {KEY_F (1), "f1", N_("Function key 1"), "F1"},
  76. {KEY_F (2), "f2", N_("Function key 2"), "F2"},
  77. {KEY_F (3), "f3", N_("Function key 3"), "F3"},
  78. {KEY_F (4), "f4", N_("Function key 4"), "F4"},
  79. {KEY_F (5), "f5", N_("Function key 5"), "F5"},
  80. {KEY_F (6), "f6", N_("Function key 6"), "F6"},
  81. {KEY_F (7), "f7", N_("Function key 7"), "F7"},
  82. {KEY_F (8), "f8", N_("Function key 8"), "F8"},
  83. {KEY_F (9), "f9", N_("Function key 9"), "F9"},
  84. {KEY_F (10), "f10", N_("Function key 10"), "F10"},
  85. {KEY_F (11), "f11", N_("Function key 11"), "F11"},
  86. {KEY_F (12), "f12", N_("Function key 12"), "F12"},
  87. {KEY_F (13), "f13", N_("Function key 13"), "F13"},
  88. {KEY_F (14), "f14", N_("Function key 14"), "F14"},
  89. {KEY_F (15), "f15", N_("Function key 15"), "F15"},
  90. {KEY_F (16), "f16", N_("Function key 16"), "F16"},
  91. {KEY_F (17), "f17", N_("Function key 17"), "F17"},
  92. {KEY_F (18), "f18", N_("Function key 18"), "F18"},
  93. {KEY_F (19), "f19", N_("Function key 19"), "F19"},
  94. {KEY_F (20), "f20", N_("Function key 20"), "F20"},
  95. {KEY_BACKSPACE, "backspace", N_("Backspace key"), "Backspace"},
  96. {KEY_END, "end", N_("End key"), "End"},
  97. {KEY_UP, "up", N_("Up arrow key"), "Up"},
  98. {KEY_DOWN, "down", N_("Down arrow key"), "Down"},
  99. {KEY_LEFT, "left", N_("Left arrow key"), "Left"},
  100. {KEY_RIGHT, "right", N_("Right arrow key"), "Right"},
  101. {KEY_HOME, "home", N_("Home key"), "Home"},
  102. {KEY_NPAGE, "pgdn", N_("Page Down key"), "PgDn"},
  103. {KEY_PPAGE, "pgup", N_("Page Up key"), "PgUp"},
  104. {KEY_IC, "insert", N_("Insert key"), "Ins"},
  105. {KEY_DC, "delete", N_("Delete key"), "Del"},
  106. {ALT ('\t'), "complete", N_("Completion/M-tab"), "Meta-Tab"},
  107. {KEY_KP_ADD, "kpplus", N_("+ on keypad"), "+"},
  108. {KEY_KP_SUBTRACT, "kpminus", N_("- on keypad"), "-"},
  109. {(int) '/', "kpslash", N_("Slash on keypad"), "/"},
  110. {KEY_KP_MULTIPLY, "kpasterisk", N_("* on keypad"), "*"},
  111. /* From here on, these won't be shown in Learn keys (no space) */
  112. {ESC_CHAR, "escape", N_("Escape key"), "Esc"},
  113. {KEY_LEFT, "kpleft", N_("Left arrow keypad"), "Left"},
  114. {KEY_RIGHT, "kpright", N_("Right arrow keypad"), "Right"},
  115. {KEY_UP, "kpup", N_("Up arrow keypad"), "Up"},
  116. {KEY_DOWN, "kpdown", N_("Down arrow keypad"), "Down"},
  117. {KEY_HOME, "kphome", N_("Home on keypad"), "Home"},
  118. {KEY_END, "kpend", N_("End on keypad"), "End"},
  119. {KEY_NPAGE, "kpnpage", N_("Page Down keypad"), "PgDn"},
  120. {KEY_PPAGE, "kpppage", N_("Page Up keypad"), "PgUp"},
  121. {KEY_IC, "kpinsert", N_("Insert on keypad"), "Ins"},
  122. {KEY_DC, "kpdelete", N_("Delete on keypad"), "Del"},
  123. {(int) '\n', "kpenter", N_("Enter on keypad"), "Enter"},
  124. {KEY_F (21), "f21", N_("Function key 21"), "F21"},
  125. {KEY_F (22), "f22", N_("Function key 22"), "F22"},
  126. {KEY_F (23), "f23", N_("Function key 23"), "F23"},
  127. {KEY_F (24), "f24", N_("Function key 24"), "F24"},
  128. {KEY_A1, "a1", N_("A1 key"), "A1"},
  129. {KEY_C1, "c1", N_("C1 key"), "C1"},
  130. /* Alternative label */
  131. {ESC_CHAR, "esc", N_("Escape key"), "Esc"},
  132. {KEY_BACKSPACE, "bs", N_("Backspace key"), "Bakspace"},
  133. {KEY_IC, "ins", N_("Insert key"), "Ins"},
  134. {KEY_DC, "del", N_("Delete key"), "Del"},
  135. {(int) '+', "plus", N_("Plus"), "+"},
  136. {(int) '-', "minus", N_("Minus"), "-"},
  137. {(int) '*', "asterisk", N_("Asterisk"), "*"},
  138. {(int) '.', "dot", N_("Dot"), "."},
  139. {(int) '<', "lt", N_("Less than"), "<"},
  140. {(int) '>', "gt", N_("Great than"), ">"},
  141. {(int) '=', "equal", N_("Equal"), "="},
  142. {(int) ',', "comma", N_("Comma"), ","},
  143. {(int) '\'', "apostrophe", N_("Apostrophe"), "\'"},
  144. {(int) ':', "colon", N_("Colon"), ":"},
  145. {(int) '!', "exclamation", N_("Exclamation mark"), "!"},
  146. {(int) '?', "question", N_("Question mark"), "?"},
  147. {(int) '&', "ampersand", N_("Ampersand"), "&"},
  148. {(int) '$', "dollar", N_("Dollar sign"), "$"},
  149. {(int) '"', "quota", N_("Quotation mark"), "\""},
  150. {(int) '^', "caret", N_("Caret"), "^"},
  151. {(int) '~', "tilda", N_("Tilda"), "~"},
  152. {(int) '`', "prime", N_("Prime"), "`"},
  153. {(int) '_', "underline", N_("Underline"), "_"},
  154. {(int) '_', "understrike", N_("Understrike"), "_"},
  155. {(int) '|', "pipe", N_("Pipe"), "|"},
  156. {(int) '(', "lparenthesis", N_("Left parenthesis"), "("},
  157. {(int) ')', "rparenthesis", N_("Right parenthesis"), ")"},
  158. {(int) '[', "lbracket", N_("Left bracket"), "["},
  159. {(int) ']', "rbracket", N_("Right bracket"), "]"},
  160. {(int) '{', "lbrace", N_("Left brace"), "{"},
  161. {(int) '}', "rbrace", N_("Right brace"), "}"},
  162. {(int) '\n', "enter", N_("Enter"), "Enter"},
  163. {(int) '\t', "tab", N_("Tab key"), "Tab"},
  164. {(int) ' ', "space", N_("Space key"), "Space"},
  165. {(int) '/', "slash", N_("Slash key"), "/"},
  166. {(int) '\\', "backslash", N_("Backslash key"), "\\"},
  167. {(int) '#', "number", N_("Number sign #"), "#"},
  168. {(int) '#', "hash", N_("Number sign #"), "#"},
  169. /* TRANSLATORS: Please translate as in "at sign" (@). */
  170. {(int) '@', "at", N_("At sign"), "@"},
  171. /* meta keys */
  172. {KEY_M_CTRL, "control", N_("Ctrl"), "C"},
  173. {KEY_M_CTRL, "ctrl", N_("Ctrl"), "C"},
  174. {KEY_M_ALT, "meta", N_("Alt"), "M"},
  175. {KEY_M_ALT, "alt", N_("Alt"), "M"},
  176. {KEY_M_ALT, "ralt", N_("Alt"), "M"},
  177. {KEY_M_SHIFT, "shift", N_("Shift"), "S"},
  178. {0, NULL, NULL, NULL}
  179. };
  180. /*** file scope macro definitions ****************************************************************/
  181. #define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *) NULL))
  182. #define DIF_TIME(t1, t2) ((t2.tv_sec - t1.tv_sec) * 1000 + (t2.tv_usec - t1.tv_usec)/1000)
  183. /* The maximum sequence length (32 + null terminator) */
  184. #define SEQ_BUFFER_LEN 33
  185. /*** file scope type declarations ****************************************************************/
  186. /* Linux console keyboard modifiers */
  187. typedef enum
  188. {
  189. SHIFT_PRESSED = (1 << 0),
  190. ALTR_PRESSED = (1 << 1),
  191. CONTROL_PRESSED = (1 << 2),
  192. ALTL_PRESSED = (1 << 3)
  193. } mod_pressed_t;
  194. typedef struct key_def
  195. {
  196. char ch; /* Holds the matching char code */
  197. int code; /* The code returned, valid if child == NULL */
  198. struct key_def *next;
  199. struct key_def *child; /* sequence continuation */
  200. int action; /* optional action to be done. Now used only
  201. to mark that we are just after the first
  202. Escape */
  203. } key_def;
  204. typedef struct
  205. {
  206. int code;
  207. const char *seq;
  208. int action;
  209. } key_define_t;
  210. /* File descriptor monitoring add/remove routines */
  211. typedef struct SelectList
  212. {
  213. int fd;
  214. select_fn callback;
  215. void *info;
  216. struct SelectList *next;
  217. } SelectList;
  218. typedef enum KeySortType
  219. {
  220. KEY_NOSORT = 0,
  221. KEY_SORTBYNAME,
  222. KEY_SORTBYCODE
  223. } KeySortType;
  224. #ifdef __QNXNTO__
  225. typedef int (*ph_dv_f) (void *, void *);
  226. typedef int (*ph_ov_f) (void *);
  227. typedef int (*ph_pqc_f) (unsigned short, PhCursorInfo_t *);
  228. #endif
  229. /*** file scope variables ************************************************************************/
  230. static key_define_t mc_default_keys[] = {
  231. {ESC_CHAR, ESC_STR, MCKEY_ESCAPE},
  232. {ESC_CHAR, ESC_STR ESC_STR, MCKEY_NOACTION},
  233. {0, NULL, MCKEY_NOACTION},
  234. };
  235. /* Broken terminfo and termcap databases on xterminals */
  236. static key_define_t xterm_key_defines[] = {
  237. {KEY_F (1), ESC_STR "OP", MCKEY_NOACTION},
  238. {KEY_F (2), ESC_STR "OQ", MCKEY_NOACTION},
  239. {KEY_F (3), ESC_STR "OR", MCKEY_NOACTION},
  240. {KEY_F (4), ESC_STR "OS", MCKEY_NOACTION},
  241. {KEY_F (1), ESC_STR "[11~", MCKEY_NOACTION},
  242. {KEY_F (2), ESC_STR "[12~", MCKEY_NOACTION},
  243. {KEY_F (3), ESC_STR "[13~", MCKEY_NOACTION},
  244. {KEY_F (4), ESC_STR "[14~", MCKEY_NOACTION},
  245. {KEY_F (5), ESC_STR "[15~", MCKEY_NOACTION},
  246. {KEY_F (6), ESC_STR "[17~", MCKEY_NOACTION},
  247. {KEY_F (7), ESC_STR "[18~", MCKEY_NOACTION},
  248. {KEY_F (8), ESC_STR "[19~", MCKEY_NOACTION},
  249. {KEY_F (9), ESC_STR "[20~", MCKEY_NOACTION},
  250. {KEY_F (10), ESC_STR "[21~", MCKEY_NOACTION},
  251. /* old xterm Shift-arrows */
  252. {KEY_M_SHIFT | KEY_UP, ESC_STR "O2A", MCKEY_NOACTION},
  253. {KEY_M_SHIFT | KEY_DOWN, ESC_STR "O2B", MCKEY_NOACTION},
  254. {KEY_M_SHIFT | KEY_RIGHT, ESC_STR "O2C", MCKEY_NOACTION},
  255. {KEY_M_SHIFT | KEY_LEFT, ESC_STR "O2D", MCKEY_NOACTION},
  256. /* new xterm Shift-arrows */
  257. {KEY_M_SHIFT | KEY_UP, ESC_STR "[1;2A", MCKEY_NOACTION},
  258. {KEY_M_SHIFT | KEY_DOWN, ESC_STR "[1;2B", MCKEY_NOACTION},
  259. {KEY_M_SHIFT | KEY_RIGHT, ESC_STR "[1;2C", MCKEY_NOACTION},
  260. {KEY_M_SHIFT | KEY_LEFT, ESC_STR "[1;2D", MCKEY_NOACTION},
  261. /* more xterm keys with modifiers */
  262. {KEY_M_CTRL | KEY_PPAGE, ESC_STR "[5;5~", MCKEY_NOACTION},
  263. {KEY_M_CTRL | KEY_NPAGE, ESC_STR "[6;5~", MCKEY_NOACTION},
  264. {KEY_M_CTRL | KEY_IC, ESC_STR "[2;5~", MCKEY_NOACTION},
  265. {KEY_M_CTRL | KEY_DC, ESC_STR "[3;5~", MCKEY_NOACTION},
  266. {KEY_M_CTRL | KEY_HOME, ESC_STR "[1;5H", MCKEY_NOACTION},
  267. {KEY_M_CTRL | KEY_END, ESC_STR "[1;5F", MCKEY_NOACTION},
  268. {KEY_M_SHIFT | KEY_HOME, ESC_STR "[1;2H", MCKEY_NOACTION},
  269. {KEY_M_SHIFT | KEY_END, ESC_STR "[1;2F", MCKEY_NOACTION},
  270. {KEY_M_CTRL | KEY_UP, ESC_STR "[1;5A", MCKEY_NOACTION},
  271. {KEY_M_CTRL | KEY_DOWN, ESC_STR "[1;5B", MCKEY_NOACTION},
  272. {KEY_M_CTRL | KEY_RIGHT, ESC_STR "[1;5C", MCKEY_NOACTION},
  273. {KEY_M_CTRL | KEY_LEFT, ESC_STR "[1;5D", MCKEY_NOACTION},
  274. {KEY_M_SHIFT | KEY_IC, ESC_STR "[2;2~", MCKEY_NOACTION},
  275. {KEY_M_SHIFT | KEY_DC, ESC_STR "[3;2~", MCKEY_NOACTION},
  276. {KEY_M_SHIFT | KEY_M_CTRL | KEY_UP, ESC_STR "[1;6A", MCKEY_NOACTION},
  277. {KEY_M_SHIFT | KEY_M_CTRL | KEY_DOWN, ESC_STR "[1;6B", MCKEY_NOACTION},
  278. {KEY_M_SHIFT | KEY_M_CTRL | KEY_RIGHT, ESC_STR "[1;6C", MCKEY_NOACTION},
  279. {KEY_M_SHIFT | KEY_M_CTRL | KEY_LEFT, ESC_STR "[1;6D", MCKEY_NOACTION},
  280. /* putty */
  281. {KEY_M_SHIFT | KEY_M_CTRL | KEY_UP, ESC_STR "[[1;6A", MCKEY_NOACTION},
  282. {KEY_M_SHIFT | KEY_M_CTRL | KEY_DOWN, ESC_STR "[[1;6B", MCKEY_NOACTION},
  283. {KEY_M_SHIFT | KEY_M_CTRL | KEY_RIGHT, ESC_STR "[[1;6C", MCKEY_NOACTION},
  284. {KEY_M_SHIFT | KEY_M_CTRL | KEY_LEFT, ESC_STR "[[1;6D", MCKEY_NOACTION},
  285. /* putty alt-arrow keys */
  286. /* removed as source esc esc esc trouble */
  287. /*
  288. { KEY_M_ALT | KEY_UP, ESC_STR ESC_STR "OA", MCKEY_NOACTION },
  289. { KEY_M_ALT | KEY_DOWN, ESC_STR ESC_STR "OB", MCKEY_NOACTION },
  290. { KEY_M_ALT | KEY_RIGHT, ESC_STR ESC_STR "OC", MCKEY_NOACTION },
  291. { KEY_M_ALT | KEY_LEFT, ESC_STR ESC_STR "OD", MCKEY_NOACTION },
  292. { KEY_M_ALT | KEY_PPAGE, ESC_STR ESC_STR "[5~", MCKEY_NOACTION },
  293. { KEY_M_ALT | KEY_NPAGE, ESC_STR ESC_STR "[6~", MCKEY_NOACTION },
  294. { KEY_M_ALT | KEY_HOME, ESC_STR ESC_STR "[1~", MCKEY_NOACTION },
  295. { KEY_M_ALT | KEY_END, ESC_STR ESC_STR "[4~", MCKEY_NOACTION },
  296. { KEY_M_CTRL | KEY_M_ALT | KEY_UP, ESC_STR ESC_STR "[1;2A", MCKEY_NOACTION },
  297. { KEY_M_CTRL | KEY_M_ALT | KEY_DOWN, ESC_STR ESC_STR "[1;2B", MCKEY_NOACTION },
  298. { KEY_M_CTRL | KEY_M_ALT | KEY_RIGHT, ESC_STR ESC_STR "[1;2C", MCKEY_NOACTION },
  299. { KEY_M_CTRL | KEY_M_ALT | KEY_LEFT, ESC_STR ESC_STR "[1;2D", MCKEY_NOACTION },
  300. { KEY_M_CTRL | KEY_M_ALT | KEY_PPAGE, ESC_STR ESC_STR "[[5;5~", MCKEY_NOACTION },
  301. { KEY_M_CTRL | KEY_M_ALT | KEY_NPAGE, ESC_STR ESC_STR "[[6;5~", MCKEY_NOACTION },
  302. { KEY_M_CTRL | KEY_M_ALT | KEY_HOME, ESC_STR ESC_STR "[1;5H", MCKEY_NOACTION },
  303. { KEY_M_CTRL | KEY_M_ALT | KEY_END, ESC_STR ESC_STR "[1;5F", MCKEY_NOACTION },
  304. */
  305. /* xterm alt-arrow keys */
  306. {KEY_M_ALT | KEY_UP, ESC_STR "[1;3A", MCKEY_NOACTION},
  307. {KEY_M_ALT | KEY_DOWN, ESC_STR "[1;3B", MCKEY_NOACTION},
  308. {KEY_M_ALT | KEY_RIGHT, ESC_STR "[1;3C", MCKEY_NOACTION},
  309. {KEY_M_ALT | KEY_LEFT, ESC_STR "[1;3D", MCKEY_NOACTION},
  310. {KEY_M_ALT | KEY_PPAGE, ESC_STR "[5;3~", MCKEY_NOACTION},
  311. {KEY_M_ALT | KEY_NPAGE, ESC_STR "[6;3~", MCKEY_NOACTION},
  312. {KEY_M_ALT | KEY_HOME, ESC_STR "[1~", MCKEY_NOACTION},
  313. {KEY_M_ALT | KEY_END, ESC_STR "[4~", MCKEY_NOACTION},
  314. {KEY_M_CTRL | KEY_M_ALT | KEY_UP, ESC_STR "[1;7A", MCKEY_NOACTION},
  315. {KEY_M_CTRL | KEY_M_ALT | KEY_DOWN, ESC_STR "[1;7B", MCKEY_NOACTION},
  316. {KEY_M_CTRL | KEY_M_ALT | KEY_RIGHT, ESC_STR "[1;7C", MCKEY_NOACTION},
  317. {KEY_M_CTRL | KEY_M_ALT | KEY_LEFT, ESC_STR "[1;7D", MCKEY_NOACTION},
  318. {KEY_M_CTRL | KEY_M_ALT | KEY_PPAGE, ESC_STR "[5;7~", MCKEY_NOACTION},
  319. {KEY_M_CTRL | KEY_M_ALT | KEY_NPAGE, ESC_STR "[6;7~", MCKEY_NOACTION},
  320. {KEY_M_CTRL | KEY_M_ALT | KEY_HOME, ESC_STR "OH", MCKEY_NOACTION},
  321. {KEY_M_CTRL | KEY_M_ALT | KEY_END, ESC_STR "OF", MCKEY_NOACTION},
  322. /* rxvt keys with modifiers */
  323. {KEY_M_SHIFT | KEY_UP, ESC_STR "[a", MCKEY_NOACTION},
  324. {KEY_M_SHIFT | KEY_DOWN, ESC_STR "[b", MCKEY_NOACTION},
  325. {KEY_M_SHIFT | KEY_RIGHT, ESC_STR "[c", MCKEY_NOACTION},
  326. {KEY_M_SHIFT | KEY_LEFT, ESC_STR "[d", MCKEY_NOACTION},
  327. {KEY_M_CTRL | KEY_UP, ESC_STR "Oa", MCKEY_NOACTION},
  328. {KEY_M_CTRL | KEY_DOWN, ESC_STR "Ob", MCKEY_NOACTION},
  329. {KEY_M_CTRL | KEY_RIGHT, ESC_STR "Oc", MCKEY_NOACTION},
  330. {KEY_M_CTRL | KEY_LEFT, ESC_STR "Od", MCKEY_NOACTION},
  331. {KEY_M_CTRL | KEY_PPAGE, ESC_STR "[5^", MCKEY_NOACTION},
  332. {KEY_M_CTRL | KEY_NPAGE, ESC_STR "[6^", MCKEY_NOACTION},
  333. {KEY_M_CTRL | KEY_HOME, ESC_STR "[7^", MCKEY_NOACTION},
  334. {KEY_M_CTRL | KEY_END, ESC_STR "[8^", MCKEY_NOACTION},
  335. {KEY_M_SHIFT | KEY_HOME, ESC_STR "[7$", MCKEY_NOACTION},
  336. {KEY_M_SHIFT | KEY_END, ESC_STR "[8$", MCKEY_NOACTION},
  337. {KEY_M_CTRL | KEY_IC, ESC_STR "[2^", MCKEY_NOACTION},
  338. {KEY_M_CTRL | KEY_DC, ESC_STR "[3^", MCKEY_NOACTION},
  339. {KEY_M_SHIFT | KEY_DC, ESC_STR "[3$", MCKEY_NOACTION},
  340. /* konsole keys with modifiers */
  341. {KEY_M_SHIFT | KEY_HOME, ESC_STR "O2H", MCKEY_NOACTION},
  342. {KEY_M_SHIFT | KEY_END, ESC_STR "O2F", MCKEY_NOACTION},
  343. /* gnome-terminal */
  344. {KEY_M_SHIFT | KEY_UP, ESC_STR "[2A", MCKEY_NOACTION},
  345. {KEY_M_SHIFT | KEY_DOWN, ESC_STR "[2B", MCKEY_NOACTION},
  346. {KEY_M_SHIFT | KEY_RIGHT, ESC_STR "[2C", MCKEY_NOACTION},
  347. {KEY_M_SHIFT | KEY_LEFT, ESC_STR "[2D", MCKEY_NOACTION},
  348. {KEY_M_CTRL | KEY_UP, ESC_STR "[5A", MCKEY_NOACTION},
  349. {KEY_M_CTRL | KEY_DOWN, ESC_STR "[5B", MCKEY_NOACTION},
  350. {KEY_M_CTRL | KEY_RIGHT, ESC_STR "[5C", MCKEY_NOACTION},
  351. {KEY_M_CTRL | KEY_LEFT, ESC_STR "[5D", MCKEY_NOACTION},
  352. {KEY_M_SHIFT | KEY_M_CTRL | KEY_UP, ESC_STR "[6A", MCKEY_NOACTION},
  353. {KEY_M_SHIFT | KEY_M_CTRL | KEY_DOWN, ESC_STR "[6B", MCKEY_NOACTION},
  354. {KEY_M_SHIFT | KEY_M_CTRL | KEY_RIGHT, ESC_STR "[6C", MCKEY_NOACTION},
  355. {KEY_M_SHIFT | KEY_M_CTRL | KEY_LEFT, ESC_STR "[6D", MCKEY_NOACTION},
  356. /* gnome-terminal - application mode */
  357. {KEY_M_CTRL | KEY_UP, ESC_STR "O5A", MCKEY_NOACTION},
  358. {KEY_M_CTRL | KEY_DOWN, ESC_STR "O5B", MCKEY_NOACTION},
  359. {KEY_M_CTRL | KEY_RIGHT, ESC_STR "O5C", MCKEY_NOACTION},
  360. {KEY_M_CTRL | KEY_LEFT, ESC_STR "O5D", MCKEY_NOACTION},
  361. {KEY_M_SHIFT | KEY_M_CTRL | KEY_UP, ESC_STR "O6A", MCKEY_NOACTION},
  362. {KEY_M_SHIFT | KEY_M_CTRL | KEY_DOWN, ESC_STR "O6B", MCKEY_NOACTION},
  363. {KEY_M_SHIFT | KEY_M_CTRL | KEY_RIGHT, ESC_STR "O6C", MCKEY_NOACTION},
  364. {KEY_M_SHIFT | KEY_M_CTRL | KEY_LEFT, ESC_STR "O6D", MCKEY_NOACTION},
  365. /* iTerm */
  366. {KEY_M_SHIFT | KEY_PPAGE, ESC_STR "[5;2~", MCKEY_NOACTION},
  367. {KEY_M_SHIFT | KEY_NPAGE, ESC_STR "[6;2~", MCKEY_NOACTION},
  368. /* putty */
  369. {KEY_M_SHIFT | KEY_PPAGE, ESC_STR "[[5;53~", MCKEY_NOACTION},
  370. {KEY_M_SHIFT | KEY_NPAGE, ESC_STR "[[6;53~", MCKEY_NOACTION},
  371. /* keypad keys */
  372. {KEY_IC, ESC_STR "Op", MCKEY_NOACTION},
  373. {KEY_DC, ESC_STR "On", MCKEY_NOACTION},
  374. {'/', ESC_STR "Oo", MCKEY_NOACTION},
  375. {'\n', ESC_STR "OM", MCKEY_NOACTION},
  376. {0, NULL, MCKEY_NOACTION},
  377. };
  378. /* qansi-m terminals have a much more key combinatios,
  379. which are undefined in termcap/terminfo */
  380. static key_define_t qansi_key_defines[] = {
  381. /* qansi-m terminal */
  382. {KEY_M_CTRL | KEY_NPAGE, ESC_STR "[u", MCKEY_NOACTION}, /* Ctrl-PgDown */
  383. {KEY_M_CTRL | KEY_PPAGE, ESC_STR "[v", MCKEY_NOACTION}, /* Ctrl-PgUp */
  384. {KEY_M_CTRL | KEY_HOME, ESC_STR "[h", MCKEY_NOACTION}, /* Ctrl-Home */
  385. {KEY_M_CTRL | KEY_END, ESC_STR "[y", MCKEY_NOACTION}, /* Ctrl-End */
  386. {KEY_M_CTRL | KEY_IC, ESC_STR "[`", MCKEY_NOACTION}, /* Ctrl-Insert */
  387. {KEY_M_CTRL | KEY_DC, ESC_STR "[p", MCKEY_NOACTION}, /* Ctrl-Delete */
  388. {KEY_M_CTRL | KEY_LEFT, ESC_STR "[d", MCKEY_NOACTION}, /* Ctrl-Left */
  389. {KEY_M_CTRL | KEY_RIGHT, ESC_STR "[c", MCKEY_NOACTION}, /* Ctrl-Right */
  390. {KEY_M_CTRL | KEY_DOWN, ESC_STR "[b", MCKEY_NOACTION}, /* Ctrl-Down */
  391. {KEY_M_CTRL | KEY_UP, ESC_STR "[a", MCKEY_NOACTION}, /* Ctrl-Up */
  392. {KEY_M_CTRL | KEY_KP_ADD, ESC_STR "[s", MCKEY_NOACTION}, /* Ctrl-Gr-Plus */
  393. {KEY_M_CTRL | KEY_KP_SUBTRACT, ESC_STR "[t", MCKEY_NOACTION}, /* Ctrl-Gr-Minus */
  394. {KEY_M_CTRL | '\t', ESC_STR "[z", MCKEY_NOACTION}, /* Ctrl-Tab */
  395. {KEY_M_SHIFT | '\t', ESC_STR "[Z", MCKEY_NOACTION}, /* Shift-Tab */
  396. {KEY_M_CTRL | KEY_F (1), ESC_STR "[1~", MCKEY_NOACTION}, /* Ctrl-F1 */
  397. {KEY_M_CTRL | KEY_F (2), ESC_STR "[2~", MCKEY_NOACTION}, /* Ctrl-F2 */
  398. {KEY_M_CTRL | KEY_F (3), ESC_STR "[3~", MCKEY_NOACTION}, /* Ctrl-F3 */
  399. {KEY_M_CTRL | KEY_F (4), ESC_STR "[4~", MCKEY_NOACTION}, /* Ctrl-F4 */
  400. {KEY_M_CTRL | KEY_F (5), ESC_STR "[5~", MCKEY_NOACTION}, /* Ctrl-F5 */
  401. {KEY_M_CTRL | KEY_F (6), ESC_STR "[6~", MCKEY_NOACTION}, /* Ctrl-F6 */
  402. {KEY_M_CTRL | KEY_F (7), ESC_STR "[7~", MCKEY_NOACTION}, /* Ctrl-F7 */
  403. {KEY_M_CTRL | KEY_F (8), ESC_STR "[8~", MCKEY_NOACTION}, /* Ctrl-F8 */
  404. {KEY_M_CTRL | KEY_F (9), ESC_STR "[9~", MCKEY_NOACTION}, /* Ctrl-F9 */
  405. {KEY_M_CTRL | KEY_F (10), ESC_STR "[10~", MCKEY_NOACTION}, /* Ctrl-F10 */
  406. {KEY_M_CTRL | KEY_F (11), ESC_STR "[11~", MCKEY_NOACTION}, /* Ctrl-F11 */
  407. {KEY_M_CTRL | KEY_F (12), ESC_STR "[12~", MCKEY_NOACTION}, /* Ctrl-F12 */
  408. {KEY_M_ALT | KEY_F (1), ESC_STR "[17~", MCKEY_NOACTION}, /* Alt-F1 */
  409. {KEY_M_ALT | KEY_F (2), ESC_STR "[18~", MCKEY_NOACTION}, /* Alt-F2 */
  410. {KEY_M_ALT | KEY_F (3), ESC_STR "[19~", MCKEY_NOACTION}, /* Alt-F3 */
  411. {KEY_M_ALT | KEY_F (4), ESC_STR "[20~", MCKEY_NOACTION}, /* Alt-F4 */
  412. {KEY_M_ALT | KEY_F (5), ESC_STR "[21~", MCKEY_NOACTION}, /* Alt-F5 */
  413. {KEY_M_ALT | KEY_F (6), ESC_STR "[22~", MCKEY_NOACTION}, /* Alt-F6 */
  414. {KEY_M_ALT | KEY_F (7), ESC_STR "[23~", MCKEY_NOACTION}, /* Alt-F7 */
  415. {KEY_M_ALT | KEY_F (8), ESC_STR "[24~", MCKEY_NOACTION}, /* Alt-F8 */
  416. {KEY_M_ALT | KEY_F (9), ESC_STR "[25~", MCKEY_NOACTION}, /* Alt-F9 */
  417. {KEY_M_ALT | KEY_F (10), ESC_STR "[26~", MCKEY_NOACTION}, /* Alt-F10 */
  418. {KEY_M_ALT | KEY_F (11), ESC_STR "[27~", MCKEY_NOACTION}, /* Alt-F11 */
  419. {KEY_M_ALT | KEY_F (12), ESC_STR "[28~", MCKEY_NOACTION}, /* Alt-F12 */
  420. {KEY_M_ALT | 'a', ESC_STR "Na", MCKEY_NOACTION}, /* Alt-a */
  421. {KEY_M_ALT | 'b', ESC_STR "Nb", MCKEY_NOACTION}, /* Alt-b */
  422. {KEY_M_ALT | 'c', ESC_STR "Nc", MCKEY_NOACTION}, /* Alt-c */
  423. {KEY_M_ALT | 'd', ESC_STR "Nd", MCKEY_NOACTION}, /* Alt-d */
  424. {KEY_M_ALT | 'e', ESC_STR "Ne", MCKEY_NOACTION}, /* Alt-e */
  425. {KEY_M_ALT | 'f', ESC_STR "Nf", MCKEY_NOACTION}, /* Alt-f */
  426. {KEY_M_ALT | 'g', ESC_STR "Ng", MCKEY_NOACTION}, /* Alt-g */
  427. {KEY_M_ALT | 'h', ESC_STR "Nh", MCKEY_NOACTION}, /* Alt-h */
  428. {KEY_M_ALT | 'i', ESC_STR "Ni", MCKEY_NOACTION}, /* Alt-i */
  429. {KEY_M_ALT | 'j', ESC_STR "Nj", MCKEY_NOACTION}, /* Alt-j */
  430. {KEY_M_ALT | 'k', ESC_STR "Nk", MCKEY_NOACTION}, /* Alt-k */
  431. {KEY_M_ALT | 'l', ESC_STR "Nl", MCKEY_NOACTION}, /* Alt-l */
  432. {KEY_M_ALT | 'm', ESC_STR "Nm", MCKEY_NOACTION}, /* Alt-m */
  433. {KEY_M_ALT | 'n', ESC_STR "Nn", MCKEY_NOACTION}, /* Alt-n */
  434. {KEY_M_ALT | 'o', ESC_STR "No", MCKEY_NOACTION}, /* Alt-o */
  435. {KEY_M_ALT | 'p', ESC_STR "Np", MCKEY_NOACTION}, /* Alt-p */
  436. {KEY_M_ALT | 'q', ESC_STR "Nq", MCKEY_NOACTION}, /* Alt-q */
  437. {KEY_M_ALT | 'r', ESC_STR "Nr", MCKEY_NOACTION}, /* Alt-r */
  438. {KEY_M_ALT | 's', ESC_STR "Ns", MCKEY_NOACTION}, /* Alt-s */
  439. {KEY_M_ALT | 't', ESC_STR "Nt", MCKEY_NOACTION}, /* Alt-t */
  440. {KEY_M_ALT | 'u', ESC_STR "Nu", MCKEY_NOACTION}, /* Alt-u */
  441. {KEY_M_ALT | 'v', ESC_STR "Nv", MCKEY_NOACTION}, /* Alt-v */
  442. {KEY_M_ALT | 'w', ESC_STR "Nw", MCKEY_NOACTION}, /* Alt-w */
  443. {KEY_M_ALT | 'x', ESC_STR "Nx", MCKEY_NOACTION}, /* Alt-x */
  444. {KEY_M_ALT | 'y', ESC_STR "Ny", MCKEY_NOACTION}, /* Alt-y */
  445. {KEY_M_ALT | 'z', ESC_STR "Nz", MCKEY_NOACTION}, /* Alt-z */
  446. {KEY_KP_SUBTRACT, ESC_STR "[S", MCKEY_NOACTION}, /* Gr-Minus */
  447. {KEY_KP_ADD, ESC_STR "[T", MCKEY_NOACTION}, /* Gr-Plus */
  448. {0, NULL, MCKEY_NOACTION},
  449. };
  450. /* timeout for old_esc_mode in usec */
  451. int old_esc_mode_timeout = 1000000; /* settable via env */
  452. /* This holds all the key definitions */
  453. static key_def *keys = NULL;
  454. static int input_fd;
  455. static int disabled_channels = 0; /* Disable channels checking */
  456. static SelectList *select_list = NULL;
  457. static int seq_buffer[SEQ_BUFFER_LEN];
  458. static int *seq_append = NULL;
  459. static int *pending_keys = NULL;
  460. #ifdef __QNXNTO__
  461. ph_dv_f ph_attach;
  462. ph_ov_f ph_input_group;
  463. ph_pqc_f ph_query_cursor;
  464. #endif
  465. #ifdef HAVE_TEXTMODE_X11_SUPPORT
  466. static Display *x11_display;
  467. static Window x11_window;
  468. #endif /* HAVE_TEXTMODE_X11_SUPPORT */
  469. static KeySortType has_been_sorted = KEY_NOSORT;
  470. static const size_t key_conv_tab_size = G_N_ELEMENTS (key_name_conv_tab) - 1;
  471. static const key_code_name_t *key_conv_tab_sorted[G_N_ELEMENTS (key_name_conv_tab) - 1];
  472. /*** file scope functions ************************************************************************/
  473. /* --------------------------------------------------------------------------------------------- */
  474. static int
  475. add_selects (fd_set * select_set)
  476. {
  477. int top_fd = 0;
  478. if (disabled_channels == 0)
  479. {
  480. SelectList *p;
  481. for (p = select_list; p != NULL; p = p->next)
  482. {
  483. FD_SET (p->fd, select_set);
  484. if (p->fd > top_fd)
  485. top_fd = p->fd;
  486. }
  487. }
  488. return top_fd;
  489. }
  490. /* --------------------------------------------------------------------------------------------- */
  491. static void
  492. check_selects (fd_set * select_set)
  493. {
  494. if (disabled_channels == 0)
  495. {
  496. gboolean retry;
  497. do
  498. {
  499. SelectList *p;
  500. retry = FALSE;
  501. for (p = select_list; p; p = p->next)
  502. if (FD_ISSET (p->fd, select_set))
  503. {
  504. FD_CLR (p->fd, select_set);
  505. (*p->callback) (p->fd, p->info);
  506. retry = TRUE;
  507. break;
  508. }
  509. }
  510. while (retry);
  511. }
  512. }
  513. /* --------------------------------------------------------------------------------------------- */
  514. /* If set timeout is set, then we wait 0.1 seconds, else, we block */
  515. static void
  516. try_channels (int set_timeout)
  517. {
  518. struct timeval time_out;
  519. static fd_set select_set;
  520. struct timeval *timeptr;
  521. int v;
  522. int maxfdp;
  523. while (1)
  524. {
  525. FD_ZERO (&select_set);
  526. FD_SET (input_fd, &select_set); /* Add stdin */
  527. maxfdp = max (add_selects (&select_set), input_fd);
  528. timeptr = NULL;
  529. if (set_timeout)
  530. {
  531. time_out.tv_sec = 0;
  532. time_out.tv_usec = 100000;
  533. timeptr = &time_out;
  534. }
  535. v = select (maxfdp + 1, &select_set, NULL, NULL, timeptr);
  536. if (v > 0)
  537. {
  538. check_selects (&select_set);
  539. if (FD_ISSET (input_fd, &select_set))
  540. break;
  541. }
  542. }
  543. }
  544. /* --------------------------------------------------------------------------------------------- */
  545. static key_def *
  546. create_sequence (const char *seq, int code, int action)
  547. {
  548. key_def *base, *p, *attach;
  549. for (base = attach = NULL; *seq; seq++)
  550. {
  551. p = g_new (key_def, 1);
  552. if (base == NULL)
  553. base = p;
  554. if (attach != NULL)
  555. attach->child = p;
  556. p->ch = *seq;
  557. p->code = code;
  558. p->child = p->next = NULL;
  559. if (seq[1] == '\0')
  560. p->action = action;
  561. else
  562. p->action = MCKEY_NOACTION;
  563. attach = p;
  564. }
  565. return base;
  566. }
  567. /* --------------------------------------------------------------------------------------------- */
  568. static void
  569. define_sequences (const key_define_t * kd)
  570. {
  571. int i;
  572. for (i = 0; kd[i].code != 0; i++)
  573. define_sequence (kd[i].code, kd[i].seq, kd[i].action);
  574. }
  575. /* --------------------------------------------------------------------------------------------- */
  576. static void
  577. init_key_x11 (void)
  578. {
  579. #ifdef HAVE_TEXTMODE_X11_SUPPORT
  580. if (getenv ("DISPLAY") != NULL)
  581. {
  582. x11_display = mc_XOpenDisplay (0);
  583. if (x11_display != NULL)
  584. x11_window = DefaultRootWindow (x11_display);
  585. }
  586. #endif /* HAVE_TEXTMODE_X11_SUPPORT */
  587. }
  588. /* --------------------------------------------------------------------------------------------- */
  589. /* Workaround for System V Curses vt100 bug */
  590. static int
  591. getch_with_delay (void)
  592. {
  593. int c;
  594. /* This routine could be used on systems without mouse support,
  595. so we need to do the select check :-( */
  596. while (1)
  597. {
  598. if (pending_keys == NULL)
  599. try_channels (0);
  600. /* Try to get a character */
  601. c = get_key_code (0);
  602. if (c != -1)
  603. break;
  604. /* Failed -> wait 0.1 secs and try again */
  605. try_channels (1);
  606. }
  607. /* Success -> return the character */
  608. return c;
  609. }
  610. /* --------------------------------------------------------------------------------------------- */
  611. static void
  612. xmouse_get_event (Gpm_Event * ev)
  613. {
  614. int btn;
  615. static struct timeval tv1 = { 0, 0 }; /* Force first click as single */
  616. static struct timeval tv2;
  617. static int clicks = 0;
  618. static int last_btn = 0;
  619. /* Decode Xterm mouse information to a GPM style event */
  620. /* Variable btn has following meaning: */
  621. /* 0 = btn1 dn, 1 = btn2 dn, 2 = btn3 dn, 3 = btn up */
  622. btn = tty_lowlevel_getch () - 32;
  623. /* There seems to be no way of knowing which button was released */
  624. /* So we assume all the buttons were released */
  625. if (btn == 3)
  626. {
  627. if (last_btn != 0)
  628. {
  629. if ((last_btn & (GPM_B_UP | GPM_B_DOWN)) != 0)
  630. {
  631. /* FIXME: DIRTY HACK */
  632. /* don't generate GPM_UP after mouse wheel */
  633. /* need for menu event handling */
  634. ev->type = 0;
  635. tv1.tv_sec = 0;
  636. tv1.tv_usec = 0;
  637. }
  638. else
  639. {
  640. ev->type = GPM_UP | (GPM_SINGLE << clicks);
  641. GET_TIME (tv1);
  642. }
  643. ev->buttons = 0;
  644. last_btn = 0;
  645. clicks = 0;
  646. }
  647. else
  648. {
  649. /* Bogus event, maybe mouse wheel */
  650. ev->type = 0;
  651. }
  652. }
  653. else
  654. {
  655. if (btn >= 32 && btn <= 34)
  656. {
  657. btn -= 32;
  658. ev->type = GPM_DRAG;
  659. }
  660. else
  661. ev->type = GPM_DOWN;
  662. GET_TIME (tv2);
  663. if (tv1.tv_sec && (DIF_TIME (tv1, tv2) < double_click_speed))
  664. {
  665. clicks++;
  666. clicks %= 3;
  667. }
  668. else
  669. clicks = 0;
  670. switch (btn)
  671. {
  672. case 0:
  673. ev->buttons = GPM_B_LEFT;
  674. break;
  675. case 1:
  676. ev->buttons = GPM_B_MIDDLE;
  677. break;
  678. case 2:
  679. ev->buttons = GPM_B_RIGHT;
  680. break;
  681. case 64:
  682. ev->buttons = GPM_B_UP;
  683. clicks = 0;
  684. break;
  685. case 65:
  686. ev->buttons = GPM_B_DOWN;
  687. clicks = 0;
  688. break;
  689. default:
  690. /* Nothing */
  691. ev->type = 0;
  692. ev->buttons = 0;
  693. break;
  694. }
  695. last_btn = ev->buttons;
  696. }
  697. /* Coordinates are 33-based */
  698. /* Transform them to 1-based */
  699. ev->x = tty_lowlevel_getch () - 32;
  700. ev->y = tty_lowlevel_getch () - 32;
  701. }
  702. /* --------------------------------------------------------------------------------------------- */
  703. /**
  704. * Get modifier state (shift, alt, ctrl) for the last key pressed.
  705. * We are assuming that the state didn't change since the key press.
  706. * This is only correct if get_modifier() is called very fast after
  707. * the input was received, so that the user didn't release the
  708. * modifier keys yet.
  709. */
  710. static int
  711. get_modifier (void)
  712. {
  713. int result = 0;
  714. #ifdef __QNXNTO__
  715. int mod_status, shift_ext_status;
  716. static int in_photon = 0;
  717. static int ph_ig = 0;
  718. PhCursorInfo_t cursor_info;
  719. #endif /* __QNXNTO__ */
  720. #ifdef HAVE_TEXTMODE_X11_SUPPORT
  721. if (x11_window != 0)
  722. {
  723. Window root, child;
  724. int root_x, root_y;
  725. int win_x, win_y;
  726. unsigned int mask;
  727. mc_XQueryPointer (x11_display, x11_window, &root, &child, &root_x,
  728. &root_y, &win_x, &win_y, &mask);
  729. if (mask & ShiftMask)
  730. result |= KEY_M_SHIFT;
  731. if (mask & ControlMask)
  732. result |= KEY_M_CTRL;
  733. return result;
  734. }
  735. #endif /* HAVE_TEXTMODE_X11_SUPPORT */
  736. #ifdef __QNXNTO__
  737. if (in_photon == 0)
  738. {
  739. /* First time here, let's load Photon library and attach
  740. to Photon */
  741. in_photon = -1;
  742. if (getenv ("PHOTON2_PATH") != NULL)
  743. {
  744. /* QNX 6.x has no support for RTLD_LAZY */
  745. void *ph_handle = dlopen ("/usr/lib/libph.so", RTLD_NOW);
  746. if (ph_handle != NULL)
  747. {
  748. ph_attach = (ph_dv_f) dlsym (ph_handle, "PhAttach");
  749. ph_input_group = (ph_ov_f) dlsym (ph_handle, "PhInputGroup");
  750. ph_query_cursor = (ph_pqc_f) dlsym (ph_handle, "PhQueryCursor");
  751. if ((ph_attach != NULL) && (ph_input_group != NULL) && (ph_query_cursor != NULL))
  752. {
  753. if ((*ph_attach) (0, 0))
  754. { /* Attached */
  755. ph_ig = (*ph_input_group) (0);
  756. in_photon = 1;
  757. }
  758. }
  759. }
  760. }
  761. }
  762. /* We do not have Photon running. Assume we are in text
  763. console or xterm */
  764. if (in_photon == -1)
  765. {
  766. if (devctl (fileno (stdin), DCMD_CHR_LINESTATUS, &mod_status, sizeof (int), NULL) == -1)
  767. return 0;
  768. shift_ext_status = mod_status & 0xffffff00UL;
  769. mod_status &= 0x7f;
  770. if (mod_status & _LINESTATUS_CON_ALT)
  771. result |= KEY_M_ALT;
  772. if (mod_status & _LINESTATUS_CON_CTRL)
  773. result |= KEY_M_CTRL;
  774. if ((mod_status & _LINESTATUS_CON_SHIFT) || (shift_ext_status & 0x00000800UL))
  775. result |= KEY_M_SHIFT;
  776. }
  777. else
  778. {
  779. (*ph_query_cursor) (ph_ig, &cursor_info);
  780. if (cursor_info.key_mods & 0x04)
  781. result |= KEY_M_ALT;
  782. if (cursor_info.key_mods & 0x02)
  783. result |= KEY_M_CTRL;
  784. if (cursor_info.key_mods & 0x01)
  785. result |= KEY_M_SHIFT;
  786. }
  787. #endif /* __QNXNTO__ */
  788. #if defined __linux__ || (defined __CYGWIN__ && defined TIOCLINUX)
  789. {
  790. unsigned char modifiers = 6;
  791. if (ioctl (0, TIOCLINUX, &modifiers) < 0)
  792. return 0;
  793. /* Translate Linux modifiers into mc modifiers */
  794. if (modifiers & SHIFT_PRESSED)
  795. result |= KEY_M_SHIFT;
  796. if (modifiers & (ALTL_PRESSED | ALTR_PRESSED))
  797. result |= KEY_M_ALT;
  798. if (modifiers & CONTROL_PRESSED)
  799. result |= KEY_M_CTRL;
  800. }
  801. #endif /* !__linux__ */
  802. return result;
  803. }
  804. /* --------------------------------------------------------------------------------------------- */
  805. static gboolean
  806. push_char (int c)
  807. {
  808. gboolean ret = FALSE;
  809. if (seq_append == NULL)
  810. seq_append = seq_buffer;
  811. if (seq_append != &(seq_buffer[SEQ_BUFFER_LEN - 2]))
  812. {
  813. *(seq_append++) = c;
  814. *seq_append = 0;
  815. ret = TRUE;
  816. }
  817. return ret;
  818. }
  819. /* --------------------------------------------------------------------------------------------- */
  820. /* Apply corrections for the keycode generated in get_key_code() */
  821. static int
  822. correct_key_code (int code)
  823. {
  824. unsigned int c = code & ~KEY_M_MASK; /* code without modifier */
  825. unsigned int mod = code & KEY_M_MASK; /* modifier */
  826. #ifdef __QNXNTO__
  827. unsigned int qmod; /* bunch of the QNX console
  828. modifiers needs unchanged */
  829. #endif /* __QNXNTO__ */
  830. /*
  831. * Add key modifiers directly from X11 or OS.
  832. * Ordinary characters only get modifiers from sequences.
  833. */
  834. if (c < 32 || c >= 256)
  835. {
  836. mod |= get_modifier ();
  837. }
  838. /* This is needed if the newline is reported as carriage return */
  839. if (c == '\r')
  840. c = '\n';
  841. /* This is reported to be useful on AIX */
  842. if (c == KEY_SCANCEL)
  843. c = '\t';
  844. /* Convert Shift+Tab and Ctrl+Tab to Back Tab */
  845. if ((c == '\t') && (mod & (KEY_M_SHIFT | KEY_M_CTRL)))
  846. {
  847. c = KEY_BTAB;
  848. mod = 0;
  849. }
  850. /* F0 is the same as F10 for out purposes */
  851. if (c == KEY_F (0))
  852. c = KEY_F (10);
  853. /*
  854. * We are not interested if Ctrl was pressed when entering control
  855. * characters, so assume that it was. When checking for such keys,
  856. * XCTRL macro should be used. In some cases, we are interested,
  857. * e.g. to distinguish Ctrl-Enter from Enter.
  858. */
  859. if (c == '\b')
  860. {
  861. /* Special case for backspase ('\b' < 32) */
  862. c = KEY_BACKSPACE;
  863. mod &= ~KEY_M_CTRL;
  864. }
  865. else if (c < 32 && c != ESC_CHAR && c != '\t' && c != '\n')
  866. {
  867. mod |= KEY_M_CTRL;
  868. }
  869. #ifdef __QNXNTO__
  870. qmod = get_modifier ();
  871. if ((c == 127) && (mod == 0))
  872. { /* Add Ctrl/Alt/Shift-BackSpace */
  873. mod |= get_modifier ();
  874. c = KEY_BACKSPACE;
  875. }
  876. if ((c == '0') && (mod == 0))
  877. { /* Add Shift-Insert on key pad */
  878. if ((qmod & KEY_M_SHIFT) == KEY_M_SHIFT)
  879. {
  880. mod = KEY_M_SHIFT;
  881. c = KEY_IC;
  882. }
  883. }
  884. if ((c == '.') && (mod == 0))
  885. { /* Add Shift-Del on key pad */
  886. if ((qmod & KEY_M_SHIFT) == KEY_M_SHIFT)
  887. {
  888. mod = KEY_M_SHIFT;
  889. c = KEY_DC;
  890. }
  891. }
  892. #endif /* __QNXNTO__ */
  893. /* Unrecognized 0177 is delete (preserve Ctrl) */
  894. if (c == 0177)
  895. {
  896. c = KEY_BACKSPACE;
  897. }
  898. #if 0
  899. /* Unrecognized Ctrl-d is delete */
  900. if (c == (31 & 'd'))
  901. {
  902. c = KEY_DC;
  903. mod &= ~KEY_M_CTRL;
  904. }
  905. /* Unrecognized Ctrl-h is backspace */
  906. if (c == (31 & 'h'))
  907. {
  908. c = KEY_BACKSPACE;
  909. mod &= ~KEY_M_CTRL;
  910. }
  911. #endif
  912. /* Shift+BackSpace is backspace */
  913. if (c == KEY_BACKSPACE && (mod & KEY_M_SHIFT))
  914. {
  915. mod &= ~KEY_M_SHIFT;
  916. }
  917. /* Convert Shift+Fn to F(n+10) */
  918. if (c >= KEY_F (1) && c <= KEY_F (10) && (mod & KEY_M_SHIFT))
  919. {
  920. c += 10;
  921. }
  922. /* Remove Shift information from function keys */
  923. if (c >= KEY_F (1) && c <= KEY_F (20))
  924. {
  925. mod &= ~KEY_M_SHIFT;
  926. }
  927. if (!alternate_plus_minus)
  928. switch (c)
  929. {
  930. case KEY_KP_ADD:
  931. c = '+';
  932. break;
  933. case KEY_KP_SUBTRACT:
  934. c = '-';
  935. break;
  936. case KEY_KP_MULTIPLY:
  937. c = '*';
  938. break;
  939. }
  940. return (mod | c);
  941. }
  942. /* --------------------------------------------------------------------------------------------- */
  943. static int
  944. xgetch_second (void)
  945. {
  946. fd_set Read_FD_Set;
  947. int c;
  948. struct timeval time_out;
  949. time_out.tv_sec = old_esc_mode_timeout / 1000000;
  950. time_out.tv_usec = old_esc_mode_timeout % 1000000;
  951. tty_nodelay (TRUE);
  952. FD_ZERO (&Read_FD_Set);
  953. FD_SET (input_fd, &Read_FD_Set);
  954. select (input_fd + 1, &Read_FD_Set, NULL, NULL, &time_out);
  955. c = tty_lowlevel_getch ();
  956. tty_nodelay (FALSE);
  957. return c;
  958. }
  959. /* --------------------------------------------------------------------------------------------- */
  960. static void
  961. learn_store_key (char *buffer, char **p, int c)
  962. {
  963. if (*p - buffer > 253)
  964. return;
  965. if (c == ESC_CHAR)
  966. {
  967. *(*p)++ = '\\';
  968. *(*p)++ = 'e';
  969. }
  970. else if (c < ' ')
  971. {
  972. *(*p)++ = '^';
  973. *(*p)++ = c + 'a' - 1;
  974. }
  975. else if (c == '^')
  976. {
  977. *(*p)++ = '^';
  978. *(*p)++ = '^';
  979. }
  980. else
  981. *(*p)++ = (char) c;
  982. }
  983. /* --------------------------------------------------------------------------------------------- */
  984. static void
  985. k_dispose (key_def * k)
  986. {
  987. if (k != NULL)
  988. {
  989. k_dispose (k->child);
  990. k_dispose (k->next);
  991. g_free (k);
  992. }
  993. }
  994. /* --------------------------------------------------------------------------------------------- */
  995. static void
  996. s_dispose (SelectList * sel)
  997. {
  998. if (sel != NULL)
  999. {
  1000. s_dispose (sel->next);
  1001. g_free (sel);
  1002. }
  1003. }
  1004. /* --------------------------------------------------------------------------------------------- */
  1005. static int
  1006. key_code_comparator_by_name (const void *p1, const void *p2)
  1007. {
  1008. const key_code_name_t *n1 = *(const key_code_name_t **) p1;
  1009. const key_code_name_t *n2 = *(const key_code_name_t **) p2;
  1010. return str_casecmp (n1->name, n2->name);
  1011. }
  1012. /* --------------------------------------------------------------------------------------------- */
  1013. static int
  1014. key_code_comparator_by_code (const void *p1, const void *p2)
  1015. {
  1016. const key_code_name_t *n1 = *(const key_code_name_t **) p1;
  1017. const key_code_name_t *n2 = *(const key_code_name_t **) p2;
  1018. return n1->code - n2->code;
  1019. }
  1020. /* --------------------------------------------------------------------------------------------- */
  1021. static inline void
  1022. sort_key_conv_tab (enum KeySortType type_sort)
  1023. {
  1024. if (has_been_sorted != type_sort)
  1025. {
  1026. size_t i;
  1027. for (i = 0; i < key_conv_tab_size; i++)
  1028. key_conv_tab_sorted[i] = &key_name_conv_tab[i];
  1029. if (type_sort == KEY_SORTBYNAME)
  1030. {
  1031. qsort (key_conv_tab_sorted, key_conv_tab_size, sizeof (key_conv_tab_sorted[0]),
  1032. &key_code_comparator_by_name);
  1033. }
  1034. else if (type_sort == KEY_SORTBYCODE)
  1035. {
  1036. qsort (key_conv_tab_sorted, key_conv_tab_size, sizeof (key_conv_tab_sorted[0]),
  1037. &key_code_comparator_by_code);
  1038. }
  1039. has_been_sorted = type_sort;
  1040. }
  1041. }
  1042. /* --------------------------------------------------------------------------------------------- */
  1043. static int
  1044. lookup_keyname (const char *name, int *idx)
  1045. {
  1046. if (name[0] != '\0')
  1047. {
  1048. const key_code_name_t key = { 0, name, NULL, NULL };
  1049. const key_code_name_t *keyp = &key;
  1050. key_code_name_t **res;
  1051. if (name[1] == '\0')
  1052. {
  1053. *idx = -1;
  1054. return (int) name[0];
  1055. }
  1056. sort_key_conv_tab (KEY_SORTBYNAME);
  1057. res = bsearch (&keyp, key_conv_tab_sorted, key_conv_tab_size,
  1058. sizeof (key_conv_tab_sorted[0]), key_code_comparator_by_name);
  1059. if (res != NULL)
  1060. {
  1061. *idx = (int) (res - (key_code_name_t **) key_conv_tab_sorted);
  1062. return (*res)->code;
  1063. }
  1064. }
  1065. *idx = -1;
  1066. return 0;
  1067. }
  1068. /* --------------------------------------------------------------------------------------------- */
  1069. static gboolean
  1070. lookup_keycode (const long code, int *idx)
  1071. {
  1072. if (code != 0)
  1073. {
  1074. const key_code_name_t key = { code, NULL, NULL, NULL };
  1075. const key_code_name_t *keyp = &key;
  1076. key_code_name_t **res;
  1077. sort_key_conv_tab (KEY_SORTBYCODE);
  1078. res = bsearch (&keyp, key_conv_tab_sorted, key_conv_tab_size,
  1079. sizeof (key_conv_tab_sorted[0]), key_code_comparator_by_code);
  1080. if (res != NULL)
  1081. {
  1082. *idx = (int) (res - (key_code_name_t **) key_conv_tab_sorted);
  1083. return TRUE;
  1084. }
  1085. }
  1086. *idx = -1;
  1087. return FALSE;
  1088. }
  1089. /* --------------------------------------------------------------------------------------------- */
  1090. /*** public functions ****************************************************************************/
  1091. /* --------------------------------------------------------------------------------------------- */
  1092. /* This has to be called before init_slang or whatever routine
  1093. calls any define_sequence */
  1094. void
  1095. init_key (void)
  1096. {
  1097. const char *term = getenv ("TERM");
  1098. /* This has to be the first define_sequence */
  1099. /* So, we can assume that the first keys member has ESC */
  1100. define_sequences (mc_default_keys);
  1101. /* Terminfo on irix does not have some keys */
  1102. if (xterm_flag
  1103. || (term != NULL
  1104. && (strncmp (term, "iris-ansi", 9) == 0
  1105. || strncmp (term, "xterm", 5) == 0
  1106. || strncmp (term, "rxvt", 4) == 0 || strcmp (term, "screen") == 0)))
  1107. define_sequences (xterm_key_defines);
  1108. /* load some additional keys (e.g. direct Alt-? support) */
  1109. load_xtra_key_defines ();
  1110. #ifdef __QNX__
  1111. if ((term != NULL) && (strncmp (term, "qnx", 3) == 0))
  1112. {
  1113. /* Modify the default value of use_8th_bit_as_meta: we would
  1114. * like to provide a working mc for a newbie who knows nothing
  1115. * about [Options|Display bits|Full 8 bits input]...
  1116. *
  1117. * Don't use 'meta'-bit, when we are dealing with a
  1118. * 'qnx*'-type terminal: clear the default value!
  1119. * These terminal types use 0xFF as an escape character,
  1120. * so use_8th_bit_as_meta==1 must not be enabled!
  1121. *
  1122. * [mc-4.1.21+,slint.c/getch(): the DEC_8BIT_HACK stuff
  1123. * is not used now (doesn't even depend on use_8th_bit_as_meta
  1124. * as in mc-3.1.2)...GREAT!...no additional code is required!]
  1125. */
  1126. use_8th_bit_as_meta = 0;
  1127. }
  1128. #endif /* __QNX__ */
  1129. init_key_x11 ();
  1130. /* Load the qansi-m key definitions
  1131. if we are running under the qansi-m terminal */
  1132. if (term != NULL && (strncmp (term, "qansi-m", 7) == 0))
  1133. define_sequences (qansi_key_defines);
  1134. }
  1135. /* --------------------------------------------------------------------------------------------- */
  1136. /**
  1137. * This has to be called after SLang_init_tty/slint_init
  1138. */
  1139. void
  1140. init_key_input_fd (void)
  1141. {
  1142. #ifdef HAVE_SLANG
  1143. input_fd = SLang_TT_Read_FD;
  1144. #endif
  1145. }
  1146. /* --------------------------------------------------------------------------------------------- */
  1147. void
  1148. done_key (void)
  1149. {
  1150. k_dispose (keys);
  1151. s_dispose (select_list);
  1152. #ifdef HAVE_TEXTMODE_X11_SUPPORT
  1153. if (x11_display)
  1154. mc_XCloseDisplay (x11_display);
  1155. #endif
  1156. }
  1157. /* --------------------------------------------------------------------------------------------- */
  1158. void
  1159. add_select_channel (int fd, select_fn callback, void *info)
  1160. {
  1161. SelectList *new;
  1162. new = g_new (SelectList, 1);
  1163. new->fd = fd;
  1164. new->callback = callback;
  1165. new->info = info;
  1166. new->next = select_list;
  1167. select_list = new;
  1168. }
  1169. /* --------------------------------------------------------------------------------------------- */
  1170. void
  1171. delete_select_channel (int fd)
  1172. {
  1173. SelectList *p = select_list;
  1174. SelectList *p_prev = NULL;
  1175. SelectList *p_next;
  1176. while (p != NULL)
  1177. if (p->fd == fd)
  1178. {
  1179. p_next = p->next;
  1180. if (p_prev != NULL)
  1181. p_prev->next = p_next;
  1182. else
  1183. select_list = p_next;
  1184. g_free (p);
  1185. p = p_next;
  1186. }
  1187. else
  1188. {
  1189. p_prev = p;
  1190. p = p->next;
  1191. }
  1192. }
  1193. /* --------------------------------------------------------------------------------------------- */
  1194. void
  1195. channels_up (void)
  1196. {
  1197. if (disabled_channels == 0)
  1198. fputs ("Error: channels_up called with disabled_channels = 0\n", stderr);
  1199. disabled_channels--;
  1200. }
  1201. /* --------------------------------------------------------------------------------------------- */
  1202. void
  1203. channels_down (void)
  1204. {
  1205. disabled_channels++;
  1206. }
  1207. /* --------------------------------------------------------------------------------------------- */
  1208. /**
  1209. * Return the code associated with the symbolic name keyname
  1210. */
  1211. long
  1212. lookup_key (const char *name, char **label)
  1213. {
  1214. char **lc_keys, **p;
  1215. int k = -1;
  1216. int key = 0;
  1217. int lc_index = -1;
  1218. int use_meta = -1;
  1219. int use_ctrl = -1;
  1220. int use_shift = -1;
  1221. if (name == NULL)
  1222. return 0;
  1223. name = g_strstrip (g_strdup (name));
  1224. p = lc_keys = g_strsplit_set (name, "-+ ", -1);
  1225. g_free ((char *) name);
  1226. while ((p != NULL) && (*p != NULL))
  1227. {
  1228. if ((*p)[0] != '\0')
  1229. {
  1230. int idx;
  1231. key = lookup_keyname (g_strstrip (*p), &idx);
  1232. if (key == KEY_M_ALT)
  1233. use_meta = idx;
  1234. else if (key == KEY_M_CTRL)
  1235. use_ctrl = idx;
  1236. else if (key == KEY_M_SHIFT)
  1237. use_shift = idx;
  1238. else
  1239. {
  1240. k = key;
  1241. lc_index = idx;
  1242. break;
  1243. }
  1244. }
  1245. p++;
  1246. }
  1247. g_strfreev (lc_keys);
  1248. /* output */
  1249. if (k <= 0)
  1250. return 0;
  1251. if (label != NULL)
  1252. {
  1253. GString *s;
  1254. s = g_string_new ("");
  1255. if (use_meta != -1)
  1256. {
  1257. g_string_append (s, key_conv_tab_sorted[use_meta]->shortcut);
  1258. g_string_append_c (s, '-');
  1259. }
  1260. if (use_ctrl != -1)
  1261. {
  1262. g_string_append (s, key_conv_tab_sorted[use_ctrl]->shortcut);
  1263. g_string_append_c (s, '-');
  1264. }
  1265. if (use_shift != -1)
  1266. {
  1267. if (k < 127)
  1268. g_string_append_c (s, (gchar) g_ascii_toupper ((gchar) k));
  1269. else
  1270. {
  1271. g_string_append (s, key_conv_tab_sorted[use_shift]->shortcut);
  1272. g_string_append_c (s, '-');
  1273. g_string_append (s, key_conv_tab_sorted[lc_index]->shortcut);
  1274. }
  1275. }
  1276. else if (k < 128)
  1277. {
  1278. if ((k >= 'A') || (lc_index < 0)
  1279. || (key_conv_tab_sorted[lc_index]->shortcut == NULL))
  1280. g_string_append_c (s, (gchar) g_ascii_tolower ((gchar) k));
  1281. else
  1282. g_string_append (s, key_conv_tab_sorted[lc_index]->shortcut);
  1283. }
  1284. else if ((lc_index != -1) && (key_conv_tab_sorted[lc_index]->shortcut != NULL))
  1285. g_string_append (s, key_conv_tab_sorted[lc_index]->shortcut);
  1286. else
  1287. g_string_append_c (s, (gchar) g_ascii_tolower ((gchar) key));
  1288. *label = g_string_free (s, FALSE);
  1289. }
  1290. if (use_shift != -1)
  1291. {
  1292. if (k < 127 && k > 31)
  1293. k = g_ascii_toupper ((gchar) k);
  1294. else
  1295. k |= KEY_M_SHIFT;
  1296. }
  1297. if (use_ctrl != -1)
  1298. {
  1299. if (k < 256)
  1300. k = XCTRL (k);
  1301. else
  1302. k |= KEY_M_CTRL;
  1303. }
  1304. if (use_meta != -1)
  1305. k = ALT (k);
  1306. return (long) k;
  1307. }
  1308. /* --------------------------------------------------------------------------------------------- */
  1309. char *
  1310. lookup_key_by_code (const int keycode)
  1311. {
  1312. /* code without modifier */
  1313. unsigned int k = keycode & ~KEY_M_MASK;
  1314. /* modifier */
  1315. unsigned int mod = keycode & KEY_M_MASK;
  1316. int use_meta = -1;
  1317. int use_ctrl = -1;
  1318. int use_shift = -1;
  1319. int key_idx = -1;
  1320. GString *s;
  1321. int idx;
  1322. s = g_string_sized_new (8);
  1323. if (lookup_keycode (k, &key_idx) || (k > 0 && k < 256))
  1324. {
  1325. if (mod & KEY_M_ALT)
  1326. {
  1327. if (lookup_keycode (KEY_M_ALT, &idx))
  1328. {
  1329. use_meta = idx;
  1330. g_string_append (s, key_conv_tab_sorted[use_meta]->name);
  1331. g_string_append_c (s, '-');
  1332. }
  1333. }
  1334. if (mod & KEY_M_CTRL)
  1335. {
  1336. /* non printeble chars like a CTRL-[A..Z] */
  1337. if (k < 32)
  1338. k += 64;
  1339. if (lookup_keycode (KEY_M_CTRL, &idx))
  1340. {
  1341. use_ctrl = idx;
  1342. g_string_append (s, key_conv_tab_sorted[use_ctrl]->name);
  1343. g_string_append_c (s, '-');
  1344. }
  1345. }
  1346. if (mod & KEY_M_SHIFT)
  1347. {
  1348. if (lookup_keycode (KEY_M_ALT, &idx))
  1349. {
  1350. use_shift = idx;
  1351. if (k < 127)
  1352. g_string_append_c (s, (gchar) g_ascii_toupper ((gchar) k));
  1353. else
  1354. {
  1355. g_string_append (s, key_conv_tab_sorted[use_shift]->name);
  1356. g_string_append_c (s, '-');
  1357. g_string_append (s, key_conv_tab_sorted[key_idx]->name);
  1358. }
  1359. }
  1360. }
  1361. else if (k < 128)
  1362. {
  1363. if ((k >= 'A') || (key_idx < 0)
  1364. || (key_conv_tab_sorted[key_idx]->name == NULL))
  1365. g_string_append_c (s, (gchar) k);
  1366. else
  1367. g_string_append (s, key_conv_tab_sorted[key_idx]->name);
  1368. }
  1369. else if ((key_idx != -1) && (key_conv_tab_sorted[key_idx]->name != NULL))
  1370. g_string_append (s, key_conv_tab_sorted[key_idx]->name);
  1371. else
  1372. g_string_append_c (s, (gchar) keycode);
  1373. }
  1374. return g_string_free (s, s->len == 0);
  1375. }
  1376. /* --------------------------------------------------------------------------------------------- */
  1377. /**
  1378. * Return TRUE on success, FALSE on error.
  1379. * An error happens if SEQ is a beginning of an existing longer sequence.
  1380. */
  1381. gboolean
  1382. define_sequence (int code, const char *seq, int action)
  1383. {
  1384. key_def *base;
  1385. if (strlen (seq) > SEQ_BUFFER_LEN - 1)
  1386. return FALSE;
  1387. for (base = keys; (base != NULL) && (*seq != '\0');)
  1388. if (*seq == base->ch)
  1389. {
  1390. if (base->child == 0)
  1391. {
  1392. if (*(seq + 1) != '\0')
  1393. base->child = create_sequence (seq + 1, code, action);
  1394. else
  1395. {
  1396. /* The sequence matches an existing one. */
  1397. base->code = code;
  1398. base->action = action;
  1399. }
  1400. return TRUE;
  1401. }
  1402. base = base->child;
  1403. seq++;
  1404. }
  1405. else
  1406. {
  1407. if (base->next)
  1408. base = base->next;
  1409. else
  1410. {
  1411. base->next = create_sequence (seq, code, action);
  1412. return TRUE;
  1413. }
  1414. }
  1415. if (*seq == '\0')
  1416. {
  1417. /* Attempt to redefine a sequence with a shorter sequence. */
  1418. return FALSE;
  1419. }
  1420. keys = create_sequence (seq, code, action);
  1421. return TRUE;
  1422. }
  1423. /* --------------------------------------------------------------------------------------------- */
  1424. /**
  1425. * Check if we are idle, i.e. there are no pending keyboard or mouse
  1426. * events. Return 1 is idle, 0 is there are pending events.
  1427. */
  1428. gboolean
  1429. is_idle (void)
  1430. {
  1431. int maxfdp;
  1432. fd_set select_set;
  1433. struct timeval time_out;
  1434. FD_ZERO (&select_set);
  1435. FD_SET (input_fd, &select_set);
  1436. maxfdp = input_fd;
  1437. #ifdef HAVE_LIBGPM
  1438. if (mouse_enabled && (use_mouse_p == MOUSE_GPM) && (gpm_fd > 0))
  1439. {
  1440. FD_SET (gpm_fd, &select_set);
  1441. maxfdp = max (maxfdp, gpm_fd);
  1442. }
  1443. #endif
  1444. time_out.tv_sec = 0;
  1445. time_out.tv_usec = 0;
  1446. return (select (maxfdp + 1, &select_set, 0, 0, &time_out) <= 0);
  1447. }
  1448. /* --------------------------------------------------------------------------------------------- */
  1449. int
  1450. get_key_code (int no_delay)
  1451. {
  1452. int c;
  1453. static key_def *this = NULL, *parent;
  1454. static struct timeval esctime = { -1, -1 };
  1455. static int lastnodelay = -1;
  1456. if (no_delay != lastnodelay)
  1457. {
  1458. this = NULL;
  1459. lastnodelay = no_delay;
  1460. }
  1461. pend_send:
  1462. if (pending_keys != NULL)
  1463. {
  1464. int d = *pending_keys++;
  1465. check_pend:
  1466. if (*pending_keys == 0)
  1467. {
  1468. pending_keys = NULL;
  1469. seq_append = NULL;
  1470. }
  1471. if ((d == ESC_CHAR) && (pending_keys != NULL))
  1472. {
  1473. d = ALT (*pending_keys++);
  1474. goto check_pend;
  1475. }
  1476. if ((d > 127 && d < 256) && use_8th_bit_as_meta)
  1477. d = ALT (d & 0x7f);
  1478. this = NULL;
  1479. return correct_key_code (d);
  1480. }
  1481. nodelay_try_again:
  1482. if (no_delay)
  1483. tty_nodelay (TRUE);
  1484. c = tty_lowlevel_getch ();
  1485. #if (defined(USE_NCURSES) || defined(USE_NCURSESW)) && defined(KEY_RESIZE)
  1486. if (c == KEY_RESIZE)
  1487. goto nodelay_try_again;
  1488. #endif
  1489. if (no_delay)
  1490. {
  1491. tty_nodelay (FALSE);
  1492. if (c == -1)
  1493. {
  1494. if (this != NULL && parent != NULL && parent->action == MCKEY_ESCAPE && old_esc_mode)
  1495. {
  1496. struct timeval current, time_out;
  1497. if (esctime.tv_sec == -1)
  1498. return -1;
  1499. GET_TIME (current);
  1500. time_out.tv_sec = old_esc_mode_timeout / 1000000 + esctime.tv_sec;
  1501. time_out.tv_usec = old_esc_mode_timeout % 1000000 + esctime.tv_usec;
  1502. if (time_out.tv_usec > 1000000)
  1503. {
  1504. time_out.tv_usec -= 1000000;
  1505. time_out.tv_sec++;
  1506. }
  1507. if (current.tv_sec < time_out.tv_sec)
  1508. return -1;
  1509. if (current.tv_sec == time_out.tv_sec && current.tv_usec < time_out.tv_usec)
  1510. return -1;
  1511. this = NULL;
  1512. pending_keys = seq_append = NULL;
  1513. return ESC_CHAR;
  1514. }
  1515. return -1;
  1516. }
  1517. }
  1518. else if (c == -1)
  1519. {
  1520. /* Maybe we got an incomplete match.
  1521. This we do only in delay mode, since otherwise
  1522. tty_lowlevel_getch can return -1 at any time. */
  1523. if (seq_append != NULL)
  1524. {
  1525. pending_keys = seq_buffer;
  1526. goto pend_send;
  1527. }
  1528. this = NULL;
  1529. return -1;
  1530. }
  1531. /* Search the key on the root */
  1532. if (!no_delay || this == NULL)
  1533. {
  1534. this = keys;
  1535. parent = NULL;
  1536. if ((c > 127 && c < 256) && use_8th_bit_as_meta)
  1537. {
  1538. c &= 0x7f;
  1539. /* The first sequence defined starts with esc */
  1540. parent = keys;
  1541. this = keys->child;
  1542. }
  1543. }
  1544. while (this != NULL)
  1545. {
  1546. if (c == this->ch)
  1547. {
  1548. if (this->child)
  1549. {
  1550. if (!push_char (c))
  1551. {
  1552. pending_keys = seq_buffer;
  1553. goto pend_send;
  1554. }
  1555. parent = this;
  1556. this = this->child;
  1557. if (parent->action == MCKEY_ESCAPE && old_esc_mode)
  1558. {
  1559. if (no_delay)
  1560. {
  1561. GET_TIME (esctime);
  1562. if (this == NULL)
  1563. {
  1564. /* Shouldn't happen */
  1565. fputs ("Internal error\n", stderr);
  1566. exit (EXIT_FAILURE);
  1567. }
  1568. goto nodelay_try_again;
  1569. }
  1570. esctime.tv_sec = -1;
  1571. c = xgetch_second ();
  1572. if (c == -1)
  1573. {
  1574. pending_keys = seq_append = NULL;
  1575. this = NULL;
  1576. return ESC_CHAR;
  1577. }
  1578. }
  1579. else
  1580. {
  1581. if (no_delay)
  1582. goto nodelay_try_again;
  1583. c = tty_lowlevel_getch ();
  1584. }
  1585. }
  1586. else
  1587. {
  1588. /* We got a complete match, return and reset search */
  1589. int code;
  1590. pending_keys = seq_append = NULL;
  1591. code = this->code;
  1592. this = NULL;
  1593. return correct_key_code (code);
  1594. }
  1595. }
  1596. else
  1597. {
  1598. if (this->next != NULL)
  1599. this = this->next;
  1600. else
  1601. {
  1602. if ((parent != NULL) && (parent->action == MCKEY_ESCAPE))
  1603. {
  1604. /* Convert escape-digits to F-keys */
  1605. if (g_ascii_isdigit (c))
  1606. c = KEY_F (c - '0');
  1607. else if (c == ' ')
  1608. c = ESC_CHAR;
  1609. else
  1610. c = ALT (c);
  1611. pending_keys = seq_append = NULL;
  1612. this = NULL;
  1613. return correct_key_code (c);
  1614. }
  1615. /* Did not find a match or {c} was changed in the if above,
  1616. so we have to return everything we had skipped
  1617. */
  1618. push_char (c);
  1619. pending_keys = seq_buffer;
  1620. goto pend_send;
  1621. }
  1622. }
  1623. }
  1624. this = NULL;
  1625. return correct_key_code (c);
  1626. }
  1627. /* --------------------------------------------------------------------------------------------- */
  1628. /* Returns a character read from stdin with appropriate interpretation */
  1629. /* Also takes care of generated mouse events */
  1630. /* Returns EV_MOUSE if it is a mouse event */
  1631. /* Returns EV_NONE if non-blocking or interrupt set and nothing was done */
  1632. int
  1633. tty_get_event (struct Gpm_Event *event, gboolean redo_event, gboolean block)
  1634. {
  1635. int c;
  1636. static int flag = 0; /* Return value from select */
  1637. #ifdef HAVE_LIBGPM
  1638. static struct Gpm_Event ev; /* Mouse event */
  1639. #endif
  1640. struct timeval time_out;
  1641. struct timeval *time_addr = NULL;
  1642. static int dirty = 3;
  1643. if ((dirty == 3) || is_idle ())
  1644. {
  1645. mc_refresh ();
  1646. dirty = 1;
  1647. }
  1648. else
  1649. dirty++;
  1650. vfs_timeout_handler ();
  1651. /* Ok, we use (event->x < 0) to signal that the event does not contain
  1652. a suitable position for the mouse, so we can't use show_mouse_pointer
  1653. on it.
  1654. */
  1655. if (event->x > 0)
  1656. {
  1657. show_mouse_pointer (event->x, event->y);
  1658. if (!redo_event)
  1659. event->x = -1;
  1660. }
  1661. /* Repeat if using mouse */
  1662. while (pending_keys == NULL)
  1663. {
  1664. int maxfdp;
  1665. fd_set select_set;
  1666. FD_ZERO (&select_set);
  1667. FD_SET (input_fd, &select_set);
  1668. maxfdp = max (add_selects (&select_set), input_fd);
  1669. #ifdef HAVE_LIBGPM
  1670. if (mouse_enabled && (use_mouse_p == MOUSE_GPM))
  1671. {
  1672. if (gpm_fd < 0)
  1673. {
  1674. /* Connection to gpm broken, possibly gpm has died */
  1675. mouse_enabled = FALSE;
  1676. use_mouse_p = MOUSE_NONE;
  1677. break;
  1678. }
  1679. FD_SET (gpm_fd, &select_set);
  1680. maxfdp = max (maxfdp, gpm_fd);
  1681. }
  1682. #endif
  1683. if (redo_event)
  1684. {
  1685. time_out.tv_usec = mou_auto_repeat * 1000;
  1686. time_out.tv_sec = 0;
  1687. time_addr = &time_out;
  1688. }
  1689. else
  1690. {
  1691. int seconds;
  1692. seconds = vfs_timeouts ();
  1693. time_addr = NULL;
  1694. if (seconds != 0)
  1695. {
  1696. /* the timeout could be improved and actually be
  1697. * the number of seconds until the next vfs entry
  1698. * timeouts in the stamp list.
  1699. */
  1700. time_out.tv_sec = seconds;
  1701. time_out.tv_usec = 0;
  1702. time_addr = &time_out;
  1703. }
  1704. }
  1705. if (!block || mc_global.tty.winch_flag)
  1706. {
  1707. time_addr = &time_out;
  1708. time_out.tv_sec = 0;
  1709. time_out.tv_usec = 0;
  1710. }
  1711. tty_enable_interrupt_key ();
  1712. flag = select (maxfdp + 1, &select_set, NULL, NULL, time_addr);
  1713. tty_disable_interrupt_key ();
  1714. /* select timed out: it could be for any of the following reasons:
  1715. * redo_event -> it was because of the MOU_REPEAT handler
  1716. * !block -> we did not block in the select call
  1717. * else -> 10 second timeout to check the vfs status.
  1718. */
  1719. if (flag == 0)
  1720. {
  1721. if (redo_event)
  1722. return EV_MOUSE;
  1723. if (!block || mc_global.tty.winch_flag)
  1724. return EV_NONE;
  1725. vfs_timeout_handler ();
  1726. }
  1727. if (flag == -1 && errno == EINTR)
  1728. return EV_NONE;
  1729. check_selects (&select_set);
  1730. if (FD_ISSET (input_fd, &select_set))
  1731. break;
  1732. #ifdef HAVE_LIBGPM
  1733. if (mouse_enabled && use_mouse_p == MOUSE_GPM
  1734. && gpm_fd > 0 && FD_ISSET (gpm_fd, &select_set))
  1735. {
  1736. Gpm_GetEvent (&ev);
  1737. Gpm_FitEvent (&ev);
  1738. *event = ev;
  1739. return EV_MOUSE;
  1740. }
  1741. #endif /* !HAVE_LIBGPM */
  1742. }
  1743. #ifndef HAVE_SLANG
  1744. flag = is_wintouched (stdscr);
  1745. untouchwin (stdscr);
  1746. #endif /* !HAVE_SLANG */
  1747. c = block ? getch_with_delay () : get_key_code (1);
  1748. #ifndef HAVE_SLANG
  1749. if (flag > 0)
  1750. tty_touch_screen ();
  1751. #endif /* !HAVE_SLANG */
  1752. if (mouse_enabled && (c == MCKEY_MOUSE
  1753. #ifdef KEY_MOUSE
  1754. || c == KEY_MOUSE
  1755. #endif /* KEY_MOUSE */
  1756. ))
  1757. {
  1758. /* Mouse event */
  1759. xmouse_get_event (event);
  1760. return (event->type != 0) ? EV_MOUSE : EV_NONE;
  1761. }
  1762. return c;
  1763. }
  1764. /* --------------------------------------------------------------------------------------------- */
  1765. /* Returns a key press, mouse events are discarded */
  1766. int
  1767. tty_getch (void)
  1768. {
  1769. Gpm_Event ev;
  1770. int key;
  1771. ev.x = -1;
  1772. while ((key = tty_get_event (&ev, FALSE, TRUE)) == EV_NONE);
  1773. return key;
  1774. }
  1775. /* --------------------------------------------------------------------------------------------- */
  1776. char *
  1777. learn_key (void)
  1778. {
  1779. /* LEARN_TIMEOUT in usec */
  1780. #define LEARN_TIMEOUT 200000
  1781. fd_set Read_FD_Set;
  1782. struct timeval endtime;
  1783. struct timeval time_out;
  1784. int c;
  1785. char buffer[256];
  1786. char *p = buffer;
  1787. tty_keypad (FALSE); /* disable intepreting keys by ncurses */
  1788. c = tty_lowlevel_getch ();
  1789. while (c == -1)
  1790. c = tty_lowlevel_getch (); /* Sanity check, should be unnecessary */
  1791. learn_store_key (buffer, &p, c);
  1792. GET_TIME (endtime);
  1793. endtime.tv_usec += LEARN_TIMEOUT;
  1794. if (endtime.tv_usec > 1000000)
  1795. {
  1796. endtime.tv_usec -= 1000000;
  1797. endtime.tv_sec++;
  1798. }
  1799. tty_nodelay (TRUE);
  1800. for (;;)
  1801. {
  1802. while ((c = tty_lowlevel_getch ()) == -1)
  1803. {
  1804. GET_TIME (time_out);
  1805. time_out.tv_usec = endtime.tv_usec - time_out.tv_usec;
  1806. if (time_out.tv_usec < 0)
  1807. time_out.tv_sec++;
  1808. time_out.tv_sec = endtime.tv_sec - time_out.tv_sec;
  1809. if (time_out.tv_sec >= 0 && time_out.tv_usec > 0)
  1810. {
  1811. FD_ZERO (&Read_FD_Set);
  1812. FD_SET (input_fd, &Read_FD_Set);
  1813. select (input_fd + 1, &Read_FD_Set, NULL, NULL, &time_out);
  1814. }
  1815. else
  1816. break;
  1817. }
  1818. if (c == -1)
  1819. break;
  1820. learn_store_key (buffer, &p, c);
  1821. }
  1822. tty_keypad (TRUE);
  1823. tty_nodelay (FALSE);
  1824. *p = '\0';
  1825. return g_strdup (buffer);
  1826. #undef LEARN_TIMEOUT
  1827. }
  1828. /* --------------------------------------------------------------------------------------------- */
  1829. /* xterm and linux console only: set keypad to numeric or application
  1830. mode. Only in application keypad mode it's possible to distinguish
  1831. the '+' key and the '+' on the keypad ('*' and '-' ditto) */
  1832. void
  1833. numeric_keypad_mode (void)
  1834. {
  1835. if (mc_global.tty.console_flag || xterm_flag)
  1836. {
  1837. fputs ("\033>", stdout);
  1838. fflush (stdout);
  1839. }
  1840. }
  1841. /* --------------------------------------------------------------------------------------------- */
  1842. void
  1843. application_keypad_mode (void)
  1844. {
  1845. if (mc_global.tty.console_flag || xterm_flag)
  1846. {
  1847. fputs ("\033=", stdout);
  1848. fflush (stdout);
  1849. }
  1850. }
  1851. /* --------------------------------------------------------------------------------------------- */