Annotation of 43BSDReno/contrib/emacs-18.55/src/undo.c, revision 1.1

1.1     ! root        1: /* Support routines for the undo facility.
        !             2:    Copyright (C) 1985, 1986 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU Emacs.
        !             5: 
        !             6: GNU Emacs is distributed in the hope that it will be useful,
        !             7: but WITHOUT ANY WARRANTY.  No author or distributor
        !             8: accepts responsibility to anyone for the consequences of using it
        !             9: or for whether it serves any particular purpose or works at all,
        !            10: unless he says so in writing.  Refer to the GNU Emacs General Public
        !            11: License for full details.
        !            12: 
        !            13: Everyone is granted permission to copy, modify and redistribute
        !            14: GNU Emacs, but only under the conditions described in the
        !            15: GNU Emacs General Public License.   A copy of this license is
        !            16: supposed to have been given to you along with GNU Emacs so you
        !            17: can know your rights and responsibilities.  It should be in a
        !            18: file named COPYING.  Among other things, the copyright notice
        !            19: and this notice must be preserved on all copies.  */
        !            20: 
        !            21: 
        !            22: #include "config.h"
        !            23: #include "lisp.h"
        !            24: #include "undo.h"
        !            25: #include "commands.h"
        !            26: #include "buffer.h"
        !            27: 
        !            28: /* Access undo records of current buffer */
        !            29: /* These assume that `u' points to the buffer's undodata */
        !            30: #define UndoRQ (u->undorecs)
        !            31: #define UndoCQ (u->undochars)
        !            32: #define FillRQ (u->nextrec)
        !            33: #define FillCQ (u->nextchar)
        !            34: 
        !            35: /* Record last undo record made, and what buffer made in */
        !            36: static struct UndoRec *LastUndoRec;
        !            37: static struct buffer *LastUndoBuf;
        !            38: 
        !            39: /* Record progress of undoing */
        !            40: static int NUndone;
        !            41: static int NCharsLeft;
        !            42: static int LastUndoneC;
        !            43: static int LastUndone;
        !            44: static struct buffer *LastUndoneBuf;
        !            45: 
        !            46: Lisp_Object Fundo_boundary ();
        !            47: 
        !            48: make_undo_records (b)
        !            49:      struct buffer *b;
        !            50: {
        !            51:   register struct UndoData *u;
        !            52:   b->undodata = u = (struct UndoData *) xmalloc (sizeof (struct UndoData));
        !            53:   u->undorecs
        !            54:     = (struct UndoRec *) xmalloc (sizeof (struct UndoRec) * InitNUndoR);
        !            55:   u->undochars = (char *) xmalloc (InitNUndoC);
        !            56:   u->undorecs[InitNUndoR - 1].kind = Unundoable;
        !            57:   u->nextrec = 0;
        !            58:   u->nextchar = 0;
        !            59:   u->num_undorecs = InitNUndoR;
        !            60:   u->num_undochars = InitNUndoC;
        !            61: }
        !            62: 
        !            63: free_undo_records (b)
        !            64:      struct buffer *b;
        !            65: {
        !            66:   register struct UndoData *u = b->undodata;
        !            67:   free (u->undorecs);
        !            68:   free (u->undochars);
        !            69:   free (u);
        !            70: }
        !            71: 
        !            72: struct UndoRec *
        !            73: record_undo (kind, pos, len)
        !            74:      enum Ukinds kind;
        !            75: {
        !            76:   register struct UndoData *u = bf_cur->undodata;
        !            77:   register struct UndoRec *p = &UndoRQ[FillRQ];
        !            78:   register struct UndoRec *np;
        !            79: 
        !            80:   FillRQ++;
        !            81:   if (FillRQ >= NUndoR)
        !            82:     FillRQ = 0;
        !            83:   else if (FillRQ >= u->num_undorecs)
        !            84:     {
        !            85:       np = (struct UndoRec *) xrealloc (UndoRQ, NUndoR * sizeof *p);
        !            86:       if (np)
        !            87:        {
        !            88:          UndoRQ = np;
        !            89:          p = &UndoRQ[FillRQ-1];
        !            90:          u->num_undorecs = NUndoR;
        !            91:          np[NUndoR - 1].kind = Unundoable;
        !            92:        }
        !            93:       else
        !            94:        FillRQ = 0;
        !            95:     }
        !            96:   UndoRQ[FillRQ].kind = Unundoable;
        !            97:   p -> kind = kind;
        !            98:   p -> pos = pos;
        !            99:   p -> len = len;
        !           100:   LastUndoRec = p;
        !           101:   LastUndoBuf = bf_cur;
        !           102:   if (kind != Uboundary)
        !           103:     LastUndone = -1;
        !           104:   return p;
        !           105: }
        !           106: 
        !           107: record_insert (pos, n)
        !           108: {
        !           109:   register struct UndoRec *p = LastUndoRec;
        !           110:   if (!bf_cur->undodata)
        !           111:     return;
        !           112:   if (LastUndoBuf != bf_cur)
        !           113:     {
        !           114:       Fundo_boundary ();
        !           115:       p = 0;
        !           116:     }
        !           117: 
        !           118:   if (bf_modified <= bf_cur->save_modified)
        !           119:     record_undo (Uunmod, pos, bf_cur->modtime);
        !           120: 
        !           121:   if (p && p -> kind == Udelete && p -> pos + p -> len == pos)
        !           122:     p -> len += n;
        !           123:   else
        !           124:     record_undo (Udelete, pos, n);
        !           125: }
        !           126: 
        !           127: record_delete (pos, n)
        !           128:      int pos, n;
        !           129: {
        !           130:   register struct UndoRec *p = LastUndoRec;
        !           131: 
        !           132:   if (!bf_cur->undodata)
        !           133:     return;
        !           134:   if (LastUndoBuf != bf_cur)
        !           135:     {
        !           136:       Fundo_boundary ();
        !           137:       p = 0;
        !           138:     }
        !           139: 
        !           140:   if (bf_modified <= bf_cur->save_modified)
        !           141:     record_undo (Uunmod, pos, bf_cur->modtime);
        !           142: 
        !           143:   if (p && p->kind == Uinsert && p->pos == pos && p->len > 0)
        !           144:     p->len += n;
        !           145:   else if (point == pos + n)
        !           146:     record_undo (Uinsert, pos + n, - n);
        !           147:   else
        !           148:     record_undo (Uinsert, pos, n);
        !           149: 
        !           150:   record_chars (pos, n);
        !           151: }
        !           152: 
        !           153: record_chars (pos, n)
        !           154:      register int pos, n;
        !           155: {
        !           156:   if (pos < bf_s1 + 1 && pos + n > bf_s1 + 1)
        !           157:     {
        !           158:       record_block (&CharAt (pos), bf_s1 + 1 - pos);
        !           159:       n -= bf_s1 + 1 - pos;
        !           160:       pos = bf_s1 + 1;
        !           161:     }
        !           162: 
        !           163:   record_block (&CharAt (pos), n);
        !           164: }
        !           165: 
        !           166: record_block (p, n)
        !           167:      register char *p;
        !           168:      register int n;
        !           169: {
        !           170:   register char *cp;
        !           171:   register struct UndoData *u = bf_cur->undodata;
        !           172:   register int i;
        !           173: 
        !           174:   NCharsLeft -= n;
        !           175:   cp = &UndoCQ[FillCQ];
        !           176: 
        !           177:   while (n > 0)
        !           178:     {
        !           179:       i = u->num_undochars - FillCQ;
        !           180:       if (i > n) i = n;
        !           181:       if (i > 0)
        !           182:        {
        !           183:          bcopy (p, cp, i);
        !           184:          p += i;
        !           185:          FillCQ += i;
        !           186:          n -= i;
        !           187:        }
        !           188: 
        !           189:       if (n == 0)
        !           190:        break;
        !           191: 
        !           192:       if (FillCQ >= NUndoC)
        !           193:        {
        !           194:          FillCQ = 0;
        !           195:          cp = UndoCQ;
        !           196:        }
        !           197:       else
        !           198:        {
        !           199:          cp = (char *) xrealloc (UndoCQ, NUndoC);
        !           200:          UndoCQ = cp;
        !           201:          cp += FillCQ;
        !           202:          NCharsLeft += NUndoC - u->num_undochars;
        !           203:          u->num_undochars = NUndoC;
        !           204:        }
        !           205:     }
        !           206: }
        !           207: 
        !           208: record_change (pos, n)
        !           209:      int pos, n;
        !           210: {
        !           211:   register struct UndoRec *p = LastUndoRec;
        !           212:   if (!bf_cur->undodata)
        !           213:     return;
        !           214:   if (LastUndoBuf != bf_cur)
        !           215:     {
        !           216:       Fundo_boundary ();
        !           217:       p = 0;
        !           218:     }
        !           219: 
        !           220:   if (bf_modified <= bf_cur->save_modified)
        !           221:     record_undo (Uunmod, pos, bf_cur->modtime);
        !           222: 
        !           223:   if (p && p->kind == Uchange && p->len > 0 && p->pos + p->len == pos)
        !           224:     p->len += n;
        !           225:   else if (point == pos + n)
        !           226:     record_undo (Uchange, pos + n, -n);
        !           227:   else
        !           228:     record_undo (Uchange, pos, n);
        !           229: 
        !           230:   record_chars (pos, n);
        !           231: }
        !           232: 
        !           233: record_change1 (pos, bufp, n)
        !           234:      int pos;
        !           235:      char *bufp;
        !           236:      int n;
        !           237: {
        !           238:   register struct UndoRec *p = LastUndoRec;
        !           239:   if (!bf_cur->undodata)
        !           240:     return;
        !           241:   if (LastUndoBuf != bf_cur)
        !           242:     {
        !           243:       Fundo_boundary ();
        !           244:       p = 0;
        !           245:     }
        !           246:   if (p && p->kind == Uchange && p->len > 0 && p->pos + p->len == pos)
        !           247:     p -> len += n;
        !           248:   else
        !           249:     record_undo (Uchange, pos, n);
        !           250: 
        !           251:   record_block (bufp, n);
        !           252: }
        !           253: 
        !           254: DoneIsDone ()
        !           255: {
        !           256:   register struct UndoData *u = bf_cur->undodata;
        !           257:   register struct UndoRec *p;
        !           258: 
        !           259:   if (!u)
        !           260:     return 0;
        !           261: 
        !           262:   p = &UndoRQ[(FillRQ + u->num_undorecs - 1) % u->num_undorecs];
        !           263:   if (p->kind != Unundoable)
        !           264:     record_undo (Unundoable, point, 0);
        !           265:   return 0;
        !           266: }
        !           267: 
        !           268: DEFUN ("undo-boundary", Fundo_boundary, Sundo_boundary, 0, 0, 0,
        !           269:   "Mark a boundary between units of undo.\n\
        !           270: An undo command will stop at this point,\n\
        !           271: but another undo command will undo to the previous boundary.")
        !           272:   ()
        !           273: {
        !           274:   register struct UndoData *u = bf_cur->undodata;
        !           275:   register struct UndoRec *p;
        !           276: 
        !           277:   if (!u)
        !           278:     return Qnil;
        !           279: 
        !           280:   p = &UndoRQ[(FillRQ + u->num_undorecs - 1) % u->num_undorecs];
        !           281:   if (p->kind != Uboundary)
        !           282:     record_undo (Uboundary, point, 0);
        !           283:   return Qnil;
        !           284: }
        !           285: 
        !           286: DEFUN ("undo-more", Fundo_more, Sundo_more, 1, 1, 0,
        !           287:   "Undo back N undo-boundaries beyond what was already undone recently.\n\
        !           288: Call undo-start to get ready to undo recent changes,\n\
        !           289: then call undo-more one or more times to undo them.")
        !           290:   (pfxarg)
        !           291:      Lisp_Object pfxarg;
        !           292: {
        !           293:   register struct UndoData *u = bf_cur->undodata;
        !           294:   register int n = 0;
        !           295:   register int chars;
        !           296:   register int i = LastUndone;
        !           297:   register int arg = XINT (pfxarg);
        !           298:   register int len, pos;
        !           299:   char tembuf[NUndoC];
        !           300: 
        !           301:   if (!u)
        !           302:     return Qnil;
        !           303: 
        !           304:   if (LastUndoneBuf != bf_cur ||
        !           305:       i == -1)
        !           306:     error ("Cannot undo more: changes have been made since the last undo");
        !           307: 
        !           308:   while (1)
        !           309:     {
        !           310:       while (UndoRQ[i = (!i ? u->num_undorecs-1 : i-1)].kind != Uboundary)
        !           311:        {
        !           312:          len = UndoRQ[i].len;
        !           313:          if (len < 0) len = - len;
        !           314:          if (((UndoRQ[i].kind == Uinsert || UndoRQ[i].kind == Uchange)
        !           315:               && (NCharsLeft -= len) < 0)
        !           316:              || UndoRQ[i].kind == Unundoable || NUndone >= u->num_undorecs)
        !           317:            error ("No further undo information available");
        !           318:          NUndone++;
        !           319:          n++;
        !           320:        }
        !           321:       NUndone++;
        !           322:       n++;
        !           323:       if (--arg <= 0)
        !           324:        break;
        !           325:     }
        !           326: 
        !           327:   i = LastUndone;
        !           328:   chars = LastUndoneC;
        !           329:   while (--n >= 0)
        !           330:     {
        !           331:       if (!i)
        !           332:        i = u->num_undorecs;
        !           333:       i--;
        !           334: 
        !           335:       len = UndoRQ[i].len;
        !           336:       pos = UndoRQ[i].pos;
        !           337: 
        !           338:       if (UndoRQ[i].kind == Uchange || UndoRQ[i].kind == Uinsert)
        !           339:        if (len < 0)
        !           340:          {
        !           341:            pos += len;
        !           342:            len = - len;
        !           343:          }
        !           344: 
        !           345: #ifdef SWITCH_ENUM_BUG
        !           346:       switch ((int) UndoRQ[i].kind)
        !           347: #else
        !           348:       switch (UndoRQ[i].kind)
        !           349: #endif
        !           350:        {
        !           351:        case Uchange:
        !           352:        case Udelete:
        !           353:          if (pos < FirstCharacter || pos + len > NumCharacters + 1)
        !           354:            error ("Changes to be undone are outside visible portion of buffer");
        !           355:          SetPoint (pos);
        !           356:          break;
        !           357: 
        !           358:        case Uinsert:
        !           359:          if (pos < FirstCharacter || pos > NumCharacters + 1)
        !           360:            error ("Changes to be undone are outside visible portion of buffer");
        !           361:          SetPoint (pos);
        !           362:        }
        !           363: 
        !           364: #ifdef SWITCH_ENUM_BUG
        !           365:       switch ((int) UndoRQ[i].kind)
        !           366: #else
        !           367:       switch (UndoRQ[i].kind)
        !           368: #endif
        !           369:        {
        !           370:        case Uboundary: 
        !           371:          break;
        !           372: 
        !           373:        case Udelete: 
        !           374:          del_range (point, point + len);
        !           375:          break;
        !           376: 
        !           377:        case Uchange:
        !           378:          if (len > NUndoC)
        !           379:            /* Should have already said "No more undo info available" */
        !           380:            abort ();
        !           381:          save_undone_chars (pos, len, tembuf);
        !           382:          chars -= len;
        !           383:          if (chars < 0)
        !           384:            {
        !           385:              replace_chars (point - chars, len + chars, UndoCQ);
        !           386:              replace_chars (point, - chars, UndoCQ + chars + u->num_undochars);
        !           387:              chars += u->num_undochars;
        !           388:            }
        !           389:          else
        !           390:            replace_chars (point, len, UndoCQ + chars);
        !           391:          record_change1 (point, tembuf, len);
        !           392:          SetPoint (UndoRQ[i].pos);
        !           393:          break;
        !           394: 
        !           395:        case Uinsert:
        !           396:          chars -= len;
        !           397:          if (chars < 0)
        !           398:            {
        !           399:              InsCStr (UndoCQ + chars + u->num_undochars, - chars);
        !           400:              InsCStr (UndoCQ, len + chars);
        !           401:              chars += u->num_undochars;
        !           402:            }
        !           403:          else
        !           404:            InsCStr (UndoCQ + chars, len);
        !           405:          SetPoint (UndoRQ[i].pos);
        !           406:          break;
        !           407: 
        !           408:        case Uunmod:
        !           409:          /* If this Uunmod records an obsolete save
        !           410:             (not matching the actual disk file)
        !           411:             then don't mark unmodified.  */
        !           412:          if (len != bf_cur->modtime)
        !           413:            break;
        !           414: #ifdef CLASH_DETECTION
        !           415:          Funlock_buffer ();
        !           416: #endif /* CLASH_DETECTION */
        !           417:          bf_cur->save_modified = bf_modified;
        !           418:          RedoModes++;
        !           419:          break;
        !           420: 
        !           421:        default: 
        !           422:          error ("Changes to great to be undone");
        !           423:          return Qnil;
        !           424:        }
        !           425:     }
        !           426:   LastUndone = i;
        !           427:   LastUndoneC = chars;
        !           428:   return Qnil;
        !           429: }
        !           430: 
        !           431: replace_chars (pos, n, string)
        !           432:      register int pos, n;
        !           433:      register unsigned char *string;
        !           434: {
        !           435:   modify_region (pos, pos + n);
        !           436:   while (--n >= 0)
        !           437:     {
        !           438:       CharAt (pos) = *string++;
        !           439:       pos++;
        !           440:     }
        !           441: }
        !           442: 
        !           443: save_undone_chars (pos, n, p)
        !           444:      register int pos, n;
        !           445:      register char *p;
        !           446: {
        !           447:   if (pos < bf_s1 + 1 && pos + n > bf_s1 + 1)
        !           448:     {
        !           449:       bcopy (&CharAt (pos), p, bf_s1 + 1 - pos);
        !           450:       p += bf_s1 + 1 - pos;
        !           451:       n -= bf_s1 + 1 - pos;
        !           452:       pos = bf_s1 + 1;
        !           453:     }
        !           454: 
        !           455:   bcopy (&CharAt (pos), p, n);
        !           456: }
        !           457: 
        !           458: DEFUN ("undo-start", Fundo_start, Sundo_start, 0, 0, 0,
        !           459:   "Move undo-pointer to front of undo records.\n\
        !           460: The next call to undo-more will undo the most recently made change.")
        !           461:   ()
        !           462: {
        !           463:   register struct UndoData *u = bf_cur->undodata;
        !           464: 
        !           465:   if (!u)
        !           466:     error ("Undo information not kept for this buffer");
        !           467:   LastUndoneBuf = bf_cur;
        !           468:   NCharsLeft = u->num_undochars;
        !           469:   NUndone = 0;
        !           470:   LastUndone = FillRQ;
        !           471:   LastUndoneC = FillCQ;
        !           472:   return Qnil;
        !           473: }
        !           474: 
        !           475: syms_of_undo ()
        !           476: {
        !           477:   defsubr (&Sundo_start);
        !           478:   defsubr (&Sundo_boundary);
        !           479:   defsubr (&Sundo_more);
        !           480: }

unix.superglobalmegacorp.com

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