|
|
1.1 ! root 1: /* Markers: examining, setting and killing. ! 2: Copyright (C) 1985 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: ! 25: /* Operations on markers. */ ! 26: ! 27: DEFUN ("marker-buffer", Fmarker_buffer, Smarker_buffer, 1, 1, 0, ! 28: "Return the buffer that MARKER points into, or nil if none.\n\ ! 29: Returns nil if MARKER points into a dead buffer.") ! 30: (marker) ! 31: register Lisp_Object marker; ! 32: { ! 33: register Lisp_Object buf; ! 34: CHECK_MARKER (marker, 0); ! 35: if (XMARKER (marker)->buffer) ! 36: { ! 37: XSET (buf, Lisp_Buffer, XMARKER (marker)->buffer); ! 38: /* Return marker's buffer only if it is not dead. */ ! 39: if (!NULL (XBUFFER (buf)->name)) ! 40: return buf; ! 41: } ! 42: return Qnil; ! 43: } ! 44: ! 45: DEFUN ("marker-position", Fmarker_position, Smarker_position, 1, 1, 0, ! 46: "Return the position MARKER points at, as a character number.") ! 47: (marker) ! 48: Lisp_Object marker; ! 49: { ! 50: register Lisp_Object pos; ! 51: register int i; ! 52: register struct buffer *buf; ! 53: ! 54: CHECK_MARKER (marker, 0); ! 55: if (XMARKER (marker)->buffer) ! 56: { ! 57: buf = XMARKER (marker)->buffer; ! 58: i = XMARKER (marker)->bufpos; ! 59: ! 60: if (i > BUF_GPT (buf) + BUF_GAP_SIZE (buf)) ! 61: i -= BUF_GAP_SIZE (buf); ! 62: else if (i > BUF_GPT (buf)) ! 63: i = BUF_GPT (buf); ! 64: ! 65: if (i < BUF_BEG (buf) || i > BUF_Z (buf)) ! 66: abort (); ! 67: ! 68: XFASTINT (pos) = i; ! 69: return pos; ! 70: } ! 71: return Qnil; ! 72: } ! 73: ! 74: DEFUN ("set-marker", Fset_marker, Sset_marker, 2, 3, 0, ! 75: "Position MARKER before character number NUMBER in BUFFER.\n\ ! 76: BUFFER defaults to the current buffer.\n\ ! 77: If NUMBER is nil, makes marker point nowhere.\n\ ! 78: Then it no longer slows down editing in any buffer.\n\ ! 79: Returns MARKER.") ! 80: (marker, pos, buffer) ! 81: Lisp_Object marker, pos, buffer; ! 82: { ! 83: register int charno; ! 84: register struct buffer *b; ! 85: register struct Lisp_Marker *m; ! 86: ! 87: CHECK_MARKER (marker, 0); ! 88: /* If position is nil or a marker that points nowhere, ! 89: make this marker point nowhere. */ ! 90: if (NULL (pos) || ! 91: (XTYPE (pos) == Lisp_Marker && !XMARKER (pos)->buffer)) ! 92: { ! 93: if (XMARKER (marker)->buffer) ! 94: unchain_marker (marker); ! 95: return marker; ! 96: } ! 97: ! 98: CHECK_NUMBER_COERCE_MARKER (pos, 1); ! 99: if (NULL (buffer)) ! 100: b = current_buffer; ! 101: else ! 102: { ! 103: CHECK_BUFFER (buffer, 1); ! 104: b = XBUFFER (buffer); ! 105: /* If buffer is dead, set marker to point nowhere. */ ! 106: if (EQ (b->name, Qnil)) ! 107: { ! 108: if (XMARKER (marker)->buffer) ! 109: unchain_marker (marker); ! 110: return marker; ! 111: } ! 112: } ! 113: ! 114: charno = XINT (pos); ! 115: m = XMARKER (marker); ! 116: ! 117: if (charno < BUF_BEG (b)) ! 118: charno = BUF_BEG (b); ! 119: if (charno > BUF_Z (b)) ! 120: charno = BUF_Z (b); ! 121: if (charno > BUF_GPT (b)) charno += BUF_GAP_SIZE (b); ! 122: m->bufpos = charno; ! 123: ! 124: if (m->buffer != b) ! 125: { ! 126: if (m->buffer != 0) ! 127: unchain_marker (marker); ! 128: m->chain = b->markers; ! 129: b->markers = marker; ! 130: m->buffer = b; ! 131: } ! 132: ! 133: return marker; ! 134: } ! 135: ! 136: /* This version of Fset_marker won't let the position be outside the visible part. */ ! 137: Lisp_Object ! 138: set_marker_restricted (marker, pos, buffer) ! 139: Lisp_Object marker, pos, buffer; ! 140: { ! 141: register int charno; ! 142: register struct buffer *b; ! 143: register struct Lisp_Marker *m; ! 144: ! 145: CHECK_MARKER (marker, 0); ! 146: /* If position is nil or a marker that points nowhere, ! 147: make this marker point nowhere. */ ! 148: if (NULL (pos) || ! 149: (XTYPE (pos) == Lisp_Marker && !XMARKER (pos)->buffer)) ! 150: { ! 151: if (XMARKER (marker)->buffer) ! 152: unchain_marker (marker); ! 153: return marker; ! 154: } ! 155: ! 156: CHECK_NUMBER_COERCE_MARKER (pos, 1); ! 157: if (NULL (buffer)) ! 158: b = current_buffer; ! 159: else ! 160: { ! 161: CHECK_BUFFER (buffer, 1); ! 162: b = XBUFFER (buffer); ! 163: /* If buffer is dead, set marker to point nowhere. */ ! 164: if (EQ (b->name, Qnil)) ! 165: { ! 166: if (XMARKER (marker)->buffer) ! 167: unchain_marker (marker); ! 168: return marker; ! 169: } ! 170: } ! 171: ! 172: charno = XINT (pos); ! 173: m = XMARKER (marker); ! 174: ! 175: if (charno < BUF_BEGV (b)) ! 176: charno = BUF_BEGV (b); ! 177: if (charno > BUF_ZV (b)) ! 178: charno = BUF_ZV (b); ! 179: if (charno > BUF_GPT (b)) ! 180: charno += BUF_GAP_SIZE (b); ! 181: m->bufpos = charno; ! 182: ! 183: if (m->buffer != b) ! 184: { ! 185: if (m->buffer != 0) ! 186: unchain_marker (marker); ! 187: m->chain = b->markers; ! 188: b->markers = marker; ! 189: m->buffer = b; ! 190: } ! 191: ! 192: return marker; ! 193: } ! 194: ! 195: /* This is called during garbage collection, ! 196: so we must be careful to ignore and preserve mark bits, ! 197: including those in chain fields of markers. */ ! 198: ! 199: unchain_marker (marker) ! 200: register Lisp_Object marker; ! 201: { ! 202: register Lisp_Object tail, prev, next; ! 203: register int omark; ! 204: register struct buffer *b; ! 205: ! 206: b = XMARKER (marker)->buffer; ! 207: ! 208: if (EQ (b->name, Qnil)) ! 209: abort (); ! 210: ! 211: tail = b->markers; ! 212: prev = Qnil; ! 213: while (XSYMBOL (tail) != XSYMBOL (Qnil)) ! 214: { ! 215: next = XMARKER (tail)->chain; ! 216: XUNMARK (next); ! 217: ! 218: if (XMARKER (marker) == XMARKER (tail)) ! 219: { ! 220: if (NULL (prev)) ! 221: { ! 222: b->markers = next; ! 223: /* Deleting first marker from the buffer's chain. ! 224: Crash if new first marker in chain does not say ! 225: it belongs to this buffer. */ ! 226: if (!EQ (next, Qnil) && b != XMARKER (next)->buffer) ! 227: abort (); ! 228: } ! 229: else ! 230: { ! 231: omark = XMARKBIT (XMARKER (prev)->chain); ! 232: XMARKER (prev)->chain = next; ! 233: XSETMARKBIT (XMARKER (prev)->chain, omark); ! 234: } ! 235: break; ! 236: } ! 237: else ! 238: prev = tail; ! 239: tail = next; ! 240: } ! 241: XMARKER (marker)->buffer = 0; ! 242: } ! 243: ! 244: marker_position (marker) ! 245: Lisp_Object marker; ! 246: { ! 247: register struct Lisp_Marker *m = XMARKER (marker); ! 248: register struct buffer *buf = m->buffer; ! 249: register int i = m->bufpos; ! 250: ! 251: if (!buf) ! 252: error ("Marker does not point anywhere"); ! 253: ! 254: if (i > BUF_GPT (buf) + BUF_GAP_SIZE (buf)) ! 255: i -= BUF_GAP_SIZE (buf); ! 256: else if (i > BUF_GPT (buf)) ! 257: i = BUF_GPT (buf); ! 258: ! 259: if (i < BUF_BEG (buf) || i > BUF_Z (buf)) ! 260: abort (); ! 261: ! 262: return i; ! 263: } ! 264: ! 265: DEFUN ("copy-marker", Fcopy_marker, Scopy_marker, 1, 1, 0, ! 266: "Return a new marker pointing at the same place as MARKER.\n\ ! 267: If argument is a number, makes a new marker pointing\n\ ! 268: at that position in the current buffer.") ! 269: (marker) ! 270: register Lisp_Object marker; ! 271: { ! 272: register Lisp_Object new; ! 273: ! 274: while (1) ! 275: { ! 276: if (XTYPE (marker) == Lisp_Int || ! 277: XTYPE (marker) == Lisp_Marker) ! 278: { ! 279: new = Fmake_marker (); ! 280: Fset_marker (new, marker, ! 281: ((XTYPE (marker) == Lisp_Marker) ! 282: ? Fmarker_buffer (marker) ! 283: : Qnil)); ! 284: return new; ! 285: } ! 286: else ! 287: marker = wrong_type_argument (Qinteger_or_marker_p, marker); ! 288: } ! 289: } ! 290: ! 291: syms_of_marker () ! 292: { ! 293: defsubr (&Smarker_position); ! 294: defsubr (&Smarker_buffer); ! 295: defsubr (&Sset_marker); ! 296: defsubr (&Scopy_marker); ! 297: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.