|
|
1.1 ! root 1: /* input.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 the input() function, which implements vi's INPUT mode. ! 12: * It also contains the code that supports digraphs. ! 13: */ ! 14: ! 15: #include <ctype.h> ! 16: #include "config.h" ! 17: #include "vi.h" ! 18: ! 19: ! 20: #ifndef NO_DIGRAPH ! 21: static struct _DIG ! 22: { ! 23: struct _DIG *next; ! 24: char key1; ! 25: char key2; ! 26: char dig; ! 27: char save; ! 28: } *digs; ! 29: ! 30: char digraph(key1, key2) ! 31: char key1; /* the underlying character */ ! 32: char key2; /* the second character */ ! 33: { ! 34: int newkey; ! 35: REG struct _DIG *dp; ! 36: ! 37: /* if digraphs are disabled, then just return the new char */ ! 38: if (!*o_digraph) ! 39: { ! 40: return key2; ! 41: } ! 42: ! 43: /* remember the new key, so we can return it if this isn't a digraph */ ! 44: newkey = key2; ! 45: ! 46: /* sort key1 and key2, so that their original order won't matter */ ! 47: if (key1 > key2) ! 48: { ! 49: key2 = key1; ! 50: key1 = newkey; ! 51: } ! 52: ! 53: /* scan through the digraph chart */ ! 54: for (dp = digs; ! 55: dp && (dp->key1 != key1 || dp->key2 != key2); ! 56: dp = dp->next) ! 57: { ! 58: } ! 59: ! 60: /* if this combination isn't in there, just use the new key */ ! 61: if (!dp) ! 62: { ! 63: return newkey; ! 64: } ! 65: ! 66: /* else use the digraph key */ ! 67: return dp->dig; ! 68: } ! 69: ! 70: /* this function lists or defines digraphs */ ! 71: void do_digraph(bang, extra) ! 72: int bang; ! 73: char extra[]; ! 74: { ! 75: int dig; ! 76: REG struct _DIG *dp; ! 77: struct _DIG *prev; ! 78: static int user_defined = FALSE; /* boolean: are all later digraphs user-defined? */ ! 79: ! 80: /* if "extra" is NULL, then we've reached the end of the built-ins */ ! 81: if (!extra) ! 82: { ! 83: user_defined = TRUE; ! 84: return; ! 85: } ! 86: ! 87: /* if no args, then display the existing digraphs */ ! 88: if (*extra < ' ') ! 89: { ! 90: for (dp = digs; dp; dp = dp->next) ! 91: { ! 92: if (dp->save || bang) ! 93: { ! 94: addstr("digraph "); ! 95: addch(dp->key1); ! 96: addch(dp->key2); ! 97: addch(' '); ! 98: addch(dp->dig); ! 99: addch('\n'); ! 100: exrefresh(); ! 101: } ! 102: } ! 103: return; ! 104: } ! 105: ! 106: /* make sure we have at least two characters */ ! 107: if (!extra[1]) ! 108: { ! 109: msg("Digraphs must be composed of two characters"); ! 110: return; ! 111: } ! 112: ! 113: /* sort key1 and key2, so that their original order won't matter */ ! 114: if (extra[0] > extra[1]) ! 115: { ! 116: dig = extra[0]; ! 117: extra[0] = extra[1]; ! 118: extra[1] = dig; ! 119: } ! 120: ! 121: /* locate the new digraph character */ ! 122: for (dig = 2; extra[dig] == ' ' || extra[dig] == '\t'; dig++) ! 123: { ! 124: } ! 125: dig = extra[dig]; ! 126: if (!bang && dig) ! 127: { ! 128: dig |= 0x80; ! 129: } ! 130: ! 131: /* search for the digraph */ ! 132: for (prev = (struct _DIG *)0, dp = digs; ! 133: dp && (dp->key1 != extra[0] || dp->key2 != extra[1]); ! 134: prev = dp, dp = dp->next) ! 135: { ! 136: } ! 137: ! 138: /* deleting the digraph? */ ! 139: if (!dig) ! 140: { ! 141: if (!dp) ! 142: { ! 143: #ifndef CRUNCH ! 144: msg("%c%c not a digraph", extra[0], extra[1]); ! 145: #endif ! 146: return; ! 147: } ! 148: if (prev) ! 149: prev->next = dp->next; ! 150: else ! 151: digs = dp->next; ! 152: free(dp); ! 153: return; ! 154: } ! 155: ! 156: /* if necessary, create a new digraph struct for the new digraph */ ! 157: if (dig && !dp) ! 158: { ! 159: dp = (struct _DIG *)malloc(sizeof *dp); ! 160: if (!dp) ! 161: { ! 162: msg("Out of space in the digraph table"); ! 163: return; ! 164: } ! 165: if (prev) ! 166: prev->next = dp; ! 167: else ! 168: digs = dp; ! 169: dp->next = (struct _DIG *)0; ! 170: } ! 171: ! 172: /* assign it the new digraph value */ ! 173: dp->key1 = extra[0]; ! 174: dp->key2 = extra[1]; ! 175: dp->dig = dig; ! 176: dp->save = user_defined; ! 177: } ! 178: ! 179: # ifndef NO_MKEXRC ! 180: void savedigs(fd) ! 181: int fd; ! 182: { ! 183: static char buf[] = "digraph! XX Y\n"; ! 184: REG struct _DIG *dp; ! 185: ! 186: for (dp = digs; dp; dp = dp->next) ! 187: { ! 188: if (dp->save) ! 189: { ! 190: buf[9] = dp->key1; ! 191: buf[10] = dp->key2; ! 192: buf[12] = dp->dig; ! 193: write(fd, buf, (unsigned)14); ! 194: } ! 195: } ! 196: } ! 197: # endif ! 198: #endif ! 199: ! 200: ! 201: #ifndef NO_ABBR ! 202: static struct _AB ! 203: { ! 204: struct _AB *next; ! 205: char *large; /* the expanded form */ ! 206: char small[1]; /* the abbreviated form (appended to struct) */ ! 207: } ! 208: *abbrev; ! 209: ! 210: /* This functions lists or defines abbreviations */ ! 211: void do_abbr(extra) ! 212: char *extra; ! 213: { ! 214: int smlen; /* length of the small form */ ! 215: int lrg; /* index of the start of the large form */ ! 216: REG struct _AB *ab; /* used to move through the abbrev list */ ! 217: struct _AB *prev; ! 218: ! 219: /* no arguments? */ ! 220: if (!*extra) ! 221: { ! 222: /* list all current abbreviations */ ! 223: for (ab = abbrev; ab; ab = ab->next) ! 224: { ! 225: qaddstr("abbr "); ! 226: qaddstr(ab->small); ! 227: qaddch(' '); ! 228: qaddstr(ab->large); ! 229: addch('\n'); ! 230: exrefresh(); ! 231: } ! 232: return; ! 233: } ! 234: ! 235: /* else one or more arguments. Parse the first & look up in abbrev[] */ ! 236: for (smlen = 0; extra[smlen] && isalnum(extra[smlen]); smlen++) ! 237: { ! 238: } ! 239: for (prev = (struct _AB *)0, ab = abbrev; ab; prev = ab, ab = ab->next) ! 240: { ! 241: if (!strncmp(extra, ab->small, smlen) && !ab->small[smlen]) ! 242: { ! 243: break; ! 244: } ! 245: } ! 246: ! 247: /* locate the start of the large form, if any */ ! 248: for (lrg = smlen; extra[lrg] && isascii(extra[lrg]) && isspace(extra[lrg]); lrg++) ! 249: { ! 250: } ! 251: ! 252: /* only one arg? */ ! 253: if (!extra[lrg]) ! 254: { ! 255: /* trying to undo an abbreviation which doesn't exist? */ ! 256: if (!ab) ! 257: { ! 258: #ifndef CRUNCH ! 259: msg("\"%s\" not an abbreviation", extra); ! 260: #endif ! 261: return; ! 262: } ! 263: ! 264: /* undo the abbreviation */ ! 265: if (prev) ! 266: prev->next = ab->next; ! 267: else ! 268: abbrev = ab->next; ! 269: free(ab->large); ! 270: free(ab); ! 271: ! 272: return; ! 273: } ! 274: ! 275: /* multiple args - [re]define an abbreviation */ ! 276: if (ab) ! 277: { ! 278: /* redefining - free the old large form */ ! 279: free(ab->large); ! 280: } ! 281: else ! 282: { ! 283: /* adding a new definition - make a new struct */ ! 284: ab = (struct _AB *)malloc((unsigned)(smlen + sizeof *ab)); ! 285: #ifndef CRUNCH ! 286: if (!ab) ! 287: { ! 288: msg("Out of memory -- Sorry"); ! 289: return; ! 290: } ! 291: #endif ! 292: strncpy(ab->small, extra, smlen); ! 293: ab->small[smlen] = '\0'; ! 294: ab->next = (struct _AB *)0; ! 295: if (prev) ! 296: prev->next = ab; ! 297: else ! 298: abbrev = ab; ! 299: } ! 300: ! 301: /* store the new form */ ! 302: ab->large = (char *)malloc((unsigned)(strlen(&extra[lrg]) + 1)); ! 303: strcpy(ab->large, &extra[lrg]); ! 304: } ! 305: ! 306: ! 307: # ifndef NO_MKEXRC ! 308: /* This function is called from cmd_mkexrc() to save the abbreviations */ ! 309: void saveabbr(fd) ! 310: int fd; /* fd to which the :abbr commands should be written */ ! 311: { ! 312: REG struct _AB *ab; ! 313: ! 314: for (ab = abbrev; ab; ab = ab->next) ! 315: { ! 316: twrite(fd, "abbr ", 5); ! 317: twrite(fd, ab->small, strlen(ab->small)); ! 318: twrite(fd, " ", 1); ! 319: twrite(fd, ab->large, strlen(ab->large)); ! 320: twrite(fd, "\n", 1); ! 321: } ! 322: } ! 323: # endif ! 324: ! 325: /* This function should be called before each char is inserted. If the next ! 326: * char is non-alphanumeric and we're at the end of a word, then that word ! 327: * is checked against the abbrev[] array and expanded, if appropriate. Upon ! 328: * returning from this function, the new char still must be inserted. ! 329: */ ! 330: static MARK expandabbr(m, ch) ! 331: MARK m; /* the cursor position */ ! 332: int ch; /* the character to insert */ ! 333: { ! 334: char *word; /* where the word starts */ ! 335: int len; /* length of the word */ ! 336: REG struct _AB *ab; ! 337: ! 338: /* if no abbreviations are in effect, or ch is aphanumeric, then ! 339: * don't do anything ! 340: */ ! 341: if (!abbrev || !isascii(ch) || isalnum(ch)) ! 342: { ! 343: return m; ! 344: } ! 345: ! 346: /* see where the preceding word starts */ ! 347: pfetch(markline(m)); ! 348: for (word = ptext + markidx(m), len = 0; ! 349: --word >= ptext && (!isascii(*word) || isalnum(*word)); ! 350: len++) ! 351: { ! 352: } ! 353: word++; ! 354: ! 355: /* if zero-length, then it isn't a word, really -- so nothing */ ! 356: if (len == 0) ! 357: { ! 358: return m; ! 359: } ! 360: ! 361: /* look it up in the abbrev list */ ! 362: for (ab = abbrev; ab; ab = ab->next) ! 363: { ! 364: if (!strncmp(ab->small, word, len) && !ab->small[len]) ! 365: { ! 366: break; ! 367: } ! 368: } ! 369: ! 370: /* not an abbreviation? then do nothing */ ! 371: if (!ab) ! 372: { ! 373: return m; ! 374: } ! 375: ! 376: /* else replace the small form with the large form */ ! 377: add(m, ab->large); ! 378: delete(m - len, m); ! 379: ! 380: /* return with the cursor after the end of the large form */ ! 381: return m - len + strlen(ab->large); ! 382: } ! 383: #endif ! 384: ! 385: ! 386: /* This function allows the user to replace an existing (possibly zero-length) ! 387: * chunk of text with typed-in text. It returns the MARK of the last character ! 388: * that the user typed in. ! 389: */ ! 390: MARK input(from, to, when) ! 391: MARK from; /* where to start inserting text */ ! 392: MARK to; /* extent of text to delete */ ! 393: int when; /* either WHEN_VIINP or WHEN_VIREP */ ! 394: { ! 395: char key[2]; /* key char followed by '\0' char */ ! 396: char *build; /* used in building a newline+indent string */ ! 397: char *scan; /* used while looking at the indent chars of a line */ ! 398: MARK m; /* some place in the text */ ! 399: #ifndef NO_EXTENSIONS ! 400: int quit = FALSE; /* boolean: are we exiting after this? */ ! 401: #endif ! 402: ! 403: #ifdef DEBUG ! 404: /* if "from" and "to" are reversed, complain */ ! 405: if (from > to) ! 406: { ! 407: msg("ERROR: input(%ld:%d, %ld:%d)", ! 408: markline(from), markidx(from), ! 409: markline(to), markidx(to)); ! 410: return MARK_UNSET; ! 411: } ! 412: #endif ! 413: ! 414: key[1] = 0; ! 415: ! 416: /* if we're replacing text with new text, save the old stuff */ ! 417: /* (Alas, there is no easy way to save text for replace mode) */ ! 418: if (from != to) ! 419: { ! 420: cut(from, to); ! 421: } ! 422: ! 423: ChangeText ! 424: { ! 425: /* if doing a dot command, then reuse the previous text */ ! 426: if (doingdot) ! 427: { ! 428: /* delete the text that's there now */ ! 429: if (from != to) ! 430: { ! 431: delete(from, to); ! 432: } ! 433: ! 434: /* insert the previous text */ ! 435: cutname('.'); ! 436: cursor = paste(from, FALSE, TRUE) + 1L; ! 437: } ! 438: else /* interactive version */ ! 439: { ! 440: /* if doing a change within the line... */ ! 441: if (from != to && markline(from) == markline(to)) ! 442: { ! 443: /* mark the end of the text with a "$" */ ! 444: change(to - 1, to, "$"); ! 445: } ! 446: else ! 447: { ! 448: /* delete the old text right off */ ! 449: if (from != to) ! 450: { ! 451: delete(from, to); ! 452: } ! 453: to = from; ! 454: } ! 455: ! 456: /* handle autoindent of the first line, maybe */ ! 457: cursor = from; ! 458: if (*o_autoindent && markline(cursor) > 1L && markidx(cursor) == 0) ! 459: { ! 460: /* Only autoindent blank lines. */ ! 461: pfetch(markline(cursor)); ! 462: if (plen == 0) ! 463: { ! 464: /* Okay, we really want to autoindent */ ! 465: pfetch(markline(cursor) - 1L); ! 466: for (scan = ptext, build = tmpblk.c; ! 467: *scan == ' ' || *scan == '\t'; ! 468: ) ! 469: { ! 470: *build++ = *scan++; ! 471: } ! 472: if (build > tmpblk.c) ! 473: { ! 474: *build = '\0'; ! 475: add(cursor, tmpblk.c); ! 476: cursor += (build - tmpblk.c); ! 477: } ! 478: } ! 479: } ! 480: ! 481: /* repeatedly add characters from the user */ ! 482: for (;;) ! 483: { ! 484: /* Get a character */ ! 485: redraw(cursor, TRUE); ! 486: #ifdef DEBUG ! 487: msg("cursor=%ld.%d, to=%ld.%d", ! 488: markline(cursor), markidx(cursor), ! 489: markline(to), markidx(to)); ! 490: #endif ! 491: key[0] = getkey(when); ! 492: ! 493: /* if whitespace & wrapmargin is set & we're ! 494: * past the warpmargin, then change the ! 495: * whitespace character into a newline ! 496: */ ! 497: if ((*key == ' ' || *key == '\t') ! 498: && *o_wrapmargin != 0) ! 499: { ! 500: pfetch(markline(cursor)); ! 501: if (idx2col(cursor, ptext, TRUE) > COLS - (*o_wrapmargin & 0xff)) ! 502: { ! 503: *key = '\n'; ! 504: } ! 505: } ! 506: ! 507: /* process it */ ! 508: switch (*key) ! 509: { ! 510: #ifndef NO_EXTENSIONS ! 511: case 0: /* special movement mapped keys */ ! 512: *key = getkey(0); ! 513: switch (*key) ! 514: { ! 515: case 'h': m = m_left(cursor, 0L); break; ! 516: case 'j': ! 517: case 'k': m = m_updnto(cursor, 0L, *key); break; ! 518: case 'l': m = cursor + 1; break; ! 519: case 'b': m = m_bword(cursor, 0L); break; ! 520: case 'w': m = m_fword(cursor, 0L); break; ! 521: case '^': m = m_front(cursor, 0L); break; ! 522: case '$': m = m_rear(cursor, 0L); break; ! 523: case ctrl('B'): ! 524: case ctrl('F'): ! 525: m = m_scroll(cursor, 0L, *key); break; ! 526: case 'x': m = v_xchar(cursor, 0L); break; ! 527: case 'i': m = to = from = cursor; break; ! 528: default: m = MARK_UNSET; break; ! 529: } ! 530: /* adjust the moved cursor */ ! 531: m = adjmove(cursor, m, (*key == 'j' || *key == 'k' ? 0x20 : 0)); ! 532: if (*key == '$' || (*key == 'l' && m <= cursor)) ! 533: { ! 534: m++; ! 535: } ! 536: /* if the cursor is reasonable, use it */ ! 537: if (m == MARK_UNSET) ! 538: { ! 539: beep(); ! 540: } ! 541: else ! 542: { ! 543: if (to > cursor) ! 544: { ! 545: delete(cursor, to); ! 546: redraw(cursor, TRUE); ! 547: } ! 548: from = to = cursor = m; ! 549: } ! 550: break; ! 551: ! 552: case ctrl('Z'): ! 553: if (getkey(0) == ctrl('Z')) ! 554: { ! 555: quit = TRUE; ! 556: goto BreakBreak; ! 557: } ! 558: break; ! 559: #endif ! 560: ! 561: case ctrl('['): ! 562: #ifndef NO_ABBR ! 563: cursor = expandabbr(cursor, ctrl('[')); ! 564: #endif ! 565: goto BreakBreak; ! 566: ! 567: case ctrl('U'): ! 568: if (markline(cursor) == markline(from)) ! 569: { ! 570: cursor = from; ! 571: } ! 572: else ! 573: { ! 574: cursor &= ~(BLKSIZE - 1); ! 575: } ! 576: break; ! 577: ! 578: case ctrl('D'): ! 579: case ctrl('T'): ! 580: if (to > cursor) ! 581: { ! 582: delete(cursor, to); ! 583: } ! 584: mark[27] = cursor; ! 585: cmd_shift(cursor, cursor, *key == ctrl('D') ? CMD_SHIFTL : CMD_SHIFTR, TRUE, ""); ! 586: if (mark[27]) ! 587: { ! 588: cursor = mark[27]; ! 589: } ! 590: else ! 591: { ! 592: cursor = m_front(cursor, 0L); ! 593: } ! 594: to = cursor; ! 595: break; ! 596: ! 597: case '\b': ! 598: if (cursor <= from) ! 599: { ! 600: beep(); ! 601: } ! 602: else if (markidx(cursor) == 0) ! 603: { ! 604: cursor -= BLKSIZE; ! 605: pfetch(markline(cursor)); ! 606: cursor += plen; ! 607: } ! 608: else ! 609: { ! 610: cursor--; ! 611: } ! 612: break; ! 613: ! 614: case ctrl('W'): ! 615: m = m_bword(cursor, 1L); ! 616: if (markline(m) == markline(cursor) && m >= from) ! 617: { ! 618: cursor = m; ! 619: if (from > cursor) ! 620: { ! 621: from = cursor; ! 622: } ! 623: } ! 624: else ! 625: { ! 626: beep(); ! 627: } ! 628: break; ! 629: ! 630: case '\n': ! 631: #if OSK ! 632: case '\l': ! 633: #else ! 634: case '\r': ! 635: #endif ! 636: #ifndef NO_ABBR ! 637: cursor = expandabbr(cursor, '\n'); ! 638: #endif ! 639: build = tmpblk.c; ! 640: *build++ = '\n'; ! 641: if (*o_autoindent) ! 642: { ! 643: /* figure out indent for next line */ ! 644: pfetch(markline(cursor)); ! 645: for (scan = ptext; *scan == ' ' || *scan == '\t'; ) ! 646: { ! 647: *build++ = *scan++; ! 648: } ! 649: ! 650: /* remove indent from this line, if blank */ ! 651: if (!*scan && plen > 0) ! 652: { ! 653: to = cursor &= ~(BLKSIZE - 1); ! 654: delete(cursor, cursor + plen); ! 655: } ! 656: } ! 657: *build = 0; ! 658: if (cursor >= to && when != WHEN_VIREP) ! 659: { ! 660: add(cursor, tmpblk.c); ! 661: } ! 662: else ! 663: { ! 664: change(cursor, to, tmpblk.c); ! 665: } ! 666: redraw(cursor, TRUE); ! 667: to = cursor = (cursor & ~(BLKSIZE - 1)) ! 668: + BLKSIZE ! 669: + (int)(build - tmpblk.c) - 1; ! 670: break; ! 671: ! 672: case ctrl('A'): ! 673: case ctrl('P'): ! 674: if (cursor < to) ! 675: { ! 676: delete(cursor, to); ! 677: } ! 678: if (*key == ctrl('A')) ! 679: { ! 680: cutname('.'); ! 681: } ! 682: to = cursor = paste(cursor, FALSE, TRUE) + 1L; ! 683: break; ! 684: ! 685: case ctrl('V'): ! 686: if (cursor >= to && when != WHEN_VIREP) ! 687: { ! 688: add(cursor, "^"); ! 689: } ! 690: else ! 691: { ! 692: change(cursor, to, "^"); ! 693: to = cursor + 1; ! 694: } ! 695: redraw(cursor, TRUE); ! 696: *key = getkey(0); ! 697: if (*key == '\n') ! 698: { ! 699: /* '\n' too hard to handle */ ! 700: #if OSK ! 701: *key = '\l'; ! 702: #else ! 703: *key = '\r'; ! 704: #endif ! 705: } ! 706: change(cursor, cursor + 1, key); ! 707: cursor++; ! 708: if (cursor > to) ! 709: { ! 710: to = cursor; ! 711: } ! 712: break; ! 713: ! 714: case ctrl('L'): ! 715: case ctrl('R'): ! 716: redraw(MARK_UNSET, FALSE); ! 717: break; ! 718: ! 719: default: ! 720: if (cursor >= to && when != WHEN_VIREP) ! 721: { ! 722: #ifndef NO_ABBR ! 723: cursor = expandabbr(cursor, *key); ! 724: #endif ! 725: add(cursor, key); ! 726: cursor++; ! 727: to = cursor; ! 728: } ! 729: else ! 730: { ! 731: pfetch(markline(cursor)); ! 732: if (markidx(cursor) == plen) ! 733: { ! 734: #ifndef NO_ABBR ! 735: cursor = expandabbr(cursor, *key); ! 736: #endif ! 737: add(cursor, key); ! 738: } ! 739: else ! 740: { ! 741: #ifndef NO_DIGRAPH ! 742: *key = digraph(ptext[markidx(cursor)], *key); ! 743: #endif ! 744: #ifndef NO_ABBR ! 745: cursor = expandabbr(cursor, *key); ! 746: #endif ! 747: change(cursor, cursor + 1, key); ! 748: } ! 749: cursor++; ! 750: } ! 751: #ifndef NO_SHOWMATCH ! 752: /* show matching "({[" if neceesary */ ! 753: if (*o_showmatch && strchr(")}]", *key)) ! 754: { ! 755: m = m_match(cursor - 1, 0L); ! 756: if (markline(m) >= topline ! 757: && markline(m) <= botline) ! 758: { ! 759: redraw(m, TRUE); ! 760: refresh(); ! 761: sleep(1); ! 762: } ! 763: } ! 764: #endif ! 765: } /* end switch(*key) */ ! 766: } /* end for(;;) */ ! 767: BreakBreak:; ! 768: ! 769: /* delete any excess characters */ ! 770: if (cursor < to) ! 771: { ! 772: delete(cursor, to); ! 773: } ! 774: ! 775: } /* end if doingdot else */ ! 776: ! 777: } /* end ChangeText */ ! 778: ! 779: /* put the new text into a cut buffer for possible reuse */ ! 780: if (!doingdot) ! 781: { ! 782: blksync(); ! 783: cutname('.'); ! 784: cut(from, cursor); ! 785: } ! 786: ! 787: /* move to last char that we inputted, unless it was newline */ ! 788: if (markidx(cursor) != 0) ! 789: { ! 790: cursor--; ! 791: } ! 792: redraw(cursor, FALSE); ! 793: ! 794: #ifndef NO_EXTENSIONS ! 795: if (quit) ! 796: { ! 797: refresh(); ! 798: cursor = v_xit(cursor, 0L, 'Z'); ! 799: } ! 800: #endif ! 801: ! 802: rptlines = 0L; ! 803: return cursor; ! 804: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.