key.c 62 KB

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