key.c 71 KB

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