Annotation of coherent/d/usr/bin/elvis/modify.c, revision 1.1.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.