home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / elvis_1.4.tar.Z / elvis_1.4.tar / tio.c < prev    next >
C/C++ Source or Header  |  1990-12-06  |  16KB  |  865 lines

  1. /* tio.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains terminal I/O functions */
  12.  
  13. #include "config.h"
  14. #if BSD || COHERENT
  15. # include <setjmp.h>
  16. #endif
  17. #include <signal.h>
  18. #include "vi.h"
  19.  
  20.  
  21. /* This function reads in a line from the terminal. */
  22. int vgets(prompt, buf, bsize)
  23.     char    prompt;    /* the prompt character, or '\0' for none */
  24.     char    *buf;    /* buffer into which the string is read */
  25.     int    bsize;    /* size of the buffer */
  26. {
  27.     int    len;    /* how much we've read so far */
  28.     int    ch;    /* a character from the user */
  29.     int    quoted;    /* is the next char quoted? */
  30.     int    tab;    /* column position of cursor */
  31.     char    widths[132];    /* widths of characters */
  32. #ifndef NO_DIGRAPH
  33.     int    erased;    /* 0, or first char of a digraph */
  34. #endif
  35.  
  36.     /* show the prompt */
  37.     move(LINES - 1, 0);
  38.     tab = 0;
  39.     if (prompt)
  40.     {
  41.         addch(prompt);
  42.         tab = 1;
  43.     }
  44.     clrtoeol();
  45.     refresh();
  46.  
  47.     /* read in the line */
  48. #ifndef NO_DIGRAPH
  49.     erased =
  50. #endif
  51.     quoted = len = 0;
  52.     for (;;)
  53.     {
  54.         ch = getkey(quoted ? 0 : WHEN_EX);
  55.  
  56.         /* some special conversions */
  57.         if (ch == ctrl('D') && len == 0)
  58.             ch = ctrl('[');
  59. #ifndef NO_DIGRAPH
  60.         if (*o_digraph && erased != 0 && ch != '\b')
  61.         {
  62.             ch = digraph(erased, ch);
  63.             erased = 0;
  64.         }
  65. #endif
  66.  
  67.         /* inhibit detection of special chars (except ^J) after a ^V */
  68.         if (quoted && ch != '\n')
  69.         {
  70.             ch |= 256;
  71.         }
  72.  
  73.         /* process the character */
  74.         switch(ch)
  75.         {
  76.           case ctrl('V'):
  77.             qaddch('^');
  78.             qaddch('\b');
  79.             quoted = TRUE;
  80.             break;
  81.  
  82.           case ctrl('['):
  83.             return -1;
  84.  
  85.           case '\n':
  86. #if OSK
  87.           case '\l':
  88. #else
  89.           case '\r':
  90. #endif
  91.             clrtoeol();
  92.             goto BreakBreak;
  93.  
  94.           case '\b':
  95.             if (len > 0)
  96.             {
  97.                 len--;
  98. #ifndef NO_DIGRAPH
  99.                 erased = buf[len];
  100. #endif
  101.                 for (ch = widths[len]; ch > 0; ch--)
  102.                     addch('\b');
  103.                 if (mode == MODE_EX)
  104.                 {
  105.                     clrtoeol();
  106.                 }
  107.                 tab -= widths[len];
  108.             }
  109.             else
  110.             {
  111.                 return -1;
  112.             }
  113.             break;
  114.  
  115.           default:
  116.             /* strip off quotation bit */
  117.             if (ch & 256)
  118.             {
  119.                 ch &= ~256;
  120.                 quoted = FALSE;
  121.                 qaddch(' ');
  122.                 qaddch('\b');
  123.             }
  124.             /* add & echo the char */
  125.             if (len < bsize - 1)
  126.             {
  127.                 if (ch == '\t')
  128.                 {
  129.                     widths[len] = *o_tabstop - (tab % *o_tabstop);
  130.                     addstr("        " + 8 - widths[len]);
  131.                     tab += widths[len];
  132.                 }
  133.                 else if (ch > 0 && ch < ' ') /* > 0 by GB */
  134.                 {
  135.                     addch('^');
  136.                     addch(ch + '@');
  137.                     widths[len] = 2;
  138.                     tab += 2;
  139.                 }
  140.                 else if (ch == '\177')
  141.                 {
  142.                     addch('^');
  143.                     addch('?');
  144.                     widths[len] = 2;
  145.                     tab += 2;
  146.                 }
  147.                 else
  148.                 {
  149.                     addch(ch);
  150.                     widths[len] = 1;
  151.                     tab++;
  152.                 }
  153.                 buf[len++] = ch;
  154.             }
  155.             else
  156.             {
  157.                 beep();
  158.             }
  159.         }
  160.     }
  161. BreakBreak:
  162.     refresh();
  163.     buf[len] = '\0';
  164.     return len;
  165. }
  166.  
  167.  
  168. /* ring the terminal's bell */
  169. void beep()
  170. {
  171.     if (*o_vbell)
  172.     {
  173.         do_VB();
  174.         refresh();
  175.     }
  176.     else if (*o_errorbells)
  177.     {
  178.         ttywrite("\007", 1);
  179.     }
  180. }
  181.  
  182. static int    manymsgs; /* This variable keeps msgs from overwriting each other */
  183. static char    pmsg[80]; /* previous message (waiting to be displayed) */
  184.  
  185.  
  186. static int showmsg()
  187. {
  188.     /* if there is no message to show, then don't */
  189.     if (!manymsgs)
  190.         return FALSE;
  191.  
  192.     /* display the message */
  193.     move(LINES - 1, 0);
  194.     if (*pmsg)
  195.     {
  196.         standout();
  197.         qaddch(' ');
  198.         qaddstr(pmsg);
  199.         qaddch(' ');
  200.         standend();
  201.     }
  202.     clrtoeol();
  203.  
  204.     manymsgs = FALSE;
  205.     return TRUE;
  206. }
  207.  
  208.  
  209. void endmsgs()
  210. {
  211.     if (manymsgs)
  212.     {
  213.         showmsg();
  214.         addch('\n');
  215.     }
  216. }
  217.  
  218. /* Write a message in an appropriate way.  This should really be a varargs
  219.  * function, but there is no such thing as vwprintw.  Hack!!!
  220.  *
  221.  * In MODE_EX or MODE_COLON, the message is written immediately, with a
  222.  * newline at the end.
  223.  *
  224.  * In MODE_VI, the message is stored in a character buffer.  It is not
  225.  * displayed until getkey() is called.  msg() will call getkey() itself,
  226.  * if necessary, to prevent messages from being lost.
  227.  *
  228.  * msg("")        - clears the message line
  229.  * msg("%s %d", ...)    - does a printf onto the message line
  230.  */
  231. /*VARARGS1*/
  232. void msg(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
  233.     char    *fmt;
  234.     long    arg1, arg2, arg3, arg4, arg5, arg6, arg7;
  235. {
  236.     if (mode != MODE_VI)
  237.     {
  238.         sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  239.         qaddstr(pmsg);
  240.         addch('\n');
  241.         exrefresh();
  242.     }
  243.     else
  244.     {
  245.         /* wait for keypress between consecutive msgs */
  246.         if (manymsgs)
  247.         {
  248.             getkey(WHEN_MSG);
  249.         }
  250.  
  251.         /* real message */
  252.         sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  253.         manymsgs = TRUE;
  254.     }
  255. }
  256.  
  257.  
  258. /* This function calls refresh() if the option exrefresh is set */
  259. void exrefresh()
  260. {
  261.     char    *scan;
  262.  
  263.     /* If this ex command wrote ANYTHING set exwrote so vi's  :  command
  264.      * can tell that it must wait for a user keystroke before redrawing.
  265.      */
  266.     for (scan=kbuf; scan<stdscr; scan++)
  267.         if (*scan == '\n')
  268.             exwrote = TRUE;
  269.  
  270. #if MICROSOFT            /* avoid compiler bug */
  271.     scan = stdscr;
  272. #define    stdscr    scan
  273. #endif
  274.     /* now we do the refresh thing */
  275.     if (*o_exrefresh)
  276.     {
  277.         refresh();
  278.     }
  279.     else
  280.     {
  281.         wqrefresh(stdscr);
  282.     }
  283. #if MICROSOFT
  284. #undef    stdscr
  285.     stdscr = scan;
  286. #endif
  287.     if (mode != MODE_VI)
  288.     {
  289.         manymsgs = FALSE;
  290.     }
  291. }
  292.  
  293.  
  294.  
  295. /* These are used for typeahead, and also for fudging the visual @ command */
  296. static char    keybuf[100];    /* array of already-read keys */
  297. static int    nkeys;        /* total number of keys in keybuf */
  298. static int    next;        /* index of next key to return */
  299. #ifndef NO_AT
  300. static int    atnext;        /* index of next key for "@", or 0 normally */
  301. int fromcutbuf(cbname)
  302.     int    cbname;
  303. {
  304.     int    len;
  305.  
  306.     /* fail if we're already doing an @ macro */
  307.     if (atnext > 0 && keybuf[atnext])
  308.     {
  309.         msg("Can't nest @ commands");
  310.         return FALSE;
  311.     }
  312.  
  313.     /* use the empty portion of keybuf[] to get chars from the cut buffer */
  314.     len = cb2str(cbname, keybuf + nkeys, sizeof keybuf - nkeys);
  315.     if (len < 0)
  316.     {
  317.         msg("Invalid cut buffer name.  Must be a-z");
  318.         return FALSE;
  319.     }
  320.     if (len == 0)
  321.     {
  322.         msg("Cut buffer \"%c is empty", cbname);
  323.         return FALSE;
  324.     }
  325.     else if (len >= sizeof keybuf - nkeys)
  326.     {
  327.         msg("Cut buffer \"%c is too large to execute", cbname);
  328.         return FALSE;
  329.     }
  330.  
  331.     /* prepare to "read" those keys on subsequent getkey() calls */
  332.     atnext = nkeys;
  333.     return TRUE;
  334. }
  335. #endif
  336.  
  337. /* This array describes mapped key sequences */
  338. static struct _keymap
  339. {
  340.     char    *name;        /* name of the key, or NULL */
  341.     char    rawin[LONGKEY];    /* the unmapped version of input */
  342.     char    cooked[80];    /* the mapped version of input */
  343.     int    len;        /* length of the unmapped version */
  344.     int    when;        /* when is this key mapped? */
  345. }
  346.     mapped[MAXMAPS];
  347.  
  348. #if !MSDOS && !TOS
  349. # if BSD || COHERENT
  350. static jmp_buf env_timeout;
  351. static int dummy()
  352. {
  353.     longjmp(env_timeout, 1);
  354.     return 0;
  355. }
  356. # else 
  357. static int dummy()
  358. {
  359. }
  360. # endif
  361. #endif
  362.  
  363. /* This function reads in a keystroke for VI mode.  It automatically handles
  364.  * key mapping.
  365.  */
  366. int getkey(when)
  367.     int        when;        /* which bits must be ON? */
  368. {
  369.     static char    *cooked;    /* rawin, or pointer to converted key */ 
  370.     static int    oldwhen;    /* "when" from last time */
  371.     static int    oldleft;
  372.     static long    oldtop;
  373.     static long    oldnlines;
  374.     static char    *cshape;    /* current cursor shape */
  375.     REG char    *kptr;        /* &keybuf[next] */
  376.     REG struct _keymap *km;    /* used to count through keymap */
  377.     REG int        i, j, k;
  378.  
  379. #ifdef DEBUG
  380.     watch();
  381. #endif
  382.  
  383.     /* if this key is needed for delay between multiple error messages,
  384.      * then reset the manymsgs flag and abort any mapped key sequence.
  385.      */
  386.     if (showmsg())
  387.     {
  388.         if (when == WHEN_MSG)
  389.         {
  390.             qaddstr("[More...]");
  391.             refresh();
  392.             cooked = (char *)0;
  393.         }
  394.         else if (when == WHEN_VIINP || when == WHEN_VIREP)
  395.         {
  396.             redraw(cursor, TRUE);
  397.         }
  398.     }
  399.  
  400. #ifndef NO_AT
  401.     /* if we're in the middle of a visual @ macro, take atnext */
  402.     if (atnext > 0)
  403.     {
  404.         if (keybuf[atnext])
  405.         {
  406.             return keybuf[atnext++];
  407.         }
  408.         atnext = 0;
  409.     }
  410. #endif
  411.  
  412.     /* if we're doing a mapped key, get the next char */
  413.     if (cooked && *cooked)
  414.     {
  415.         return *cooked++;
  416.     }
  417.  
  418.     /* if keybuf is empty, fill it */
  419.     if (next == nkeys)
  420.     {
  421. #ifndef NO_CURSORSHAPE
  422.         /* make sure the cursor is the right shape */
  423.         if (has_CQ)
  424.         {
  425.             cooked = cshape;
  426.             switch (when)
  427.             {
  428.               case WHEN_EX:        cooked = CX;    break;
  429.               case WHEN_VICMD:    cooked = CV;    break;
  430.               case WHEN_VIINP:    cooked = CI;    break;
  431.               case WHEN_VIREP:    cooked = CR;    break;
  432.             }
  433.             if (cooked != cshape)
  434.             {
  435.                 cshape = cooked;
  436.                 switch (when)
  437.                 {
  438.                   case WHEN_EX:        do_CX();    break;
  439.                   case WHEN_VICMD:    do_CV();    break;
  440.                   case WHEN_VIINP:    do_CI();    break;
  441.                   case WHEN_VIREP:    do_CR();    break;
  442.                 }
  443.             }
  444.             cooked = (char *)0;
  445.         }
  446. #endif
  447.  
  448. #ifndef NO_SHOWMODE
  449.         /* if "showmode" then say which mode we're in */
  450.         if (*o_smd
  451.          && mode == MODE_VI
  452.          && (when != oldwhen || topline != oldtop || leftcol != oldleft || nlines != oldnlines))
  453.         {
  454.             oldwhen = when;
  455.             oldtop = topline;
  456.             oldleft = leftcol;
  457.             oldnlines = nlines;
  458.  
  459.             if (when & WHEN_VICMD)
  460.             {
  461.                 redraw(cursor, FALSE);
  462.                 move(LINES - 1, COLS - 10);
  463.                 standout();
  464.                 addstr("Command");
  465.                 standend();
  466.                 redraw(cursor, FALSE);
  467.             }
  468.             else if (when & WHEN_VIINP)
  469.             {
  470.                 redraw(cursor, TRUE);
  471.                 move(LINES - 1, COLS - 10);
  472.                 standout();
  473.                 addstr(" Input ");
  474.                 standend();
  475.                 redraw(cursor, TRUE);
  476.             }
  477.             else if (when & WHEN_VIREP)
  478.             {
  479.                 redraw(cursor, TRUE);
  480.                 move(LINES - 1, COLS - 10);
  481.                 standout();
  482.                 addstr("Replace");
  483.                 standend();
  484.                 redraw(cursor, TRUE);
  485.             }
  486.         }
  487.         else
  488. #endif
  489.  
  490.         /* redraw if getting a VI command */
  491.         if (when & WHEN_VICMD)
  492.         {
  493.             redraw(cursor, FALSE);
  494.         }
  495.  
  496.         /* read the rawin keystrokes */
  497.         refresh();
  498.         while ((nkeys = ttyread(keybuf, sizeof keybuf)) < 0)
  499.         {
  500.             /* terminal was probably resized */
  501.             *o_lines = LINES;
  502.             *o_columns = COLS;
  503.             if (when & (WHEN_VICMD|WHEN_VIINP|WHEN_VIREP))
  504.             {
  505.                 redraw(MARK_UNSET, FALSE);
  506.                 redraw(cursor, (when & WHEN_VICMD) == 0);
  507.                 refresh();
  508.             }
  509.         }
  510.         next = 0;
  511.  
  512.         /* if nkeys == 0 then we've reached EOF of an ex script. */
  513.         if (nkeys == 0)
  514.         {
  515.             tmpabort(TRUE);
  516.             move(LINES - 1, 0);
  517.             clrtoeol();
  518.             refresh();
  519.             endwin();
  520.             exit(1);
  521.         }
  522.     }
  523.  
  524.     /* see how many mapped keys this might be */
  525.     kptr = &keybuf[next];
  526.     for (i = j = 0, k = -1, km = mapped; i < MAXMAPS; i++, km++)
  527.     {
  528.         if ((km->when & when) && km->len > 0 && *km->rawin == *kptr)
  529.         {
  530.             if (km->len > nkeys - next)
  531.             {
  532.                 if (!strncmp(km->rawin, kptr, nkeys - next))
  533.                 {
  534.                     j++;
  535.                 }
  536.             }
  537.             else
  538.             {
  539.                 if (!strncmp(km->rawin, kptr, km->len))
  540.                 {
  541.                     j++;
  542.                     k = i;
  543.                 }
  544.             }
  545.         }
  546.     }
  547.  
  548.     /* if more than one, try to read some more */
  549.     while (j > 1)
  550.     {
  551. #if BSD || COHERENT
  552.         if (setjmp(env_timeout))
  553.         {
  554.             /* we timed out - assume no mapping */
  555.             j = 0;
  556.             break;
  557.         }
  558. #endif
  559. #if ANY_UNIX
  560.         signal(SIGALRM, dummy);
  561. #endif
  562. #if OSK
  563.         signal(SIGQUIT, dummy);
  564. #endif
  565.         alarm((unsigned)*o_keytime);
  566.         i = nkeys;
  567.         if ((k = ttyread(keybuf + nkeys, sizeof keybuf - nkeys)) >= 0)
  568.         {
  569.             nkeys += k;
  570.         }
  571.         alarm(0);
  572. #if OSK
  573. # ifndef DEBUG
  574.         signal(SIGQUIT, SIG_IGN);
  575. # endif
  576. #endif
  577.  
  578.         /* if we couldn't read any more, pretend 0 mapped keys */
  579.         if (i == nkeys)
  580.         {
  581.             j = 0;
  582.         }
  583.         else /* else we got some more - try again */
  584.         {
  585.             for (i = j = 0, k = -1, km = mapped; i < MAXMAPS; i++, km++)
  586.             {
  587.                 if ((km->when & when) && km->len > 0 && *km->rawin == *kptr)
  588.                 {
  589.                     if (km->len > nkeys - next)
  590.                     {
  591.                         if (!strncmp(km->rawin, kptr, nkeys - next))
  592.                         {
  593.                             j++;
  594.                         }
  595.                     }
  596.                     else
  597.                     {
  598.                         if (!strncmp(km->rawin, kptr, km->len))
  599.                         {
  600.                             j++;
  601.                             k = i;
  602.                         }
  603.                     }
  604.                 }
  605.             }
  606.         }
  607.     }
  608.  
  609.     /* if unambiguously mapped key, use it! */
  610.     if (j == 1 && k >= 0)
  611.     {
  612.         next += mapped[k].len;
  613.         cooked = mapped[k].cooked;
  614. #ifndef NO_EXTENSIONS
  615.         if ((when & (WHEN_VIINP|WHEN_VIREP))
  616.          && (mapped[k].when & WHEN_INMV))
  617.         {
  618.             return 0; /* special case, means "a movement char follows" */
  619.         }
  620.         else
  621. #endif
  622.         {
  623.             return *cooked++;
  624.         }
  625.     }
  626.     else
  627.     /* assume key is unmapped, but still translate weird erase key to '\b' */
  628.     if (keybuf[next] == ERASEKEY && when != 0)
  629.     {
  630.         next++;
  631.         return '\b';
  632.     }
  633.     else if (keybuf[next] == '\0')
  634.     {
  635.         next++;
  636.         return ('A' & 0x1f);
  637.     }
  638.     else
  639.     {
  640.         return keybuf[next++];
  641.     }
  642. }
  643.  
  644.  
  645. /* This function maps or unmaps a key */
  646. void mapkey(rawin, cooked, when, name)
  647.     char    *rawin;    /* the input key sequence, before mapping */
  648.     char    *cooked;/* after mapping */
  649.     short    when;    /* bitmap of when mapping should happen */
  650.     char    *name;    /* name of the key, if any */
  651. {
  652.     int    i, j;
  653.  
  654. #ifndef NO_EXTENSIONS
  655.     /* if the mapped version starts with the word "visual" then set WHEN_INMV */
  656.     if (!strncmp(cooked, "visual ", 7))
  657.     {
  658.         when |= WHEN_INMV;
  659.         cooked += 7;
  660.     }
  661.     /* if WHEN_INMV is set, then WHEN_VIINP and WHEN_VIREP must be set */
  662.     if (when & WHEN_INMV)
  663.     {
  664.         when |= (WHEN_VIINP | WHEN_VIREP);
  665.     }
  666. #endif
  667.  
  668.     /* see if the key sequence was mapped before */
  669.     j = strlen(rawin);
  670.     for (i = 0; i < MAXMAPS; i++)
  671.     {
  672.         if (mapped[i].len == j
  673.          && !strncmp(mapped[i].rawin, rawin, j)
  674.          && (mapped[i].when & when))
  675.         {
  676.             break;
  677.         }
  678.     }
  679.  
  680.     /* if not already mapped, then try to find a new slot to use */
  681.     if (i == MAXMAPS)
  682.     {
  683.         for (i = 0; i < MAXMAPS && mapped[i].len > 0; i++)
  684.         {
  685.         }
  686.     }
  687.  
  688.     /* no room for the new key? */
  689.     if (i == MAXMAPS)
  690.     {
  691.         msg("No room left in the key map table");
  692.         return;
  693.     }
  694.  
  695.     /* map the key */
  696.     if (cooked && *cooked)
  697.     {
  698.         /* Map the key */
  699.         mapped[i].len = j;
  700.         strncpy(mapped[i].rawin, rawin, j);
  701.         strcpy(mapped[i].cooked, cooked);
  702.         mapped[i].when = when;
  703.         mapped[i].name = name;
  704.     }
  705.     else /* unmap the key */
  706.     {
  707.         mapped[i].len = 0;
  708.     }
  709. }
  710.  
  711. /* Dump keys of a given type - WHEN_VICMD dumps the ":map" keys, and
  712.  * WHEN_VIINP|WHEN_VIREP dumps the ":map!" keys
  713.  */
  714. void dumpkey(when)
  715.     int    when;    /* WHEN_XXXX of mappings to be dumped */
  716. {
  717.     int    i, len, mlen;
  718.     char    *scan;
  719.     char    *mraw;
  720.  
  721.     for (i = 0; i < MAXMAPS; i++)
  722.     {
  723.         /* skip unused entries, or entries that don't match "when" */
  724.         if (mapped[i].len <= 0 || !(mapped[i].when & when))
  725.         {
  726.             continue;
  727.         }
  728.  
  729.         /* dump the key label, if any */
  730.         len = 8;
  731.         if (mapped[i].name)
  732.         {
  733.             qaddstr(mapped[i].name);
  734.             len -= strlen(mapped[i].name);
  735.         }
  736.         do
  737.         {
  738.             qaddch(' ');
  739.         } while (len-- > 0);
  740.  
  741.         /* dump the raw version */
  742.         len = 0;
  743.         mlen = mapped[i].len;
  744.         mraw = mapped[i].rawin;
  745.         for (scan = mraw; scan < mraw + mlen; scan++)
  746.         {
  747.             if (UCHAR(*scan) < ' ' || *scan == '\177')
  748.             {
  749.                 qaddch('^');
  750.                 qaddch(*scan ^ '@');
  751.                 len += 2;
  752.             }
  753.             else
  754.             {
  755.                 qaddch(*scan);
  756.                 len++;
  757.             }
  758.         }
  759.         do
  760.         {
  761.             qaddch(' ');
  762.         } while (++len < 8);
  763.  
  764.         /* dump the mapped version */
  765. #ifndef NO_EXTENSIONS
  766.         if ((mapped[i].when & WHEN_INMV) && (when & (WHEN_VIINP|WHEN_VIREP)))
  767.         {
  768.             qaddstr("visual ");
  769.         }
  770. #endif
  771.         for (scan = mapped[i].cooked; *scan; scan++)
  772.         {
  773.             if (UCHAR(*scan) < ' ' || *scan == '\177')
  774.             {
  775.                 qaddch('^');
  776.                 qaddch(*scan ^ '@');
  777.             }
  778.             else
  779.             {
  780.                 qaddch(*scan);
  781.             }
  782.         }
  783.  
  784.         addch('\n');
  785.         exrefresh();
  786.     }
  787. }
  788.  
  789.  
  790.  
  791. #ifndef MKEXRC
  792. /* This function saves the current configuration of mapped keys to a file */
  793. void savekeys(fd)
  794.     int    fd;    /* file descriptor to save them to */
  795. {
  796.     int    i;
  797.     char    buf[80];
  798.  
  799.     /* now write a map command for each key other than the arrows */
  800.     for (i = 0; i < MAXMAPS; i++)
  801.     {
  802.         /* ignore keys that came from termcap */
  803.         if (mapped[i].name)
  804.         {
  805.             continue;
  806.         }
  807.  
  808.         /* If this isn't used, ignore it */
  809.         if (mapped[i].len <= 0)
  810.         {
  811.             continue;
  812.         }
  813.  
  814.         /* write the map command */
  815. #ifndef NO_EXTENSIONS
  816.         if (mapped[i].when & WHEN_INMV)
  817.         {
  818. #if OSK
  819.             char    fmt[80];
  820.             sprintf(fmt, "map%%s %%.%ds %%s\n", mapped[i].len);
  821.             sprintf(buf, fmt,
  822.                 (mapped[i].when & WHEN_VICMD) ? "" : "!",
  823. #else
  824.             sprintf(buf, "map%s %.*s visual %s\n",
  825.                 (mapped[i].when & WHEN_VICMD) ? "" : "!",
  826.                 mapped[i].len,
  827. #endif
  828.                 mapped[i].rawin,
  829.                 mapped[i].cooked);
  830.             twrite(fd, buf, strlen(buf));
  831.         }
  832.         else
  833. #endif
  834.         {
  835.             if (mapped[i].when & WHEN_VICMD)
  836.             {
  837. #if OSK
  838.                 char    fmt[80];
  839.                 sprintf(fmt, "map %%.%ds %%s\n", mapped[i].len);
  840.                 sprintf(buf, fmt,
  841. #else
  842.                 sprintf(buf, "map %.*s %s\n", mapped[i].len,
  843. #endif
  844.                     mapped[i].rawin,
  845.                     mapped[i].cooked);
  846.                 twrite(fd, buf, strlen(buf));
  847.             }
  848.             if (mapped[i].when & (WHEN_VIINP | WHEN_VIREP))
  849.             {
  850. #if OSK
  851.                 char    fmt[80];
  852.                 sprintf(fmt, "map! %%.%ds %%s\n", mapped[i].len);
  853.                 sprintf(buf, fmt,
  854. #else
  855.                 sprintf(buf, "map! %.*s %s\n", mapped[i].len,
  856. #endif
  857.                     mapped[i].rawin,
  858.                     mapped[i].cooked);
  859.                 twrite(fd, buf, strlen(buf));
  860.             }
  861.         }
  862.     }
  863. }
  864. #endif
  865.