[BACK]Return to undo.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/undo.c, Revision 1.55

1.55    ! lum         1: /* $OpenBSD: undo.c,v 1.54 2013/06/01 16:27:56 lum Exp $ */
1.1       vincent     2: /*
1.45      kjell       3:  * This file is in the public domain
1.1       vincent     4:  */
                      5:
                      6: #include "def.h"
                      7: #include "kbd.h"
                      8:
                      9: #define MAX_FREE_RECORDS       32
                     10:
                     11: /*
                     12:  * Local variables
                     13:  */
1.50      oga        14: static struct undoq             undo_free;
1.7       vincent    15: static int                      undo_free_num;
1.42      kjell      16: static int                      boundary_flag = TRUE;
1.43      deraadt    17: static int                      undo_enable_flag = TRUE;
1.1       vincent    18:
                     19: /*
                     20:  * Local functions
                     21:  */
1.35      deraadt    22: static int find_dot(struct line *, int);
1.39      kjell      23: static int find_lo(int, struct line **, int *, int *);
1.1       vincent    24: static struct undo_rec *new_undo_record(void);
                     25: static int drop_oldest_undo_record(void);
                     26:
1.9       vincent    27: /*
1.24      vincent    28:  * find_dot, find_lo()
1.9       vincent    29:  *
                     30:  * Find an absolute dot in the buffer from a line/offset pair, and vice-versa.
                     31:  *
1.13      deraadt    32:  * Since lines can be deleted while they are referenced by undo record, we
1.9       vincent    33:  * need to have an absolute dot to have something reliable.
                     34:  */
1.1       vincent    35: static int
1.35      deraadt    36: find_dot(struct line *lp, int off)
1.1       vincent    37: {
1.25      db         38:        int      count = 0;
1.35      deraadt    39:        struct line     *p;
1.1       vincent    40:
1.41      kjell      41:        for (p = curbp->b_headp; p != lp; p = lforw(p)) {
1.1       vincent    42:                if (count != 0) {
1.41      kjell      43:                        if (p == curbp->b_headp) {
1.55    ! lum        44:                                dobeep();
1.1       vincent    45:                                ewprintf("Error: Undo stuff called with a"
1.9       vincent    46:                                    "nonexistent line");
1.11      vincent    47:                                return (FALSE);
1.1       vincent    48:                        }
                     49:                }
                     50:                count += llength(p) + 1;
                     51:        }
                     52:        count += off;
                     53:
1.11      vincent    54:        return (count);
1.1       vincent    55: }
                     56:
                     57: static int
1.39      kjell      58: find_lo(int pos, struct line **olp, int *offset, int *lnum)
1.1       vincent    59: {
1.35      deraadt    60:        struct line *p;
1.39      kjell      61:        int lineno;
1.1       vincent    62:
1.41      kjell      63:        p = curbp->b_headp;
1.39      kjell      64:        lineno = 0;
1.9       vincent    65:        while (pos > llength(p)) {
1.1       vincent    66:                pos -= llength(p) + 1;
1.41      kjell      67:                if ((p = lforw(p)) == curbp->b_headp) {
1.1       vincent    68:                        *olp = NULL;
                     69:                        *offset = 0;
1.11      vincent    70:                        return (FALSE);
1.1       vincent    71:                }
1.39      kjell      72:                lineno++;
1.1       vincent    73:        }
                     74:        *olp = p;
                     75:        *offset = pos;
1.39      kjell      76:        *lnum = lineno;
1.1       vincent    77:
1.11      vincent    78:        return (TRUE);
1.1       vincent    79: }
                     80:
                     81: static struct undo_rec *
                     82: new_undo_record(void)
                     83: {
                     84:        struct undo_rec *rec;
                     85:
1.50      oga        86:        rec = TAILQ_FIRST(&undo_free);
1.9       vincent    87:        if (rec != NULL) {
1.50      oga        88:                /* Remove it from the free-list */
                     89:                TAILQ_REMOVE(&undo_free, rec, next);
1.9       vincent    90:                undo_free_num--;
                     91:        } else {
1.25      db         92:                if ((rec = malloc(sizeof(*rec))) == NULL)
1.1       vincent    93:                        panic("Out of memory in undo code (record)");
                     94:        }
                     95:        memset(rec, 0, sizeof(struct undo_rec));
1.9       vincent    96:
1.11      vincent    97:        return (rec);
1.1       vincent    98: }
                     99:
1.7       vincent   100: void
1.1       vincent   101: free_undo_record(struct undo_rec *rec)
                    102: {
1.9       vincent   103:        static int initialised = 0;
                    104:
                    105:        /*
                    106:         * On the first run, do initialisation of the free list.
                    107:         */
                    108:        if (initialised == 0) {
1.50      oga       109:                TAILQ_INIT(&undo_free);
1.9       vincent   110:                initialised = 1;
                    111:        }
1.1       vincent   112:        if (rec->content != NULL) {
                    113:                free(rec->content);
                    114:                rec->content = NULL;
                    115:        }
                    116:        if (undo_free_num >= MAX_FREE_RECORDS) {
                    117:                free(rec);
                    118:                return;
                    119:        }
                    120:        undo_free_num++;
1.9       vincent   121:
1.50      oga       122:        TAILQ_INSERT_HEAD(&undo_free, rec, next);
1.1       vincent   123: }
                    124:
                    125: /*
                    126:  * Drop the oldest undo record in our list. Return 1 if we could remove it,
1.25      db        127:  * 0 if the undo list was empty.
1.1       vincent   128:  */
                    129: static int
                    130: drop_oldest_undo_record(void)
                    131: {
                    132:        struct undo_rec *rec;
                    133:
1.50      oga       134:        rec = TAILQ_LAST(&curbp->b_undo, undoq);
1.1       vincent   135:        if (rec != NULL) {
                    136:                undo_free_num--;
1.50      oga       137:                TAILQ_REMOVE(&curbp->b_undo, rec, next);
1.1       vincent   138:                free_undo_record(rec);
1.11      vincent   139:                return (1);
1.1       vincent   140:        }
1.11      vincent   141:        return (0);
1.1       vincent   142: }
1.9       vincent   143:
1.44      kjell     144: static int
1.22      vincent   145: lastrectype(void)
1.1       vincent   146: {
1.9       vincent   147:        struct undo_rec *rec;
                    148:
1.50      oga       149:        if ((rec = TAILQ_FIRST(&curbp->b_undo)) != NULL)
1.22      vincent   150:                return (rec->type);
1.11      vincent   151:        return (0);
1.1       vincent   152: }
                    153:
1.30      kjell     154: /*
1.42      kjell     155:  * Returns TRUE if undo is enabled, FALSE otherwise.
                    156:  */
                    157: int
                    158: undo_enabled(void)
                    159: {
                    160:        return (undo_enable_flag);
                    161: }
                    162:
                    163: /*
1.47      kjell     164:  * undo_enable: toggle undo_enable.
                    165:  * Returns the previous value of the flag.
1.30      kjell     166:  */
1.1       vincent   167: int
1.47      kjell     168: undo_enable(int f, int n)
1.1       vincent   169: {
1.42      kjell     170:        int pon = undo_enable_flag;
1.22      vincent   171:
1.47      kjell     172:        if (f & (FFARG | FFRAND))
                    173:                undo_enable_flag = n > 0;
                    174:        else
                    175:                undo_enable_flag = !undo_enable_flag;
                    176:
                    177:        if (!(f & FFRAND))
                    178:                ewprintf("Undo %sabled", undo_enable_flag ? "en" : "dis");
                    179:
1.42      kjell     180:        return (pon);
1.5       vincent   181: }
                    182:
1.30      kjell     183: /*
                    184:  * If undo is enabled, then:
1.47      kjell     185:  *  Toggle undo boundary recording.
                    186:  *  If called with an argument, (n > 0) => enable. Otherwise disable.
                    187:  * In either case, add an undo boundary
1.30      kjell     188:  * If undo is disabled, this function has no effect.
                    189:  */
1.47      kjell     190: int
                    191: undo_boundary_enable(int f, int n)
                    192: {
                    193:        int bon = boundary_flag;
1.42      kjell     194:
1.47      kjell     195:        if (!undo_enable_flag)
                    196:                return (FALSE);
                    197:
                    198:        undo_add_boundary(FFRAND, 1);
                    199:
                    200:        if (f & (FFARG | FFRAND))
                    201:                boundary_flag = n > 0;
                    202:        else
                    203:                boundary_flag = !boundary_flag;
                    204:
                    205:        if (!(f & FFRAND))
                    206:                ewprintf("Undo boundaries %sabled",
                    207:                    boundary_flag ? "en" : "dis");
                    208:
                    209:        return (bon);
1.28      kjell     210: }
                    211:
1.30      kjell     212: /*
1.42      kjell     213:  * Record an undo boundary, unless boundary_flag == FALSE.
1.40      kjell     214:  * Does nothing if previous undo entry is already a boundary or 'modified' flag.
1.30      kjell     215:  */
1.47      kjell     216: int
                    217: undo_add_boundary(int f, int n)
1.5       vincent   218: {
                    219:        struct undo_rec *rec;
1.40      kjell     220:        int last;
1.5       vincent   221:
1.42      kjell     222:        if (boundary_flag == FALSE)
1.47      kjell     223:                return (FALSE);
1.12      vincent   224:
1.40      kjell     225:        last = lastrectype();
                    226:        if (last == BOUNDARY || last == MODIFIED)
1.47      kjell     227:                return (TRUE);
1.31      deraadt   228:
1.5       vincent   229:        rec = new_undo_record();
1.9       vincent   230:        rec->type = BOUNDARY;
1.5       vincent   231:
1.50      oga       232:        TAILQ_INSERT_HEAD(&curbp->b_undo, rec, next);
1.9       vincent   233:
1.47      kjell     234:        return (TRUE);
1.1       vincent   235: }
                    236:
1.40      kjell     237: /*
                    238:  * Record an undo "modified" boundary
                    239:  */
                    240: void
                    241: undo_add_modified(void)
                    242: {
1.52      florian   243:        struct undo_rec *rec, *trec;
                    244:
                    245:        TAILQ_FOREACH_SAFE(rec, &curbp->b_undo, next, trec)
                    246:                if (rec->type == MODIFIED) {
                    247:                        TAILQ_REMOVE(&curbp->b_undo, rec, next);
                    248:                        free_undo_record(rec);
                    249:                }
1.40      kjell     250:
                    251:        rec = new_undo_record();
                    252:        rec->type = MODIFIED;
                    253:
1.50      oga       254:        TAILQ_INSERT_HEAD(&curbp->b_undo, rec, next);
1.40      kjell     255:
                    256:        return;
                    257: }
                    258:
1.1       vincent   259: int
1.35      deraadt   260: undo_add_insert(struct line *lp, int offset, int size)
1.1       vincent   261: {
1.35      deraadt   262:        struct region   reg;
1.25      db        263:        struct  undo_rec *rec;
                    264:        int     pos;
1.9       vincent   265:
1.47      kjell     266:        if (!undo_enable_flag)
1.11      vincent   267:                return (TRUE);
1.1       vincent   268:        reg.r_linep = lp;
                    269:        reg.r_offset = offset;
                    270:        reg.r_size = size;
1.9       vincent   271:
1.24      vincent   272:        pos = find_dot(lp, offset);
1.9       vincent   273:
1.1       vincent   274:        /*
                    275:         * We try to reuse the last undo record to `compress' things.
1.13      deraadt   276:         */
1.50      oga       277:        rec = TAILQ_FIRST(&curbp->b_undo);
1.23      vincent   278:        if (rec != NULL && rec->type == INSERT) {
                    279:                if (rec->pos + rec->region.r_size == pos) {
                    280:                        rec->region.r_size += reg.r_size;
                    281:                        return (TRUE);
1.1       vincent   282:                }
                    283:        }
1.9       vincent   284:
1.1       vincent   285:        /*
1.25      db        286:         * We couldn't reuse the last undo record, so prepare a new one.
1.1       vincent   287:         */
                    288:        rec = new_undo_record();
1.9       vincent   289:        rec->pos = pos;
1.1       vincent   290:        rec->type = INSERT;
1.35      deraadt   291:        memmove(&rec->region, &reg, sizeof(struct region));
1.1       vincent   292:        rec->content = NULL;
1.9       vincent   293:
1.47      kjell     294:        undo_add_boundary(FFRAND, 1);
1.9       vincent   295:
1.50      oga       296:        TAILQ_INSERT_HEAD(&curbp->b_undo, rec, next);
1.1       vincent   297:
1.11      vincent   298:        return (TRUE);
1.1       vincent   299: }
                    300:
                    301: /*
1.25      db        302:  * This of course must be done _before_ the actual deletion is done.
1.1       vincent   303:  */
                    304: int
1.49      kjell     305: undo_add_delete(struct line *lp, int offset, int size, int isreg)
1.1       vincent   306: {
1.35      deraadt   307:        struct region   reg;
1.25      db        308:        struct  undo_rec *rec;
                    309:        int     pos;
1.1       vincent   310:
1.47      kjell     311:        if (!undo_enable_flag)
1.11      vincent   312:                return (TRUE);
1.1       vincent   313:
                    314:        reg.r_linep = lp;
                    315:        reg.r_offset = offset;
                    316:        reg.r_size = size;
                    317:
1.24      vincent   318:        pos = find_dot(lp, offset);
1.3       vincent   319:
1.10      vincent   320:        if (offset == llength(lp))      /* if it's a newline... */
1.47      kjell     321:                undo_add_boundary(FFRAND, 1);
1.50      oga       322:        else if ((rec = TAILQ_FIRST(&curbp->b_undo)) != NULL) {
1.9       vincent   323:                /*
                    324:                 * Separate this command from the previous one if we're not
                    325:                 * just before the previous record...
                    326:                 */
1.49      kjell     327:                if (!isreg && rec->type == DELETE) {
1.9       vincent   328:                        if (rec->pos - rec->region.r_size != pos)
1.47      kjell     329:                                undo_add_boundary(FFRAND, 1);
1.23      vincent   330:                }
1.3       vincent   331:        }
1.1       vincent   332:        rec = new_undo_record();
                    333:        rec->pos = pos;
1.49      kjell     334:        if (isreg)
                    335:                rec->type = DELREG;
                    336:        else
                    337:                rec->type = DELETE;
1.35      deraadt   338:        memmove(&rec->region, &reg, sizeof(struct region));
1.1       vincent   339:        do {
                    340:                rec->content = malloc(reg.r_size + 1);
                    341:        } while ((rec->content == NULL) && drop_oldest_undo_record());
1.9       vincent   342:
1.1       vincent   343:        if (rec->content == NULL)
                    344:                panic("Out of memory");
1.9       vincent   345:
1.1       vincent   346:        region_get_data(&reg, rec->content, reg.r_size);
                    347:
1.49      kjell     348:        if (isreg || lastrectype() != DELETE)
1.47      kjell     349:                undo_add_boundary(FFRAND, 1);
1.22      vincent   350:
1.50      oga       351:        TAILQ_INSERT_HEAD(&curbp->b_undo, rec, next);
1.1       vincent   352:
1.11      vincent   353:        return (TRUE);
1.1       vincent   354: }
                    355:
                    356: /*
1.25      db        357:  * This of course must be called before the change takes place.
1.1       vincent   358:  */
                    359: int
1.35      deraadt   360: undo_add_change(struct line *lp, int offset, int size)
1.1       vincent   361: {
1.47      kjell     362:        if (!undo_enable_flag)
1.11      vincent   363:                return (TRUE);
1.47      kjell     364:        undo_add_boundary(FFRAND, 1);
1.42      kjell     365:        boundary_flag = FALSE;
1.49      kjell     366:        undo_add_delete(lp, offset, size, 0);
1.12      vincent   367:        undo_add_insert(lp, offset, size);
1.42      kjell     368:        boundary_flag = TRUE;
1.47      kjell     369:        undo_add_boundary(FFRAND, 1);
1.9       vincent   370:
1.11      vincent   371:        return (TRUE);
1.8       vincent   372: }
                    373:
                    374: /*
                    375:  * Show the undo records for the current buffer in a new buffer.
                    376:  */
1.32      kjell     377: /* ARGSUSED */
1.8       vincent   378: int
1.18      vincent   379: undo_dump(int f, int n)
1.8       vincent   380: {
1.25      db        381:        struct   undo_rec *rec;
1.35      deraadt   382:        struct buffer   *bp;
                    383:        struct mgwin    *wp;
1.25      db        384:        char     buf[4096], tmp[1024];
                    385:        int      num;
1.8       vincent   386:
                    387:        /*
                    388:         * Prepare the buffer for insertion.
                    389:         */
                    390:        if ((bp = bfind("*undo*", TRUE)) == NULL)
1.11      vincent   391:                return (FALSE);
1.9       vincent   392:        bp->b_flag |= BFREADONLY;
1.8       vincent   393:        bclear(bp);
1.54      lum       394:        if ((wp = popbuf(bp, WNONE)) == NULL)
                    395:                return (FALSE);
1.8       vincent   396:
1.10      vincent   397:        for (wp = wheadp; wp != NULL; wp = wp->w_wndp) {
1.8       vincent   398:                if (wp->w_bufp == bp) {
1.41      kjell     399:                        wp->w_dotp = bp->b_headp;
1.8       vincent   400:                        wp->w_doto = 0;
                    401:                }
1.10      vincent   402:        }
1.8       vincent   403:
                    404:        num = 0;
1.50      oga       405:        TAILQ_FOREACH(rec, &curbp->b_undo, next) {
1.8       vincent   406:                num++;
1.25      db        407:                snprintf(buf, sizeof(buf),
1.38      kjell     408:                    "%d:\t %s at %d ", num,
1.8       vincent   409:                    (rec->type == DELETE) ? "DELETE":
1.49      kjell     410:                    (rec->type == DELREG) ? "DELREGION":
1.8       vincent   411:                    (rec->type == INSERT) ? "INSERT":
1.40      kjell     412:                    (rec->type == BOUNDARY) ? "----" :
                    413:                    (rec->type == MODIFIED) ? "MODIFIED": "UNKNOWN",
1.8       vincent   414:                    rec->pos);
1.10      vincent   415:
1.12      vincent   416:                if (rec->content) {
1.38      kjell     417:                        (void)strlcat(buf, "\"", sizeof(buf));
1.25      db        418:                        snprintf(tmp, sizeof(tmp), "%.*s", rec->region.r_size,
1.8       vincent   419:                            rec->content);
1.38      kjell     420:                        (void)strlcat(buf, tmp, sizeof(buf));
                    421:                        (void)strlcat(buf, "\"", sizeof(buf));
1.8       vincent   422:                }
1.25      db        423:                snprintf(tmp, sizeof(tmp), " [%d]", rec->region.r_size);
1.33      kjell     424:                if (strlcat(buf, tmp, sizeof(buf)) >= sizeof(buf)) {
1.55    ! lum       425:                        dobeep();
1.33      kjell     426:                        ewprintf("Undo record too large. Aborted.");
                    427:                        return (FALSE);
                    428:                }
1.17      deraadt   429:                addlinef(bp, "%s", buf);
1.53      florian   430:        }
                    431:        for (wp = wheadp; wp != NULL; wp = wp->w_wndp) {
                    432:                if (wp->w_bufp == bp) {
                    433:                        wp->w_dotline = num+1;
                    434:                        wp->w_rflag |= WFFULL;
                    435:                }
1.8       vincent   436:        }
1.11      vincent   437:        return (TRUE);
1.1       vincent   438: }
                    439:
1.9       vincent   440: /*
1.25      db        441:  * After the user did action1, then action2, then action3:
1.9       vincent   442:  *
                    443:  *     [action3] <--- Undoptr
                    444:  *     [action2]
                    445:  *     [action1]
                    446:  *      ------
                    447:  *      [undo]
                    448:  *
                    449:  * After undo:
                    450:  *
                    451:  *     [undo of action3]
                    452:  *     [action2] <--- Undoptr
                    453:  *     [action1]
                    454:  *      ------
                    455:  *      [undo]
1.13      deraadt   456:  *
1.9       vincent   457:  * After another undo:
                    458:  *
                    459:  *
                    460:  *     [undo of action2]
                    461:  *     [undo of action3]
                    462:  *     [action1]  <--- Undoptr
                    463:  *      ------
                    464:  *      [undo]
1.13      deraadt   465:  *
1.25      db        466:  * Note that the "undo of actionX" have no special meaning. Only when
                    467:  * we undo a deletion, the insertion will be recorded just as if it
1.10      vincent   468:  * was typed on the keyboard. Resulting in the inverse operation being
1.9       vincent   469:  * saved in the list.
                    470:  *
                    471:  * If undoptr reaches the bottom of the list, or if we moved between
                    472:  * two undo actions, we make it point back at the topmost record. This is
                    473:  * how we handle redoing.
                    474:  */
1.32      kjell     475: /* ARGSUSED */
1.1       vincent   476: int
1.4       vincent   477: undo(int f, int n)
1.1       vincent   478: {
1.25      db        479:        struct undo_rec *ptr, *nptr;
1.31      deraadt   480:        int              done, rval;
1.36      kjell     481:        struct line     *lp;
1.51      florian   482:        int              offset, save;
1.28      kjell     483:        static int       nulled = FALSE;
1.39      kjell     484:        int              lineno;
1.23      vincent   485:
1.46      kjell     486:        if (n < 0)
                    487:                return (FALSE);
                    488:
1.29      kjell     489:        ptr = curbp->b_undoptr;
1.9       vincent   490:
1.46      kjell     491:        /* first invocation, make ptr point back to the top of the list */
                    492:        if ((ptr == NULL && nulled == TRUE) ||  rptcount == 0) {
1.50      oga       493:                ptr = TAILQ_FIRST(&curbp->b_undo);
1.28      kjell     494:                nulled = TRUE;
                    495:        }
1.1       vincent   496:
1.9       vincent   497:        rval = TRUE;
1.10      vincent   498:        while (n--) {
1.9       vincent   499:                /* if we have a spurious boundary, free it and move on.... */
                    500:                while (ptr && ptr->type == BOUNDARY) {
1.50      oga       501:                        nptr = TAILQ_NEXT(ptr, next);
                    502:                        TAILQ_REMOVE(&curbp->b_undo, ptr, next);
1.9       vincent   503:                        free_undo_record(ptr);
                    504:                        ptr = nptr;
1.4       vincent   505:                }
                    506:                /*
1.9       vincent   507:                 * Ptr is NULL, but on the next run, it will point to the
                    508:                 * top again, redoing all stuff done in the buffer since
                    509:                 * its creation.
1.4       vincent   510:                 */
1.9       vincent   511:                if (ptr == NULL) {
1.55    ! lum       512:                        dobeep();
1.11      vincent   513:                        ewprintf("No further undo information");
1.9       vincent   514:                        rval = FALSE;
1.28      kjell     515:                        nulled = TRUE;
1.4       vincent   516:                        break;
                    517:                }
1.28      kjell     518:                nulled = FALSE;
1.6       vincent   519:
1.13      deraadt   520:                /*
1.9       vincent   521:                 * Loop while we don't get a boundary specifying we've
                    522:                 * finished the current action...
                    523:                 */
1.22      vincent   524:
1.47      kjell     525:                undo_add_boundary(FFRAND, 1);
1.22      vincent   526:
1.42      kjell     527:                save = boundary_flag;
                    528:                boundary_flag = FALSE;
1.22      vincent   529:
1.9       vincent   530:                done = 0;
                    531:                do {
                    532:                        /*
                    533:                         * Move to where this has to apply
                    534:                         *
1.40      kjell     535:                         * Boundaries (and the modified flag)  are put as
                    536:                         * position 0 (to save lookup time in find_dot)
                    537:                         * so we must not move there...
1.9       vincent   538:                         */
1.40      kjell     539:                        if (ptr->type != BOUNDARY && ptr->type != MODIFIED) {
1.24      vincent   540:                                if (find_lo(ptr->pos, &lp,
1.39      kjell     541:                                    &offset, &lineno) == FALSE) {
1.55    ! lum       542:                                        dobeep();
1.9       vincent   543:                                        ewprintf("Internal error in Undo!");
                    544:                                        rval = FALSE;
                    545:                                        break;
                    546:                                }
                    547:                                curwp->w_dotp = lp;
                    548:                                curwp->w_doto = offset;
1.39      kjell     549:                                curwp->w_markline = curwp->w_dotline;
                    550:                                curwp->w_dotline = lineno;
1.9       vincent   551:                        }
                    552:
                    553:                        /*
                    554:                         * Do operation^-1
                    555:                         */
                    556:                        switch (ptr->type) {
                    557:                        case INSERT:
1.34      kjell     558:                                ldelete(ptr->region.r_size, KNONE);
1.9       vincent   559:                                break;
                    560:                        case DELETE:
1.46      kjell     561:                                lp = curwp->w_dotp;
                    562:                                offset = curwp->w_doto;
1.13      deraadt   563:                                region_put_data(ptr->content,
1.9       vincent   564:                                    ptr->region.r_size);
1.46      kjell     565:                                curwp->w_dotp = lp;
                    566:                                curwp->w_doto = offset;
1.49      kjell     567:                                break;
                    568:                        case DELREG:
                    569:                                region_put_data(ptr->content,
                    570:                                    ptr->region.r_size);
1.9       vincent   571:                                break;
                    572:                        case BOUNDARY:
                    573:                                done = 1;
1.40      kjell     574:                                break;
                    575:                        case MODIFIED:
                    576:                                curbp->b_flag &= ~BFCHG;
1.9       vincent   577:                                break;
                    578:                        default:
                    579:                                break;
                    580:                        }
                    581:
                    582:                        /* And move to next record */
1.50      oga       583:                        ptr = TAILQ_NEXT(ptr, next);
1.9       vincent   584:                } while (ptr != NULL && !done);
1.22      vincent   585:
1.42      kjell     586:                boundary_flag = save;
1.47      kjell     587:                undo_add_boundary(FFRAND, 1);
1.9       vincent   588:
                    589:                ewprintf("Undo!");
1.1       vincent   590:        }
1.51      florian   591:
1.29      kjell     592:        curbp->b_undoptr = ptr;
1.9       vincent   593:
1.13      deraadt   594:        return (rval);
1.1       vincent   595: }