Annotation of coherent/g/usr/bin/vi/cmd2.c, revision 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.