|
|
1.1 ! root 1: /* Buffer insertion/deletion and gap motion for GNU Emacs. ! 2: Copyright (C) 1985 Richard M. Stallman. ! 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 "buffer.h" ! 25: #include "window.h" ! 26: ! 27: /* Move gap to position `pos'. */ ! 28: ! 29: GapTo (pos) ! 30: int pos; ! 31: { ! 32: if (bf_p2 != bf_gap + bf_p1) ! 33: abort (); ! 34: ! 35: if (pos <= bf_s1) ! 36: gap_left (pos); ! 37: else if (pos > bf_s1 + 1) ! 38: gap_right (pos); ! 39: } ! 40: ! 41: gap_left (pos) ! 42: register int pos; ! 43: { ! 44: register unsigned char *to, *from; ! 45: register int i; ! 46: ! 47: pos--; ! 48: ! 49: if (unchanged_modified == bf_modified) ! 50: { ! 51: beg_unchanged = pos; ! 52: end_unchanged = bf_s1 + bf_s2 - pos; ! 53: } ! 54: else ! 55: { ! 56: if (bf_s2 < end_unchanged) ! 57: end_unchanged = bf_s2; ! 58: if (pos < beg_unchanged) ! 59: beg_unchanged = pos; ! 60: } ! 61: ! 62: adjust_markers (pos + 1, bf_s1 + 1, bf_gap); ! 63: ! 64: to = bf_p2; ! 65: from = bf_p1; ! 66: ! 67: i = bf_s1 + 1; ! 68: while (--i > pos) ! 69: to[i] = from[i]; ! 70: ! 71: bf_s2 += bf_s1 - pos; ! 72: bf_s1 = pos; ! 73: } ! 74: ! 75: gap_right (pos) ! 76: register int pos; ! 77: { ! 78: register unsigned char *to, *from; ! 79: register int i; ! 80: ! 81: pos--; ! 82: ! 83: if (unchanged_modified == bf_modified) ! 84: { ! 85: beg_unchanged = pos; ! 86: end_unchanged = bf_s1 + bf_s2 - pos; ! 87: } ! 88: else ! 89: { ! 90: if (bf_s1 + bf_s2 - pos < end_unchanged) ! 91: end_unchanged = bf_s1 + bf_s2 - pos; ! 92: if (bf_s1 < beg_unchanged) ! 93: beg_unchanged = bf_s1; ! 94: } ! 95: ! 96: adjust_markers (bf_s1 + bf_gap + 1, pos + bf_gap + 1, - bf_gap); ! 97: ! 98: from = bf_p2; ! 99: to = bf_p1; ! 100: ! 101: i = bf_s1; ! 102: while (++i <= pos) ! 103: to[i] = from[i]; ! 104: ! 105: bf_s2 += bf_s1 - pos; ! 106: bf_s1 = pos; ! 107: } ! 108: ! 109: /* Add `amount' to the position of every marker in the current buffer ! 110: whose current position is between `from' (exclusive) and `to' (inclusive). ! 111: Also, any markers past the outside of that interval, in the direction ! 112: of adjustment, are first moved back to the near end of the interval ! 113: and then adjusted by `amount'. */ ! 114: ! 115: adjust_markers (from, to, amount) ! 116: register int from, to, amount; ! 117: { ! 118: Lisp_Object marker; ! 119: register struct Lisp_Marker *m; ! 120: register int mpos; ! 121: ! 122: marker = bf_cur->markers; ! 123: ! 124: while (!NULL (marker)) ! 125: { ! 126: m = XMARKER (marker); ! 127: mpos = m->bufpos; ! 128: if (amount > 0) ! 129: { ! 130: if (mpos > to && mpos < to + amount) ! 131: mpos = to + amount; ! 132: } ! 133: else ! 134: { ! 135: if (mpos > from + amount && mpos <= from) ! 136: mpos = from + amount; ! 137: } ! 138: if (mpos > from && mpos <= to) ! 139: mpos += amount; ! 140: if (m->bufpos != mpos) ! 141: m->bufpos = mpos, m->modified++; ! 142: marker = m->chain; ! 143: } ! 144: } ! 145: ! 146: /* make sure that the gap in the current buffer is at least k ! 147: characters wide */ ! 148: ! 149: make_gap (k) ! 150: int k; ! 151: { ! 152: register unsigned char *p1, *p2, *lim; ! 153: ! 154: if (bf_gap >= k) ! 155: return; ! 156: ! 157: k += 2000; /* Get more than just enough */ ! 158: ! 159: p1 = (unsigned char *) realloc (bf_p1 + 1, bf_s1 + bf_s2 + k); ! 160: if (p1 == 0) ! 161: memory_full (); ! 162: ! 163: k -= bf_gap; /* Amount of increase. */ ! 164: ! 165: /* Record new location of text */ ! 166: bf_p1 = p1 - 1; ! 167: ! 168: /* Transfer the new free space from the end to the gap ! 169: by shifting the second segment upward */ ! 170: p2 = bf_p1 + 1 + bf_s1 + bf_s2 + bf_gap; ! 171: p1 = p2 + k; ! 172: lim = p2 - bf_s2; ! 173: while (lim < p2) ! 174: *--p1 = *--p2; ! 175: ! 176: /* Finish updating text location data */ ! 177: bf_gap += k; ! 178: bf_p2 = bf_p1 + bf_gap; ! 179: ! 180: /* Don't wait for next SetBfp; make it permanent now. */ ! 181: bf_cur->text = bf_text; ! 182: ! 183: /* adjust markers */ ! 184: adjust_markers (bf_s1 + 1, bf_s1 + bf_s2 + bf_gap + 1, k); ! 185: } ! 186: ! 187: /* Insert the character c before point */ ! 188: ! 189: insert_char (c) ! 190: unsigned char c; ! 191: { ! 192: InsCStr (&c, 1); ! 193: } ! 194: ! 195: /* Insert the null-terminated string s before point */ ! 196: ! 197: InsStr (s) ! 198: char *s; ! 199: { ! 200: InsCStr (s, strlen (s)); ! 201: } ! 202: ! 203: /* Insert a string of specified length before point */ ! 204: ! 205: InsCStr (string, length) ! 206: register unsigned char *string; ! 207: register length; ! 208: { ! 209: if (length<1) ! 210: return; ! 211: ! 212: prepare_to_modify_buffer (); ! 213: RecordInsert (point, length); ! 214: bf_modified++; ! 215: ! 216: if (point != bf_s1 + 1) ! 217: GapTo (point); ! 218: if (bf_gap < length) ! 219: make_gap (length); ! 220: ! 221: bcopy (string, bf_p1 + point, length); ! 222: ! 223: bf_gap -= length; ! 224: bf_p2 -= length; ! 225: bf_s1 += length; ! 226: point += length; ! 227: } ! 228: ! 229: /* like InsCStr except that all markers pointing at the place where ! 230: the insertion happens are adjusted to point after it. */ ! 231: ! 232: insert_before_markers (string, length) ! 233: unsigned char *string; ! 234: register int length; ! 235: { ! 236: register int opoint = point; ! 237: InsCStr (string, length); ! 238: adjust_markers (opoint - 1, opoint, length); ! 239: } ! 240: ! 241: /* Delete characters in current buffer ! 242: from `from' up to (but not incl) `to' */ ! 243: ! 244: del_range (from, to) ! 245: register int from, to; ! 246: { ! 247: register int numdel; ! 248: ! 249: /* Make args be valid */ ! 250: if (from < FirstCharacter) ! 251: from = FirstCharacter; ! 252: if (to > NumCharacters) ! 253: to = NumCharacters + 1; ! 254: ! 255: if ((numdel = to - from) <= 0) ! 256: return; ! 257: ! 258: if (from < point) ! 259: { ! 260: if (point < to) ! 261: point = from; ! 262: else ! 263: point -= numdel; ! 264: } ! 265: ! 266: /* Make sure the gap is somewhere in or next to what we are deleting */ ! 267: if (from - 1 > bf_s1) ! 268: gap_right (from); ! 269: if (to - 1 < bf_s1) ! 270: gap_left (to); ! 271: ! 272: prepare_to_modify_buffer (); ! 273: RecordDelete (from, numdel); ! 274: bf_modified++; ! 275: ! 276: /* All markers pointing between from and to, inclusive, ! 277: should now point at from. */ ! 278: adjust_markers (to, to, -numdel); ! 279: ! 280: bf_gap += numdel; ! 281: bf_p2 += numdel; ! 282: bf_s2 -= to - 1 - bf_s1; ! 283: bf_s1 = from - 1; ! 284: ! 285: if (bf_s1 < beg_unchanged) ! 286: beg_unchanged = bf_s1; ! 287: if (bf_s2 < end_unchanged) ! 288: end_unchanged = bf_s2; ! 289: } ! 290: ! 291: modify_region (start, end) ! 292: int start, end; ! 293: { ! 294: prepare_to_modify_buffer (); ! 295: if (start - 1 < beg_unchanged || unchanged_modified == bf_modified) ! 296: beg_unchanged = start - 1; ! 297: if (bf_s1 + bf_s2 + 1 - end < end_unchanged ! 298: || unchanged_modified == bf_modified) ! 299: end_unchanged = bf_s1 + bf_s2 + 1 - end; ! 300: bf_modified++; ! 301: } ! 302: ! 303: prepare_to_modify_buffer () ! 304: { ! 305: if (!NULL (bf_cur->read_only)) ! 306: Fbarf_if_buffer_read_only(); ! 307: ! 308: #ifdef CLASH_DETECTION ! 309: if (!NULL (bf_cur->filename) ! 310: && bf_cur->save_modified >= bf_modified) ! 311: lock_file (bf_cur->filename); ! 312: #endif /* CLASH_DETECTION */ ! 313: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.