|
|
1.1 ! root 1: /* tio.c */ ! 2: ! 3: /* Author: ! 4: * Steve Kirkendall ! 5: * 16820 SW Tallac Way ! 6: * Beaverton, OR 97006 ! 7: * [email protected], or ...uunet!tektronix!psueea!jove!kirkenda ! 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.