comparison src/marker.c @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 859a2309aef8
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 /* Markers: examining, setting and killing.
2 Copyright (C) 1985, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4 This file is part of XEmacs.
5
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /* Synched up with: FSF 19.30. */
22
23 /* This file has been Mule-ized. */
24
25 /* Note that markers are currently kept in an unordered list.
26 This means that marker operations may be inefficient if
27 there are a bunch of markers in the buffer. This probably
28 won't have a significant impact on redisplay (which uses
29 markers), but if it does, it wouldn't be too hard to change
30 to an ordered gap array. (Just copy the code from extents.c.)
31 */
32
33 #include <config.h>
34 #include "lisp.h"
35
36 #include "buffer.h"
37
38 static Lisp_Object mark_marker (Lisp_Object, void (*) (Lisp_Object));
39 static void print_marker (Lisp_Object, Lisp_Object, int);
40 static int marker_equal (Lisp_Object, Lisp_Object, int);
41 static unsigned long marker_hash (Lisp_Object obj, int depth);
42 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("marker", marker,
43 mark_marker, print_marker, 0,
44 marker_equal, marker_hash,
45 struct Lisp_Marker);
46
47 static Lisp_Object
48 mark_marker (Lisp_Object obj, void (*markobj) (Lisp_Object))
49 {
50 struct Lisp_Marker *marker = XMARKER (obj);
51 Lisp_Object buf;
52 /* DO NOT mark through the marker's chain.
53 The buffer's markers chain does not preserve markers from gc;
54 Instead, markers are removed from the chain when they are freed
55 by gc.
56 */
57 if (!marker->buffer)
58 return (Qnil);
59
60 XSETBUFFER (buf, marker->buffer);
61 return (buf);
62 }
63
64 static void
65 print_marker (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
66 {
67 if (print_readably)
68 error ("printing unreadable object #<marker>");
69
70 write_c_string (GETTEXT ("#<marker "), printcharfun);
71 if (!(XMARKER (obj)->buffer))
72 write_c_string (GETTEXT ("in no buffer"), printcharfun);
73 else
74 {
75 char buf[200];
76 sprintf (buf, "at %d", marker_position (obj));
77 write_c_string (buf, printcharfun);
78 write_c_string (" in ", printcharfun);
79 print_internal (XMARKER (obj)->buffer->name, printcharfun, 0);
80 }
81 write_c_string (">", printcharfun);
82 }
83
84 static int
85 marker_equal (Lisp_Object o1, Lisp_Object o2, int depth)
86 {
87 struct buffer *b1 = XMARKER (o1)->buffer;
88 if (b1 != XMARKER (o2)->buffer)
89 return (0);
90 else if (!b1)
91 /* All markers pointing nowhere are equal */
92 return (1);
93 else
94 return ((XMARKER (o1)->memind == XMARKER (o2)->memind));
95 }
96
97 static unsigned long
98 marker_hash (Lisp_Object obj, int depth)
99 {
100 unsigned long hash = (unsigned long) XMARKER (obj)->buffer;
101 if (hash)
102 hash = HASH2 (hash, XMARKER (obj)->memind);
103 return hash;
104 }
105
106
107 /* Operations on markers. */
108
109 DEFUN ("marker-buffer", Fmarker_buffer, Smarker_buffer, 1, 1, 0 /*
110 Return the buffer that MARKER points into, or nil if none.
111 Returns nil if MARKER points into a dead buffer.
112 */ )
113 (marker)
114 Lisp_Object marker;
115 {
116 Lisp_Object buf;
117 CHECK_MARKER (marker);
118 if (XMARKER (marker)->buffer)
119 {
120 XSETBUFFER (buf, XMARKER (marker)->buffer);
121 /* Return marker's buffer only if it is not dead. */
122 if (BUFFER_LIVE_P (XBUFFER (buf)))
123 return buf;
124 }
125 return Qnil;
126 }
127
128 DEFUN ("marker-position", Fmarker_position, Smarker_position, 1, 1, 0 /*
129 Return the position MARKER points at, as a character number.
130 Returns `nil' if marker doesn't point anywhere.
131 */ )
132 (marker)
133 Lisp_Object marker;
134 {
135 CHECK_MARKER (marker);
136 if (XMARKER (marker)->buffer)
137 {
138 return (make_int (marker_position (marker)));
139 }
140 return Qnil;
141 }
142
143 #if 0 /* useful debugging function */
144
145 static void
146 check_marker_circularities (struct buffer *buf)
147 {
148 struct Lisp_Marker *tortoise, *hare;
149
150 tortoise = BUF_MARKERS (buf);
151 hare = tortoise;
152
153 if (!tortoise)
154 return;
155
156 while (1)
157 {
158 assert (hare->buffer == buf);
159 hare = hare->next;
160 if (!hare)
161 return;
162 assert (hare->buffer == buf);
163 hare = hare->next;
164 if (!hare)
165 return;
166 tortoise = tortoise->next;
167 assert (tortoise != hare);
168 }
169 }
170
171 #endif
172
173 static Lisp_Object
174 set_marker_internal (Lisp_Object marker, Lisp_Object pos, Lisp_Object buffer,
175 int restricted_p)
176 {
177 Bufpos charno;
178 struct buffer *b;
179 struct Lisp_Marker *m;
180 int point_p;
181
182 CHECK_MARKER (marker);
183
184 point_p = POINT_MARKER_P (marker);
185
186 /* If position is nil or a marker that points nowhere,
187 make this marker point nowhere. */
188 if (NILP (pos) ||
189 (MARKERP (pos) && !XMARKER (pos)->buffer))
190 {
191 if (point_p)
192 signal_simple_error ("can't make point-marker point nowhere",
193 marker);
194 if (XMARKER (marker)->buffer)
195 unchain_marker (marker);
196 return marker;
197 }
198
199 CHECK_INT_COERCE_MARKER (pos);
200 if (NILP (buffer))
201 b = current_buffer;
202 else
203 {
204 CHECK_BUFFER (buffer);
205 b = XBUFFER (buffer);
206 /* If buffer is dead, set marker to point nowhere. */
207 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
208 {
209 if (point_p)
210 signal_simple_error
211 ("can't move point-marker in a killed buffer", marker);
212 if (XMARKER (marker)->buffer)
213 unchain_marker (marker);
214 return marker;
215 }
216 }
217
218 charno = XINT (pos);
219 m = XMARKER (marker);
220
221 if (restricted_p)
222 {
223 if (charno < BUF_BEGV (b)) charno = BUF_BEGV (b);
224 if (charno > BUF_ZV (b)) charno = BUF_ZV (b);
225 }
226 else
227 {
228 if (charno < BUF_BEG (b)) charno = BUF_BEG (b);
229 if (charno > BUF_Z (b)) charno = BUF_Z (b);
230 }
231
232 if (point_p)
233 {
234 #ifndef moving_point_by_moving_its_marker_is_a_bug
235 BUF_SET_PT (b, charno); /* this will move the marker */
236 #else /* It's not a feature, so it must be a bug */
237 signal_simple_error ("DEBUG: attempt to move point via point-marker",
238 marker);
239 #endif
240 }
241 else
242 {
243 m->memind = bufpos_to_memind (b, charno);
244 }
245
246 if (m->buffer != b)
247 {
248 if (point_p)
249 signal_simple_error ("can't change buffer of point-marker", marker);
250 if (m->buffer != 0)
251 unchain_marker (marker);
252 m->buffer = b;
253 marker_next (m) = BUF_MARKERS (b);
254 marker_prev (m) = 0;
255 if (BUF_MARKERS (b))
256 marker_prev (BUF_MARKERS (b)) = m;
257 BUF_MARKERS (b) = m;
258 }
259
260 return marker;
261 }
262
263
264 DEFUN ("set-marker", Fset_marker, Sset_marker, 2, 3, 0 /*
265 Position MARKER before character number NUMBER in BUFFER.
266 BUFFER defaults to the current buffer.
267 If NUMBER is nil, makes marker point nowhere.
268 Then it no longer slows down editing in any buffer.
269 If this marker was returned by (point-marker t), then changing its position
270 moves point. You cannot change its buffer or make it point nowhere.
271 Returns MARKER.
272 */ )
273 (marker, number, buffer)
274 Lisp_Object marker, number, buffer;
275 {
276 return set_marker_internal (marker, number, buffer, 0);
277 }
278
279
280 /* This version of Fset_marker won't let the position
281 be outside the visible part. */
282 Lisp_Object
283 set_marker_restricted (Lisp_Object marker, Lisp_Object pos, Lisp_Object buffer)
284 {
285 return set_marker_internal (marker, pos, buffer, 1);
286 }
287
288
289 /* This is called during garbage collection,
290 so we must be careful to ignore and preserve mark bits,
291 including those in chain fields of markers. */
292
293 void
294 unchain_marker (Lisp_Object m)
295 {
296 struct Lisp_Marker *marker = XMARKER (m);
297 struct buffer *b = marker->buffer;
298
299 if (b == 0)
300 return;
301
302 assert (BUFFER_LIVE_P (b));
303
304 if (marker_next (marker))
305 marker_prev (marker_next (marker)) = marker_prev (marker);
306 if (marker_prev (marker))
307 marker_next (marker_prev (marker)) = marker_next (marker);
308 else
309 BUF_MARKERS (b) = marker_next (marker);
310
311 assert (marker != XMARKER (b->point_marker));
312
313 marker->buffer = 0;
314 }
315
316 Bytind
317 bi_marker_position (Lisp_Object marker)
318 {
319 struct Lisp_Marker *m = XMARKER (marker);
320 struct buffer *buf = m->buffer;
321 Bytind pos;
322
323 if (!buf)
324 error ("Marker does not point anywhere");
325
326 /* FSF claims that marker indices could end up denormalized, i.e.
327 in the gap. This is way bogus if it ever happens, and means
328 something fucked up elsewhere. Since I've overhauled all this
329 shit, I don't think this can happen. In any case, the following
330 macro has an assert() in it that will catch these denormalized
331 positions. */
332 pos = memind_to_bytind (buf, m->memind);
333
334 if (pos < BI_BUF_BEG (buf) || pos > BI_BUF_Z (buf))
335 abort ();
336
337 return pos;
338 }
339
340 Bufpos
341 marker_position (Lisp_Object marker)
342 {
343 struct buffer *buf = XMARKER (marker)->buffer;
344
345 if (!buf)
346 error ("Marker does not point anywhere");
347
348 return bytind_to_bufpos (buf, bi_marker_position (marker));
349 }
350
351 void
352 set_bi_marker_position (Lisp_Object marker, Bytind pos)
353 {
354 struct Lisp_Marker *m = XMARKER (marker);
355 struct buffer *buf = m->buffer;
356
357 if (!buf)
358 error ("Marker does not point anywhere");
359
360 if (pos < BI_BUF_BEG (buf) || pos > BI_BUF_Z (buf))
361 abort ();
362
363 m->memind = bytind_to_memind (buf, pos);
364 }
365
366 void
367 set_marker_position (Lisp_Object marker, Bufpos pos)
368 {
369 struct buffer *buf = XMARKER (marker)->buffer;
370
371 if (!buf)
372 error ("Marker does not point anywhere");
373
374 set_bi_marker_position (marker, bufpos_to_bytind (buf, pos));
375 }
376
377 static Lisp_Object
378 copy_marker_1 (Lisp_Object marker, Lisp_Object type, int noseeum)
379 {
380 REGISTER Lisp_Object new;
381
382 while (1)
383 {
384 if (INTP (marker) || MARKERP (marker))
385 {
386 if (noseeum)
387 new = noseeum_make_marker ();
388 else
389 new = Fmake_marker ();
390 Fset_marker (new, marker,
391 (MARKERP (marker) ? Fmarker_buffer (marker) : Qnil));
392 XMARKER (new)->insertion_type = !NILP (type);
393 return new;
394 }
395 else
396 marker = wrong_type_argument (Qinteger_or_marker_p, marker);
397 }
398
399 RETURN_NOT_REACHED (Qnil) /* not reached */
400 }
401
402 DEFUN ("copy-marker", Fcopy_marker, Scopy_marker, 1, 2, 0 /*
403 Return a new marker pointing at the same place as MARKER.
404 If argument is a number, makes a new marker pointing
405 at that position in the current buffer.
406 The optional argument TYPE specifies the insertion type of the new marker;
407 see `marker-insertion-type'.
408 */ )
409 (marker, type)
410 Lisp_Object marker, type;
411 {
412 return copy_marker_1 (marker, type, 0);
413 }
414
415 Lisp_Object
416 noseeum_copy_marker (Lisp_Object marker, Lisp_Object type)
417 {
418 return copy_marker_1 (marker, type, 1);
419 }
420
421 DEFUN ("marker-insertion-type", Fmarker_insertion_type,
422 Smarker_insertion_type, 1, 1, 0 /*
423 Return insertion type of MARKER: t if it stays after inserted text.
424 nil means the marker stays before text inserted there.
425 */ )
426 (marker)
427 register Lisp_Object marker;
428 {
429 CHECK_MARKER (marker);
430 return XMARKER (marker)->insertion_type ? Qt : Qnil;
431 }
432
433 DEFUN ("set-marker-insertion-type", Fset_marker_insertion_type,
434 Sset_marker_insertion_type, 2, 2, 0 /*
435 Set the insertion-type of MARKER to TYPE.
436 If TYPE is t, it means the marker advances when you insert text at it.
437 If TYPE is nil, it means the marker stays behind when you insert text at it.
438 */ )
439 (marker, type)
440 Lisp_Object marker, type;
441 {
442 CHECK_MARKER (marker);
443
444 XMARKER (marker)->insertion_type = ! NILP (type);
445 return type;
446 }
447
448 #ifdef MEMORY_USAGE_STATS
449
450 int
451 compute_buffer_marker_usage (struct buffer *b, struct overhead_stats *ovstats)
452 {
453 struct Lisp_Marker *m;
454 int total = 0;
455 int overhead;
456
457 for (m = BUF_MARKERS (b); m; m = m->next)
458 total += sizeof (struct Lisp_Marker);
459 ovstats->was_requested += total;
460 overhead = fixed_type_block_overhead (total);
461 /* #### claiming this is all malloc overhead is not really right,
462 but it has to go somewhere. */
463 ovstats->malloc_overhead += overhead;
464 return total + overhead;
465 }
466
467 #endif /* MEMORY_USAGE_STATS */
468
469
470 void
471 syms_of_marker (void)
472 {
473 defsubr (&Smarker_position);
474 defsubr (&Smarker_buffer);
475 defsubr (&Sset_marker);
476 defsubr (&Scopy_marker);
477 defsubr (&Smarker_insertion_type);
478 defsubr (&Sset_marker_insertion_type);
479 }
480
481 void init_buffer_markers (struct buffer *b);
482 void
483 init_buffer_markers (struct buffer *b)
484 {
485 Lisp_Object buf = Qnil;
486
487 XSETBUFFER (buf, b);
488 b->mark = Fmake_marker ();
489 BUF_MARKERS (b) = 0;
490 b->point_marker = Fmake_marker ();
491 Fset_marker (b->point_marker, make_int (1), buf);
492 }
493
494 void uninit_buffer_markers (struct buffer *b);
495 void
496 uninit_buffer_markers (struct buffer *b)
497 {
498 /* Unchain all markers of this buffer
499 and leave them pointing nowhere. */
500 REGISTER struct Lisp_Marker *m, *next;
501 for (m = BUF_MARKERS (b); m; m = next)
502 {
503 m->buffer = 0;
504 next = marker_next (m);
505 marker_next (m) = 0;
506 marker_prev (m) = 0;
507 }
508 BUF_MARKERS (b) = 0;
509 }