key.c 57 KB

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