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