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

unix.superglobalmegacorp.com

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