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

  1. /*    SC    A Spreadsheet Calculator
  2.  *        Lexical analyser
  3.  *
  4.  *        original by James Gosling, September 1982
  5.  *        modifications by Mark Weiser and Bruce Israel,
  6.  *            University of Maryland
  7.  *
  8.  *              More mods Robert Bond, 12/86
  9.  *        More mods by Alan Silverstein, 3/88, see list of changes.
  10.  *        $Revision: 6.21 A $
  11.  *
  12.  */
  13.  
  14.  
  15. #include <sys/types.h>
  16. #include "config.h"
  17.  
  18. #if defined(BSD42) || defined(BSD43)
  19. #include <sys/ioctl.h>
  20. #include <strings.h>
  21. #else
  22. #ifndef SYSIII
  23. #include <string.h>
  24. #endif
  25. #endif
  26.  
  27. #ifdef IEEE_MATH
  28. #include <ieeefp.h>
  29. #endif /* IEEE_MATH */
  30.  
  31. #ifdef DOINGX
  32. #include <stdio.h>
  33. #include <X11/Xlib.h>
  34. #include <X11/Xutil.h>
  35. #include <X11/keysym.h>
  36. #else
  37. #include <curses.h>
  38. #endif
  39. #include <signal.h>
  40. #include <setjmp.h>
  41. #include "sc.h"
  42. #ifdef DOINGX
  43. #include "scXstuff.h"
  44. #endif
  45. #include <ctype.h>
  46.  
  47. #ifdef NONOTIMEOUT
  48. #define    notimeout(a1, a2)
  49. #endif
  50.  
  51. #ifdef VMS
  52. #include "gram_tab.h"
  53. typedef union {
  54.     int ival;
  55.     double fval;
  56.     struct ent *ent;
  57.     struct enode *enode;
  58.     char *sval;
  59.     struct range_s rval;
  60. } YYSTYPE;
  61. extern YYSTYPE yylval;
  62. extern int VMS_read_raw;   /*sigh*/
  63. #else    /* VMS */
  64. #if defined(MSDOS)
  65. #include "y_tab.h"
  66. #else
  67. #include "y.tab.h"
  68. #endif /* MSDOS */
  69. #endif /* VMS */
  70.  
  71. #ifdef hpux
  72. extern YYSTYPE yylval;
  73. #endif /* hpux */
  74.  
  75. #if !defined(SIMPLE) && (defined(BSD42) || defined (SYSIII) || defined(BSD43))
  76. #ifdef __STDC__
  77. static    void    charout(int);
  78. #else    /* __STDC__ */
  79. static    void    charout();
  80. #endif    /* __STDC__ */
  81. #endif
  82.  
  83. char *mystrtof();
  84.  
  85. #ifdef __STDC__
  86. /*#include <term.h>*/
  87. extern int    tgetent(char *, char *);
  88. extern int    tputs(char *, int, int (*)(char));
  89. #else    /* __STDC__ */
  90. extern int    tgetent();
  91. extern int    tputs();
  92. #endif    /* __STDC__ */
  93.  
  94. jmp_buf wakeup;
  95. jmp_buf fpe_buf;
  96.  
  97. extern    int    anychanged;
  98.  
  99. sig_type
  100. fpe_trap(signo)
  101. int signo;
  102. {
  103. #if defined(i386) && !defined(M_XENIX)
  104.     /*asm("    fnclex");*/
  105.     /*asm("    fwait");*/
  106. #else
  107. #ifdef IEEE_MATH
  108.     (void)fpsetsticky((fp_except)0);    /* Clear exception */
  109. #endif /* IEEE_MATH */
  110. #ifdef PC
  111.     _fpreset();
  112. #endif
  113. #endif
  114.     longjmp(fpe_buf, 1);
  115. }
  116.  
  117. struct key {
  118.     char *key;
  119.     int val;
  120. };
  121.  
  122. struct key experres[] = {
  123. #include "experres.h"
  124.     0, 0};
  125.  
  126. struct key statres[] = {
  127. #include "statres.h"
  128.     0, 0};
  129.  
  130.  
  131. int
  132. yylex ()
  133. {
  134. #ifdef __STDC__
  135.     char *volatile p = line+linelim;
  136. #else
  137.     char *p = line+linelim;
  138. #endif
  139.     int ret;
  140.  
  141.     while (isspace(*p))
  142.     p++;
  143.     if (*p == '\0') ret = -1;
  144.     else if (isalpha(*p)) {
  145.     char *tokenst = p;
  146.     register tokenl;
  147.     register struct key *tblp;
  148.     tokenl = 0;
  149.     /*
  150.      * This picks up either 1 or 2 alpha characters (a column) or
  151.      * tokens with at least three leading alphas and '_' or digits
  152.      * (a function or token or command or a range name)
  153.     */
  154.     while (isalpha(*p) || (((*p == '_') || isdigit(*p)) && (tokenl > 2))) {
  155.         p++;
  156.         tokenl++;
  157.     }
  158.     if (tokenl <= 2) { /* a COL is 1 or 2 char alpha
  159.         (but not pi, ln, fv, pv, if -- this should be fixed!) */
  160.         if (tokenl == 2 && tokenst[0] == 'p' && tokenst[1] == 'i') {
  161.         ret = K_PI;
  162.         } else if (tokenl == 2 && tokenst[0] == 'l' && tokenst[1] == 'n') {
  163.         ret = K_LN;
  164.         } else if (tokenl == 2 && tokenst[0] == 'f' && tokenst[1] == 'v') {
  165.         ret = K_FV;
  166.         } else if (tokenl == 2 && tokenst[0] == 'p' && tokenst[1] == 'v') {
  167.         ret = K_PV;
  168.         } else if (tokenl == 2 && tokenst[0] == 'i' && tokenst[1] == 'f') {
  169.         ret = K_IF;
  170.  
  171.         } else {
  172.         ret = COL;
  173.         yylval.ival = atocol (tokenst, tokenl);
  174.         }
  175.     } else {
  176.         ret = WORD;
  177.         for (tblp = linelim ? experres : statres; tblp->key; tblp++)
  178.             if (((tblp->key[0]^tokenst[0])&0137)==0
  179.              && tblp->key[tokenl]==0) {
  180.             register i = 1;
  181.             while (i<tokenl && ((tokenst[i]^tblp->key[i])&0137)==0)
  182.                 i++;
  183.             if (i>=tokenl) {
  184.                 ret = tblp->val;
  185.                 break;
  186.             }
  187.             }
  188.         if (ret==WORD) { 
  189.         struct range *r;
  190.         if (r = find_range(tokenst, tokenl,
  191.                    (struct ent *)0, (struct ent *)0)) {
  192.             yylval.rval.left = r->r_left;
  193.             yylval.rval.right = r->r_right;
  194.             if (r->r_is_range)
  195.                 ret = RANGE;
  196.             else
  197.             ret = VAR;
  198.         } else {
  199.             linelim = p-line;
  200.             yyerror ("Unintelligible word");
  201.         }
  202.         }
  203.     }
  204.     } else if ((*p == '.') || isdigit(*p)) {
  205.     sig_type (*sig_save)();
  206. #ifdef __STDC__
  207.     double volatile v = 0.0;
  208.     char *volatile nstart = p;
  209. #else
  210.     double v = 0.0;
  211.     char *nstart = p;
  212. #endif
  213.     int temp;
  214.  
  215.     sig_save = signal(SIGFPE, fpe_trap);
  216.     if (setjmp(fpe_buf)) {
  217.         (void) signal(SIGFPE, sig_save);
  218.         yylval.fval = v;
  219.         error("Floating point exception\n");
  220.         return FNUMBER;
  221.     }
  222.  
  223.     if (*p != '.') {
  224.         do v = v*10.0 + (double) ((unsigned) *p - '0');
  225.         while (isdigit(*++p));
  226.     }
  227.     if (*p=='.' || *p == 'e' || *p == 'E') {
  228.         ret = FNUMBER;
  229.         p = mystrtof(nstart, &yylval.fval);
  230.     } else {
  231.         /* A NUMBER must hold at least MAXROW and MAXCOL */
  232.         /* This is consistent with a short row and col in struct ent */
  233.         if (v > (double)32767 || v < (double)-32768) {
  234.         ret = FNUMBER;
  235.         yylval.fval = v;
  236.         } else {
  237.         temp = (int)v;
  238.         if((double)temp != v) {
  239.             ret = FNUMBER;
  240.             yylval.fval = v;
  241.         } else {
  242.             ret = NUMBER;
  243.             yylval.ival = temp;
  244.         }
  245.         }
  246.     }
  247.     (void) signal(SIGFPE, sig_save);
  248.     } else if (*p=='"') {
  249.     char *ptr;
  250.         ptr = p+1;    /* "string" or "string\"quoted\"" */
  251.         while(*ptr && ((*ptr != '"') || (*(ptr-1) == '\\')))
  252.         ptr++;
  253.         ptr = scxmalloc((unsigned)(ptr-p));
  254.     yylval.sval = ptr;
  255.     p += 1;
  256.     while (*p && ((*p != '"') || (*(p-1) == '\\')))
  257.         *ptr++ = *p++;
  258.     *ptr = 0;
  259.     if (*p)
  260.         p += 1;
  261.     ret = STRING;
  262.     } else if (*p=='[') {
  263.     while (*p && *p!=']')
  264.         p++;
  265.     if (*p)
  266.         p++;
  267.     linelim = p-line;
  268.     return yylex();
  269.     } else ret = *p++;
  270.     linelim = p-line;
  271.     return ret;
  272. }
  273.  
  274.  
  275. /*
  276.  * Given a token string starting with a symbolic column name and its valid
  277.  * length, convert column name ("A"-"Z" or "AA"-"ZZ") to a column number (0-N).
  278.  * Never mind if the column number is illegal (too high).  The procedure's name
  279.  * and function are the inverse of coltoa().
  280.  * 
  281.  * Case-insensitivity is done crudely, by ignoring the 040 bit.
  282.  */
  283.  
  284. int
  285. atocol (string, len)
  286.     char    *string;
  287.     int    len;
  288. {
  289.     register int col;
  290.  
  291.     col = (string [0] & 0137) - 'A';
  292.  
  293.     if (len == 2)        /* has second char */
  294.         col = ((col + 1) * 26) + ((string [1] & 0137) - 'A');
  295.  
  296.     return (col);
  297. }
  298.  
  299. /*
  300.  * This converts a floating point number of the form
  301.  * [s]ddd[.d*][esd*]  where s can be a + or - and e is E or e.
  302.  * to floating point. 
  303.  * p is advanced.
  304.  */
  305.  
  306. char * mystrtof(p, res)
  307. #ifdef __STDC__
  308.   char *volatile p;
  309. #else
  310.   char *p;
  311. #endif
  312. double *res;
  313. {
  314.     double acc;
  315.     int sign;
  316.     double fpos;
  317.     int exp;
  318.     int exps;
  319.     sig_type (*sig_save)();
  320.  
  321.     sig_save = signal(SIGFPE, fpe_trap);
  322.     if (setjmp(fpe_buf)) {
  323.     error("Floating point exception\n");
  324.     *res = 0.0; 
  325.         (void) signal(SIGFPE, sig_save);
  326.     return(p);
  327.     }
  328.     acc = 0.0;
  329.     sign = 1;
  330.     exp = 0;
  331.     exps = 1;
  332.     if (*p == '+')
  333.         p++;
  334.     else if (*p == '-') {
  335.         p++;
  336.         sign = -1;
  337.     }
  338.     while (isdigit(*p)) {
  339.         acc = acc * 10.0 + (double)(*p - '0');
  340.         p++;
  341.     }
  342.     if (*p == 'e' || *p == 'E') {
  343.         p++;
  344.         if (*p == '+')
  345.         p++;
  346.         else if (*p == '-') {
  347.         p++;
  348.         exps = -1;
  349.         }
  350.         while(isdigit(*p)) {
  351.         exp = exp * 10 + (*p - '0');
  352.         p++;
  353.         }
  354.     }
  355.     if (*p == '.') {
  356.     fpos = 1.0/10.0;
  357.     p++;
  358.     while(isdigit(*p)) {
  359.         acc += (*p - '0') * fpos;
  360.         fpos *= 1.0/10.0;
  361.         p++;
  362.     }
  363.     }
  364.     if (*p == 'e' || *p == 'E') {
  365.     exp = 0;
  366.     exps = 1;
  367.         p++;
  368.     if (*p == '+')
  369.         p++;
  370.     else if (*p == '-') {
  371.         p++;
  372.         exps = -1;
  373.     }
  374.     while(isdigit(*p)) {
  375.         exp = exp * 10 + (*p - '0');
  376.         p++;
  377.     }
  378.     }
  379.     if (exp) {
  380.     if (exps > 0)
  381.         while (exp--)
  382.         acc *= 10.0;
  383.     else
  384.         while (exp--)
  385.         acc *= 1.0/10.0;
  386.     }
  387.     if (sign > 0)
  388.         *res = acc;
  389.     else
  390.     *res = -acc;
  391.  
  392.     (void) signal(SIGFPE, sig_save);
  393.     return(p);
  394. }
  395.  
  396.  
  397. /*
  398.  *************************************************
  399.  * Keyboard functions below
  400.  */
  401. #ifdef DOINGX
  402. int
  403. nmgetch()
  404. {
  405.     XEvent event;
  406.     KeySym  key;
  407.     char buffer[8];
  408.     int count;
  409.     int done;
  410.     int complete;
  411.     int pixel; 
  412.  
  413.   while(TRUE)
  414.   {
  415.     XNextEvent(dpy,&event);
  416.     
  417.     while (event.type == MotionNotify)
  418.         XNextEvent(dpy,&event);
  419.  
  420.     if (event.xbutton.button == 3)
  421.     {    Main_Menu();
  422.         show_top_line();
  423.         if (!running)
  424.             return((int)'q');
  425.     }
  426.     else
  427.         if (event.type == ButtonPress)
  428.         {
  429.                 /* find x (column) */
  430.         cr_line();
  431.         pixel = 5 * curfontwidth + 1; 
  432.         complete=0;
  433.         curcol=stcol-1; 
  434.         if ((stcol > 0) && (event.xbutton.x < pixel)) 
  435.             curcol=stcol-1;
  436.         else
  437.         { 
  438.             while (!complete)
  439.             {    curcol++;
  440.             checkbounds(&currow, &curcol);
  441.             if (!col_hidden[curcol])
  442.             {     pixel = pixel + fwidth[curcol] * curfontwidth;
  443.                 if (event.xbutton.x < pixel)
  444.                     complete++;
  445.             }
  446.             }
  447.         }
  448.  
  449.                 /* find y (row) */
  450.         pixel = 4 * curfontheight + 3; 
  451.         complete=0; 
  452.         currow=strow-1; 
  453.         if ((strow > 0) && (event.xbutton.y < pixel))
  454.             currow=strow-1;
  455.         else
  456.         {
  457.             while (!complete)
  458.             {    currow++; 
  459.             checkbounds(&currow, &curcol);
  460.             if (!row_hidden[currow]) 
  461.             {    pixel = pixel + curfontheight;
  462.                 if (event.xbutton.y < pixel)
  463.                     complete++;
  464.             }
  465.             }
  466.         }
  467.         update(anychanged);
  468.     }
  469.         else
  470.     if (event.type == KeyPress)
  471.     {  
  472.       if (XLookupString(&(event.xkey), buffer,8,&key,0))
  473.         return(buffer[0]);
  474.       else
  475.       if (IsCursorKey(key))
  476.           {
  477.                 switch(key) 
  478.                 {
  479. #ifdef XK_Left
  480.                         case XK_Left:   return(ctl('b'));
  481. #endif
  482. #ifdef XK_Right
  483.                         case XK_Right:  return(ctl('f'));
  484. #endif
  485. #ifdef XK_Down
  486.                         case XK_Down:   return(ctl('n'));
  487. #endif
  488. #ifdef XK_Up
  489.                         case XK_Up:     return(ctl('p'));
  490. #endif
  491.                 }
  492.         return(key);
  493.           }
  494.  
  495. /*        if(!IsCursorKey(key))
  496.         {    return(buffer[0]);
  497.         }
  498. */
  499.     }
  500.     else
  501.     switch(event.type)
  502.     {
  503.         case Expose:
  504.             if (event.xexpose.count != 0)
  505.                 break;
  506.             FullUpdate++;
  507.             update(anychanged);
  508.             break;
  509.  
  510.         case MappingNotify:
  511.             XRefreshKeyboardMapping (&(event.xmapping));
  512.             break;
  513.  
  514.         case ConfigureNotify:
  515.             sc_handleresize(&event);
  516.             break;
  517.     }
  518.   }
  519. }
  520. #else /* DOINGX */
  521. #ifdef SIMPLE
  522.  
  523. void
  524. initkbd()
  525. {}
  526.  
  527. void
  528. kbd_again()
  529. {}
  530.  
  531. void
  532. resetkbd()
  533. {}
  534.  
  535. #ifndef VMS
  536.  
  537. int
  538. nmgetch()
  539. {
  540.     return (toascii(getchar()));
  541. }
  542.  
  543. #else /* VMS */
  544.  
  545. int
  546. nmgetch()
  547. /*
  548.    This is not perfect, it doesn't move the cursor when goraw changes
  549.    over to deraw, but it works well enough since the whole sc package
  550.    is incredibly stable (loop constantly positions cursor).
  551.  
  552.    Question, why didn't the VMS people just implement cbreak?
  553.  
  554.    NOTE: During testing it was discovered that the DEBUGGER and curses
  555.    and this method of reading would collide (the screen was not updated
  556.    when continuing from screen mode in the debugger).
  557. */
  558. {
  559.     short c;
  560.     static int key_id=0;
  561.     int status;
  562. #define VMScheck(a) {if (~(status = (a)) & 1) VMS_MSG (status);}
  563.  
  564.     if (VMS_read_raw) {
  565.       VMScheck(smg$read_keystroke (&stdkb->_id, &c, 0, 0, 0));
  566.     }
  567.     else
  568.        c = getchar();
  569.  
  570.     switch (c) {
  571.     case SMG$K_TRM_LEFT:  c = ctl('b'); break;
  572.     case SMG$K_TRM_RIGHT: c = ctl('f'); break;
  573.     case SMG$K_TRM_UP:    c = ctl('p'); break;
  574.     case SMG$K_TRM_DOWN:  c = ctl('n'); break;
  575.     default:   c = c & A_CHARTEXT;
  576.     }
  577.     return (c);
  578. }
  579.  
  580.  
  581. VMS_MSG (status)
  582. int status;
  583. /*
  584.    Routine to put out the VMS operating system error (if one occurs).
  585. */
  586. {
  587. #include <descrip.h>
  588.    char errstr[81], buf[120];
  589.    $DESCRIPTOR(errdesc, errstr);
  590.    short int length;
  591. #define err_out(msg) fprintf (stderr,msg)
  592.  
  593. /* Check for no error or standard error */
  594.  
  595.    if (~status & 1) {
  596.       status = status & 0x8000 ? status & 0xFFFFFFF : status & 0xFFFF;
  597.       if (SYS$GETMSG(status, &length, &errdesc, 1, 0) == SS$_NORMAL) {
  598.      errstr[length] = '\0';
  599.      (void) sprintf (buf, "<0x%x> %s", status, errdesc.dsc$a_pointer);
  600.      err_out (buf);
  601.       }
  602.       else
  603.          err_out ("System error");
  604.    }
  605. }
  606. #endif /* VMS */
  607.  
  608. #else /* end of SIMPLE */
  609.  
  610. #ifndef DOINGX
  611. sig_type
  612. time_out(signo)
  613. int signo;
  614. {
  615.     longjmp(wakeup, 1);
  616. }
  617. #endif
  618.  
  619. #if defined(BSD42) || defined (SYSIII) || defined(BSD43)
  620.  
  621. #define N_KEY 4
  622.  
  623. struct key_map {
  624.     char *k_str;
  625.     char k_val;
  626.     char k_index;
  627. }; 
  628.  
  629. struct key_map km[N_KEY];
  630.  
  631. char keyarea[N_KEY*30];
  632.  
  633. char *tgetstr();
  634. char *getenv();
  635. char *ks;
  636. char ks_buf[20];
  637. char *ke;
  638. char ke_buf[20];
  639.  
  640. #ifdef TIOCSLTC
  641. struct ltchars old_chars, new_chars;
  642. #endif
  643.  
  644. char dont_use[] = {
  645.     ctl('['), ctl('a'), ctl('b'), ctl('c'), ctl('e'), ctl('f'), ctl('g'), ctl('h'),
  646.     ctl('i'), ctl('j'),  ctl('l'), ctl('m'), ctl('n'), ctl('p'), ctl('q'),
  647.     ctl('r'), ctl('s'), ctl('t'), ctl('u'), ctl('v'),  ctl('w'), ctl('x'),
  648.     ctl('z'), 0
  649. };
  650.  
  651. static void
  652. charout(c)
  653. int c;
  654. {
  655.     (void)putchar(c);
  656. }
  657.  
  658. void
  659. initkbd()
  660. {
  661.     register struct key_map *kp;
  662.     register i,j;
  663.     char *p = keyarea;
  664.     char *ktmp;
  665.     static char buf[1024]; /* Why do I have to do this again? */
  666.  
  667.     if (!(ktmp = getenv("TERM"))) {
  668.     (void) fprintf(stderr, "TERM environment variable not set\n");
  669.     exit (1);
  670.     }
  671.     if (tgetent(buf, ktmp) <= 0)
  672.     return;
  673.  
  674.     km[0].k_str = tgetstr("kl", &p); km[0].k_val = ctl('b');
  675.     km[1].k_str = tgetstr("kr", &p); km[1].k_val = ctl('f');
  676.     km[2].k_str = tgetstr("ku", &p); km[2].k_val = ctl('p');
  677.     km[3].k_str = tgetstr("kd", &p); km[3].k_val = ctl('n');
  678.  
  679.     ktmp = tgetstr("ks",&p);
  680.     if (ktmp)  {
  681.     (void) strcpy(ks_buf, ktmp);
  682.     ks = ks_buf;
  683.     tputs(ks, 1, charout);
  684.     }
  685.     ktmp = tgetstr("ke",&p);
  686.     if (ktmp)  {
  687.     (void) strcpy(ke_buf, ktmp);
  688.     ke = ke_buf;
  689.     }
  690.  
  691.     /* Unmap arrow keys which conflict with our ctl keys   */
  692.     /* Ignore unset, longer than length 1, and 1-1 mapped keys */
  693.  
  694.     for (i = 0; i < N_KEY; i++) {
  695.     kp = &km[i];
  696.     if (kp->k_str && (kp->k_str[1] == 0) && (kp->k_str[0] != kp->k_val))
  697.         for (j = 0; dont_use[j] != 0; j++)
  698.             if (kp->k_str[0] == dont_use[j]) {
  699.              kp->k_str = (char *)0;
  700.              break;
  701.         }
  702.     }
  703.  
  704.  
  705. #ifdef TIOCSLTC
  706.     (void)ioctl(fileno(stdin), TIOCGLTC, (char *)&old_chars);
  707.     new_chars = old_chars;
  708.     if (old_chars.t_lnextc == ctl('v'))
  709.     new_chars.t_lnextc = -1;
  710.     if (old_chars.t_rprntc == ctl('r'))
  711.     new_chars.t_rprntc = -1;
  712.     (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars);
  713. #endif
  714. }
  715.  
  716. void
  717. kbd_again()
  718. {
  719.     if (ks) 
  720.     tputs(ks, 1, charout);
  721.  
  722. #ifdef TIOCSLTC
  723.     (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars);
  724. #endif
  725. }
  726.  
  727. void
  728. resetkbd()
  729. {
  730.     if (ke) 
  731.     tputs(ke, 1, charout);
  732.  
  733. #ifdef TIOCSLTC
  734.     (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&old_chars);
  735. #endif
  736. }
  737.  
  738. int
  739. nmgetch() 
  740. {
  741.     register int c;
  742.     register struct key_map *kp;
  743.     register struct key_map *biggest;
  744.     register int i;
  745.     int almost;
  746.     int maybe;
  747.  
  748.     static char dumpbuf[10];
  749.     static char *dumpindex;
  750.  
  751.     sig_type time_out();
  752.  
  753.     if (dumpindex && *dumpindex)
  754.         return (*dumpindex++);
  755.  
  756.     c = toascii(getchar());
  757.     biggest = 0;
  758.     almost = 0;
  759.  
  760.     for (kp = &km[0]; kp < &km[N_KEY]; kp++) {
  761.     if (!kp->k_str)
  762.         continue;
  763.     if (c == kp->k_str[kp->k_index]) {
  764.         almost = 1;
  765.         kp->k_index++;
  766.         if (kp->k_str[kp->k_index] == 0) {
  767.         c = kp->k_val;
  768.             for (kp = &km[0]; kp < &km[N_KEY]; kp++)
  769.                 kp->k_index = 0;
  770.             return(c);
  771.         }
  772.     }
  773.     if (!biggest && kp->k_index)
  774.         biggest = kp;
  775.         else if (kp->k_index && biggest->k_index < kp->k_index)
  776.         biggest = kp;
  777.     }
  778.  
  779.     if (almost) { 
  780.         (void) signal(SIGALRM, time_out);
  781.         (void) alarm(1);
  782.  
  783.     if (setjmp(wakeup) == 0) { 
  784.         maybe = nmgetch();
  785.         (void) alarm(0);
  786.         return(maybe);
  787.     }
  788.     }
  789.     
  790.     if (biggest) {
  791.     for (i = 0; i<biggest->k_index; i++) 
  792.         dumpbuf[i] = biggest->k_str[i];
  793.     if (!almost)
  794.         dumpbuf[i++] = c;
  795.     dumpbuf[i] = '\0';
  796.     dumpindex = &dumpbuf[1];
  797.     for (kp = &km[0]; kp < &km[N_KEY]; kp++)
  798.         kp->k_index = 0;
  799.     return (dumpbuf[0]);
  800.     }
  801.  
  802.     return(c);
  803. }
  804.  
  805. #endif /* defined(BSD42) || defined (SYSIII) || defined(BSD43) */
  806.  
  807. #if defined(SYSV2) || defined(SYSV3) || defined(MSDOS)
  808.  
  809. void
  810. initkbd()
  811. {
  812.     keypad(stdscr, TRUE);
  813.     notimeout(stdscr,TRUE);
  814. }
  815.  
  816. void
  817. kbd_again()
  818. {
  819.     keypad(stdscr, TRUE);
  820.     notimeout(stdscr,TRUE);
  821. }
  822.  
  823. void
  824. resetkbd()
  825. {
  826.     keypad(stdscr, FALSE);
  827.     notimeout(stdscr, FALSE);
  828. }
  829.  
  830. int
  831. nmgetch()
  832. {
  833.     register int c;
  834.  
  835.     c = wgetch(stdscr);
  836.     switch (c) {
  837. #ifdef KEY_LEFT
  838.     case KEY_LEFT:  c = ctl('b'); break;
  839. #endif
  840. #ifdef KEY_RIGHT
  841.     case KEY_RIGHT: c = ctl('f'); break;
  842. #endif
  843. #ifdef KEY_UP
  844.     case KEY_UP:    c = ctl('p'); break;
  845. #endif
  846. #ifdef KEY_DOWN
  847.     case KEY_DOWN:  c = ctl('n'); break;
  848. #endif
  849. #ifdef KEY_BACKSPACE
  850.     case KEY_BACKSPACE:  c = ctl('h'); break;
  851. #endif
  852. #ifdef KEY_NPAGE
  853.     case KEY_NPAGE:    break;
  854. #endif
  855. #ifdef KEY_PPAGE
  856.     case KEY_PPAGE:    break;
  857. #endif
  858. #ifdef KEY_HOME
  859.     case KEY_HOME:    break;
  860. #endif
  861. #ifdef KEY_DC
  862.     case KEY_DC:    c = 'x'; break;
  863. #endif
  864. #ifdef KEY_FIND
  865.     case KEY_FIND:  c = 'g'; break;
  866. #endif
  867. #ifdef KEY_HELP
  868.     case KEY_HELP:  c = '?'; break;
  869. #endif
  870. #ifdef KEY_SELECT
  871.     case KEY_SELECT:c = 'm'; break;
  872. #endif
  873. #ifdef KEY_C1
  874. /* This stuff works for a wyse wy75 in ANSI mode under 5.3.  Good luck. */
  875. /* It is supposed to map the curses keypad back to the numeric equiv. */
  876.     case KEY_C1:    c = '0'; break;
  877.     case KEY_A1:    c = '1'; break;
  878.     case KEY_B2:    c = '2'; break;
  879.     case KEY_A3:    c = '3'; break;
  880.     case KEY_F(5):  c = '4'; break;
  881.     case KEY_F(6):  c = '5'; break;
  882.     case KEY_F(7):  c = '6'; break;
  883.     case KEY_F(9):  c = '7'; break;
  884.     case KEY_F(10): c = '8'; break;
  885.     case KEY_F0:    c = '9'; break;
  886.     case KEY_C3:    c = '.'; break;
  887.     case KEY_ENTER: c = ctl('m'); break;
  888. #endif
  889.     default:        c = toascii(c); 
  890.     break;
  891.     }
  892.     return (c);
  893. }
  894.  
  895. #endif /* defined(SYSV2) || defined(SYSV3) || defined(MSDOS) */
  896.  
  897. #endif /* SIMPLE */
  898. #endif /* DOINGX */
  899.