Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  1. #include "escape.hxx"
  2. #include "io.hxx"
  3. #include "replxx.hxx"
  4. #ifndef _WIN32
  5. namespace replxx {
  6. namespace EscapeSequenceProcessing { // move these out of global namespace
  7. // This chunk of code does parsing of the escape sequences sent by various Linux
  8. // terminals.
  9. //
  10. // It handles arrow keys, Home, End and Delete keys by interpreting the
  11. // sequences sent by
  12. // gnome terminal, xterm, rxvt, konsole, aterm and yakuake including the Alt and
  13. // Ctrl key
  14. // combinations that are understood by replxx.
  15. //
  16. // The parsing uses tables, a bunch of intermediate dispatch routines and a
  17. // doDispatch
  18. // loop that reads the tables and sends control to "deeper" routines to continue
  19. // the
  20. // parsing. The starting call to doDispatch( c, initialDispatch ) will
  21. // eventually return
  22. // either a character (with optional CTRL and META bits set), or -1 if parsing
  23. // fails, or
  24. // zero if an attempt to read from the keyboard fails.
  25. //
  26. // This is rather sloppy escape sequence processing, since we're not paying
  27. // attention to what the
  28. // actual TERM is set to and are processing all key sequences for all terminals,
  29. // but it works with
  30. // the most common keystrokes on the most common terminals. It's intricate, but
  31. // the nested 'if'
  32. // statements required to do it directly would be worse. This way has the
  33. // advantage of allowing
  34. // changes and extensions without having to touch a lot of code.
  35. static char32_t thisKeyMetaCtrl = 0; // holds pre-set Meta and/or Ctrl modifiers
  36. // This dispatch routine is given a dispatch table and then farms work out to
  37. // routines
  38. // listed in the table based on the character it is called with. The dispatch
  39. // routines can
  40. // read more input characters to decide what should eventually be returned.
  41. // Eventually,
  42. // a called routine returns either a character or -1 to indicate parsing
  43. // failure.
  44. //
  45. char32_t doDispatch(char32_t c, CharacterDispatch& dispatchTable) {
  46. for (unsigned int i = 0; i < dispatchTable.len; ++i) {
  47. if (static_cast<unsigned char>(dispatchTable.chars[i]) == c) {
  48. return dispatchTable.dispatch[i](c);
  49. }
  50. }
  51. return dispatchTable.dispatch[dispatchTable.len](c);
  52. }
  53. // Final dispatch routines -- return something
  54. //
  55. static char32_t normalKeyRoutine(char32_t c) { return thisKeyMetaCtrl | c; }
  56. static char32_t upArrowKeyRoutine(char32_t) {
  57. return thisKeyMetaCtrl | Replxx::KEY::UP;;
  58. }
  59. static char32_t downArrowKeyRoutine(char32_t) {
  60. return thisKeyMetaCtrl | Replxx::KEY::DOWN;
  61. }
  62. static char32_t rightArrowKeyRoutine(char32_t) {
  63. return thisKeyMetaCtrl | Replxx::KEY::RIGHT;
  64. }
  65. static char32_t leftArrowKeyRoutine(char32_t) {
  66. return thisKeyMetaCtrl | Replxx::KEY::LEFT;
  67. }
  68. static char32_t homeKeyRoutine(char32_t) { return thisKeyMetaCtrl | Replxx::KEY::HOME; }
  69. static char32_t endKeyRoutine(char32_t) { return thisKeyMetaCtrl | Replxx::KEY::END; }
  70. static char32_t shiftTabRoutine(char32_t) { return Replxx::KEY::BASE_SHIFT | Replxx::KEY::TAB; }
  71. static char32_t f1KeyRoutine(char32_t) { return thisKeyMetaCtrl | Replxx::KEY::F1; }
  72. static char32_t f2KeyRoutine(char32_t) { return thisKeyMetaCtrl | Replxx::KEY::F2; }
  73. static char32_t f3KeyRoutine(char32_t) { return thisKeyMetaCtrl | Replxx::KEY::F3; }
  74. static char32_t f4KeyRoutine(char32_t) { return thisKeyMetaCtrl | Replxx::KEY::F4; }
  75. static char32_t f5KeyRoutine(char32_t) { return thisKeyMetaCtrl | Replxx::KEY::F5; }
  76. static char32_t f6KeyRoutine(char32_t) { return thisKeyMetaCtrl | Replxx::KEY::F6; }
  77. static char32_t f7KeyRoutine(char32_t) { return thisKeyMetaCtrl | Replxx::KEY::F7; }
  78. static char32_t f8KeyRoutine(char32_t) { return thisKeyMetaCtrl | Replxx::KEY::F8; }
  79. static char32_t f9KeyRoutine(char32_t) { return thisKeyMetaCtrl | Replxx::KEY::F9; }
  80. static char32_t f10KeyRoutine(char32_t) { return thisKeyMetaCtrl | Replxx::KEY::F10; }
  81. static char32_t f11KeyRoutine(char32_t) { return thisKeyMetaCtrl | Replxx::KEY::F11; }
  82. static char32_t f12KeyRoutine(char32_t) { return thisKeyMetaCtrl | Replxx::KEY::F12; }
  83. static char32_t pageUpKeyRoutine(char32_t) {
  84. return thisKeyMetaCtrl | Replxx::KEY::PAGE_UP;
  85. }
  86. static char32_t pageDownKeyRoutine(char32_t) {
  87. return thisKeyMetaCtrl | Replxx::KEY::PAGE_DOWN;
  88. }
  89. static char32_t deleteCharRoutine(char32_t) {
  90. return thisKeyMetaCtrl | Replxx::KEY::BACKSPACE;
  91. } // key labeled Backspace
  92. static char32_t insertKeyRoutine(char32_t) {
  93. return thisKeyMetaCtrl | Replxx::KEY::INSERT;
  94. } // key labeled Delete
  95. static char32_t deleteKeyRoutine(char32_t) {
  96. return thisKeyMetaCtrl | Replxx::KEY::DELETE;
  97. } // key labeled Delete
  98. static char32_t ctrlUpArrowKeyRoutine(char32_t) {
  99. return thisKeyMetaCtrl | Replxx::KEY::BASE_CONTROL | Replxx::KEY::UP;
  100. }
  101. static char32_t ctrlDownArrowKeyRoutine(char32_t) {
  102. return thisKeyMetaCtrl | Replxx::KEY::BASE_CONTROL | Replxx::KEY::DOWN;
  103. }
  104. static char32_t ctrlRightArrowKeyRoutine(char32_t) {
  105. return thisKeyMetaCtrl | Replxx::KEY::BASE_CONTROL | Replxx::KEY::RIGHT;
  106. }
  107. static char32_t ctrlLeftArrowKeyRoutine(char32_t) {
  108. return thisKeyMetaCtrl | Replxx::KEY::BASE_CONTROL | Replxx::KEY::LEFT;
  109. }
  110. static char32_t escFailureRoutine(char32_t) {
  111. beep();
  112. return -1;
  113. }
  114. // Handle ESC [ 1 ; 2 or 3 (or 5) <more stuff> escape sequences
  115. //
  116. static CharacterDispatchRoutine escLeftBracket1Semicolon2or3or5Routines[] = {
  117. upArrowKeyRoutine,
  118. downArrowKeyRoutine,
  119. rightArrowKeyRoutine,
  120. leftArrowKeyRoutine,
  121. homeKeyRoutine,
  122. endKeyRoutine,
  123. f1KeyRoutine,
  124. f2KeyRoutine,
  125. f3KeyRoutine,
  126. f4KeyRoutine,
  127. escFailureRoutine
  128. };
  129. static CharacterDispatch escLeftBracket1Semicolon2or3or5Dispatch = {
  130. 10, "ABCDHFPQRS", escLeftBracket1Semicolon2or3or5Routines
  131. };
  132. // Handle ESC [ 1 ; <more stuff> escape sequences
  133. //
  134. static char32_t escLeftBracket1Semicolon2Routine(char32_t c) {
  135. c = read_unicode_character();
  136. if (c == 0) return 0;
  137. thisKeyMetaCtrl |= Replxx::KEY::BASE_SHIFT;
  138. return doDispatch(c, escLeftBracket1Semicolon2or3or5Dispatch);
  139. }
  140. static char32_t escLeftBracket1Semicolon3Routine(char32_t c) {
  141. c = read_unicode_character();
  142. if (c == 0) return 0;
  143. thisKeyMetaCtrl |= Replxx::KEY::BASE_META;
  144. return doDispatch(c, escLeftBracket1Semicolon2or3or5Dispatch);
  145. }
  146. static char32_t escLeftBracket1Semicolon5Routine(char32_t c) {
  147. c = read_unicode_character();
  148. if (c == 0) return 0;
  149. thisKeyMetaCtrl |= Replxx::KEY::BASE_CONTROL;
  150. return doDispatch(c, escLeftBracket1Semicolon2or3or5Dispatch);
  151. }
  152. static CharacterDispatchRoutine escLeftBracket1SemicolonRoutines[] = {
  153. escLeftBracket1Semicolon2Routine,
  154. escLeftBracket1Semicolon3Routine,
  155. escLeftBracket1Semicolon5Routine,
  156. escFailureRoutine
  157. };
  158. static CharacterDispatch escLeftBracket1SemicolonDispatch = {
  159. 3, "235", escLeftBracket1SemicolonRoutines
  160. };
  161. // Handle ESC [ 1 ; <more stuff> escape sequences
  162. //
  163. static char32_t escLeftBracket1SemicolonRoutine(char32_t c) {
  164. c = read_unicode_character();
  165. if (c == 0) return 0;
  166. return doDispatch(c, escLeftBracket1SemicolonDispatch);
  167. }
  168. // (S)-F5
  169. static CharacterDispatchRoutine escLeftBracket15Semicolon2Routines[] = {
  170. f5KeyRoutine, escFailureRoutine
  171. };
  172. static CharacterDispatch escLeftBracket15Semicolon2Dispatch = {
  173. 1, "~", escLeftBracket15Semicolon2Routines
  174. };
  175. static char32_t escLeftBracket15Semicolon2Routine(char32_t c) {
  176. c = read_unicode_character();
  177. if (c == 0) return 0;
  178. thisKeyMetaCtrl |= Replxx::KEY::BASE_SHIFT;
  179. return doDispatch(c, escLeftBracket15Semicolon2Dispatch);
  180. }
  181. // (C)-F5
  182. static CharacterDispatchRoutine escLeftBracket15Semicolon5Routines[] = {
  183. f5KeyRoutine, escFailureRoutine
  184. };
  185. static CharacterDispatch escLeftBracket15Semicolon5Dispatch = {
  186. 1, "~", escLeftBracket15Semicolon5Routines
  187. };
  188. static char32_t escLeftBracket15Semicolon5Routine(char32_t c) {
  189. c = read_unicode_character();
  190. if (c == 0) return 0;
  191. thisKeyMetaCtrl |= Replxx::KEY::BASE_CONTROL;
  192. return doDispatch(c, escLeftBracket15Semicolon5Dispatch);
  193. }
  194. static CharacterDispatchRoutine escLeftBracket15SemicolonRoutines[] = {
  195. escLeftBracket15Semicolon2Routine, escLeftBracket15Semicolon5Routine, escFailureRoutine
  196. };
  197. static CharacterDispatch escLeftBracket15SemicolonDispatch = {
  198. 2, "25", escLeftBracket15SemicolonRoutines
  199. };
  200. static char32_t escLeftBracket15SemicolonRoutine(char32_t c) {
  201. c = read_unicode_character();
  202. if (c == 0) return 0;
  203. return doDispatch(c, escLeftBracket15SemicolonDispatch);
  204. }
  205. static CharacterDispatchRoutine escLeftBracket15Routines[] = {
  206. f5KeyRoutine, escLeftBracket15SemicolonRoutine, escFailureRoutine
  207. };
  208. static CharacterDispatch escLeftBracket15Dispatch = {
  209. 2, "~;", escLeftBracket15Routines
  210. };
  211. static char32_t escLeftBracket15Routine(char32_t c) {
  212. c = read_unicode_character();
  213. if (c == 0) return 0;
  214. return doDispatch(c, escLeftBracket15Dispatch);
  215. }
  216. // (S)-F6
  217. static CharacterDispatchRoutine escLeftBracket17Semicolon2Routines[] = {
  218. f6KeyRoutine, escFailureRoutine
  219. };
  220. static CharacterDispatch escLeftBracket17Semicolon2Dispatch = {
  221. 1, "~", escLeftBracket17Semicolon2Routines
  222. };
  223. static char32_t escLeftBracket17Semicolon2Routine(char32_t c) {
  224. c = read_unicode_character();
  225. if (c == 0) return 0;
  226. thisKeyMetaCtrl |= Replxx::KEY::BASE_SHIFT;
  227. return doDispatch(c, escLeftBracket17Semicolon2Dispatch);
  228. }
  229. // (C)-F6
  230. static CharacterDispatchRoutine escLeftBracket17Semicolon5Routines[] = {
  231. f6KeyRoutine, escFailureRoutine
  232. };
  233. static CharacterDispatch escLeftBracket17Semicolon5Dispatch = {
  234. 1, "~", escLeftBracket17Semicolon5Routines
  235. };
  236. static char32_t escLeftBracket17Semicolon5Routine(char32_t c) {
  237. c = read_unicode_character();
  238. if (c == 0) return 0;
  239. thisKeyMetaCtrl |= Replxx::KEY::BASE_CONTROL;
  240. return doDispatch(c, escLeftBracket17Semicolon5Dispatch);
  241. }
  242. static CharacterDispatchRoutine escLeftBracket17SemicolonRoutines[] = {
  243. escLeftBracket17Semicolon2Routine, escLeftBracket17Semicolon5Routine, escFailureRoutine
  244. };
  245. static CharacterDispatch escLeftBracket17SemicolonDispatch = {
  246. 2, "25", escLeftBracket17SemicolonRoutines
  247. };
  248. static char32_t escLeftBracket17SemicolonRoutine(char32_t c) {
  249. c = read_unicode_character();
  250. if (c == 0) return 0;
  251. return doDispatch(c, escLeftBracket17SemicolonDispatch);
  252. }
  253. static CharacterDispatchRoutine escLeftBracket17Routines[] = {
  254. f6KeyRoutine, escLeftBracket17SemicolonRoutine, escFailureRoutine
  255. };
  256. static CharacterDispatch escLeftBracket17Dispatch = {
  257. 2, "~;", escLeftBracket17Routines
  258. };
  259. static char32_t escLeftBracket17Routine(char32_t c) {
  260. c = read_unicode_character();
  261. if (c == 0) return 0;
  262. return doDispatch(c, escLeftBracket17Dispatch);
  263. }
  264. // (S)-F7
  265. static CharacterDispatchRoutine escLeftBracket18Semicolon2Routines[] = {
  266. f7KeyRoutine, escFailureRoutine
  267. };
  268. static CharacterDispatch escLeftBracket18Semicolon2Dispatch = {
  269. 1, "~", escLeftBracket18Semicolon2Routines
  270. };
  271. static char32_t escLeftBracket18Semicolon2Routine(char32_t c) {
  272. c = read_unicode_character();
  273. if (c == 0) return 0;
  274. thisKeyMetaCtrl |= Replxx::KEY::BASE_SHIFT;
  275. return doDispatch(c, escLeftBracket18Semicolon2Dispatch);
  276. }
  277. // (C)-F7
  278. static CharacterDispatchRoutine escLeftBracket18Semicolon5Routines[] = {
  279. f7KeyRoutine, escFailureRoutine
  280. };
  281. static CharacterDispatch escLeftBracket18Semicolon5Dispatch = {
  282. 1, "~", escLeftBracket18Semicolon5Routines
  283. };
  284. static char32_t escLeftBracket18Semicolon5Routine(char32_t c) {
  285. c = read_unicode_character();
  286. if (c == 0) return 0;
  287. thisKeyMetaCtrl |= Replxx::KEY::BASE_CONTROL;
  288. return doDispatch(c, escLeftBracket18Semicolon5Dispatch);
  289. }
  290. static CharacterDispatchRoutine escLeftBracket18SemicolonRoutines[] = {
  291. escLeftBracket18Semicolon2Routine, escLeftBracket18Semicolon5Routine, escFailureRoutine
  292. };
  293. static CharacterDispatch escLeftBracket18SemicolonDispatch = {
  294. 2, "25", escLeftBracket18SemicolonRoutines
  295. };
  296. static char32_t escLeftBracket18SemicolonRoutine(char32_t c) {
  297. c = read_unicode_character();
  298. if (c == 0) return 0;
  299. return doDispatch(c, escLeftBracket18SemicolonDispatch);
  300. }
  301. static CharacterDispatchRoutine escLeftBracket18Routines[] = {
  302. f7KeyRoutine, escLeftBracket18SemicolonRoutine, escFailureRoutine
  303. };
  304. static CharacterDispatch escLeftBracket18Dispatch = {
  305. 2, "~;", escLeftBracket18Routines
  306. };
  307. static char32_t escLeftBracket18Routine(char32_t c) {
  308. c = read_unicode_character();
  309. if (c == 0) return 0;
  310. return doDispatch(c, escLeftBracket18Dispatch);
  311. }
  312. // (S)-F8
  313. static CharacterDispatchRoutine escLeftBracket19Semicolon2Routines[] = {
  314. f8KeyRoutine, escFailureRoutine
  315. };
  316. static CharacterDispatch escLeftBracket19Semicolon2Dispatch = {
  317. 1, "~", escLeftBracket19Semicolon2Routines
  318. };
  319. static char32_t escLeftBracket19Semicolon2Routine(char32_t c) {
  320. c = read_unicode_character();
  321. if (c == 0) return 0;
  322. thisKeyMetaCtrl |= Replxx::KEY::BASE_SHIFT;
  323. return doDispatch(c, escLeftBracket19Semicolon2Dispatch);
  324. }
  325. // (C)-F8
  326. static CharacterDispatchRoutine escLeftBracket19Semicolon5Routines[] = {
  327. f8KeyRoutine, escFailureRoutine
  328. };
  329. static CharacterDispatch escLeftBracket19Semicolon5Dispatch = {
  330. 1, "~", escLeftBracket19Semicolon5Routines
  331. };
  332. static char32_t escLeftBracket19Semicolon5Routine(char32_t c) {
  333. c = read_unicode_character();
  334. if (c == 0) return 0;
  335. thisKeyMetaCtrl |= Replxx::KEY::BASE_CONTROL;
  336. return doDispatch(c, escLeftBracket19Semicolon5Dispatch);
  337. }
  338. static CharacterDispatchRoutine escLeftBracket19SemicolonRoutines[] = {
  339. escLeftBracket19Semicolon2Routine, escLeftBracket19Semicolon5Routine, escFailureRoutine
  340. };
  341. static CharacterDispatch escLeftBracket19SemicolonDispatch = {
  342. 2, "25", escLeftBracket19SemicolonRoutines
  343. };
  344. static char32_t escLeftBracket19SemicolonRoutine(char32_t c) {
  345. c = read_unicode_character();
  346. if (c == 0) return 0;
  347. return doDispatch(c, escLeftBracket19SemicolonDispatch);
  348. }
  349. static CharacterDispatchRoutine escLeftBracket19Routines[] = {
  350. f8KeyRoutine, escLeftBracket19SemicolonRoutine, escFailureRoutine
  351. };
  352. static CharacterDispatch escLeftBracket19Dispatch = {
  353. 2, "~;", escLeftBracket19Routines
  354. };
  355. static char32_t escLeftBracket19Routine(char32_t c) {
  356. c = read_unicode_character();
  357. if (c == 0) return 0;
  358. return doDispatch(c, escLeftBracket19Dispatch);
  359. }
  360. // Handle ESC [ 1 <more stuff> escape sequences
  361. //
  362. static CharacterDispatchRoutine escLeftBracket1Routines[] = {
  363. homeKeyRoutine, escLeftBracket1SemicolonRoutine,
  364. escLeftBracket15Routine,
  365. escLeftBracket17Routine,
  366. escLeftBracket18Routine,
  367. escLeftBracket19Routine,
  368. escFailureRoutine
  369. };
  370. static CharacterDispatch escLeftBracket1Dispatch = {
  371. 6, "~;5789", escLeftBracket1Routines
  372. };
  373. // Handle ESC [ 2 <more stuff> escape sequences
  374. //
  375. // (S)-F9
  376. static CharacterDispatchRoutine escLeftBracket20Semicolon2Routines[] = {
  377. f9KeyRoutine, escFailureRoutine
  378. };
  379. static CharacterDispatch escLeftBracket20Semicolon2Dispatch = {
  380. 1, "~", escLeftBracket20Semicolon2Routines
  381. };
  382. static char32_t escLeftBracket20Semicolon2Routine(char32_t c) {
  383. c = read_unicode_character();
  384. if (c == 0) return 0;
  385. thisKeyMetaCtrl |= Replxx::KEY::BASE_SHIFT;
  386. return doDispatch(c, escLeftBracket20Semicolon2Dispatch);
  387. }
  388. // (C)-F9
  389. static CharacterDispatchRoutine escLeftBracket20Semicolon5Routines[] = {
  390. f9KeyRoutine, escFailureRoutine
  391. };
  392. static CharacterDispatch escLeftBracket20Semicolon5Dispatch = {
  393. 1, "~", escLeftBracket20Semicolon5Routines
  394. };
  395. static char32_t escLeftBracket20Semicolon5Routine(char32_t c) {
  396. c = read_unicode_character();
  397. if (c == 0) return 0;
  398. thisKeyMetaCtrl |= Replxx::KEY::BASE_CONTROL;
  399. return doDispatch(c, escLeftBracket20Semicolon5Dispatch);
  400. }
  401. static CharacterDispatchRoutine escLeftBracket20SemicolonRoutines[] = {
  402. escLeftBracket20Semicolon2Routine, escLeftBracket20Semicolon5Routine, escFailureRoutine
  403. };
  404. static CharacterDispatch escLeftBracket20SemicolonDispatch = {
  405. 2, "25", escLeftBracket20SemicolonRoutines
  406. };
  407. static char32_t escLeftBracket20SemicolonRoutine(char32_t c) {
  408. c = read_unicode_character();
  409. if (c == 0) return 0;
  410. return doDispatch(c, escLeftBracket20SemicolonDispatch);
  411. }
  412. static CharacterDispatchRoutine escLeftBracket20Routines[] = {
  413. f9KeyRoutine, escLeftBracket20SemicolonRoutine, escFailureRoutine
  414. };
  415. static CharacterDispatch escLeftBracket20Dispatch = {
  416. 2, "~;", escLeftBracket20Routines
  417. };
  418. static char32_t escLeftBracket20Routine(char32_t c) {
  419. c = read_unicode_character();
  420. if (c == 0) return 0;
  421. return doDispatch(c, escLeftBracket20Dispatch);
  422. }
  423. // (S)-F10
  424. static CharacterDispatchRoutine escLeftBracket21Semicolon2Routines[] = {
  425. f10KeyRoutine, escFailureRoutine
  426. };
  427. static CharacterDispatch escLeftBracket21Semicolon2Dispatch = {
  428. 1, "~", escLeftBracket21Semicolon2Routines
  429. };
  430. static char32_t escLeftBracket21Semicolon2Routine(char32_t c) {
  431. c = read_unicode_character();
  432. if (c == 0) return 0;
  433. thisKeyMetaCtrl |= Replxx::KEY::BASE_SHIFT;
  434. return doDispatch(c, escLeftBracket21Semicolon2Dispatch);
  435. }
  436. // (C)-F10
  437. static CharacterDispatchRoutine escLeftBracket21Semicolon5Routines[] = {
  438. f10KeyRoutine, escFailureRoutine
  439. };
  440. static CharacterDispatch escLeftBracket21Semicolon5Dispatch = {
  441. 1, "~", escLeftBracket21Semicolon5Routines
  442. };
  443. static char32_t escLeftBracket21Semicolon5Routine(char32_t c) {
  444. c = read_unicode_character();
  445. if (c == 0) return 0;
  446. thisKeyMetaCtrl |= Replxx::KEY::BASE_CONTROL;
  447. return doDispatch(c, escLeftBracket21Semicolon5Dispatch);
  448. }
  449. static CharacterDispatchRoutine escLeftBracket21SemicolonRoutines[] = {
  450. escLeftBracket21Semicolon2Routine, escLeftBracket21Semicolon5Routine, escFailureRoutine
  451. };
  452. static CharacterDispatch escLeftBracket21SemicolonDispatch = {
  453. 2, "25", escLeftBracket21SemicolonRoutines
  454. };
  455. static char32_t escLeftBracket21SemicolonRoutine(char32_t c) {
  456. c = read_unicode_character();
  457. if (c == 0) return 0;
  458. return doDispatch(c, escLeftBracket21SemicolonDispatch);
  459. }
  460. static CharacterDispatchRoutine escLeftBracket21Routines[] = {
  461. f10KeyRoutine, escLeftBracket21SemicolonRoutine, escFailureRoutine
  462. };
  463. static CharacterDispatch escLeftBracket21Dispatch = {
  464. 2, "~;", escLeftBracket21Routines
  465. };
  466. static char32_t escLeftBracket21Routine(char32_t c) {
  467. c = read_unicode_character();
  468. if (c == 0) return 0;
  469. return doDispatch(c, escLeftBracket21Dispatch);
  470. }
  471. // (S)-F11
  472. static CharacterDispatchRoutine escLeftBracket23Semicolon2Routines[] = {
  473. f11KeyRoutine, escFailureRoutine
  474. };
  475. static CharacterDispatch escLeftBracket23Semicolon2Dispatch = {
  476. 1, "~", escLeftBracket23Semicolon2Routines
  477. };
  478. static char32_t escLeftBracket23Semicolon2Routine(char32_t c) {
  479. c = read_unicode_character();
  480. if (c == 0) return 0;
  481. thisKeyMetaCtrl |= Replxx::KEY::BASE_SHIFT;
  482. return doDispatch(c, escLeftBracket23Semicolon2Dispatch);
  483. }
  484. // (C)-F11
  485. static CharacterDispatchRoutine escLeftBracket23Semicolon5Routines[] = {
  486. f11KeyRoutine, escFailureRoutine
  487. };
  488. static CharacterDispatch escLeftBracket23Semicolon5Dispatch = {
  489. 1, "~", escLeftBracket23Semicolon5Routines
  490. };
  491. static char32_t escLeftBracket23Semicolon5Routine(char32_t c) {
  492. c = read_unicode_character();
  493. if (c == 0) return 0;
  494. thisKeyMetaCtrl |= Replxx::KEY::BASE_CONTROL;
  495. return doDispatch(c, escLeftBracket23Semicolon5Dispatch);
  496. }
  497. static CharacterDispatchRoutine escLeftBracket23SemicolonRoutines[] = {
  498. escLeftBracket23Semicolon2Routine, escLeftBracket23Semicolon5Routine, escFailureRoutine
  499. };
  500. static CharacterDispatch escLeftBracket23SemicolonDispatch = {
  501. 2, "25", escLeftBracket23SemicolonRoutines
  502. };
  503. static char32_t escLeftBracket23SemicolonRoutine(char32_t c) {
  504. c = read_unicode_character();
  505. if (c == 0) return 0;
  506. return doDispatch(c, escLeftBracket23SemicolonDispatch);
  507. }
  508. static CharacterDispatchRoutine escLeftBracket23Routines[] = {
  509. f11KeyRoutine, escLeftBracket23SemicolonRoutine, escFailureRoutine
  510. };
  511. static CharacterDispatch escLeftBracket23Dispatch = {
  512. 2, "~;", escLeftBracket23Routines
  513. };
  514. static char32_t escLeftBracket23Routine(char32_t c) {
  515. c = read_unicode_character();
  516. if (c == 0) return 0;
  517. return doDispatch(c, escLeftBracket23Dispatch);
  518. }
  519. // (S)-F12
  520. static CharacterDispatchRoutine escLeftBracket24Semicolon2Routines[] = {
  521. f12KeyRoutine, escFailureRoutine
  522. };
  523. static CharacterDispatch escLeftBracket24Semicolon2Dispatch = {
  524. 1, "~", escLeftBracket24Semicolon2Routines
  525. };
  526. static char32_t escLeftBracket24Semicolon2Routine(char32_t c) {
  527. c = read_unicode_character();
  528. if (c == 0) return 0;
  529. thisKeyMetaCtrl |= Replxx::KEY::BASE_SHIFT;
  530. return doDispatch(c, escLeftBracket24Semicolon2Dispatch);
  531. }
  532. // (C)-F12
  533. static CharacterDispatchRoutine escLeftBracket24Semicolon5Routines[] = {
  534. f12KeyRoutine, escFailureRoutine
  535. };
  536. static CharacterDispatch escLeftBracket24Semicolon5Dispatch = {
  537. 1, "~", escLeftBracket24Semicolon5Routines
  538. };
  539. static char32_t escLeftBracket24Semicolon5Routine(char32_t c) {
  540. c = read_unicode_character();
  541. if (c == 0) return 0;
  542. thisKeyMetaCtrl |= Replxx::KEY::BASE_CONTROL;
  543. return doDispatch(c, escLeftBracket24Semicolon5Dispatch);
  544. }
  545. static CharacterDispatchRoutine escLeftBracket24SemicolonRoutines[] = {
  546. escLeftBracket24Semicolon2Routine, escLeftBracket24Semicolon5Routine, escFailureRoutine
  547. };
  548. static CharacterDispatch escLeftBracket24SemicolonDispatch = {
  549. 2, "25", escLeftBracket24SemicolonRoutines
  550. };
  551. static char32_t escLeftBracket24SemicolonRoutine(char32_t c) {
  552. c = read_unicode_character();
  553. if (c == 0) return 0;
  554. return doDispatch(c, escLeftBracket24SemicolonDispatch);
  555. }
  556. static CharacterDispatchRoutine escLeftBracket24Routines[] = {
  557. f12KeyRoutine, escLeftBracket24SemicolonRoutine, escFailureRoutine
  558. };
  559. static CharacterDispatch escLeftBracket24Dispatch = {
  560. 2, "~;", escLeftBracket24Routines
  561. };
  562. static char32_t escLeftBracket24Routine(char32_t c) {
  563. c = read_unicode_character();
  564. if (c == 0) return 0;
  565. return doDispatch(c, escLeftBracket24Dispatch);
  566. }
  567. // Handle ESC [ 2 <more stuff> escape sequences
  568. //
  569. static CharacterDispatchRoutine escLeftBracket2Routines[] = {
  570. insertKeyRoutine,
  571. escLeftBracket20Routine,
  572. escLeftBracket21Routine,
  573. escLeftBracket23Routine,
  574. escLeftBracket24Routine,
  575. escFailureRoutine
  576. };
  577. static CharacterDispatch escLeftBracket2Dispatch = {
  578. 5, "~0134", escLeftBracket2Routines
  579. };
  580. // Handle ESC [ 3 <more stuff> escape sequences
  581. //
  582. static CharacterDispatchRoutine escLeftBracket3Routines[] = {
  583. deleteKeyRoutine, escFailureRoutine
  584. };
  585. static CharacterDispatch escLeftBracket3Dispatch = {
  586. 1, "~", escLeftBracket3Routines
  587. };
  588. // Handle ESC [ 4 <more stuff> escape sequences
  589. //
  590. static CharacterDispatchRoutine escLeftBracket4Routines[] = {
  591. endKeyRoutine, escFailureRoutine
  592. };
  593. static CharacterDispatch escLeftBracket4Dispatch = {
  594. 1, "~", escLeftBracket4Routines
  595. };
  596. // Handle ESC [ 5 <more stuff> escape sequences
  597. //
  598. static CharacterDispatchRoutine escLeftBracket5Semicolon5Routines[] = {
  599. pageUpKeyRoutine, escFailureRoutine
  600. };
  601. static CharacterDispatch escLeftBracket5Semicolon5Dispatch = {
  602. 1, "~", escLeftBracket5Semicolon5Routines
  603. };
  604. static char32_t escLeftBracket5Semicolon5Routine(char32_t c) {
  605. c = read_unicode_character();
  606. if (c == 0) return 0;
  607. thisKeyMetaCtrl |= Replxx::KEY::BASE_CONTROL;
  608. return doDispatch(c, escLeftBracket5Semicolon5Dispatch);
  609. }
  610. static CharacterDispatchRoutine escLeftBracket5SemicolonRoutines[] = {
  611. escLeftBracket5Semicolon5Routine,
  612. escFailureRoutine
  613. };
  614. static CharacterDispatch escLeftBracket5SemicolonDispatch = {
  615. 1, "5", escLeftBracket5SemicolonRoutines
  616. };
  617. static char32_t escLeftBracket5SemicolonRoutine(char32_t c) {
  618. c = read_unicode_character();
  619. if (c == 0) return 0;
  620. return doDispatch(c, escLeftBracket5SemicolonDispatch);
  621. }
  622. static CharacterDispatchRoutine escLeftBracket5Routines[] = {
  623. pageUpKeyRoutine, escLeftBracket5SemicolonRoutine, escFailureRoutine
  624. };
  625. static CharacterDispatch escLeftBracket5Dispatch = {
  626. 2, "~;", escLeftBracket5Routines
  627. };
  628. // Handle ESC [ 6 <more stuff> escape sequences
  629. //
  630. static CharacterDispatchRoutine escLeftBracket6Semicolon5Routines[] = {
  631. pageDownKeyRoutine, escFailureRoutine
  632. };
  633. static CharacterDispatch escLeftBracket6Semicolon5Dispatch = {
  634. 1, "~", escLeftBracket6Semicolon5Routines
  635. };
  636. static char32_t escLeftBracket6Semicolon5Routine(char32_t c) {
  637. c = read_unicode_character();
  638. if (c == 0) return 0;
  639. thisKeyMetaCtrl |= Replxx::KEY::BASE_CONTROL;
  640. return doDispatch(c, escLeftBracket6Semicolon5Dispatch);
  641. }
  642. static CharacterDispatchRoutine escLeftBracket6SemicolonRoutines[] = {
  643. escLeftBracket6Semicolon5Routine,
  644. escFailureRoutine
  645. };
  646. static CharacterDispatch escLeftBracket6SemicolonDispatch = {
  647. 1, "5", escLeftBracket6SemicolonRoutines
  648. };
  649. static char32_t escLeftBracket6SemicolonRoutine(char32_t c) {
  650. c = read_unicode_character();
  651. if (c == 0) return 0;
  652. return doDispatch(c, escLeftBracket6SemicolonDispatch);
  653. }
  654. static CharacterDispatchRoutine escLeftBracket6Routines[] = {
  655. pageDownKeyRoutine, escLeftBracket6SemicolonRoutine, escFailureRoutine
  656. };
  657. static CharacterDispatch escLeftBracket6Dispatch = {
  658. 2, "~;", escLeftBracket6Routines
  659. };
  660. // Handle ESC [ 7 <more stuff> escape sequences
  661. //
  662. static CharacterDispatchRoutine escLeftBracket7Routines[] = {
  663. homeKeyRoutine, escFailureRoutine
  664. };
  665. static CharacterDispatch escLeftBracket7Dispatch = {
  666. 1, "~", escLeftBracket7Routines
  667. };
  668. // Handle ESC [ 8 <more stuff> escape sequences
  669. //
  670. static CharacterDispatchRoutine escLeftBracket8Routines[] = {
  671. endKeyRoutine, escFailureRoutine
  672. };
  673. static CharacterDispatch escLeftBracket8Dispatch = {
  674. 1, "~", escLeftBracket8Routines
  675. };
  676. // Handle ESC [ <digit> escape sequences
  677. //
  678. static char32_t escLeftBracket0Routine(char32_t c) {
  679. return escFailureRoutine(c);
  680. }
  681. static char32_t escLeftBracket1Routine(char32_t c) {
  682. c = read_unicode_character();
  683. if (c == 0) return 0;
  684. return doDispatch(c, escLeftBracket1Dispatch);
  685. }
  686. static char32_t escLeftBracket2Routine(char32_t c) {
  687. c = read_unicode_character();
  688. if (c == 0) return 0;
  689. return doDispatch(c, escLeftBracket2Dispatch);
  690. }
  691. static char32_t escLeftBracket3Routine(char32_t c) {
  692. c = read_unicode_character();
  693. if (c == 0) return 0;
  694. return doDispatch(c, escLeftBracket3Dispatch);
  695. }
  696. static char32_t escLeftBracket4Routine(char32_t c) {
  697. c = read_unicode_character();
  698. if (c == 0) return 0;
  699. return doDispatch(c, escLeftBracket4Dispatch);
  700. }
  701. static char32_t escLeftBracket5Routine(char32_t c) {
  702. c = read_unicode_character();
  703. if (c == 0) return 0;
  704. return doDispatch(c, escLeftBracket5Dispatch);
  705. }
  706. static char32_t escLeftBracket6Routine(char32_t c) {
  707. c = read_unicode_character();
  708. if (c == 0) return 0;
  709. return doDispatch(c, escLeftBracket6Dispatch);
  710. }
  711. static char32_t escLeftBracket7Routine(char32_t c) {
  712. c = read_unicode_character();
  713. if (c == 0) return 0;
  714. return doDispatch(c, escLeftBracket7Dispatch);
  715. }
  716. static char32_t escLeftBracket8Routine(char32_t c) {
  717. c = read_unicode_character();
  718. if (c == 0) return 0;
  719. return doDispatch(c, escLeftBracket8Dispatch);
  720. }
  721. static char32_t escLeftBracket9Routine(char32_t c) {
  722. return escFailureRoutine(c);
  723. }
  724. // Handle ESC [ <more stuff> escape sequences
  725. //
  726. static CharacterDispatchRoutine escLeftBracketRoutines[] = {
  727. upArrowKeyRoutine, downArrowKeyRoutine, rightArrowKeyRoutine,
  728. leftArrowKeyRoutine, homeKeyRoutine, endKeyRoutine,
  729. shiftTabRoutine,
  730. escLeftBracket0Routine, escLeftBracket1Routine, escLeftBracket2Routine,
  731. escLeftBracket3Routine, escLeftBracket4Routine, escLeftBracket5Routine,
  732. escLeftBracket6Routine, escLeftBracket7Routine, escLeftBracket8Routine,
  733. escLeftBracket9Routine, escFailureRoutine
  734. };
  735. static CharacterDispatch escLeftBracketDispatch = {17, "ABCDHFZ0123456789",
  736. escLeftBracketRoutines};
  737. // Handle ESC O <char> escape sequences
  738. //
  739. static CharacterDispatchRoutine escORoutines[] = {
  740. upArrowKeyRoutine, downArrowKeyRoutine, rightArrowKeyRoutine,
  741. leftArrowKeyRoutine, homeKeyRoutine, endKeyRoutine,
  742. f1KeyRoutine, f2KeyRoutine, f3KeyRoutine,
  743. f4KeyRoutine,
  744. ctrlUpArrowKeyRoutine, ctrlDownArrowKeyRoutine, ctrlRightArrowKeyRoutine,
  745. ctrlLeftArrowKeyRoutine, escFailureRoutine
  746. };
  747. static CharacterDispatch escODispatch = {14, "ABCDHFPQRSabcd", escORoutines};
  748. // Initial ESC dispatch -- could be a Meta prefix or the start of an escape
  749. // sequence
  750. //
  751. static char32_t escLeftBracketRoutine(char32_t c) {
  752. c = read_unicode_character();
  753. if (c == 0) return 0;
  754. return doDispatch(c, escLeftBracketDispatch);
  755. }
  756. static char32_t escORoutine(char32_t c) {
  757. c = read_unicode_character();
  758. if (c == 0) return 0;
  759. return doDispatch(c, escODispatch);
  760. }
  761. static char32_t setMetaRoutine(char32_t c); // need forward reference
  762. static CharacterDispatchRoutine escRoutines[] = {
  763. escLeftBracketRoutine, escORoutine, setMetaRoutine
  764. };
  765. static CharacterDispatch escDispatch = {2, "[O", escRoutines};
  766. // Initial dispatch -- we are not in the middle of anything yet
  767. //
  768. static char32_t escRoutine(char32_t c) {
  769. c = read_unicode_character();
  770. if (c == 0) return 0;
  771. return doDispatch(c, escDispatch);
  772. }
  773. static CharacterDispatchRoutine initialRoutines[] = {
  774. escRoutine, deleteCharRoutine, normalKeyRoutine
  775. };
  776. static CharacterDispatch initialDispatch = {2, "\x1B\x7F", initialRoutines};
  777. // Special handling for the ESC key because it does double duty
  778. //
  779. static char32_t setMetaRoutine(char32_t c) {
  780. thisKeyMetaCtrl = Replxx::KEY::BASE_META;
  781. if (c == 0x1B) { // another ESC, stay in ESC processing mode
  782. c = read_unicode_character();
  783. if (c == 0) return 0;
  784. return doDispatch(c, escDispatch);
  785. }
  786. return doDispatch(c, initialDispatch);
  787. }
  788. char32_t doDispatch(char32_t c) {
  789. EscapeSequenceProcessing::thisKeyMetaCtrl = 0; // no modifiers yet at initialDispatch
  790. return doDispatch(c, initialDispatch);
  791. }
  792. } // namespace EscapeSequenceProcessing // move these out of global namespace
  793. }
  794. #endif /* #ifndef _WIN32 */