home *** CD-ROM | disk | FTP | other *** search
/ pc.louisiana.edu/pub/unix/ / Louisiana_UNIX.tar / Louisiana_UNIX / xspread3.0.zoo / vi.c < prev    next >
C/C++ Source or Header  |  1994-03-25  |  18KB  |  884 lines

  1. /*    SC    A Spreadsheet Calculator
  2.  *
  3.  *    One line vi emulation
  4.  *    $Revision: 6.21 A $
  5.  */
  6.  
  7. #include <sys/types.h>
  8. #include "config.h"
  9.  
  10. #if defined(BSD42) || defined(BSD43)
  11. #include <strings.h>
  12. #else
  13. #ifndef SYSIII
  14. #include <string.h>
  15. #endif
  16. #endif
  17.  
  18. #include <signal.h>
  19. #ifdef DOINGX
  20. #include <X11/Xlib.h>
  21. #include <X11/Xutil.h>
  22. #else
  23. #include <curses.h>
  24. #endif
  25.  
  26. #include <stdio.h>
  27. #include <ctype.h>
  28. #include "sc.h"
  29.  
  30. #ifdef DOINGX
  31. #include "scXstuff.h"
  32. #endif
  33.  
  34. #define istext(a) (isalnum(a) || ((a) == '_'))
  35.  
  36. #ifdef __STDC__
  37. static void    append_line(void);
  38. static void    back_hist(void);
  39. static int    back_line(void);
  40. static int    back_word(void);
  41. static void    back_space(void);
  42. static void    change_cmd(void);
  43. static void    col_0(void);
  44. static void    delete_cmd(void);
  45. static void    del_chars(int, int);
  46. static void    del_in_line(void);
  47. static void    del_to_end(void);
  48. static void    dotcmd(void);
  49. static int    find_char(void);
  50. static void    for_hist(void);
  51. static int    for_line(int);
  52. static int    for_word(int);
  53. static int    get_motion(void);
  54. static void    ins_in_line(int);
  55. static void    last_col(void);
  56. static void    rep_char(void);
  57. static void    replace_in_line(int);
  58. static void    replace_mode(void);
  59. static void    restore_it(void);
  60. static void    savedot(int);
  61. static void    save_hist(void);
  62. static void    search_again(void);
  63. static void    search_hist(void);
  64. static void    search_mode(void);
  65. static void    stop_edit(void);
  66. static int    to_char(void);
  67. static void    u_save(int);
  68. #else    /* __STDC__ */
  69. static void    append_line();
  70. static void    back_hist();
  71. static int    back_line();
  72. static int    back_word();
  73. static void    back_space();
  74. static void    change_cmd();
  75. static void    col_0();
  76. static void    delete_cmd();
  77. static void    del_chars();
  78. static void    del_in_line();
  79. static void    del_to_end();
  80. static void    dotcmd();
  81. static int    find_char();
  82. static void    for_hist();
  83. static int    for_line();
  84. static int    for_word();
  85. static int    get_motion();
  86. static void    ins_in_line();
  87. static void    last_col();
  88. static void    rep_char();
  89. static void    replace_in_line();
  90. static void    replace_mode();
  91. static void    restore_it();
  92. static void    savedot();
  93. static void    save_hist();
  94. static void    search_again();
  95. static void    search_hist();
  96. static void    search_mode();
  97. static void    stop_edit();
  98. static int    to_char();
  99. static void    u_save();
  100. #endif    /* __STDC__ */
  101.  
  102. extern int showrange;
  103. extern char mode_ind;        /* Mode indicator */
  104.  
  105. /* values for mode below */
  106.  
  107. #define INSERT_MODE    0    /* Insert mode */
  108. #define EDIT_MODE       1    /* Edit mode */
  109. #define REP_MODE        2    /* Replace mode */
  110. #define SEARCH_MODE    3    /* Get arguments for '/' command */
  111.  
  112. #define    DOTLEN        200
  113.  
  114. static int mode = INSERT_MODE;
  115. struct    hist {
  116.     unsigned    int    len;
  117.     char    *histline;
  118. } history[HISTLEN];
  119.  
  120. static int histp = -1;
  121. static int lasthist = -1;
  122. static int endhist = -1;
  123. static char *last_search = NULL;
  124. static char *undo_line = NULL;
  125. static int undo_lim;
  126. static char dotb[DOTLEN];
  127. static int doti = 0;
  128. static int do_dot = 0;
  129.  
  130. void
  131. write_line(c)
  132. int c;
  133. {
  134.     if (mode == EDIT_MODE) {
  135.     switch(c) {
  136.     case (ctl('h')):    linelim = back_line();        break;
  137.     case (ctl('m')):  cr_line();            break;
  138.     case ESC:    stop_edit();            break;
  139.     case '+':    for_hist();            break;
  140.     case '-':    back_hist();            break;
  141.     case '$':    last_col();            break;
  142.     case '.':    dotcmd();            break;
  143.     case '/':    search_mode();            break;
  144.     case '0':    col_0();            break;
  145.     case 'D':    u_save(c);del_to_end();        break;
  146.     case 'I':    u_save(c);col_0();insert_mode();break;
  147.     case 'R':    replace_mode();            break;
  148.     case 'X':    u_save(c); back_space();    break;
  149.     case 'a':    u_save(c); append_line();    break;
  150.     case 'A':    u_save(c);last_col();append_line();    break;
  151.     case 'b':    linelim = back_word();        break;
  152.     case 'c':    u_save(c); change_cmd();    break;
  153.     case 'd':    u_save(c); delete_cmd();    break;
  154.     case 'f':    linelim = find_char();        break;
  155.     case 'h':    linelim = back_line();        break;
  156.     case 'i':    u_save(c); insert_mode();    break;
  157.     case 'j':    for_hist();            break;
  158.     case 'k':    back_hist();            break;
  159.     case ' ':
  160.     case 'l':    linelim = for_line(0);        break;
  161.     case 'n':    search_again();            break;
  162.     case 'q':    stop_edit();            break;
  163.     case 'r':    u_save(c); rep_char();        break;
  164.     case 't':    linelim = to_char();        break;
  165.     case 'u':    restore_it();            break;
  166.     case 'w':    linelim = for_word(0);        break;
  167.     case 'x':    u_save(c); del_in_line();    break;
  168.     default:    break;
  169.     }
  170.     } else if (mode == INSERT_MODE) { 
  171.     savedot(c);
  172.     switch(c) {
  173.     case (ctl('h')):    back_space();            break;
  174.     case (ctl('m')):  cr_line();            break;
  175.     case ESC:    edit_mode();            break;
  176.     default:    ins_in_line(c);            break;
  177.     }
  178.     } else if (mode == SEARCH_MODE) {
  179.     switch(c) {
  180.     case (ctl('h')):    back_space();            break;
  181.     case (ctl('m')):  search_hist();            break;
  182.     case ESC:    edit_mode();            break;
  183.     default:    ins_in_line(c);            break;
  184.     }
  185.    } else if (mode == REP_MODE) {
  186.     savedot(c);
  187.     switch(c) {
  188.     case (ctl('h')):    back_space();            break;
  189.     case (ctl('m')):  cr_line();            break;
  190.     case ESC:    edit_mode();            break;
  191.     default:    replace_in_line(c);        break;
  192.     }
  193.     }
  194. }
  195.  
  196. void
  197. edit_mode()
  198. {
  199.     mode = EDIT_MODE;
  200.     mode_ind = 'e';
  201.     histp = -1;
  202.     if (linelim < 0)    /* -1 says stop editing, ...so we still aren't */
  203.     return;
  204.     if (line[linelim] == '\0')
  205.     linelim = back_line();
  206. }
  207.  
  208. void
  209. insert_mode()
  210. {
  211.     mode_ind = 'i';
  212.     mode = INSERT_MODE;
  213. }
  214.  
  215. static    void
  216. search_mode()
  217. {
  218.     line[0] = '/';
  219.     line[1] = '\0';
  220.     linelim = 1;
  221.     histp = -1;
  222.     mode_ind = '/';
  223.     mode = SEARCH_MODE;
  224. }
  225.  
  226. static    void
  227. replace_mode()
  228. {
  229.     mode_ind = 'R';
  230.     mode = REP_MODE;
  231. }
  232.  
  233. /* dot command functions.  Saves info so we can redo on a '.' command */
  234.  
  235. static    void
  236. savedot(c)
  237. int c;
  238. {
  239.     if (do_dot || (c == '\n'))
  240.     return;
  241.  
  242.     if (doti < DOTLEN-1)
  243.     {
  244.     dotb[doti++] = c;
  245.     dotb[doti] = '\0';
  246.     }
  247. }
  248.  
  249. static int dotcalled = 0;
  250.  
  251. static    void
  252. dotcmd()
  253. {
  254.     int c;
  255.  
  256.     if (dotcalled)    /* stop recursive calling of dotcmd() */
  257.     return;
  258.     do_dot = 1;
  259.     doti = 0;
  260.     while(dotb[doti] != '\0') {
  261.     c = dotb[doti++];
  262.     dotcalled = 1;
  263.     write_line(c);
  264.     }
  265.     do_dot = 0;
  266.     doti = 0;
  267.     dotcalled = 0;
  268. }
  269.  
  270. int
  271. vigetch()
  272. {
  273.     int c;
  274.  
  275.     if(do_dot) {
  276.     if (dotb[doti] != '\0') {
  277.         return(dotb[doti++]);
  278.     } else {
  279.         do_dot = 0;
  280.         doti = 0;
  281.         return(nmgetch());
  282.     }
  283.     }
  284.     c = nmgetch();
  285.     savedot(c);
  286.     return(c);
  287. }
  288.  
  289. /* saves the current line for possible use by an undo cmd */
  290. static    void
  291. u_save(c)
  292. int c;
  293. {   static    unsigned    undolen = 0;
  294.  
  295.     if (strlen(line)+1 > undolen)
  296.     {    undolen = strlen(line)+40;
  297.  
  298.     undo_line = scxrealloc(undo_line, undolen);
  299.     }
  300.     (void) strcpy(undo_line, line);
  301.  
  302.     undo_lim = linelim;
  303.  
  304.     /* reset dot command if not processing it. */
  305.  
  306.     if (!do_dot) {
  307.         doti = 0;
  308.     savedot(c);
  309.     }
  310. }
  311.  
  312. /* Restores the current line saved by u_save() */
  313. static    void
  314. restore_it()
  315. {
  316.     static    char *tempc = NULL;
  317.     static    unsigned templen = 0;
  318.     int        tempi;
  319.  
  320.     if ((undo_line == NULL) || (*undo_line == '\0')) 
  321.     return;
  322.  
  323.     if (strlen(line)+1 > templen)
  324.     {    templen = strlen(line)+40;
  325.     tempc = scxrealloc(tempc, templen);
  326.     }
  327.  
  328.     strcpy(tempc, line);
  329.     tempi = linelim;
  330.     (void) strcpy(line, undo_line);
  331.     linelim = undo_lim;
  332.     strcpy(undo_line, tempc);
  333.     undo_lim = tempi;
  334. }
  335.  
  336. /* This command stops the editing process. */
  337. static    void
  338. stop_edit()
  339. {
  340.     showrange = 0;
  341.     linelim = -1;
  342. #ifndef DOINGX         /*ifndef added by Bob Parbs 12-92 */
  343.     (void) move(1, 0);
  344.     (void) clrtoeol();
  345. #endif
  346. }
  347.  
  348. /*
  349.  * Motion commands.  Forward motion commands take an argument
  350.  * which, when set, cause the forward motion to continue onto
  351.  * the null at the end of the line instead of stopping at the
  352.  * the last character of the line.
  353.  */
  354. static    int
  355. for_line(stop_null)
  356. int stop_null;
  357. {
  358.     if (linelim >= 0 && line[linelim] != '\0' && 
  359.                     (line[linelim+1] != '\0' || stop_null))
  360.     return(linelim+1);
  361.     else
  362.     return(linelim);
  363. }
  364.  
  365. static    int
  366. for_word(stop_null)
  367. int stop_null;
  368. {
  369.     register int c;
  370.     register int cpos;
  371.  
  372.     cpos = linelim;
  373.  
  374.     if (line[cpos] == ' ') {
  375.     while (line[cpos] == ' ')
  376.         cpos++;
  377.     if (cpos > 0 && line[cpos] == '\0')
  378.         --cpos;
  379.     return(cpos);
  380.     }
  381.  
  382.     if (istext(line[cpos])) {
  383.         while ((c = line[cpos]) && istext(c)) 
  384.         cpos++;
  385.     } else {
  386.     while ((c = line[cpos]) && !istext(c) && c != ' ')
  387.         cpos++;
  388.     }
  389.  
  390.     while (line[cpos] == ' ')
  391.         cpos++;
  392.  
  393.     if (cpos > 0 && line[cpos] == '\0' && !stop_null) 
  394.         --cpos;
  395.  
  396.     return(cpos);
  397. }
  398.  
  399. static    int
  400. back_line()
  401. {
  402.     if (linelim)
  403.         return(linelim-1);
  404.     else
  405.     return(0);
  406. }
  407.  
  408. static    int
  409. back_word()
  410. {
  411.     register int c;
  412.     register int cpos;
  413.  
  414.     cpos = linelim;
  415.  
  416.     if (line[cpos] == ' ') {
  417.     /* Skip white space */
  418.         while (cpos > 0 && line[cpos] == ' ')
  419.         --cpos;
  420.     } else if (cpos > 0 && (line[cpos-1] == ' ' 
  421.              || (istext(line[cpos]) && !istext(line[cpos-1]))
  422.              || (!istext(line[cpos]) &&  istext(line[cpos-1])))) {
  423.     /* Started on the first char of a word - back up to prev. word */
  424.     --cpos;
  425.         while (cpos > 0 && line[cpos] == ' ')
  426.         --cpos;
  427.     }
  428.  
  429.     /* Skip across the word - goes 1 too far */
  430.     if (istext(line[cpos])) {
  431.         while (cpos > 0 && (c = line[cpos]) && istext(c)) 
  432.         --cpos;
  433.     } else {
  434.     while (cpos > 0 && (c = line[cpos]) && !istext(c) && c != ' ')
  435.         --cpos;
  436.     }
  437.  
  438.     /* We are done - fix up the one too far */
  439.     if (cpos > 0 && line[cpos] && line[cpos+1]) 
  440.     cpos++;
  441.  
  442.     return(cpos);
  443. }
  444.  
  445. /* Text manipulation commands */
  446.  
  447. static    void
  448. del_in_line()
  449. {
  450.     register int len, i;
  451.  
  452.     if (linelim >= 0) {
  453.     len = strlen(line);
  454.     if (linelim == len && linelim > 0)
  455.         linelim--;
  456.     for (i = linelim; i < len; i++)
  457.         line[i] = line[i+1];
  458.     }
  459.     if (linelim > 0 && line[linelim] == '\0')
  460.     --linelim;
  461. }
  462.  
  463. static    void
  464. ins_in_line(c)
  465. int c;
  466. {
  467.     register int i, len;
  468.  
  469.     if (linelim < 0)
  470.     {    *line = '\0';
  471.     linelim = 0;
  472.     }
  473.     len = strlen(line);
  474.     for (i = len; i >= linelim; --i)
  475.     line[i+1] = line[i];
  476.     line[linelim++] = c;
  477.     line[len+1] = '\0';
  478. }
  479.  
  480. void
  481. ins_string(s)
  482. char *s;
  483. {
  484.     while (*s)
  485.     ins_in_line(*s++);
  486. }
  487.  
  488. static    void
  489. append_line()
  490. {
  491.     register int i;
  492.  
  493.     i = linelim;
  494.     if (i >= 0 && line[i])
  495.     linelim++;
  496.     insert_mode();
  497. }
  498.  
  499. static    void
  500. rep_char()
  501. {
  502.     int c;
  503.  
  504.     if (linelim < 0)
  505.     {    linelim = 0;
  506.     *line = '\0';
  507.     }
  508.     c = vigetch();
  509.     if (line[linelim] != '\0') {
  510.         line[linelim] = c;
  511.     } else {
  512.     line[linelim] = c;
  513.     line[linelim+1] = '\0';
  514.     }
  515. }
  516.  
  517. static    void
  518. replace_in_line(c)
  519. int    c;
  520. {
  521.     register int len;
  522.  
  523.     if (linelim < 0)
  524.     {    linelim = 0;
  525.     *line = '\0';
  526.     }
  527.     len = strlen(line);
  528.     line[linelim++] = c;
  529.     if (linelim > len)
  530.     line[linelim] = '\0';
  531. }
  532.  
  533. static    void
  534. back_space()
  535. {
  536.     if (linelim == 0)
  537.     return;
  538.  
  539.     if (line[linelim] == '\0') {
  540.     linelim = back_line();
  541.     del_in_line();
  542.     linelim = strlen(line);
  543.     } else {
  544.     linelim = back_line();
  545.     del_in_line();
  546.     }
  547. }
  548.  
  549. static    int
  550. get_motion()
  551. {
  552.     int c;
  553.  
  554.     c = vigetch();
  555.     switch (c) {
  556.     case 'b':    return(back_word());
  557.     case 'f':    return(find_char()+1);
  558.     case 'h':    return(back_line());
  559.     case 'l':    return(for_line(1));
  560.     case 't':    return(to_char()+1);
  561.     case 'w':    return(for_word(1));
  562.     default:    return(linelim);
  563.     }
  564. }
  565.  
  566. static    void
  567. delete_cmd()
  568. {
  569.     int cpos;
  570.  
  571.     cpos = get_motion();
  572.     del_chars(cpos, linelim);
  573. }
  574.  
  575. static    void
  576. change_cmd()
  577. {
  578.     delete_cmd();
  579.     insert_mode();
  580. }
  581.  
  582. static    void
  583. del_chars(first, last)
  584. register int first, last;
  585. {
  586.     int temp;
  587.  
  588.     if (first == last)
  589.     return;
  590.  
  591.     if (last < first) {
  592.     temp = last; last = first; first = temp;
  593.     }
  594.  
  595.     linelim = first;
  596.     while(first < last) {
  597.     del_in_line();
  598.     --last;
  599.     }
  600. }
  601.  
  602. static    void
  603. del_to_end()
  604. {
  605.     if (linelim < 0)
  606.     return;
  607.     line[linelim] = '\0';
  608.     linelim = back_line();
  609. }
  610.  
  611. void
  612. cr_line()
  613. {
  614.     insert_mode();
  615.     if (linelim != -1) {
  616.     showrange = 0;
  617.     save_hist();
  618.     linelim = 0;
  619.     (void) yyparse ();
  620.     linelim = -1;
  621.     }
  622.     else    /* '\n' alone will put you into insert mode */
  623.     {    *line = '\0';
  624.     linelim = 0;
  625.     }
  626. }
  627.  
  628. /* History functions */
  629.  
  630. static    void
  631. save_hist()
  632. {
  633.     if (lasthist < 0)
  634.     {    lasthist = 0;
  635.     }
  636.     else
  637.     lasthist = (lasthist + 1) % HISTLEN;
  638.  
  639.     if (lasthist > endhist)
  640.     endhist = lasthist;
  641.  
  642.     if (history[lasthist].len < strlen(line)+1)
  643.     {    history[lasthist].len = strlen(line)+40;
  644.     history[lasthist].histline = scxrealloc(history[lasthist].histline,
  645.                           history[lasthist].len);
  646.     }
  647.     (void) strcpy(history[lasthist].histline, line);
  648. }
  649.  
  650. static    void
  651. back_hist()
  652. {
  653.     if (histp == -1)
  654.     histp = lasthist;
  655.     else
  656.     if (histp == 0)
  657.     {    if (endhist != lasthist)
  658.         histp = endhist;
  659.     }
  660.     else
  661.     if (histp != ((lasthist + 1) % (endhist + 1)))
  662.     histp--;
  663.  
  664.     if (lasthist < 0)
  665.     line[linelim = 0] = '\0';
  666.     else {
  667.         (void) strcpy(line, history[histp].histline);
  668.     linelim = 0;
  669.     }
  670. }
  671.  
  672. static    void
  673. search_hist()
  674. {
  675.     static    unsigned lastsrchlen = 0;
  676.  
  677.     if(linelim < 1) {
  678.     linelim = 0;
  679.     edit_mode();
  680.     return;
  681.     }
  682.  
  683.     if (strlen(line)+1 > lastsrchlen)
  684.     {    lastsrchlen = strlen(line)+40;
  685.     last_search = scxrealloc(last_search, lastsrchlen);
  686.     }
  687.     (void)strcpy(last_search, line+1);
  688.     search_again();
  689.     mode = EDIT_MODE;
  690. }
  691.  
  692. static    void
  693. search_again()
  694. {
  695.     int found_it;
  696.     int do_next;
  697.     int prev_histp;
  698.     char *look_here;
  699.  
  700.     prev_histp = histp;
  701.     if ((last_search == NULL) || (*last_search == '\0'))
  702.     return;
  703.  
  704.     do {
  705.     back_hist();
  706.     if (prev_histp == histp)
  707.         break;
  708.     prev_histp = histp;
  709.     look_here = line;
  710.     found_it = do_next = 0;
  711.     for ( look_here = strchr(look_here, last_search[0]);
  712.           look_here != NULL && !found_it && !do_next;
  713.           look_here = strchr(look_here, last_search[0]) )
  714.     {
  715.         if (strncmp(look_here, last_search, strlen(last_search)) == 0)
  716.         found_it++;
  717.         else if (look_here < line + strlen(line) - 1)
  718.             look_here++;
  719.         else
  720.         do_next++;
  721.     }
  722.     } while (!found_it);
  723. }
  724.  
  725. static    void
  726. for_hist()
  727. {
  728.     if (histp == -1)
  729.     histp = lasthist;
  730.     else
  731.     if (histp != lasthist)
  732.     histp = (histp + 1) % (endhist + 1);
  733.  
  734.     if (lasthist < 0)
  735.     line[linelim = 0] = '\0';
  736.     else {
  737.     (void) strcpy(line, history[histp].histline);
  738.     linelim = 0;
  739.     }
  740. }
  741.  
  742. static    void
  743. col_0()
  744. {
  745.     linelim = 0;
  746. }
  747.  
  748. static    void
  749. last_col()
  750. {
  751.     linelim = strlen(line);
  752.     if (linelim > 0)
  753.     --linelim;
  754. }
  755.  
  756. static    int
  757. find_char()
  758. {
  759.     register int c;
  760.     register int i;
  761.  
  762.  
  763.     c = vigetch();
  764.     i = linelim;
  765.     while(line[i] && line[i] != c)
  766.     i++;
  767.     if (!line[i])
  768.     i = linelim;
  769.     return(i);
  770. }
  771.  
  772. static    int
  773. to_char()
  774. {
  775.     register int i;
  776.  
  777.     i = find_char();
  778.     if (i > 0 && i != linelim)
  779.     --i;
  780.  
  781.     return(i);
  782. }
  783.  
  784.  
  785. #ifdef DOINGX
  786. char *
  787. get_str(s, max_str_len)
  788.    char *s;               /* prompt and returned string */
  789.    int max_str_len;
  790. {
  791.   static char buf[1024]; /* hold the characters as they are typed */
  792.   int count=0;           /* how many characters have been entered */
  793.   int maxcount;          /* the max number of chars to be entered */
  794.   int done=0;            /* true when input is finished */
  795.   int slen;              /* length of prompt string */
  796.   XEvent event;          /* input event structure */
  797.   char keystr[3];        /* ASCII version of keypress */
  798.  
  799.   clearlines(0,0);
  800.   slen = strlen(s);
  801.   max_str_len--;      /* decrease this to save room for null byte */
  802.   maxcount = maintextcols - slen;
  803.   maxcount = ((maxcount < max_str_len) ? maxcount : max_str_len);
  804.   buf[0]='_'; /* the "cursor" */
  805.  
  806.   if (slen)
  807.      XDrawImageString(dpy,mainwin,maingc, textcol(0), textrow(0), s, slen);
  808.  
  809.   XDrawImageString(dpy,mainwin,maingc, textcol(slen+1), textrow(0), "_", 1 );
  810.   while (!done){
  811.     XNextEvent(dpy, &event);
  812.     switch(event.type){
  813.  
  814.       case Expose:
  815.         update(FALSE);
  816.         if (slen)
  817.             XDrawImageString(dpy, mainwin, maingc,
  818.                            textcol(0), textrow(0), s, slen);
  819.         if (count)
  820.             XDrawImageString(dpy, mainwin, maingc,
  821.                            textcol(slen), textrow(0), buf, count);
  822.  
  823.         XDrawImageString(dpy, mainwin, maingc,
  824.                          textcol(slen+count), textrow(0), "_", 1 );
  825.         break;
  826.  
  827.       case MappingNotify:
  828.         XRefreshKeyboardMapping(&(event.xmapping));
  829.         break;
  830.  
  831.       case ConfigureNotify:
  832.         sc_handleresize(&event);
  833.         maxcount = maintextcols - slen;
  834.         maxcount = ((maxcount < max_str_len) ? maxcount : max_str_len);
  835.         break;
  836.  
  837.       case KeyPress:
  838.         if (XLookupString(&(event.xkey), keystr, 3, 0, 0)){
  839.           switch( keystr[0]){
  840.             case 10: /* linefeed */
  841.             case 13: /* carriage return */
  842.               done = 1;
  843.               break;
  844.             case ctl('h'):  /* backspace */
  845.             case ctl('?'):  /* delete */
  846.         case DEL:
  847.               if (count){
  848.                 buf[--count]='_';
  849.                 XDrawImageString(dpy,mainwin,maingc,
  850.                                  textcol(slen+count+1),textrow(0), "_ ", 2);
  851.               } else {
  852.                 XBell(dpy,50);
  853.                 /*fprintf(stderr,"\007");*/ /* bell */
  854.               }
  855.               break;
  856.  
  857.             default:
  858.                 if ((keystr[0]>=32) && (keystr[0]<127)){
  859.                     if (count<maxcount){
  860.                       buf[count++]=keystr[0];
  861.                       buf[count]='_';
  862.                       XDrawImageString(dpy,mainwin,maingc,
  863.                                    textcol(slen+count),textrow(0),
  864.                    buf+count-1, 2);
  865.                     } else
  866.                        XBell(dpy,50);
  867.                        /*fprintf(stderr,"\007");*/
  868.                 } else
  869.                     XBell(dpy,50);
  870.                     /*fprintf(stderr,"\007");*/
  871.               break;
  872.  
  873.           } /* switch keystr[0] */
  874.         } /* if XLookupString */
  875.       } /* switch event.type */
  876.     } /* while !done */
  877.     buf[count] = 0;
  878.     strcpy(s, buf);
  879.     clearlines(0,0);
  880.     show_top_line();
  881.     return s;
  882. }
  883. #endif
  884.