home *** CD-ROM | disk | FTP | other *** search
/ Informática Multimedia: Special Games (Alt) / INFESPGAMES.iso / os2 / backgam / source / keyboard.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-22  |  19.1 KB  |  761 lines

  1. /*************************************************************
  2.  *    ______                                                 *
  3.  *   /     /\  TinyFugue was derived from a client initially *
  4.  *  /   __/  \ written by Anton Rang (Tarrant) and later     *
  5.  *  |  / /\  | modified by Leo Plotkin (Grod).  The early    *
  6.  *  |  |/    | versions of TinyFugue written by Greg Hudson  *
  7.  *  |  X__/  | (Explorer_Bob).  The current version is       *
  8.  *  \ /      / written and maintained by Ken Keys (Hawkeye), *
  9.  *   \______/  who can be reached at kkeys@ucsd.edu.         *
  10.  *                                                           *
  11.  *             No copyright 1992, no rights reserved.        *
  12.  *             Fugue is in the public domain.                *
  13.  *************************************************************/
  14.  
  15. /**************************************************
  16.  * Fugue keyboard handling.                       *
  17.  * Handles all keyboard input and keybindings.    *
  18.  * Also deals with tty driver.                    *
  19.  **************************************************/
  20.  
  21. #ifdef hpux
  22. # include <sys/ioctl.h>
  23. # include <termio.h>
  24. # include <bsdtty.h>
  25. #else
  26. # ifdef SYSVTTY
  27. #  ifdef WINS
  28. #   include <sys/types.h> 
  29. #   include <sys/inet.h>
  30. #   include <sys/stream.h>
  31. #   include <sys/ptem.h>
  32. #  endif
  33. #  include <termio.h>
  34. static int first_time = 1;           /* first time in cbreak/noecho mode? */
  35. static struct termio old_tty_state;  /* save termio state for return to shell */
  36. # else
  37. #  include <sys/ioctl.h>
  38. #  include <sgtty.h>
  39. # endif
  40. #endif
  41.  
  42. #include <ctype.h>
  43. #include <errno.h>
  44. #include <stdio.h>
  45. #include "tf.h"
  46. #include "dstring.h"
  47. #include "util.h"
  48. #include "macro.h"
  49. #include "output.h"
  50. #include "history.h"
  51. #include "socket.h"
  52. #include "expand.h"
  53.  
  54. #undef CTRL
  55. #define CTRL(x) ctrl_values[x]
  56. #define DEFAULT_COLUMNS 80
  57.  
  58. typedef struct KeyNode {
  59.     int children;
  60.     union {
  61.         struct KeyNode **child;
  62.         Macro *macro;
  63.     } u;
  64. } KeyNode;
  65.  
  66. static void     NDECL(init_ctrl_table);
  67. static Macro   *FDECL(trie_insert,(KeyNode **root, Macro *macro, char *key));
  68. static KeyNode *FDECL(untrie_key,(KeyNode **root, char *s));
  69.  
  70. void NDECL(do_newline);
  71. void NDECL(do_recallb);
  72. void NDECL(do_recallf);
  73. void NDECL(do_socketb);
  74. void NDECL(do_socketf);
  75. void NDECL(do_bspc);
  76. void NDECL(do_bword);
  77. void NDECL(do_dline);
  78. void NDECL(do_dch);
  79. void NDECL(do_redraw);
  80. void NDECL(do_up);
  81. void NDECL(do_down);
  82. void NDECL(do_left);
  83. void NDECL(do_right);
  84. void NDECL(do_home);
  85. void NDECL(do_end);
  86. void NDECL(do_wleft);
  87. void NDECL(do_wright);
  88. void NDECL(do_deol);
  89. void NDECL(do_insert);
  90.  
  91. void   NDECL(init_keyboard);
  92. void   NDECL(use_stty);
  93. void   NDECL(get_window_size);
  94. Macro *FDECL(bind_key,(Macro *macro));
  95. void   FDECL(unbind_key,(Macro *macro));
  96. Macro *FDECL(find_key,(char *key));
  97. char  *FDECL(translate_keystring,(char *src));
  98. char  *FDECL(keyname,(char *key));
  99. void   NDECL(handle_keyboard_input);
  100. void   FDECL(handle_input_string,(char *input, int len));
  101. void   FDECL(process_buffer,(Stringp inbuf));
  102. void   NDECL(cbreak_noecho_mode);
  103. void   NDECL(cooked_echo_mode);
  104. void   NDECL((*FDECL(find_efunc,(char *name))));
  105.  
  106. extern int visual, redef;
  107.  
  108. static Stringp scratch;                 /* buffer for manipulating text */
  109. static char ctrl_values[128];           /* map of '^X' form to ascii */
  110. static Stringp cat_keybuf;              /* Total buffer for /cat */
  111. static Stringp current_input;           /* unprocessed keystrokes */
  112. static KeyNode *keytrie = NULL;         /* root of keybinding trie */
  113.  
  114. Stringp keybuf;                         /* input buffer */
  115. int keyboard_pos;                       /* current position in buffer */
  116.  
  117. typedef struct EditFunc {
  118.     char *name;
  119.     NFunc *func;
  120. } EditFunc;
  121.  
  122. static EditFunc efunc[] = {
  123.     { "RECALLB",  do_recallb  },
  124.     { "RECALLF",  do_recallf  },
  125.     { "SOCKETB",  do_socketb  },
  126.     { "SOCKETF",  do_socketf  },
  127.     { "BSPC"   ,  do_bspc     },
  128.     { "BWORD"  ,  do_bword    },
  129.     { "DLINE"  ,  do_dline    },
  130.     { "DCH"    ,  do_dch      },
  131.     { "REFRESH",  do_refresh  },
  132.     { "REDRAW" ,  do_redraw   },
  133.     { "UP"     ,  do_up       },
  134.     { "DOWN"   ,  do_down     },
  135.     { "RIGHT"  ,  do_right    },
  136.     { "LEFT"   ,  do_left     },
  137.     { "HOME"   ,  do_home     },
  138.     { "END"    ,  do_end      },
  139.     { "WLEFT"  ,  do_wleft    },
  140.     { "WRIGHT" ,  do_wright   },
  141.     { "DEOL"   ,  do_deol     },
  142.     { "INSERT" ,  do_insert   },
  143.     { "PAGE"   ,  do_page     },
  144.     { "HPAGE"  ,  do_hpage    },
  145.     { "LINE"   ,  do_line     },
  146.     { "FLUSH"  ,  do_flush    },
  147.     { "NEWLINE",  do_newline  }
  148. };
  149.  
  150. static int nfuncs = sizeof(efunc) / sizeof(struct EditFunc);
  151.  
  152. NFunc *find_efunc(name)
  153.     char *name;
  154. {
  155.     int i;
  156.  
  157.     for (i = 0; i < nfuncs; i++)
  158.         if (cstrcmp(name, efunc[i].name) == 0) break;
  159.     return (i < nfuncs) ? efunc[i].func : NULL;
  160. }
  161.  
  162. void init_keyboard()
  163. {
  164.     init_ctrl_table();
  165.     keytrie = NULL;
  166.     use_stty();
  167.     get_window_size();
  168.     Stringinit(scratch);
  169.     Stringinit(keybuf);
  170.     Stringinit(cat_keybuf);
  171.     Stringinit(current_input);
  172.     cbreak_noecho_mode();
  173.     keyboard_pos = 0;
  174. }
  175.  
  176. #ifdef DMALLOC
  177. void free_keyboard()
  178. {
  179.     Stringfree(scratch);
  180.     Stringfree(keybuf);
  181.     Stringfree(cat_keybuf);
  182.     Stringfree(current_input);
  183. }
  184. #endif
  185.  
  186. static void init_ctrl_table()
  187. {
  188.     int i, j;
  189.  
  190.     for (i = 0; i < 128; i++) {
  191.         j = ucase(i) - 'A' + 1;
  192.         ctrl_values[i] = (j < 0) ? (j + 128) : j;
  193.     }
  194. }
  195.  
  196. static void set_ekey(key, cmd)
  197.     char *key, *cmd;
  198. {
  199.     Macro *macro;
  200.  
  201.     if (macro = find_key(key)) {
  202.         if (redef) {
  203.             do_hook(H_REDEF, "%% Redefined %s %s", "%s %s", "binding", key);
  204.             nuke_macro(macro);
  205.         } else return;
  206.     }
  207.     macro = new_macro("", "", key, 0, "", cmd, NULL, 0, 0, 0, 0, TRUE);
  208.     if (bind_key(macro)) add_macro(macro);
  209.     else nuke_macro(macro);
  210. }
  211.  
  212. char *keyname(key)
  213.     char *key;
  214. {
  215.     STATIC_BUFFER(buffer)
  216.  
  217.     Stringterm(buffer, 0);
  218.     for ( ; *key; key++) {
  219.         if (*key == '^' || *key == '\\') {
  220.             Sprintf(buffer, "\200\\%c", *key);
  221.         } else if (!isprint(*key) || iscntrl(*key)) {
  222.             Sprintf(buffer, "\200^%c", (*key + '@') % 128);
  223.         } else Stringadd(buffer, *key);
  224.     }
  225.     return buffer->s;
  226. }
  227.  
  228. void use_stty()
  229. {
  230.     char bs[2], dline[2], bword[2], refresh[2];
  231.  
  232. #ifdef hpux
  233.     struct termio te_blob;
  234.     struct ltchars lt_blob;
  235.  
  236.     if (ioctl(0, TCGETA, &te_blob) == -1) perror("TCGETA ioctl");
  237.     if (ioctl(0, TIOCGLTC, <_blob) == -1) perror("TIOCGLTC ioctl");
  238.     *bs = te_blob.c_cc[VERASE];
  239.     *dline = te_blob.c_cc[VKILL];
  240.     *bword = lt_blob.t_werasc;
  241.     *refresh = lt_blob.t_rprntc;
  242. #else
  243. # ifdef SYSVTTY
  244.     struct termio tcblob;
  245.  
  246.     if (ioctl(0, TCGETA, &tcblob) == -1) perror("TCGETA ioctl");
  247.     *bs = tcblob.c_cc[VERASE];
  248.     *dline = tcblob.c_cc[VKILL];
  249. #  ifdef sgi
  250.     *bword = tcblob.c_cc[VWERASE];
  251.     *refresh = tcblob.c_cc[VRPRNT];
  252. #  else
  253.     *bword = CTRL('W');
  254.     *refresh = CTRL('R');
  255. #  endif
  256. # else
  257.     struct sgttyb sg_blob;
  258.     struct ltchars lt_blob;
  259.  
  260.     if (ioctl(0, TIOCGETP, &sg_blob) == -1) perror("TIOCGETP ioctl");
  261.     if (ioctl(0, TIOCGLTC, <_blob) == -1) perror("TIOCGLTC ioctl");
  262.     *bs = sg_blob.sg_erase;
  263.     *dline = sg_blob.sg_kill;
  264.     *bword = lt_blob.t_werasc;
  265.     *refresh = lt_blob.t_rprntc;
  266. # endif /* SYSVTTY */
  267. #endif /* hpux */
  268.     bs[1] = dline[1] = bword[1] = refresh[1] = '\0';
  269.     set_ekey(isascii(*bs) && *bs ? bs : "^H", "/DOKEY BSPC");
  270.     set_ekey(isascii(*bword) && *bword ? bword : "^W", "/DOKEY BWORD");
  271.     set_ekey(isascii(*dline) && *dline ? dline : "^X", "/DOKEY DLINE");
  272.     set_ekey(isascii(*refresh) && *refresh ? refresh : "^R", "/DOKEY REFRESH");
  273. }
  274.  
  275. void get_window_size()
  276. {
  277. #ifndef WINS
  278. # ifdef TIOCGWINSZ
  279.     extern int columns, lines, current_wrap_column;
  280.     struct winsize size;
  281.     int ocol, oline;
  282.  
  283.     ocol = columns;
  284.     oline = lines;
  285.     if (ioctl(0, TIOCGWINSZ, &size) == -1) {
  286.         perror("TIOCGWINSZ ioctl");
  287.         return;
  288.     }
  289.     if (!size.ws_col || !size.ws_row) return;
  290.     columns = size.ws_col;
  291.     lines = size.ws_row;
  292.     if (columns <= 20) columns = DEFAULT_COLUMNS;
  293.     if (columns != ocol || lines != oline) do_redraw();
  294.     if (current_wrap_column) current_wrap_column = columns - 1;
  295.     do_hook(H_RESIZE, NULL, "%d %d", columns, lines);
  296. # endif
  297. #endif
  298. }
  299.  
  300. Macro *find_key(key)
  301.     char *key;
  302. {
  303.     KeyNode *n;
  304.  
  305.     for (n = keytrie; n && n->children && *key; n = n->u.child[*key++]);
  306.     return (n && !n->children && !*key) ? n->u.macro : NULL;
  307. }
  308.  
  309. static Macro *trie_insert(root, macro, key)
  310.     KeyNode **root;
  311.     Macro *macro;
  312.     char *key;
  313. {
  314.     int i;
  315.  
  316.     if (!*root) {
  317.         *root = (KeyNode *) MALLOC(sizeof(KeyNode));
  318.         if (*key) {
  319.             (*root)->children = 1;
  320.             (*root)->u.child = (KeyNode **) MALLOC(128 * sizeof(KeyNode *));
  321.             for (i = 0; i < 128; i++) (*root)->u.child[i] = NULL;
  322.             return trie_insert(&(*root)->u.child[*key], macro, key + 1);
  323.         } else {
  324.             (*root)->children = 0;
  325.             return (*root)->u.macro = macro;
  326.         }
  327.     } else {
  328.         if (*key) {
  329.             if ((*root)->children) {
  330.                 if (!(*root)->u.child[*key]) (*root)->children++;
  331.                 return trie_insert(&(*root)->u.child[*key], macro, key + 1);
  332.             } else {
  333.                 oprintf("%% %s is prefixed by an existing sequence.",
  334.                     keyname(macro->bind));
  335.                 return NULL;
  336.             }
  337.         } else {
  338.             if ((*root)->children) {
  339.                 oprintf("%% %s is prefix of an existing sequence.",
  340.                   keyname(macro->bind));
  341.                 return NULL;
  342.             } else if (redef) {
  343.                 return (*root)->u.macro = macro;
  344.             } else {
  345.                 oprintf("%% Binding %s already exists.", keyname(macro->bind));
  346.                 return NULL;
  347.             }
  348.         }
  349.     }
  350. }
  351.  
  352. Macro *bind_key(macro)
  353.     Macro *macro;
  354. {
  355.     return trie_insert(&keytrie, macro, macro->bind);
  356. }
  357.  
  358. static KeyNode *untrie_key(root, s)
  359.     KeyNode **root;
  360.     char *s;
  361. {
  362.     if (!*s) {
  363.         FREE(*root);
  364.         return *root = NULL;
  365.     }
  366.     if (untrie_key(&((*root)->u.child[*s]), s + 1)) return *root;
  367.     if (--(*root)->children) return *root;
  368.     FREE((*root)->u.child);
  369.     FREE(*root);
  370.     return *root = NULL;
  371. }
  372.  
  373. void unbind_key(macro)
  374.     Macro *macro;
  375. {
  376.     untrie_key(&keytrie, macro->bind);
  377. }
  378.  
  379. /* translate_keystring returns ptr to static area.  Copy if needed. */
  380. char *translate_keystring(src)
  381.     char *src;
  382. {
  383.     STATIC_BUFFER(dest);
  384.  
  385.     Stringterm(dest, 0);
  386.     while (*src) {
  387.         if (*src == '^') {
  388.             src++;
  389.             if (*src) {
  390.                 Stringadd(dest, CTRL(*src));
  391.                 src++;
  392.             } else Stringadd(dest, '^');
  393.         } else if (*src == '\\' && isdigit(*++src)) {
  394.             Stringadd(dest, (char)atoi(src) % 128);
  395.             while (isdigit(*++src));
  396.         } else Stringadd(dest, *src++);
  397.     }
  398.     return dest->s;
  399. }
  400.  
  401. void handle_keyboard_input()
  402. {
  403.     char *s, buf[64];
  404.     int i, count;
  405.     Macro *macro;
  406.     static KeyNode *n;
  407.     static int key_start = 0, input_start = 0, place = 0;
  408.     STATIC_BUFFER(dest)
  409.  
  410.     if ((count = read(0, buf, 64)) == -1) {
  411.         if (errno == EINTR) return;
  412.         else die("%% Couldn't read keyboard.\n");
  413.     }
  414.     if (!count) return;
  415.     for (i = 0; i < count; i++) {
  416.         buf[i] &= 0x7f;
  417. #ifdef SYSVTTY
  418.         if (buf[i] == '\r') Stringadd(current_input, '\n');
  419.         else
  420. #endif
  421.         if (buf[i] != '\0') Stringadd(current_input, buf[i]);
  422.     }
  423.  
  424.     s = current_input->s;
  425.     if (!n) n = keytrie;
  426.     while (s[place]) {
  427.         while (s[place] && n && n->children) n = n->u.child[s[place++]];
  428.         if (!n || !keytrie->children) {                   /* No match      */
  429.             place = ++key_start;                             /* try suffix */
  430.             n = keytrie;
  431.         } else if (n->children) {                         /* Partial match */
  432.             /* do nothing */
  433.         } else {                                          /* Total match   */
  434.             macro = n->u.macro;
  435.             handle_input_string(s + input_start, key_start - input_start);
  436.             key_start = input_start = place;
  437.             reset_outcount();
  438.             if (macro->func) (*macro->func)();
  439.             else {
  440.                 Stringinit(dest);
  441.                 process_macro(macro->body, "", dest, TRUE);
  442.                 Stringfree(dest);
  443.             }
  444.             n = keytrie;
  445.         }
  446.     }
  447.  
  448.     handle_input_string(s + input_start, key_start - input_start);
  449.     if (!s[key_start]) {
  450.         Stringterm(current_input, 0);
  451.         place = key_start = 0;
  452.     }
  453.     input_start = key_start;
  454. }
  455.  
  456. void handle_input_string(input, len)
  457.     char *input;
  458.     int len;
  459. {
  460.     extern int input_cursor, insert;
  461.     int i, j;
  462.     char save;
  463.  
  464.     if (len == 0) return;
  465.     if (!input_cursor) ipos();
  466.     for (i = j = 0; i < len; i++) {
  467.         if (isprint(input[i])) input[j++] = input[i];
  468.     }
  469.     save = input[len = j];
  470.     input[len] = '\0';
  471.     iputs(input);
  472.     input[len] = save;
  473.  
  474.     if (keyboard_pos == keybuf->len) {                    /* add to end */
  475.         Stringncat(keybuf, input, len);
  476.     } else if (insert) {                                  /* insert in middle */
  477.         Stringcpy(scratch, keybuf->s + keyboard_pos);
  478.         Stringterm(keybuf, keyboard_pos);
  479.         Stringncat(keybuf, input, len);
  480.         SStringcat(keybuf, scratch);
  481.     } else if (keyboard_pos + len < keybuf->len) {        /* overwrite */
  482.         for (i = 0, j = keyboard_pos; i < len; keybuf->s[j++] = input[i++]);
  483.     } else {                                              /* write past end */
  484.         Stringterm(keybuf, keyboard_pos);
  485.         Stringncat(keybuf, input, len);
  486.     }                      
  487.     keyboard_pos += len;
  488. }
  489.  
  490. void do_newline()
  491. {
  492.     clear_refresh_pending();
  493.     reset_outcount();
  494.     inewline();
  495.     SStringcpy(scratch, keybuf);
  496.     Stringterm(keybuf, keyboard_pos = 0);
  497.     process_buffer(scratch);
  498.     if (visual) ipos();
  499. }
  500.  
  501. void do_recallb()
  502. {
  503.     recall_input(keybuf, -1);
  504.     keyboard_pos = keybuf->len;
  505.     do_replace();
  506. }
  507.  
  508. void do_recallf()
  509. {
  510.     recall_input(keybuf, 1);
  511.     keyboard_pos = keybuf->len;
  512.     do_replace();
  513. }
  514.  
  515. void do_socketb()
  516. {
  517.     movesock(-1);
  518. }
  519.  
  520. void do_socketf()
  521. {
  522.     movesock(1);
  523. }
  524.  
  525. void do_bspc()
  526. {
  527.     if (!keyboard_pos) return;
  528.     Stringcpy(scratch, keybuf->s + keyboard_pos);
  529.     Stringterm(keybuf, --keyboard_pos);
  530.     SStringcat(keybuf, scratch);
  531.     ibs();
  532. }
  533.  
  534. void do_bword()
  535. {
  536.     int place;
  537.  
  538.     if (!keyboard_pos) return;
  539.     place = keyboard_pos - 1;
  540.     while(isspace(keybuf->s[place])) place--;
  541.     while(!isspace(keybuf->s[place])) place--;
  542.     place++;
  543.     if (place < 0) place = 0;
  544.     Stringcpy(scratch, keybuf->s + keyboard_pos);
  545.     Stringterm(keybuf, place);
  546.     SStringcat(keybuf, scratch);
  547.     ibackword(place);
  548.     keyboard_pos = place;
  549. }
  550.  
  551. void do_dline()
  552. {
  553.     Stringterm(keybuf, keyboard_pos = 0);
  554.     do_replace();
  555. }
  556.  
  557. void do_dch()
  558. {
  559.     if (keyboard_pos == keybuf->len) return;
  560.     newpos(keyboard_pos + 1);
  561.     do_bspc();
  562. }
  563.  
  564. void do_redraw()
  565. {
  566.     extern int screen_setup;
  567.  
  568.     if (!screen_setup || !visual) return;
  569.     clr();
  570.     setup_screen();
  571.     do_replace();
  572. }
  573.  
  574. void do_up()
  575. {
  576.     newpos(keyboard_pos - getwrap());
  577. }
  578.  
  579. void do_down()
  580. {
  581.     newpos(keyboard_pos + getwrap());
  582. }
  583.  
  584. void do_left()
  585. {
  586.     newpos(keyboard_pos - 1);
  587. }
  588.  
  589. void do_right()
  590. {
  591.     newpos(keyboard_pos + 1);
  592. }
  593.  
  594. void do_home()
  595. {
  596.     newpos(0);
  597. }
  598.  
  599. void do_end()
  600. {
  601.     newpos(keybuf->len);
  602. }
  603.  
  604. void do_wleft()
  605. {
  606.     int place;
  607.  
  608.     place = keyboard_pos - 1;
  609.     while(isspace(keybuf->s[place])) place--;
  610.     while(!isspace(keybuf->s[place])) if (--place < 0) break;
  611.     place++;
  612.     newpos(place);
  613. }
  614.  
  615. void do_wright()
  616. {
  617.     int place;
  618.  
  619.     place = keyboard_pos;
  620.     while (!isspace(keybuf->s[place]))
  621.         if (++place > keybuf->len) break;
  622.     while (isspace(keybuf->s[place])) place++;
  623.     newpos(place);
  624. }
  625.  
  626. void do_deol()
  627. {
  628.     dEOL();
  629.     Stringterm(keybuf, keyboard_pos);
  630. }
  631.  
  632. void do_insert()
  633. {
  634.     toggle_insert();
  635. }
  636.  
  637. void process_buffer(inbuf)
  638.     Stringp inbuf;
  639. {
  640.     extern Stringp kprefix;
  641.     extern int kecho, concat, sub;
  642.     char *temp, *ptr, code;
  643.     STATIC_BUFFER(buffer)
  644.  
  645.     Stringterm(buffer, 0);
  646.     if (concat) {
  647.         if (inbuf->s[0] == '.' && !inbuf->s[1]) {
  648.             SStringcpy(inbuf, cat_keybuf);
  649.             Stringterm(cat_keybuf, 0);
  650.             concat = 0;
  651.         } else {
  652.             SStringcat(cat_keybuf, inbuf);
  653.             if (concat == 2) Stringcat(cat_keybuf, "%\\");
  654.             return;
  655.         }
  656.     }
  657.  
  658.     if (kecho) oprintf("%S%S", kprefix, inbuf);
  659.     else if (!inbuf->len && visual) oputs("");
  660.  
  661. #ifdef SNARF_BLANKS
  662.     if (!inbuf->len) return;
  663. #endif
  664.  
  665.     temp = inbuf->s;
  666.     if (!sub || *temp == '^') SStringcpy(buffer, inbuf);
  667.     else if (sub == 2) {
  668.         process_macro(inbuf->s, "", buffer, 1);
  669.         if (inbuf->len) record_input(inbuf->s);
  670.         return;
  671.     } else if (*temp == '/') SStringcpy(buffer, inbuf);
  672.     else while (*temp) {
  673.         if (*temp == '%' && sub) {
  674.             if (*++temp == '%')
  675.                 while (*temp == '%') Stringadd(buffer, *temp++);
  676.             else if (*temp == '\\' || *temp == ';') {
  677.                 Stringadd(buffer, '\n');
  678.                 temp++;
  679.             } else if (*temp == 'e' || *temp == 'E') {
  680.                 Stringadd(buffer, '\033');
  681.                 temp++;
  682.             } else Stringadd(buffer, '%');
  683.         } else if (*temp == '\\') {
  684.             temp++;
  685.             if (isdigit(*temp)) {
  686.                 code = (char)atoi(temp);
  687.                 Stringadd(buffer, code);
  688.                 while (isdigit(*++temp));
  689.             } else Stringadd(buffer, '\\');
  690.         } else {
  691.             for (ptr = temp++; *temp && *temp != '%' && *temp != '\\'; temp++);
  692.             Stringncat(buffer, ptr, temp - ptr);
  693.         }
  694.     }
  695.  
  696.     if (buffer->s[0] == '^') {
  697.         newline_package(buffer, 0);
  698.         history_sub(buffer->s + 1);
  699.     } else {
  700.         check_command(TRUE, buffer);
  701.         if (inbuf->len) record_input(inbuf->s);
  702.     }
  703. }
  704.  
  705. void cbreak_noecho_mode()
  706. {
  707. #ifdef hpux
  708.     struct termio blob;
  709.  
  710.     if (ioctl(0, TCGETA, &blob) == -1) perror("TCGETA ioctl");
  711.     blob.c_lflag &= ~(ECHO | ECHOE | ICANON);
  712.     blob.c_cc[VMIN] = 0;
  713.     blob.c_cc[VTIME] = 0;
  714.     if (ioctl(0, TCSETAF, &blob) == -1) perror("TCSETAF ioctl");
  715. #else
  716. # ifdef SYSVTTY
  717.     struct termio blob;
  718.  
  719.     first_time = FALSE;
  720.     if (ioctl(0, TCGETA, &blob) == -1) perror("TCGETA ioctl");
  721.     bcopy(&blob, &old_tty_state, sizeof(struct termio));
  722.     blob.c_iflag = IGNBRK | IGNPAR | ICRNL;
  723.     blob.c_oflag = OPOST | ONLCR;
  724.     blob.c_lflag = ISIG;
  725.     blob.c_cc[VMIN] = 0;
  726.     blob.c_cc[VTIME] = 0;
  727.     if (ioctl(0, TCSETAF, &blob) == -1) perror("TCSETAF ioctl");
  728. # else
  729.     struct sgttyb blob;
  730.  
  731.     if (ioctl(0, TIOCGETP, &blob) == -1) perror("TIOCGETP ioctl");
  732.     blob.sg_flags |= CBREAK;
  733.     blob.sg_flags &= ~ECHO;
  734.     if (ioctl(0, TIOCSETP, &blob) == -1) perror("TIOCSETP ioctl");
  735. # endif
  736. #endif
  737. }
  738.  
  739. void cooked_echo_mode()
  740. {
  741. #ifdef hpux
  742.     struct termio blob;
  743.  
  744.     if (ioctl(0, TCGETA, &blob) == -1) perror("TCGETA ioctl");
  745.     blob.c_lflag |= ECHO | ECHOE | ICANON;
  746.     if (ioctl(0, TCSETAF, &blob) == -1) perror("TCSETAF ioctl");
  747. #else
  748. # ifdef SYSVTTY
  749.     if (!first_time)
  750.         if (ioctl(0, TCSETA, &old_tty_state) == -1) perror("TCSETA ioctl");
  751. # else
  752.     struct sgttyb blob;
  753.  
  754.     if (ioctl(0, TIOCGETP, &blob) == -1) perror("TIOCGETP ioctl");
  755.     blob.sg_flags &= ~CBREAK;
  756.     blob.sg_flags |= ECHO;
  757.     if (ioctl(0, TIOCSETP, &blob) == -1) perror("TIOCSETP ioctl");
  758. # endif
  759. #endif
  760. }
  761.