Annotation of coherent/g/usr/bin/vi/modify.c, revision 1.1

1.1     ! root        1: /* modify.c */
        !             2: 
        !             3: /* This file contains the low-level file modification functions:
        !             4:  *     delete(frommark, tomark)        - removes line or portions of lines
        !             5:  *     add(frommark, text)             - inserts new text
        !             6:  *     change(frommark, tomark, text)  - delete, then add
        !             7:  */
        !             8: 
        !             9: #include "config.h"
        !            10: #include "vi.h"
        !            11: 
        !            12: #ifdef DEBUG2
        !            13: # include <stdio.h>
        !            14: static FILE *dbg;
        !            15: 
        !            16: /*VARARGS1*/
        !            17: debout(msg, arg1, arg2, arg3, arg4, arg5)
        !            18:        char    *msg, *arg1, *arg2, *arg3, *arg4, *arg5;
        !            19: {
        !            20:        if (!dbg)
        !            21:        {
        !            22:                dbg = fopen("debug.out", "w");
        !            23:                if (!dbg)
        !            24:                        return;
        !            25:                setbuf(dbg, (FILE *)0);
        !            26:        }
        !            27:        fprintf(dbg, msg, arg1, arg2, arg3, arg4, arg5);
        !            28: }
        !            29: #endif /* DEBUG2 */
        !            30: 
        !            31: /* delete a range of text from the file */
        !            32: void delete(frommark, tomark)
        !            33:        MARK            frommark;       /* first char to be deleted */
        !            34:        MARK            tomark;         /* AFTER last char to be deleted */
        !            35: {
        !            36:        int             i;              /* used to move thru logical blocks */
        !            37:        REG char        *scan;          /* used to scan thru text of the blk */
        !            38:        REG char        *cpy;           /* used when copying chars */
        !            39:        BLK             *blk;           /* a text block */
        !            40:        long            l;              /* a line number */
        !            41:        MARK            m;              /* a traveling version of frommark */
        !            42: 
        !            43: #ifdef DEBUG2
        !            44:        debout("delete(%ld.%d, %ld.%d)\n", markline(frommark), markidx(frommark), markline(tomark), markidx(tomark));
        !            45: #endif
        !            46: 
        !            47:        /* if not deleting anything, quit now */
        !            48:        if (frommark == tomark)
        !            49:        {
        !            50:                return;
        !            51:        }
        !            52: 
        !            53:        /* This is a change */
        !            54:        changes++;
        !            55:        significant = TRUE;
        !            56: 
        !            57:        /* supply clues to the redraw module */
        !            58:        redrawrange(markline(frommark), markline(tomark), markline(frommark));
        !            59: 
        !            60:        /* adjust marks 'a through 'z and '' as needed */
        !            61:        l = markline(tomark);
        !            62:        for (i = 0; i < NMARKS; i++)
        !            63:        {
        !            64:                if (mark[i] < frommark)
        !            65:                {
        !            66:                        continue;
        !            67:                }
        !            68:                else if (mark[i] < tomark)
        !            69:                {
        !            70:                        mark[i] = MARK_UNSET;
        !            71:                }
        !            72:                else if (markline(mark[i]) == l)
        !            73:                {
        !            74:                        if (markline(frommark) == l)
        !            75:                        {
        !            76:                                mark[i] -= markidx(tomark) - markidx(frommark);
        !            77:                        }
        !            78:                        else
        !            79:                        {
        !            80:                                mark[i] -= markidx(tomark);
        !            81:                        }
        !            82:                }
        !            83:                else
        !            84:                {
        !            85:                        mark[i] -= MARK_AT_LINE(l - markline(frommark));
        !            86:                }
        !            87:        }
        !            88: 
        !            89:        /* Reporting... */
        !            90:        if (markidx(frommark) == 0 && markidx(tomark) == 0)
        !            91:        {
        !            92:                rptlines = markline(tomark) - markline(frommark);
        !            93:                rptlabel = "deleted";
        !            94:        }
        !            95: 
        !            96:        /* find the block containing frommark */
        !            97:        l = markline(frommark);
        !            98:        for (i = 1; lnum[i] < l; i++)
        !            99:        {
        !           100:        }
        !           101: 
        !           102:        /* process each affected block... */
        !           103:        for (m = frommark;
        !           104:             m < tomark && lnum[i] < INFINITY;
        !           105:             m = MARK_AT_LINE(lnum[i - 1] + 1))
        !           106:        {
        !           107:                /* fetch the block */
        !           108:                blk = blkget(i);
        !           109: 
        !           110:                /* find the mark in the block */
        !           111:                scan = blk->c;
        !           112:                for (l = markline(m) - lnum[i - 1] - 1; l > 0; l--)
        !           113:                {
        !           114:                        while (*scan++ != '\n')
        !           115:                        {
        !           116:                        }
        !           117:                }
        !           118:                scan += markidx(m);
        !           119: 
        !           120:                /* figure out where the changes to this block end */
        !           121:                if (markline(tomark) > lnum[i])
        !           122:                {
        !           123:                        cpy = blk->c + BLKSIZE;
        !           124:                }
        !           125:                else if (markline(tomark) == markline(m))
        !           126:                {
        !           127:                        cpy = scan - markidx(m) + markidx(tomark);
        !           128:                }
        !           129:                else
        !           130:                {
        !           131:                        cpy = scan;
        !           132:                        for (l = markline(tomark) - markline(m);
        !           133:                             l > 0;
        !           134:                             l--)
        !           135:                        {
        !           136:                                while (*cpy++ != '\n')
        !           137:                                {
        !           138:                                }
        !           139:                        }
        !           140:                        cpy += markidx(tomark);
        !           141:                }
        !           142: 
        !           143:                /* delete the stuff by moving chars within this block */
        !           144:                while (cpy < blk->c + BLKSIZE)
        !           145:                {
        !           146:                        *scan++ = *cpy++;
        !           147:                }
        !           148:                while (scan < blk->c + BLKSIZE)
        !           149:                {
        !           150:                        *scan++ = '\0';
        !           151:                }
        !           152: 
        !           153:                /* adjust tomark to allow for lines deleted from this block */
        !           154:                tomark -= MARK_AT_LINE(lnum[i] + 1 - markline(m));
        !           155: 
        !           156:                /* if this block isn't empty now, then advance i */
        !           157:                if (*blk->c)
        !           158:                {
        !           159:                        i++;
        !           160:                }
        !           161: 
        !           162:                /* the buffer has changed.  Update hdr and lnum. */
        !           163:                blkdirty(blk);
        !           164:        }
        !           165: 
        !           166:        /* must have at least 1 line */
        !           167:        if (nlines == 0)
        !           168:        {
        !           169:                blk = blkadd(1);
        !           170:                blk->c[0] = '\n';
        !           171:                blkdirty(blk);
        !           172:                cursor = MARK_FIRST;
        !           173:        }
        !           174: }
        !           175: 
        !           176: 
        !           177: /* add some text at a specific place in the file */
        !           178: void add(atmark, newtext)
        !           179:        MARK            atmark;         /* where to insert the new text */
        !           180:        char            *newtext;       /* NUL-terminated string to insert */
        !           181: {
        !           182:        REG char        *scan;          /* used to move through string */
        !           183:        REG char        *build;         /* used while copying chars */
        !           184:        int             addlines;       /* number of lines we're adding */
        !           185:        int             lastpart;       /* size of last partial line */
        !           186:        BLK             *blk;           /* the block to be modified */
        !           187:        int             blkno;          /* the logical block# of (*blk) */
        !           188:        REG char        *newptr;        /* where new text starts in blk */
        !           189:        BLK             buf;            /* holds chars from orig blk */
        !           190:        BLK             linebuf;        /* holds part of line that didn't fit */
        !           191:        BLK             *following;     /* the BLK following the last BLK */
        !           192:        int             i;
        !           193:        long            l;
        !           194: 
        !           195: #ifdef DEBUG2
        !           196:        debout("add(%ld.%d, \"%s\")\n", markline(atmark), markidx(atmark), newtext);
        !           197: #endif
        !           198: #ifdef lint
        !           199:        buf.c[0] = 0;
        !           200: #endif
        !           201:        /* if not adding anything, return now */
        !           202:        if (!*newtext)
        !           203:        {
        !           204:                return;
        !           205:        }
        !           206: 
        !           207:        /* This is a change */
        !           208:        changes++;
        !           209:        significant = TRUE;
        !           210: 
        !           211:        /* count the number of lines in the new text */
        !           212:        for (scan = newtext, lastpart = addlines = 0; *scan; )
        !           213:        {
        !           214:                if (*scan++ == '\n')
        !           215:                {
        !           216:                        addlines++;
        !           217:                        lastpart = 0;
        !           218:                }
        !           219:                else
        !           220:                {
        !           221:                        lastpart++;
        !           222:                }
        !           223:        }
        !           224: 
        !           225:        /* Reporting... */
        !           226:        if (lastpart == 0 && markidx(atmark) == 0)
        !           227:        {
        !           228:                rptlines = addlines;
        !           229:                rptlabel = "added";
        !           230:        }
        !           231: 
        !           232:        /* extract the line# from atmark */
        !           233:        l = markline(atmark);
        !           234: 
        !           235:        /* supply clues to the redraw module */
        !           236:        if ((markidx(atmark) == 0 && lastpart == 0) || addlines == 0)
        !           237:        {
        !           238:                redrawrange(l, l, l + addlines);
        !           239:        }
        !           240:        else
        !           241:        {
        !           242:                /* make sure the last line gets redrawn -- it was
        !           243:                 * split, so its appearance has changed
        !           244:                 */
        !           245:                redrawrange(l, l + 1L, l + addlines + 1L);
        !           246:        }
        !           247: 
        !           248:        /* adjust marks 'a through 'z and '' as needed */
        !           249:        for (i = 0; i < NMARKS; i++)
        !           250:        {
        !           251:                if (mark[i] < atmark)
        !           252:                {
        !           253:                        /* earlier line, or earlier in same line: no change */
        !           254:                        continue;
        !           255:                }
        !           256:                else if (markline(mark[i]) > l)
        !           257:                {
        !           258:                        /* later line: move down a whole number of lines */
        !           259:                        mark[i] += MARK_AT_LINE(addlines);
        !           260:                }
        !           261:                else
        !           262:                {
        !           263:                        /* later in same line */
        !           264:                        if (addlines > 0)
        !           265:                        {
        !           266:                                /* multi-line add, which split this line:
        !           267:                                 * move down, and possibly left or right,
        !           268:                                 * depending on where the split was and how
        !           269:                                 * much text was inserted after the last \n
        !           270:                                 */
        !           271:                                mark[i] += MARK_AT_LINE(addlines) + lastpart - markidx(atmark);
        !           272:                        }
        !           273:                        else
        !           274:                        {
        !           275:                                /* totally within this line: move right */
        !           276:                                mark[i] += lastpart;
        !           277:                        }
        !           278:                }
        !           279:        }
        !           280: 
        !           281:        /* get the block to be modified */
        !           282:        for (blkno = 1; lnum[blkno] < l && lnum[blkno + 1] < INFINITY; blkno++)
        !           283:        {
        !           284:        }
        !           285:        blk = blkget(blkno);
        !           286:        buf = *blk;
        !           287: 
        !           288:        /* figure out where the new text starts */
        !           289:        for (newptr = buf.c, l = markline(atmark) - lnum[blkno - 1] - 1;
        !           290:             l > 0;
        !           291:             l--)
        !           292:        {
        !           293:                while (*newptr++ != '\n')
        !           294:                {
        !           295:                }
        !           296:        }
        !           297:        newptr += markidx(atmark);
        !           298: 
        !           299:        /* keep start of old block */
        !           300:        build = blk->c + (int)(newptr - buf.c);
        !           301: 
        !           302:        /* fill this block (or blocks) from the newtext string */
        !           303:        while (*newtext)
        !           304:        {
        !           305:                while (*newtext && build < blk->c + BLKSIZE - 1)
        !           306:                {
        !           307:                        *build++ = *newtext++;
        !           308:                }
        !           309:                if (*newtext)
        !           310:                {
        !           311:                        /* save the excess */
        !           312:                        for (scan = linebuf.c + BLKSIZE;
        !           313:                             build > blk->c && build[-1] != '\n';
        !           314:                             )
        !           315:                        {
        !           316:                                *--scan = *--build;
        !           317:                        }
        !           318: 
        !           319:                        /* write the block */
        !           320:                        while (build < blk->c + BLKSIZE)
        !           321:                        {
        !           322:                                *build++ = '\0';
        !           323:                        }
        !           324:                        blkdirty(blk);
        !           325: 
        !           326:                        /* add another block */
        !           327:                        blkno++;
        !           328:                        blk = blkadd(blkno);
        !           329: 
        !           330:                        /* copy in the excess from last time */
        !           331:                        for (build = blk->c; scan < linebuf.c + BLKSIZE; )
        !           332:                        {
        !           333:                                *build++ = *scan++;
        !           334:                        }
        !           335:                }
        !           336:        }
        !           337: 
        !           338:        /* fill this block(s) from remainder of orig block */
        !           339:        while (newptr < buf.c + BLKSIZE && *newptr)
        !           340:        {
        !           341:                while (newptr < buf.c + BLKSIZE
        !           342:                    && *newptr
        !           343:                    && build < blk->c + BLKSIZE - 1)
        !           344:                {
        !           345:                        *build++ = *newptr++;
        !           346:                }
        !           347:                if (newptr < buf.c + BLKSIZE && *newptr)
        !           348:                {
        !           349:                        /* save the excess */
        !           350:                        for (scan = linebuf.c + BLKSIZE;
        !           351:                             build > blk->c && build[-1] != '\n';
        !           352:                             )
        !           353:                        {
        !           354:                                *--scan = *--build;
        !           355:                        }
        !           356: 
        !           357:                        /* write the block */
        !           358:                        while (build < blk->c + BLKSIZE)
        !           359:                        {
        !           360:                                *build++ = '\0';
        !           361:                        }
        !           362:                        blkdirty(blk);
        !           363: 
        !           364:                        /* add another block */
        !           365:                        blkno++;
        !           366:                        blk = blkadd(blkno);
        !           367: 
        !           368:                        /* copy in the excess from last time */
        !           369:                        for (build = blk->c; scan < linebuf.c + BLKSIZE; )
        !           370:                        {
        !           371:                                *build++ = *scan++;
        !           372:                        }
        !           373:                }
        !           374:        }
        !           375: 
        !           376:        /* see if we can combine our last block with the following block */
        !           377:        if (lnum[blkno] < nlines && lnum[blkno + 1] - lnum[blkno] < (BLKSIZE >> 6))
        !           378:        {
        !           379:                /* hey, we probably can!  Get the following block & see... */
        !           380:                following = blkget(blkno + 1);
        !           381:                if (strlen(following->c) + (build - blk->c) < BLKSIZE - 1)
        !           382:                {
        !           383:                        /* we can!  Copy text from following to blk */
        !           384:                        for (scan = following->c; *scan; )
        !           385:                        {
        !           386:                                *build++ = *scan++;
        !           387:                        }
        !           388:                        while (build < blk->c + BLKSIZE)
        !           389:                        {
        !           390:                                *build++ = '\0';
        !           391:                        }
        !           392:                        blkdirty(blk);
        !           393: 
        !           394:                        /* pretend the following was the last blk */
        !           395:                        blk = following;
        !           396:                        build = blk->c;
        !           397:                }
        !           398:        }
        !           399: 
        !           400:        /* that last block is dirty by now */
        !           401:        while (build < blk->c + BLKSIZE)
        !           402:        {
        !           403:                *build++ = '\0';
        !           404:        }
        !           405:        blkdirty(blk);
        !           406: }
        !           407: 
        !           408: 
        !           409: /* change the text of a file */
        !           410: void change(frommark, tomark, newtext)
        !           411:        MARK    frommark, tomark;
        !           412:        char    *newtext;
        !           413: {
        !           414:        int     i;
        !           415:        long    l;
        !           416:        char    *text;
        !           417:        BLK     *blk;
        !           418: 
        !           419: #ifdef DEBUG2
        !           420:        debout("change(%ld.%d, %ld.%d, \"%s\")\n", markline(frommark), markidx(frommark), markline(tomark), markidx(tomark), newtext);
        !           421: #endif
        !           422: 
        !           423:        /* optimize for single-character replacement */
        !           424:        if (frommark + 1 == tomark && newtext[0] && !newtext[1] && newtext[0] != '\n')
        !           425:        {
        !           426:                /* find the block containing frommark */
        !           427:                l = markline(frommark);
        !           428:                for (i = 1; lnum[i] < l; i++)
        !           429:                {
        !           430:                }
        !           431: 
        !           432:                /* get the block */
        !           433:                blk = blkget(i);
        !           434: 
        !           435:                /* find the line within the block */
        !           436:                for (text = blk->c, i = l - lnum[i - 1] - 1; i > 0; text++)
        !           437:                {
        !           438:                        if (*text == '\n')
        !           439:                        {
        !           440:                                i--;
        !           441:                        }
        !           442:                }
        !           443: 
        !           444:                /* replace the char */
        !           445:                text += markidx(frommark);
        !           446:                if (*text == newtext[0])
        !           447:                {
        !           448:                        /* no change was needed - same char */
        !           449:                        return;
        !           450:                }
        !           451:                else if (*text != '\n')
        !           452:                {
        !           453:                        /* This is a change */
        !           454:                        changes++;
        !           455:                        significant = TRUE;
        !           456:                        ChangeText
        !           457:                        {
        !           458:                                *text = newtext[0];
        !           459:                                blkdirty(blk);
        !           460:                        }
        !           461:                        redrawrange(markline(frommark), markline(tomark), markline(frommark));
        !           462:                        return;
        !           463:                }
        !           464:                /* else it is a complex change involving newline... */
        !           465:        }
        !           466: 
        !           467:        /* couldn't optimize, so do delete & add */
        !           468:        ChangeText
        !           469:        {
        !           470:                delete(frommark, tomark);
        !           471:                add(frommark, newtext);
        !           472:                rptlabel = "changed";
        !           473:        }
        !           474: }

unix.superglobalmegacorp.com

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