Annotation of GNUtools/emacs/src/insdel.c, revision 1.1

1.1     ! root        1: /* Buffer insertion/deletion and gap motion for GNU Emacs.
        !             2:    Copyright (C) 1985, 1986, 1990 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU Emacs.
        !             5: 
        !             6: GNU Emacs is free software; you can redistribute it and/or modify
        !             7: it under the terms of the GNU General Public License as published by
        !             8: the Free Software Foundation; either version 1, or (at your option)
        !             9: any later version.
        !            10: 
        !            11: GNU Emacs is distributed in the hope that it will be useful,
        !            12: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: GNU General Public License for more details.
        !            15: 
        !            16: You should have received a copy of the GNU General Public License
        !            17: along with GNU Emacs; see the file COPYING.  If not, write to
        !            18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            19: 
        !            20: 
        !            21: #include "config.h"
        !            22: #include "lisp.h"
        !            23: #include "buffer.h"
        !            24: #include "window.h"
        !            25: 
        !            26: /* Move gap to position `pos'.
        !            27:    Note that this can quit!  */
        !            28: 
        !            29: move_gap (pos)
        !            30:      int pos;
        !            31: {
        !            32:   if (pos < GPT)
        !            33:     gap_left (pos, 0);
        !            34:   else if (pos > GPT)
        !            35:     gap_right (pos);
        !            36: }
        !            37: 
        !            38: /* Move the gap to POS, which is less than the current GPT.
        !            39:    If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged.  */
        !            40: 
        !            41: gap_left (pos, newgap)
        !            42:      register int pos;
        !            43:      int newgap;
        !            44: {
        !            45:   register unsigned char *to, *from;
        !            46:   register int i;
        !            47:   int new_s1;
        !            48: 
        !            49:   pos--;
        !            50: 
        !            51:   if (!newgap)
        !            52:     {
        !            53:       if (unchanged_modified == MODIFF)
        !            54:        {
        !            55:          beg_unchanged = pos;
        !            56:          end_unchanged = Z - pos - 1;
        !            57:        }
        !            58:       else
        !            59:        {
        !            60:          if (Z - GPT < end_unchanged)
        !            61:            end_unchanged = Z - GPT;
        !            62:          if (pos < beg_unchanged)
        !            63:            beg_unchanged = pos;
        !            64:        }
        !            65:     }
        !            66: 
        !            67:   i = GPT;
        !            68:   to = GAP_END_ADDR;
        !            69:   from = GPT_ADDR;
        !            70:   new_s1 = GPT - BEG;
        !            71: 
        !            72:   /* Now copy the characters.  To move the gap down,
        !            73:      copy characters up.  */
        !            74: 
        !            75:   while (1)
        !            76:     {
        !            77:       /* I gets number of characters left to copy.  */
        !            78:       i = new_s1 - pos;
        !            79:       if (i == 0)
        !            80:        break;
        !            81:       /* If a quit is requested, stop copying now.
        !            82:         Change POS to be where we have actually moved the gap to.  */
        !            83:       if (QUITP)
        !            84:        {
        !            85:          pos = new_s1;
        !            86:          break;
        !            87:        }
        !            88:       /* Move at most 32000 chars before checking again for a quit.  */
        !            89:       if (i > 32000)
        !            90:        i = 32000;
        !            91:       new_s1 -= i;
        !            92:       while (--i >= 0)
        !            93:        *--to = *--from;
        !            94:     }
        !            95: 
        !            96:   /* Adjust markers, and buffer data structure, to put the gap at POS.
        !            97:      POS is where the loop above stopped, which may be what was specified
        !            98:      or may be where a quit was detected.  */
        !            99:   adjust_markers (pos + 1, GPT, GAP_SIZE);
        !           100:   GPT = pos + 1;
        !           101:   QUIT;
        !           102: }
        !           103: 
        !           104: gap_right (pos)
        !           105:      register int pos;
        !           106: {
        !           107:   register unsigned char *to, *from;
        !           108:   register int i;
        !           109:   int new_s1;
        !           110: 
        !           111:   pos--;
        !           112: 
        !           113:   if (unchanged_modified == MODIFF)
        !           114:     {
        !           115:       beg_unchanged = pos;
        !           116:       end_unchanged = Z - pos - 1;
        !           117:     }
        !           118:   else
        !           119:     {
        !           120:       if (Z - pos - 1 < end_unchanged)
        !           121:        end_unchanged = Z - pos - 1;
        !           122:       if (GPT - BEG < beg_unchanged)
        !           123:        beg_unchanged = GPT - BEG;
        !           124:     }
        !           125: 
        !           126:   i = GPT;
        !           127:   from = GAP_END_ADDR;
        !           128:   to = GPT_ADDR;
        !           129:   new_s1 = GPT - 1;
        !           130: 
        !           131:   /* Now copy the characters.  To move the gap up,
        !           132:      copy characters down.  */
        !           133: 
        !           134:   while (1)
        !           135:     {
        !           136:       /* I gets number of characters left to copy.  */
        !           137:       i = pos - new_s1;
        !           138:       if (i == 0)
        !           139:        break;
        !           140:       /* If a quit is requested, stop copying now.
        !           141:         Change POS to be where we have actually moved the gap to.  */
        !           142:       if (QUITP)
        !           143:        {
        !           144:          pos = new_s1;
        !           145:          break;
        !           146:        }
        !           147:       /* Move at most 32000 chars before checking again for a quit.  */
        !           148:       if (i > 32000)
        !           149:        i = 32000;
        !           150:       new_s1 += i;
        !           151:       while (--i >= 0)
        !           152:        *to++ = *from++;
        !           153:     }
        !           154: 
        !           155:   adjust_markers (GPT + GAP_SIZE, pos + 1 + GAP_SIZE, - GAP_SIZE);
        !           156:   GPT = pos + 1;
        !           157:   QUIT;
        !           158: }
        !           159: 
        !           160: /* Add `amount' to the position of every marker in the current buffer
        !           161:    whose current position is between `from' (exclusive) and `to' (inclusive).
        !           162:    Also, any markers past the outside of that interval, in the direction
        !           163:    of adjustment, are first moved back to the near end of the interval
        !           164:    and then adjusted by `amount'.  */
        !           165: 
        !           166: adjust_markers (from, to, amount)
        !           167:      register int from, to, amount;
        !           168: {
        !           169:   Lisp_Object marker;
        !           170:   register struct Lisp_Marker *m;
        !           171:   register int mpos;
        !           172: 
        !           173:   marker = current_buffer->markers;
        !           174: 
        !           175:   while (!NULL (marker))
        !           176:     {
        !           177:       m = XMARKER (marker);
        !           178:       mpos = m->bufpos;
        !           179:       if (amount > 0)
        !           180:        {
        !           181:          if (mpos > to && mpos < to + amount)
        !           182:            mpos = to + amount;
        !           183:        }
        !           184:       else
        !           185:        {
        !           186:          if (mpos > from + amount && mpos <= from)
        !           187:            mpos = from + amount;
        !           188:        }
        !           189:       if (mpos > from && mpos <= to)
        !           190:        mpos += amount;
        !           191:       m->bufpos = mpos;
        !           192:       marker = m->chain;
        !           193:     }
        !           194: }
        !           195: 
        !           196: /* Make the gap INCREMENT characters longer.  */
        !           197: 
        !           198: make_gap (increment)
        !           199:      int increment;
        !           200: {
        !           201:   unsigned char *memory;
        !           202:   Lisp_Object tem;
        !           203:   int real_gap_loc;
        !           204:   int old_gap_size;
        !           205: 
        !           206:   /* If we have to get more space, get enough to last a while.  */
        !           207:   increment += 2000;
        !           208: 
        !           209:   memory = (unsigned char *) realloc (BEG_ADDR,
        !           210:                                      Z - BEG + GAP_SIZE + increment);
        !           211:   if (memory == 0)
        !           212:     memory_full ();
        !           213:   BEG_ADDR = memory;
        !           214: 
        !           215:   /* Prevent quitting in move_gap.  */
        !           216:   tem = Vinhibit_quit;
        !           217:   Vinhibit_quit = Qt;
        !           218: 
        !           219:   real_gap_loc = GPT;
        !           220:   old_gap_size = GAP_SIZE;
        !           221:   /* Call the newly allocated space a gap at the end of the whole space.  */
        !           222:   GPT = Z + GAP_SIZE;
        !           223:   GAP_SIZE = increment;
        !           224:   /* Move the new gap down to be consecutive with the end of the old one.
        !           225:      This adjusts the markers properly too.  */
        !           226:   gap_left (real_gap_loc + old_gap_size, 1);
        !           227:   /* Now combine the two into one large gap.  */
        !           228:   GAP_SIZE += old_gap_size;
        !           229:   GPT = real_gap_loc;
        !           230: 
        !           231:   Vinhibit_quit = tem;
        !           232: }
        !           233: 
        !           234: /* Insert the character c before point */
        !           235: 
        !           236: insert_char (c)
        !           237:      unsigned char c;
        !           238: {
        !           239:   insert (&c, 1);
        !           240: }
        !           241: 
        !           242: /* Insert the null-terminated string s before point */
        !           243: 
        !           244: InsStr (s)
        !           245:      char *s;
        !           246: {
        !           247:   insert (s, strlen (s));
        !           248: }
        !           249: 
        !           250: /* Insert a string of specified length before point.
        !           251:    DO NOT use this for the contents of a Lisp string!
        !           252:    prepare_to_modify_buffer could relocate the string.  */
        !           253: 
        !           254: insert (string, length)
        !           255:      register unsigned char *string;
        !           256:      register length;
        !           257: {
        !           258:   register Lisp_Object temp;
        !           259: 
        !           260:   if (length < 1)
        !           261:     return;
        !           262: 
        !           263:   /* Make sure point-max won't overflow after this insertion.  */
        !           264:   XSET (temp, Lisp_Int, length + Z);
        !           265:   if (length + Z != XINT (temp))
        !           266:     error ("maximum buffer size exceeded");
        !           267: 
        !           268:   prepare_to_modify_buffer ();
        !           269: 
        !           270:   if (point != GPT)
        !           271:     move_gap (point);
        !           272:   if (GAP_SIZE < length)
        !           273:     make_gap (length - GAP_SIZE);
        !           274: 
        !           275:   record_insert (point, length);
        !           276:   MODIFF++;
        !           277: 
        !           278:   bcopy (string, GPT_ADDR, length);
        !           279: 
        !           280:   GAP_SIZE -= length;
        !           281:   GPT += length;
        !           282:   ZV += length;
        !           283:   Z += length;
        !           284:   point += length;
        !           285: }
        !           286: 
        !           287: /* Function to insert part of the text of a string (STRING) consisting
        !           288:    of LENGTH characters at position POS.
        !           289:    It does not work to use `insert' for this, becase a GC could happen
        !           290:    before we bcopy the stuff into the buffer, and relocate the string
        !           291:    without insert noticing.  */
        !           292: insert_from_string (string, pos, length)
        !           293:      Lisp_Object string;
        !           294:      register int pos, length;
        !           295: {
        !           296:   register Lisp_Object temp;
        !           297:   struct gcpro gcpro1;
        !           298: 
        !           299:   if (length < 1)
        !           300:     return;
        !           301: 
        !           302:   /* Make sure point-max won't overflow after this insertion.  */
        !           303:   XSET (temp, Lisp_Int, length + Z);
        !           304:   if (length + Z != XINT (temp))
        !           305:     error ("maximum buffer size exceeded");
        !           306: 
        !           307:   GCPRO1 (string);
        !           308:   prepare_to_modify_buffer ();
        !           309: 
        !           310:   if (point != GPT)
        !           311:     move_gap (point);
        !           312:   if (GAP_SIZE < length)
        !           313:     make_gap (length - GAP_SIZE);
        !           314: 
        !           315:   record_insert (point, length);
        !           316:   MODIFF++;
        !           317:   UNGCPRO;
        !           318: 
        !           319:   bcopy (XSTRING (string)->data, GPT_ADDR, length);
        !           320: 
        !           321:   GAP_SIZE -= length;
        !           322:   GPT += length;
        !           323:   ZV += length;
        !           324:   Z += length;
        !           325:   point += length;
        !           326: }
        !           327: 
        !           328: /* Like `insert' except that all markers pointing at the place where
        !           329:    the insertion happens are adjusted to point after it.
        !           330:    Don't use this function to insert part of a Lisp string,
        !           331:    since gc could happen and relocate it.  */
        !           332: 
        !           333: insert_before_markers (string, length)
        !           334:      unsigned char *string;
        !           335:      register int length;
        !           336: {
        !           337:   register int opoint = point;
        !           338:   insert (string, length);
        !           339:   adjust_markers (opoint - 1, opoint, length);
        !           340: }
        !           341: 
        !           342: /* Insert part of a Lisp string, relocating markers after.  */
        !           343: 
        !           344: insert_from_string_before_markers (string, pos, length)
        !           345:      Lisp_Object string;
        !           346:      register int pos, length;
        !           347: {
        !           348:   register int opoint = point;
        !           349:   insert_from_string (string, pos, length);
        !           350:   adjust_markers (opoint - 1, opoint, length);
        !           351: }
        !           352: 
        !           353: /* Delete characters in current buffer
        !           354:   from `from' up to (but not incl) `to' */
        !           355: 
        !           356: del_range (from, to)
        !           357:      register int from, to;
        !           358: {
        !           359:   register int numdel;
        !           360: 
        !           361:   /* Make args be valid */
        !           362:   if (from < BEGV)
        !           363:     from = BEGV;
        !           364:   if (to > ZV)
        !           365:     to = ZV;
        !           366: 
        !           367:   if ((numdel = to - from) <= 0)
        !           368:     return;
        !           369: 
        !           370:   /* Make sure the gap is somewhere in or next to what we are deleting */
        !           371:   if (from > GPT)
        !           372:     gap_right (from);
        !           373:   if (to < GPT)
        !           374:     gap_left (to, 0);
        !           375: 
        !           376:   prepare_to_modify_buffer ();
        !           377:   record_delete (from, numdel);
        !           378:   MODIFF++;
        !           379: 
        !           380:   /* Relocate point as if it were a marker.  */
        !           381:   if (from < point)
        !           382:     {
        !           383:       if (point < to)
        !           384:        point = from;
        !           385:       else
        !           386:        point -= numdel;
        !           387:     }
        !           388: 
        !           389:   /* Relocate all markers pointing into the new, larger gap
        !           390:      to point at the end of the text before the gap.  */
        !           391:   adjust_markers (to + GAP_SIZE, to + GAP_SIZE, - numdel - GAP_SIZE);
        !           392: 
        !           393:   GAP_SIZE += numdel;
        !           394:   ZV -= numdel;
        !           395:   Z -= numdel;
        !           396:   GPT = from;
        !           397: 
        !           398:   if (GPT - BEG < beg_unchanged)
        !           399:     beg_unchanged = GPT - BEG;
        !           400:   if (Z - GPT < end_unchanged)
        !           401:     end_unchanged = Z - GPT;
        !           402: }
        !           403: 
        !           404: modify_region (start, end)
        !           405:      int start, end;
        !           406: {
        !           407:   prepare_to_modify_buffer ();
        !           408:   if (start - 1 < beg_unchanged || unchanged_modified == MODIFF)
        !           409:     beg_unchanged = start - 1;
        !           410:   if (Z - end < end_unchanged
        !           411:       || unchanged_modified == MODIFF)
        !           412:     end_unchanged = Z - end;
        !           413:   MODIFF++;
        !           414: }
        !           415: 
        !           416: prepare_to_modify_buffer ()
        !           417: {
        !           418:   if (!NULL (current_buffer->read_only))
        !           419:     Fbarf_if_buffer_read_only();
        !           420: 
        !           421: #ifdef CLASH_DETECTION
        !           422:   if (!NULL (current_buffer->filename)
        !           423:       && current_buffer->save_modified >= MODIFF)
        !           424:     lock_file (current_buffer->filename);
        !           425: #else
        !           426:   /* At least warn if this file has changed on disk since it was visited.  */
        !           427:   if (!NULL (current_buffer->filename)
        !           428:       && current_buffer->save_modified >= MODIFF
        !           429:       && NULL (Fverify_visited_file_modtime (Fcurrent_buffer ()))
        !           430:       && !NULL (Ffile_exists_p (current_buffer->filename)))
        !           431:     call1 (intern ("ask-user-about-supersession-threat"),
        !           432:           current_buffer->filename);
        !           433: #endif /* not CLASH_DETECTION */
        !           434: }

unix.superglobalmegacorp.com

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