funckeymap.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. /* #define NONANSI_DEBUG */
  2. /*+-----------------------------------------------------------------
  3. funckeymap.c - keyboard function key -> ECU internal
  4. wht@wht.net
  5. Defined functions:
  6. fkmap_command(argc, argv)
  7. funckeymap(buf, buflen)
  8. funckeymap_define(bufptr)
  9. funckeymap_display(fp)
  10. funckeymap_display_single(ikde, fp)
  11. funckeymap_init()
  12. funckeymap_read(name)
  13. ------------------------------------------------------------------*/
  14. /*+:EDITS:*/
  15. /*:04-26-2000-11:15-wht@bob-RELEASE 4.42 */
  16. /*:01-24-1997-02:37-wht@yuriatin-SOURCE RELEASE 4.00 */
  17. /*:09-11-1996-20:00-wht@yuriatin-3.48-major telnet,curses,structural overhaul */
  18. /*:12-06-1995-13:30-wht@n4hgf-termecu w/errno -1 consideration */
  19. /*:11-23-1995-11:20-wht@kepler-source control 3.37 for tsx-11 */
  20. /*:11-14-1995-10:23-wht@kepler-3.37.80-source control point: SOCKETS */
  21. /*:11-06-1995-17:27-wht@kepler-entry name comments fell out? */
  22. /*:11-03-1995-18:11-wht@wwtp1-icc found unreported bug in fkmap_command */
  23. /*:10-21-1995-11:36-wht@wwtp1-now entry names can have comments */
  24. /*:01-12-1995-15:20-wht@n4hgf-apply Andrew Chernov 8-bit clean+FreeBSD patch */
  25. /*:05-04-1994-04:39-wht@n4hgf-ECU release 3.30 */
  26. /*:03-27-1993-17:48-wht@n4hgf-SVR4 found mk_char_graphic decl out of scope */
  27. /*:09-16-1992-13:33-wht@n4hgf-add fkmap -l name */
  28. /*:09-10-1992-13:59-wht@n4hgf-ECU release 3.20 */
  29. /*:08-30-1992-23:06-wht@n4hgf-add fkmap_command */
  30. /*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  31. /*:08-28-1991-14:51-wht@n4hgf2-look correctly for funckeymap in CFG_EcuLibDir */
  32. /*:08-26-1991-05:45-wht@n4hgf2-# got included in key def */
  33. /*:08-06-1991-13:19-wht@n4hgf-allow any code as first in key sequence */
  34. /*:08-03-1991-14:44-wht@n4hgf-look for funckeymap in CFG_EcuLibDir too */
  35. /*:07-25-1991-12:58-wht@n4hgf-ECU release 3.10 */
  36. /*:03-20-1991-03:06-root@n4hgf-no Metro Link problems here */
  37. /*:03-20-1991-01:04-root@n4hgf-diagnose Metro Link xterm differences */
  38. /*:01-10-1991-23:15-wht@n4hgf-string overflow rptd by spooley@compulink.co.uk */
  39. /*:12-01-1990-12:51-wht@n4hgf-creation, borrowing from and using ecufkey.c */
  40. #include "ecu.h"
  41. #include "ecuerror.h"
  42. #include "ecukey.h"
  43. #include "ecufkey.h"
  44. #include "ecuxkey.h"
  45. #include "ecufork.h"
  46. extern int tty_not_char_special;
  47. extern char *dash_f_funckeytype;
  48. KDE funckeymap_table[KDE_COUNT];
  49. char funckeymap_name[32] = "";
  50. #if defined(NONANSI_DEBUG)
  51. static FILE *nadbg = (FILE *) 0;
  52. #endif
  53. /*+-------------------------------------------------------------------------
  54. funckeymap_init() - initialize function key mapping (recognition)
  55. --------------------------------------------------------------------------*/
  56. void
  57. funckeymap_init()
  58. {
  59. int itmp;
  60. KDE *tkde;
  61. for (itmp = 0; itmp < KDE_COUNT; itmp++)
  62. {
  63. tkde = &funckeymap_table[itmp];
  64. tkde->logical[0] = 0;
  65. tkde->count = 0;
  66. tkde->ikde = 0;
  67. }
  68. funckeymap_name[0] = 0;
  69. } /* end of funckeymap_init */
  70. /*+-------------------------------------------------------------------------
  71. funckeymap_define(bufptr) - use funckeymap line to define a mapping
  72. returns 0 good keydef
  73. -1 if syntax error
  74. --------------------------------------------------------------------------*/
  75. int
  76. funckeymap_define(bufptr)
  77. char *bufptr;
  78. {
  79. int itmp;
  80. int token_number = 0;
  81. KDE *tkde = (KDE *) 0;
  82. int ikde = 0;
  83. int octothorpe = 0;
  84. char *token;
  85. char *arg_token();
  86. char *str_token();
  87. char *skip_ld_break();
  88. while (!octothorpe &&
  89. (token = (token_number < 2) ? str_token(bufptr, ":")
  90. : arg_token(bufptr, " \t")))
  91. {
  92. bufptr = (char *)0; /* further calls to arg_token need NULL */
  93. token = skip_ld_break(token);
  94. strip_trail_break(token);
  95. switch (token_number)
  96. {
  97. case 0: /* first field is key identifier */
  98. if ((ikde = kde_name_to_ikde(token)) < 0)
  99. {
  100. pprintf(" %s is not a legal key identifier\r\n", token);
  101. return (-1);
  102. }
  103. tkde = &funckeymap_table[ikde];
  104. tkde->logical[0] = 0;
  105. tkde->count = 0;
  106. tkde->ikde = ikde;
  107. break;
  108. case 1: /* second field is logical key name */
  109. if (*token == '#')
  110. goto MISSING_LABEL;
  111. strncpy(tkde->logical, token, sizeof(tkde->logical));
  112. tkde->logical[sizeof(tkde->logical) - 1] = 0;
  113. break;
  114. case 2: /* third field is first token of sequence */
  115. if (*token == '#')
  116. goto MISSING_SEQUENCE;
  117. default: /* third and subsequent to define key */
  118. if (*token == '#')
  119. {
  120. octothorpe = 1;
  121. break;
  122. }
  123. if (tkde->count == sizeof(tkde->str))
  124. {
  125. pprintf(" %s: output count too long",
  126. keyset_idstr(ikde));
  127. return (-1);
  128. }
  129. if ((itmp = ascii_to_hex(token)) < 0)
  130. {
  131. pprintf(" %s: '%s' invalid\r\n",
  132. keyset_idstr(ikde), token);
  133. return (-1);
  134. }
  135. tkde->str[tkde->count] = itmp;
  136. tkde->count++;
  137. break;
  138. } /* end of switch(token_number) */
  139. if (octothorpe)
  140. break;
  141. token_number++;
  142. } /* end while not end of record */
  143. switch (token_number)
  144. {
  145. case 0:
  146. pprintf("funckeymap_define logic error\n");
  147. errno = -1;
  148. termecu(TERMECU_LOGIC_ERROR);
  149. break;
  150. case 1:
  151. MISSING_LABEL:
  152. pprintf("%s: missing key label\r\n", keyset_idstr(ikde));
  153. break;
  154. case 2:
  155. MISSING_SEQUENCE:
  156. pprintf("%s: missing char sequence\r\n", keyset_idstr(ikde));
  157. break;
  158. default:
  159. /* special init string entry */
  160. if (ikde == IKDE_InitStr)
  161. fwrite(tkde->str, 1, tkde->count, stderr);
  162. else if (tkde->count)
  163. {
  164. uchar ch = tkde->str[0];
  165. extern uchar kbdeof; /* current input EOF */
  166. extern uchar kbdeol2; /* current secondary input EOL */
  167. extern uchar kbdeol; /* current input EOL */
  168. extern uchar kbderase; /* current input ERASE */
  169. extern uchar kbdintr; /* current input INTR */
  170. extern uchar kbdkill; /* current input KILL */
  171. extern uchar kbdquit; /* current input QUIT */
  172. if ((ch == kbdeof) || (ch == kbdeol2) ||
  173. (ch == kbdeol) || (ch == kbderase) ||
  174. (ch == kbdintr) || (ch == kbdkill) ||
  175. (ch == kbdquit))
  176. {
  177. pprintf(
  178. "%s: 1st char cannot be input control character\r\n",
  179. keyset_idstr(ikde));
  180. break;
  181. }
  182. }
  183. return (0);
  184. }
  185. return (-1); /* error */
  186. } /* end of funckeymap_define */
  187. /*+-------------------------------------------------------------------------
  188. funckeymap_read(name) - read key-sequence-to-fkey map from funckeymap
  189. --------------------------------------------------------------------------*/
  190. void
  191. funckeymap_read(name)
  192. char *name;
  193. {
  194. int itmp;
  195. char buf[128];
  196. FILE *fp_keys;
  197. int errstat = 0;
  198. static char ecukeys_name[128];
  199. #if defined(NONANSI_DEBUG)
  200. if (!nadbg)
  201. {
  202. nadbg = fopen("/tmp/nadbg.log", "w");
  203. setbuf(nadbg, NULL);
  204. }
  205. #endif
  206. funckeymap_init(); /* clear any previous key defns */
  207. if (!ecukeys_name[0])
  208. {
  209. get_home_dir(ecukeys_name);
  210. strcat(ecukeys_name, "/.ecu/funckeymap");
  211. }
  212. if (!(fp_keys = fopen(ecukeys_name, "r")))
  213. {
  214. strcpy(ecukeys_name, eculibdir);
  215. strcat(ecukeys_name, "/funckeymap");
  216. if (!(fp_keys = fopen(ecukeys_name, "r")))
  217. {
  218. ff(stderr, "'funckeymap' not in ~/.ecu or %s; cannot proceed\r\n",
  219. eculibdir);
  220. termecu(TERMECU_UNRECOVERABLE);
  221. }
  222. }
  223. /* find funckeymap name */
  224. errstat = 1;
  225. while ((itmp = kde_fgets(buf, sizeof(buf), fp_keys)) != KDETYPE_EOF)
  226. {
  227. char *cptr;
  228. if ((itmp == KDETYPE_COMMENT) || (itmp == KDETYPE_ENTRY))
  229. continue;
  230. if (cptr = strchr(buf, '#'))
  231. *cptr = 0;
  232. if (cptr = strchr(buf, ' '))
  233. *cptr = 0;
  234. if (cptr = strchr(buf, '\t'))
  235. *cptr = 0;
  236. if (!strcmp(buf, name))
  237. {
  238. errstat = 0; /* indicate success */
  239. break;
  240. }
  241. }
  242. if (errstat)
  243. {
  244. ff(stderr, "terminal type '%s'\r\n", name);
  245. ff(stderr, "not found in %s; unable to proceed\r\n", ecukeys_name);
  246. errno = -1;
  247. termecu(TERMECU_UNRECOVERABLE);
  248. }
  249. /* read past any other funckeymap names matching this set */
  250. errstat = 1;
  251. while ((itmp = kde_fgets(buf, sizeof(buf), fp_keys)) != KDETYPE_EOF)
  252. {
  253. if (itmp == KDETYPE_ENTRY)
  254. {
  255. errstat = 0; /* indicate success */
  256. break;
  257. }
  258. }
  259. if (errstat)
  260. {
  261. ff(stderr,
  262. "terminal type '%s' has null entry in %s; unable to proceed\r\n",
  263. name, ecukeys_name);
  264. errno = -1;
  265. termecu(TERMECU_UNRECOVERABLE);
  266. }
  267. /* we found the definition ... process it */
  268. errstat = 0;
  269. itmp = KDETYPE_ENTRY;
  270. do
  271. {
  272. if (itmp == KDETYPE_NAME)
  273. break;
  274. else if (itmp == KDETYPE_ENTRY)
  275. {
  276. if (funckeymap_define(buf))
  277. errstat = 1;
  278. }
  279. }
  280. while ((itmp = kde_fgets(buf, sizeof(buf), fp_keys)) != KDETYPE_EOF);
  281. /* finish up */
  282. strncpy(funckeymap_name, name, sizeof(funckeymap_name));
  283. funckeymap_name[sizeof(funckeymap_name) - 1] = 0;
  284. fclose(fp_keys);
  285. if (!funckeymap_table[IKDE_HOME].count)
  286. {
  287. ff(stderr, "You MUST have a 'Home' key defined\r\n");
  288. errstat = 2;
  289. }
  290. if (!funckeymap_table[IKDE_END].count)
  291. {
  292. ff(stderr, "You MUST have a 'End' key defined\r\n");
  293. errstat = 2;
  294. }
  295. if ((errstat == 2) || (errstat && tty_not_char_special))
  296. {
  297. errno = -1;
  298. termecu(TERMECU_UNRECOVERABLE);
  299. }
  300. if (errstat)
  301. {
  302. ff(stderr,
  303. "WARNING: key mapping syntax errors\r\nContinue anyway (y,[n])? ");
  304. if ((itmp = ttygetc(0)) == 'Y' || (itmp == 'y'))
  305. {
  306. ff(stderr, "YES\r\n");
  307. return;
  308. }
  309. ff(stderr, "NO\r\n");
  310. errno = -1;
  311. termecu(TERMECU_UNRECOVERABLE);
  312. }
  313. } /* end of funckeymap_read */
  314. /*+-------------------------------------------------------------------------
  315. funckeymap(buf,buflen) - map char sequence to ikde code
  316. return XF_ code or XF_not_yet if no match yet, XF_no_way if no match possible
  317. --------------------------------------------------------------------------*/
  318. UINT
  319. funckeymap(buf, buflen)
  320. uchar *buf;
  321. int buflen;
  322. {
  323. int ikde;
  324. KDE *tkde;
  325. int err_rtn = XF_no_way;
  326. if (!buflen)
  327. return (XF_not_yet);
  328. #if defined(NONANSI_DEBUG)
  329. if (nadbg)
  330. hex_dump_fp(nadbg, buf, -buflen, "mapna", 1);
  331. #endif
  332. for (ikde = 0, tkde = funckeymap_table; ikde <= IKDE_lastKey;
  333. ikde++, tkde++)
  334. {
  335. #if defined(NONANSI_DEBUG)
  336. if (nadbg)
  337. fprintf(nadbg, "--> %s ", tkde->logical);
  338. #endif
  339. if ((tkde->count == buflen) && !memcmp(tkde->str, buf, buflen))
  340. {
  341. #if defined(NONANSI_DEBUG)
  342. if (nadbg)
  343. fprintf(nadbg, "yes\n");
  344. #endif
  345. return (tkde->ikde);
  346. }
  347. #if defined(NONANSI_DEBUG)
  348. if (nadbg)
  349. fprintf(nadbg, "no\n");
  350. #endif
  351. if ((tkde->count > buflen) &&
  352. ((uchar) * (tkde->str + buflen) == *(buf + buflen)))
  353. {
  354. err_rtn = XF_not_yet;
  355. }
  356. }
  357. return (err_rtn);
  358. } /* end of funckeymap */
  359. /*+-------------------------------------------------------------------------
  360. funckeymap_display_single(tkde,fp) - display single mapping on FILE fp
  361. --------------------------------------------------------------------------*/
  362. void
  363. funckeymap_display_single(ikde, fp)
  364. int ikde;
  365. FILE *fp;
  366. {
  367. int keys_left;
  368. char *keys;
  369. char s64[64];
  370. KDE *tkde;
  371. if ((unsigned)ikde > IKDE_lastKey)
  372. return;
  373. tkde = &funckeymap_table[ikde];
  374. sprintf(s64, " %s:%s: ",
  375. keyset_idstr(ikde), tkde->logical);
  376. s64[16] = 0;
  377. if (fp == stderr)
  378. pputs(s64);
  379. else
  380. fputs(s64, fp);
  381. keys_left = tkde->count;
  382. keys = tkde->str;
  383. while (keys_left--)
  384. {
  385. if (fp == stderr)
  386. {
  387. pprintf("%s%s",
  388. graphic_char_text(*keys++, 0),
  389. (keys_left) ? " " : "");
  390. }
  391. else
  392. {
  393. fprintf(fp, "%s%s",
  394. graphic_char_text(*keys++, 0),
  395. (keys_left) ? " " : "");
  396. }
  397. }
  398. if (fp == stderr)
  399. pputs("\n");
  400. else
  401. fputs("\n", fp);
  402. } /* end of funckeymap_display_single */
  403. /*+-------------------------------------------------------------------------
  404. funckeymap_display(fp) - display function key table of FILE fp
  405. --------------------------------------------------------------------------*/
  406. void
  407. funckeymap_display(fp)
  408. FILE *fp;
  409. {
  410. int ikde;
  411. char *ftype = 0;
  412. if (dash_f_funckeytype)
  413. ftype = dash_f_funckeytype;
  414. else
  415. ftype = getenv("ECUFUNCKEY");
  416. if (ttype && ftype)
  417. {
  418. fprintf(fp, "#$TERM=%s -F/$ECUFUNCKEY=%s", ftype, ttype);
  419. if (fp == stderr)
  420. fputs("\r\n", fp);
  421. else
  422. fputs("\n", fp);
  423. }
  424. if (ttype || ftype)
  425. {
  426. fputs((ftype) ? ftype : ttype, fp);
  427. if (fp == stderr)
  428. fputs("\r\n", fp);
  429. else
  430. fputs("\n", fp);
  431. }
  432. for (ikde = 0; ikde <= IKDE_lastKey; ikde++)
  433. funckeymap_display_single(ikde, fp);
  434. } /* end of funckeymap_display */
  435. /*+-------------------------------------------------------------------------
  436. fkmap_command(argc,argv) - common interactive and procedure 'fkmap' cmd
  437. return procedure error codes
  438. --------------------------------------------------------------------------*/
  439. int
  440. fkmap_command(argc, argv)
  441. int argc;
  442. char **argv;
  443. {
  444. int itmp;
  445. int err = 0;
  446. char *ftype = 0;
  447. int iargv = 1;
  448. char *arg;
  449. char fkcmd[512 + 1];
  450. char *fkcptr = fkcmd;
  451. int fkclen = 0;
  452. int ikde;
  453. KDE save;
  454. FILE *fp;
  455. while ((iargv < argc) && (*(arg = argv[iargv]) == '-'))
  456. {
  457. switch (*++arg)
  458. {
  459. case 'r': /* reset */
  460. if (err)
  461. break;
  462. if (iargv != (argc - 1))
  463. {
  464. pputs("no arguments allowed for -r\n");
  465. err = 1;
  466. break;
  467. }
  468. if (dash_f_funckeytype)
  469. ftype = dash_f_funckeytype;
  470. else
  471. ftype = getenv("ECUFUNCKEY");
  472. if (ttype || ftype)
  473. funckeymap_read((ftype) ? ftype : ttype);
  474. if (!proc_level || proc_trace)
  475. pputs("funckeymap reset to startup configuration\n");
  476. return (0);
  477. case 's': /* save in file */
  478. if (err)
  479. break;
  480. if (iargv != (argc - 2))
  481. {
  482. pputs("exactly one argument required for -s\n");
  483. err = 1;
  484. break;
  485. }
  486. iargv++;
  487. if (!(fp = fopen(argv[iargv], "a")))
  488. {
  489. pperror(argv[iargv]);
  490. return (eFATAL_ALREADY);
  491. }
  492. funckeymap_display(fp);
  493. fclose(fp);
  494. if (!proc_level || proc_trace)
  495. pprintf("current mapping saved in %s\n", argv[iargv]);
  496. return (0);
  497. case 'l': /* load entire */
  498. if (err)
  499. break;
  500. if (iargv != (argc - 2))
  501. {
  502. pputs("exactly one argument required for -l\n");
  503. err = 1;
  504. break;
  505. }
  506. iargv++;
  507. funckeymap_read(argv[iargv]);
  508. return (0);
  509. default:
  510. pprintf("unknown switch -%c\n", *arg);
  511. err = 1;
  512. }
  513. iargv++;
  514. }
  515. if (err)
  516. {
  517. fkmap_cmd_usage();
  518. return (eFATAL_ALREADY);
  519. }
  520. if (iargv == argc)
  521. {
  522. funckeymap_display(stderr);
  523. return (0);
  524. }
  525. arg = argv[iargv++];
  526. if ((ikde = kde_name_to_ikde(arg)) < 0)
  527. {
  528. pprintf("key name '%s' not recognized\n", arg);
  529. return (eFATAL_ALREADY);
  530. }
  531. sprintf(fkcptr, " %s:%s: ", keyset_idstr(ikde), keyset_idstr(ikde));
  532. fkcptr += (itmp = strlen(fkcptr));
  533. fkclen += itmp;
  534. if (iargv == argc)
  535. {
  536. funckeymap_display_single(ikde, stderr);
  537. return (0);
  538. }
  539. while (iargv < argc)
  540. {
  541. arg = argv[iargv++];
  542. itmp = strlen(arg);
  543. if ((unsigned)(fkclen + itmp + 2) > (unsigned)sizeof(fkcmd))
  544. {
  545. pprintf("fkmap command may be no longer than %d characters\n",
  546. sizeof(fkcmd) - 1);
  547. return (eFATAL_ALREADY);
  548. }
  549. strcpy(fkcptr, arg);
  550. fkcptr += itmp;
  551. fkclen += itmp;
  552. if (iargv != argc)
  553. {
  554. *fkcptr++ = ' ';
  555. *fkcptr = 0;
  556. fkclen++;
  557. }
  558. }
  559. save = funckeymap_table[ikde];
  560. if (err = funckeymap_define(fkcmd))
  561. funckeymap_table[ikde] = save;
  562. if (!err && (!proc_level || proc_trace))
  563. funckeymap_display_single(ikde, stderr);
  564. return ((err) ? eFATAL_ALREADY : 0);
  565. } /* end of fkmap_command */
  566. /* end of funckeymap.c */
  567. /* vi: set tabstop=4 shiftwidth=4: */