Annotation of GNUtools/emacs/src/insdel.c, revision 1.1.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.