Annotation of coherent/g/usr/bin/vi/cmd2.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.