|
|
1.1 ! root 1: /* cmd2.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 some of the commands - mostly ones that change text */ ! 12: ! 13: #include <ctype.h> ! 14: #include "config.h" ! 15: #include "vi.h" ! 16: #include "regexp.h" ! 17: #if TOS ! 18: # include <stat.h> ! 19: #else ! 20: # if OSK ! 21: # include "osk.h" ! 22: # else ! 23: # include <sys/stat.h> ! 24: # endif ! 25: #endif ! 26: ! 27: ! 28: /*ARGSUSED*/ ! 29: void cmd_substitute(frommark, tomark, cmd, bang, extra) ! 30: MARK frommark; ! 31: MARK tomark; ! 32: CMD cmd; ! 33: int bang; ! 34: char *extra; /* rest of the command line */ ! 35: { ! 36: char *line; /* a line from the file */ ! 37: regexp *re; /* the compiled search expression */ ! 38: char *subst; /* the substitution string */ ! 39: char *opt; /* substitution options */ ! 40: long l; /* a line number */ ! 41: char *s, *d; /* used during subtitutions */ ! 42: char *conf; /* used during confirmation */ ! 43: long chline; /* # of lines changed */ ! 44: long chsub; /* # of substitutions made */ ! 45: static optp; /* boolean option: print when done? */ ! 46: static optg; /* boolean option: substitute globally in line? */ ! 47: static optc; /* boolean option: confirm before subst? */ ! 48: ! 49: ! 50: /* for now, assume this will fail */ ! 51: rptlines = -1L; ! 52: ! 53: if (cmd == CMD_SUBAGAIN) ! 54: { ! 55: #ifndef NO_MAGIC ! 56: if (*o_magic) ! 57: subst = "~"; ! 58: else ! 59: #endif ! 60: subst = "\\~"; ! 61: re = regcomp(""); ! 62: ! 63: /* if visual "&", then turn off the "p" and "c" options */ ! 64: if (bang) ! 65: { ! 66: optp = optc = FALSE; ! 67: } ! 68: } ! 69: else ! 70: { ! 71: /* make sure we got a search pattern */ ! 72: if (*extra != '/' && *extra != '?') ! 73: { ! 74: msg("Usage: s/regular expression/new text/"); ! 75: return; ! 76: } ! 77: ! 78: /* parse & compile the search pattern */ ! 79: subst = parseptrn(extra); ! 80: re = regcomp(extra + 1); ! 81: } ! 82: ! 83: /* abort if RE error -- error message already given by regcomp() */ ! 84: if (!re) ! 85: { ! 86: return; ! 87: } ! 88: ! 89: if (cmd == CMD_SUBSTITUTE) ! 90: { ! 91: /* parse the substitution string & find the option string */ ! 92: for (opt = subst; *opt && *opt != *extra; opt++) ! 93: { ! 94: if (*opt == '\\' && opt[1]) ! 95: { ! 96: opt++; ! 97: } ! 98: } ! 99: if (*opt) ! 100: { ! 101: *opt++ = '\0'; ! 102: } ! 103: ! 104: /* analyse the option string */ ! 105: if (!*o_edcompatible) ! 106: { ! 107: optp = optg = optc = FALSE; ! 108: } ! 109: while (*opt) ! 110: { ! 111: switch (*opt++) ! 112: { ! 113: case 'p': optp = !optp; break; ! 114: case 'g': optg = !optg; break; ! 115: case 'c': optc = !optc; break; ! 116: case ' ': ! 117: case '\t': break; ! 118: default: ! 119: msg("Subst options are p, c, and g -- not %c", opt[-1]); ! 120: return; ! 121: } ! 122: } ! 123: } ! 124: ! 125: /* if "c" or "p" flag was given, and we're in visual mode, then NEWLINE */ ! 126: if ((optc || optp) && mode == MODE_VI) ! 127: { ! 128: addch('\n'); ! 129: exrefresh(); ! 130: } ! 131: ! 132: ChangeText ! 133: { ! 134: /* reset the change counters */ ! 135: chline = chsub = 0L; ! 136: ! 137: /* for each selected line */ ! 138: for (l = markline(frommark); l <= markline(tomark); l++) ! 139: { ! 140: /* fetch the line */ ! 141: line = fetchline(l); ! 142: ! 143: /* if it contains the search pattern... */ ! 144: if (regexec(re, line, TRUE)) ! 145: { ! 146: /* increment the line change counter */ ! 147: chline++; ! 148: ! 149: /* initialize the pointers */ ! 150: s = line; ! 151: d = tmpblk.c; ! 152: ! 153: /* do once or globally ... */ ! 154: do ! 155: { ! 156: #ifndef CRUNCH ! 157: /* confirm, if necessary */ ! 158: if (optc) ! 159: { ! 160: for (conf = line; conf < re->startp[0]; conf++) ! 161: addch(*conf); ! 162: standout(); ! 163: for ( ; conf < re->endp[0]; conf++) ! 164: addch(*conf); ! 165: standend(); ! 166: for (; *conf; conf++) ! 167: addch(*conf); ! 168: addch('\n'); ! 169: exrefresh(); ! 170: if (getkey(0) != 'y') ! 171: { ! 172: /* copy accross the original chars */ ! 173: while (s < re->endp[0]) ! 174: *d++ = *s++; ! 175: ! 176: /* skip to next match on this line, if any */ ! 177: continue; ! 178: } ! 179: } ! 180: #endif /* not CRUNCH */ ! 181: ! 182: /* increment the substitution change counter */ ! 183: chsub++; ! 184: ! 185: /* this may be the first line to redraw */ ! 186: redrawrange(l, l + 1L, l + 1L); ! 187: ! 188: /* copy stuff from before the match */ ! 189: while (s < re->startp[0]) ! 190: { ! 191: *d++ = *s++; ! 192: } ! 193: ! 194: /* substitute for the matched part */ ! 195: regsub(re, subst, d); ! 196: s = re->endp[0]; ! 197: d += strlen(d); ! 198: ! 199: } while (optg && regexec(re, s, FALSE)); ! 200: ! 201: /* copy stuff from after the match */ ! 202: while (*d++ = *s++) /* yes, ASSIGNMENT! */ ! 203: { ! 204: } ! 205: ! 206: /* replace the old version of the line with the new */ ! 207: d[-1] = '\n'; ! 208: d[0] = '\0'; ! 209: change(MARK_AT_LINE(l), MARK_AT_LINE(l + 1), tmpblk.c); ! 210: ! 211: /* if supposed to print it, do so */ ! 212: if (optp) ! 213: { ! 214: addstr(tmpblk.c); ! 215: exrefresh(); ! 216: } ! 217: ! 218: /* move the cursor to that line */ ! 219: cursor = MARK_AT_LINE(l); ! 220: } ! 221: } ! 222: } ! 223: ! 224: /* tweak for redrawing */ ! 225: mustredraw = TRUE; ! 226: ! 227: /* free the regexp */ ! 228: free(re); ! 229: ! 230: /* if done from within a ":g" command, then finish silently */ ! 231: if (doingglobal) ! 232: { ! 233: rptlines = chline; ! 234: rptlabel = "changed"; ! 235: return; ! 236: } ! 237: ! 238: /* Reporting */ ! 239: if (chsub == 0) ! 240: { ! 241: msg("Substitution failed"); ! 242: } ! 243: else if (chline >= *o_report) ! 244: { ! 245: msg("%ld substitutions on %ld lines", chsub, chline); ! 246: } ! 247: } ! 248: ! 249: ! 250: ! 251: ! 252: /*ARGSUSED*/ ! 253: void cmd_delete(frommark, tomark, cmd, bang, extra) ! 254: MARK frommark; ! 255: MARK tomark; ! 256: CMD cmd; ! 257: int bang; ! 258: char *extra; ! 259: { ! 260: MARK curs2; /* an altered form of the cursor */ ! 261: ! 262: /* choose your cut buffer */ ! 263: if (*extra == '"') ! 264: { ! 265: extra++; ! 266: } ! 267: if (*extra) ! 268: { ! 269: cutname(*extra); ! 270: } ! 271: ! 272: /* make sure we're talking about whole lines here */ ! 273: frommark = frommark & ~(BLKSIZE - 1); ! 274: tomark = (tomark & ~(BLKSIZE - 1)) + BLKSIZE; ! 275: ! 276: /* yank the lines */ ! 277: cut(frommark, tomark); ! 278: ! 279: /* if CMD_DELETE then delete the lines */ ! 280: if (cmd != CMD_YANK) ! 281: { ! 282: curs2 = cursor; ! 283: ChangeText ! 284: { ! 285: /* delete the lines */ ! 286: delete(frommark, tomark); ! 287: } ! 288: if (curs2 > tomark) ! 289: { ! 290: cursor = curs2 - tomark + frommark; ! 291: } ! 292: else if (curs2 > frommark) ! 293: { ! 294: cursor = frommark; ! 295: } ! 296: } ! 297: } ! 298: ! 299: ! 300: /*ARGSUSED*/ ! 301: void cmd_append(frommark, tomark, cmd, bang, extra) ! 302: MARK frommark; ! 303: MARK tomark; ! 304: CMD cmd; ! 305: int bang; ! 306: char *extra; ! 307: { ! 308: long l; /* line counter */ ! 309: ! 310: ChangeText ! 311: { ! 312: /* if we're doing a change, delete the old version */ ! 313: if (cmd == CMD_CHANGE) ! 314: { ! 315: /* delete 'em */ ! 316: cmd_delete(frommark, tomark, cmd, bang, extra); ! 317: } ! 318: ! 319: /* new lines start at the frommark line, or after it */ ! 320: l = markline(frommark); ! 321: if (cmd == CMD_APPEND) ! 322: { ! 323: l++; ! 324: } ! 325: ! 326: /* get lines until no more lines, or "." line, and insert them */ ! 327: while (vgets('\0', tmpblk.c, BLKSIZE) >= 0) ! 328: { ! 329: addch('\n'); ! 330: if (!strcmp(tmpblk.c, ".")) ! 331: { ! 332: break; ! 333: } ! 334: ! 335: strcat(tmpblk.c, "\n"); ! 336: add(MARK_AT_LINE(l), tmpblk.c); ! 337: l++; ! 338: } ! 339: } ! 340: ! 341: /* on the odd chance that we're calling this from vi mode ... */ ! 342: redraw(MARK_UNSET, FALSE); ! 343: } ! 344: ! 345: ! 346: /*ARGSUSED*/ ! 347: void cmd_put(frommark, tomark, cmd, bang, extra) ! 348: MARK frommark; ! 349: MARK tomark; ! 350: CMD cmd; ! 351: int bang; ! 352: char *extra; ! 353: { ! 354: /* choose your cut buffer */ ! 355: if (*extra == '"') ! 356: { ! 357: extra++; ! 358: } ! 359: if (*extra) ! 360: { ! 361: cutname(*extra); ! 362: } ! 363: ! 364: /* paste it */ ! 365: ChangeText ! 366: { ! 367: cursor = paste(frommark, TRUE, FALSE); ! 368: } ! 369: } ! 370: ! 371: ! 372: /*ARGSUSED*/ ! 373: void cmd_join(frommark, tomark, cmd, bang, extra) ! 374: MARK frommark; ! 375: MARK tomark; ! 376: CMD cmd; ! 377: int bang; ! 378: char *extra; ! 379: { ! 380: long l; ! 381: char *scan; ! 382: int len; /* length of the new line */ ! 383: ! 384: /* if only one line is specified, assume the following one joins too */ ! 385: if (markline(frommark) == nlines) ! 386: { ! 387: msg("Nothing to join with this line"); ! 388: return; ! 389: } ! 390: if (markline(frommark) == markline(tomark)) ! 391: { ! 392: tomark += BLKSIZE; ! 393: } ! 394: ! 395: /* get the first line */ ! 396: l = markline(frommark); ! 397: strcpy(tmpblk.c, fetchline(l)); ! 398: len = strlen(tmpblk.c); ! 399: ! 400: /* build the longer line */ ! 401: while (++l <= markline(tomark)) ! 402: { ! 403: /* get the next line */ ! 404: scan = fetchline(l); ! 405: ! 406: /* remove any leading whitespace */ ! 407: while (*scan == '\t' || *scan == ' ') ! 408: { ! 409: scan++; ! 410: } ! 411: ! 412: /* see if the line will fit */ ! 413: if (strlen(scan) + len + 3 > BLKSIZE) ! 414: { ! 415: msg("Can't join -- the resulting line would be too long"); ! 416: return; ! 417: } ! 418: ! 419: /* catenate it, with a space (or two) in between */ ! 420: if (len >= 1 && ! 421: (tmpblk.c[len - 1] == '.' ! 422: || tmpblk.c[len - 1] == '?' ! 423: || tmpblk.c[len - 1] == '!')) ! 424: { ! 425: tmpblk.c[len++] = ' '; ! 426: } ! 427: tmpblk.c[len++] = ' '; ! 428: strcpy(tmpblk.c + len, scan); ! 429: len += strlen(scan); ! 430: } ! 431: tmpblk.c[len++] = '\n'; ! 432: tmpblk.c[len] = '\0'; ! 433: ! 434: /* make the change */ ! 435: ChangeText ! 436: { ! 437: frommark &= ~(BLKSIZE - 1); ! 438: tomark &= ~(BLKSIZE - 1); ! 439: tomark += BLKSIZE; ! 440: change(frommark, tomark, tmpblk.c); ! 441: } ! 442: ! 443: /* Reporting... */ ! 444: rptlines = markline(tomark) - markline(frommark) - 1L; ! 445: rptlabel = "joined"; ! 446: } ! 447: ! 448: ! 449: ! 450: /*ARGSUSED*/ ! 451: void cmd_shift(frommark, tomark, cmd, bang, extra) ! 452: MARK frommark; ! 453: MARK tomark; ! 454: CMD cmd; ! 455: int bang; ! 456: char *extra; ! 457: { ! 458: long l; /* line number counter */ ! 459: int oldidx; /* number of chars previously used for indent */ ! 460: int newidx; /* number of chars in the new indent string */ ! 461: int oldcol; /* previous indent amount */ ! 462: int newcol; /* new indent amount */ ! 463: char *text; /* pointer to the old line's text */ ! 464: ! 465: /* figure out how much of the screen we must redraw (for vi mode) */ ! 466: if (markline(frommark) != markline(tomark)) ! 467: { ! 468: mustredraw = TRUE; ! 469: redrawrange(markline(frommark), markline(tomark) + 1L, markline(tomark) + 1L); ! 470: } ! 471: ! 472: ChangeText ! 473: { ! 474: /* for each line to shift... */ ! 475: for (l = markline(frommark); l <= markline(tomark); l++) ! 476: { ! 477: /* get the line - ignore empty lines unless ! mode */ ! 478: text = fetchline(l); ! 479: if (!*text && !bang) ! 480: continue; ! 481: ! 482: /* calc oldidx and oldcol */ ! 483: for (oldidx = 0, oldcol = 0; ! 484: text[oldidx] == ' ' || text[oldidx] == '\t'; ! 485: oldidx++) ! 486: { ! 487: if (text[oldidx] == ' ') ! 488: { ! 489: oldcol += 1; ! 490: } ! 491: else ! 492: { ! 493: oldcol += *o_tabstop - (oldcol % *o_tabstop); ! 494: } ! 495: } ! 496: ! 497: /* calc newcol */ ! 498: if (cmd == CMD_SHIFTR) ! 499: { ! 500: newcol = oldcol + (*o_shiftwidth & 0xff); ! 501: } ! 502: else ! 503: { ! 504: newcol = oldcol - (*o_shiftwidth & 0xff); ! 505: if (newcol < 0) ! 506: newcol = 0; ! 507: } ! 508: ! 509: /* if no change, then skip to next line */ ! 510: if (oldcol == newcol) ! 511: continue; ! 512: ! 513: /* build a new indent string */ ! 514: newidx = 0; ! 515: while (newcol >= *o_tabstop) ! 516: { ! 517: tmpblk.c[newidx++] = '\t'; ! 518: newcol -= *o_tabstop; ! 519: } ! 520: while (newcol > 0) ! 521: { ! 522: tmpblk.c[newidx++] = ' '; ! 523: newcol--; ! 524: } ! 525: tmpblk.c[newidx] = '\0'; ! 526: ! 527: /* change the old indent string into the new */ ! 528: change(MARK_AT_LINE(l), MARK_AT_LINE(l) + oldidx, tmpblk.c); ! 529: } ! 530: } ! 531: ! 532: /* Reporting... */ ! 533: rptlines = markline(tomark) - markline(frommark) + 1L; ! 534: if (cmd == CMD_SHIFTR) ! 535: { ! 536: rptlabel = ">ed"; ! 537: } ! 538: else ! 539: { ! 540: rptlabel = "<ed"; ! 541: } ! 542: } ! 543: ! 544: ! 545: /*ARGSUSED*/ ! 546: void cmd_read(frommark, tomark, cmd, bang, extra) ! 547: MARK frommark; ! 548: MARK tomark; ! 549: CMD cmd; ! 550: int bang; ! 551: char *extra; ! 552: { ! 553: int fd, rc; /* used while reading from the file */ ! 554: char *scan; /* used for finding NUL characters */ ! 555: int hadnul; /* boolean: any NULs found? */ ! 556: int addnl; /* boolean: forced to add newlines? */ ! 557: int len; /* number of chars in current line */ ! 558: long lines; /* number of lines in current block */ ! 559: struct stat statb; ! 560: ! 561: /* special case: if ":r !cmd" then let the filter() function do it */ ! 562: if (extra[0] == '!') ! 563: { ! 564: filter(frommark, MARK_UNSET, extra + 1); ! 565: return; ! 566: } ! 567: ! 568: /* open the file */ ! 569: fd = open(extra, O_RDONLY); ! 570: if (fd < 0) ! 571: { ! 572: msg("Can't open \"%s\"", extra); ! 573: return; ! 574: } ! 575: ! 576: #ifndef CRUNCH ! 577: if (stat(extra, &statb) < 0) ! 578: { ! 579: msg("Can't stat \"%s\"", extra); ! 580: } ! 581: # if TOS ! 582: if (statb.st_mode & S_IJDIR) ! 583: # else ! 584: # if OSK ! 585: if (statb.st_mode & S_IFDIR) ! 586: # else ! 587: if ((statb.st_mode & S_IFMT) != S_IFREG) ! 588: # endif ! 589: # endif ! 590: { ! 591: msg("\"%s\" is not a regular file", extra); ! 592: return; ! 593: } ! 594: #endif /* not CRUNCH */ ! 595: ! 596: /* get blocks from the file, and add them */ ! 597: ChangeText ! 598: { ! 599: /* insertion starts at the line following frommark */ ! 600: tomark = frommark = (frommark | (BLKSIZE - 1L)) + 1L; ! 601: len = 0; ! 602: hadnul = addnl = FALSE; ! 603: ! 604: /* add an extra newline, so partial lines at the end of ! 605: * the file don't trip us up ! 606: */ ! 607: add(tomark, "\n"); ! 608: ! 609: /* for each chunk of text... */ ! 610: while ((rc = read(fd, tmpblk.c, BLKSIZE - 1)) > 0) ! 611: { ! 612: /* count newlines, convert NULs, etc. ... */ ! 613: for (lines = 0, scan = tmpblk.c; rc > 0; rc--, scan++) ! 614: { ! 615: /* break up long lines */ ! 616: if (*scan != '\n' && len + 2 > BLKSIZE) ! 617: { ! 618: *scan = '\n'; ! 619: addnl = TRUE; ! 620: } ! 621: ! 622: /* protect against NUL chars in file */ ! 623: if (!*scan) ! 624: { ! 625: *scan = 0x80; ! 626: hadnul = TRUE; ! 627: } ! 628: ! 629: /* starting a new line? */ ! 630: if (*scan == '\n') ! 631: { ! 632: /* reset length at newline */ ! 633: len = 0; ! 634: lines++; ! 635: } ! 636: else ! 637: { ! 638: len++; ! 639: } ! 640: } ! 641: ! 642: /* add the text */ ! 643: *scan = '\0'; ! 644: add(tomark, tmpblk.c); ! 645: tomark += MARK_AT_LINE(lines) + len - markidx(tomark); ! 646: } ! 647: ! 648: /* if partial last line, then retain that first newline */ ! 649: if (len > 0) ! 650: { ! 651: msg("Last line had no newline"); ! 652: tomark += BLKSIZE; /* <- for the rptlines calc */ ! 653: } ! 654: else /* delete that first newline */ ! 655: { ! 656: delete(tomark, (tomark | (BLKSIZE - 1L)) + 1L); ! 657: } ! 658: } ! 659: ! 660: /* close the file */ ! 661: close(fd); ! 662: ! 663: /* Reporting... */ ! 664: rptlines = markline(tomark) - markline(frommark); ! 665: rptlabel = "read"; ! 666: ! 667: if (addnl) ! 668: msg("Newlines were added to break up long lines"); ! 669: if (hadnul) ! 670: msg("NULs were converted to 0x80"); ! 671: } ! 672: ! 673: ! 674: ! 675: /*ARGSUSED*/ ! 676: void cmd_undo(frommark, tomark, cmd, bang, extra) ! 677: MARK frommark; ! 678: MARK tomark; ! 679: CMD cmd; ! 680: int bang; ! 681: char *extra; ! 682: { ! 683: undo(); ! 684: } ! 685: ! 686: ! 687: /* print the selected lines */ ! 688: /*ARGSUSED*/ ! 689: void cmd_print(frommark, tomark, cmd, bang, extra) ! 690: MARK frommark; ! 691: MARK tomark; ! 692: CMD cmd; ! 693: int bang; ! 694: char *extra; ! 695: { ! 696: REG char *scan; ! 697: REG long l; ! 698: REG int col; ! 699: ! 700: for (l = markline(frommark); l <= markline(tomark); l++) ! 701: { ! 702: /* display a line number, if CMD_NUMBER */ ! 703: if (cmd == CMD_NUMBER) ! 704: { ! 705: sprintf(tmpblk.c, "%6ld ", l); ! 706: qaddstr(tmpblk.c); ! 707: col = 8; ! 708: } ! 709: else ! 710: { ! 711: col = 0; ! 712: } ! 713: ! 714: /* get the next line & display it */ ! 715: for (scan = fetchline(l); *scan; scan++) ! 716: { ! 717: /* expand tabs to the proper width */ ! 718: if (*scan == '\t' && cmd != CMD_LIST) ! 719: { ! 720: do ! 721: { ! 722: qaddch(' '); ! 723: col++; ! 724: } while (col % *o_tabstop != 0); ! 725: } ! 726: else if (*scan >= 0 && *scan < ' ' || *scan == '\177') ! 727: { ! 728: qaddch('^'); ! 729: qaddch(*scan ^ 0x40); ! 730: col += 2; ! 731: } ! 732: else if ((*scan & 0x80) && cmd == CMD_LIST) ! 733: { ! 734: sprintf(tmpblk.c, "\\%03o", *scan); ! 735: qaddstr(tmpblk.c); ! 736: col += 4; ! 737: } ! 738: else ! 739: { ! 740: qaddch(*scan); ! 741: col++; ! 742: } ! 743: ! 744: /* wrap at the edge of the screen */ ! 745: if (!has_AM && col >= COLS) ! 746: { ! 747: addch('\n'); ! 748: col -= COLS; ! 749: } ! 750: } ! 751: if (cmd == CMD_LIST) ! 752: { ! 753: qaddch('$'); ! 754: } ! 755: addch('\n'); ! 756: exrefresh(); ! 757: } ! 758: } ! 759: ! 760: ! 761: /* move or copy selected lines */ ! 762: /*ARGSUSED*/ ! 763: void cmd_move(frommark, tomark, cmd, bang, extra) ! 764: MARK frommark; ! 765: MARK tomark; ! 766: CMD cmd; ! 767: int bang; ! 768: char *extra; ! 769: { ! 770: MARK destmark; ! 771: ! 772: /* parse the destination linespec. No defaults. Line 0 is okay */ ! 773: destmark = cursor; ! 774: if (!strcmp(extra, "0")) ! 775: { ! 776: destmark = 0L; ! 777: } ! 778: else if (linespec(extra, &destmark) == extra || !destmark) ! 779: { ! 780: msg("invalid destination address"); ! 781: return; ! 782: } ! 783: ! 784: /* flesh the marks out to encompass whole lines */ ! 785: frommark &= ~(BLKSIZE - 1); ! 786: tomark = (tomark & ~(BLKSIZE - 1)) + BLKSIZE; ! 787: destmark = (destmark & ~(BLKSIZE - 1)) + BLKSIZE; ! 788: ! 789: /* make sure the destination is valid */ ! 790: if (cmd == CMD_MOVE && destmark >= frommark && destmark < tomark) ! 791: { ! 792: msg("invalid destination address"); ! 793: } ! 794: ! 795: /* Do it */ ! 796: ChangeText ! 797: { ! 798: /* save the text to a cut buffer */ ! 799: cutname('\0'); ! 800: cut(frommark, tomark); ! 801: ! 802: /* if we're not copying, delete the old text & adjust destmark */ ! 803: if (cmd != CMD_COPY) ! 804: { ! 805: delete(frommark, tomark); ! 806: if (destmark >= frommark) ! 807: { ! 808: destmark -= (tomark - frommark); ! 809: } ! 810: } ! 811: ! 812: /* add the new text */ ! 813: paste(destmark, FALSE, FALSE); ! 814: } ! 815: ! 816: /* move the cursor to the last line of the moved text */ ! 817: cursor = destmark + (tomark - frommark) - BLKSIZE; ! 818: if (cursor < MARK_FIRST || cursor >= MARK_LAST + BLKSIZE) ! 819: { ! 820: cursor = MARK_LAST; ! 821: } ! 822: ! 823: /* Reporting... */ ! 824: rptlabel = ( (cmd == CMD_COPY) ? "copied" : "moved" ); ! 825: } ! 826: ! 827: ! 828: ! 829: /* execute EX commands from a file */ ! 830: /*ARGSUSED*/ ! 831: void cmd_source(frommark, tomark, cmd, bang, extra) ! 832: MARK frommark; ! 833: MARK tomark; ! 834: CMD cmd; ! 835: int bang; ! 836: char *extra; ! 837: { ! 838: /* must have a filename */ ! 839: if (!*extra) ! 840: { ! 841: msg("\"source\" requires a filename"); ! 842: return; ! 843: } ! 844: ! 845: doexrc(extra); ! 846: } ! 847: ! 848: ! 849: #ifndef NO_AT ! 850: /*ARGSUSED*/ ! 851: void cmd_at(frommark, tomark, cmd, bang, extra) ! 852: MARK frommark; ! 853: MARK tomark; ! 854: CMD cmd; ! 855: int bang; ! 856: char *extra; ! 857: { ! 858: static nest = FALSE; ! 859: int result; ! 860: char buf[MAXRCLEN]; ! 861: ! 862: /* don't allow nested macros */ ! 863: if (nest) ! 864: { ! 865: msg("@ macros can't be nested"); ! 866: return; ! 867: } ! 868: nest = TRUE; ! 869: ! 870: /* require a buffer name */ ! 871: if (*extra == '"') ! 872: extra++; ! 873: if (!*extra || !isascii(*extra) ||!islower(*extra)) ! 874: { ! 875: msg("@ requires a cut buffer name (a-z)"); ! 876: } ! 877: ! 878: /* get the contents of the buffer */ ! 879: result = cb2str(*extra, buf, (unsigned)(sizeof buf)); ! 880: if (result <= 0) ! 881: { ! 882: msg("buffer \"%c is empty", *extra); ! 883: } ! 884: else if (result >= sizeof buf) ! 885: { ! 886: msg("buffer \"%c is too large to execute", *extra); ! 887: } ! 888: else ! 889: { ! 890: /* execute the contents of the buffer as ex commands */ ! 891: exstring(buf, result); ! 892: } ! 893: ! 894: nest = FALSE; ! 895: } ! 896: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.