Annotation of coherent/d/usr/bin/elvis/cmd2.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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