comparison src/line-number.c @ 219:262b8bb4a523 r20-4b8

Import from CVS: tag r20-4b8
author cvs
date Mon, 13 Aug 2007 10:09:35 +0200
parents 78478c60bfcd
children f955c73f5258
comparison
equal deleted inserted replaced
218:c9f226976f56 219:262b8bb4a523
1 /* Line number cache routines. 1 /* Line number cache.
2 Copyright (C) 1997 Free Software Foundation, Inc. 2 Copyright (C) 1997 Free Software Foundation, Inc.
3 3
4 This file is part of XEmacs. 4 This file is part of XEmacs.
5 5
6 XEmacs is free software; you can redistribute it and/or modify it 6 XEmacs is free software; you can redistribute it and/or modify it
36 buffer (see the comment to window_line_number.) 36 buffer (see the comment to window_line_number.)
37 37
38 Insertion and deletions that contain/delete newlines invalidate the 38 Insertion and deletions that contain/delete newlines invalidate the
39 cached positions after the insertion point. This guarantees 39 cached positions after the insertion point. This guarantees
40 relatively fast line numbers caching (even in buffers where point 40 relatively fast line numbers caching (even in buffers where point
41 moves a lot), and low memory usage. 41 moves a lot), and low memory usage. All of this is done only in
42 the buffers where the cache is actually initialized -- i.e. where
43 line-numbering is on, and you move the point farther than
44 LINE_NUMBER_FAR from the beginning of buffer. In this sense, the
45 cache is lazy. If you don't use it, you don't pay for it.
42 46
43 NOTE: line-number cache should not be confused with line-start 47 NOTE: line-number cache should not be confused with line-start
44 cache. Line-start cache (a part of redisplay) works with the 48 cache. Line-start cache (a part of redisplay) works with the
45 display lines, whereas this works with the buffer lines (literally 49 display lines, whereas this works with the buffer lines (literally
46 counting the newlines). */ 50 counting the newlines). */
52 56
53 #include "line-number.h" 57 #include "line-number.h"
54 58
55 59
56 /* #### The following three values could use some tweaking, to get the 60 /* #### The following three values could use some tweaking, to get the
57 best performance. */ 61 best performance. I suspect LINE_NUMBER_FAR and
62 LINE_NUMBER_LARGE_STRING could be made bigger. */
58 63
59 /* Size of the ring. The current code expects this to be a small 64 /* Size of the ring. The current code expects this to be a small
60 number. If you make it much bigger, you should probably tr yto 65 number. If you make it much bigger, you should probably tr yto
61 optimize the various routines to keep it sorted. */ 66 optimize the various routines to keep it sorted. */
62 #define LINE_NUMBER_RING_SIZE 8 67 #define LINE_NUMBER_RING_SIZE 8
94 b->line_number_cache = Fcons (make_vector (LINE_NUMBER_RING_SIZE, Qnil), 99 b->line_number_cache = Fcons (make_vector (LINE_NUMBER_RING_SIZE, Qnil),
95 Qzero); 100 Qzero);
96 narrow_line_number_cache (b); 101 narrow_line_number_cache (b);
97 } 102 }
98 103
99 /* Update line_number_begv. Do it only if the line number cache is 104 /* Update line_number_begv, or flag it as dirty. Do it only if the
100 already initialized. */ 105 line number cache is already initialized. */
101 void 106 void
102 narrow_line_number_cache (struct buffer *b) 107 narrow_line_number_cache (struct buffer *b)
103 { 108 {
104 EMACS_INT lots = 999999999, shortage;
105
106 if (NILP (b->line_number_cache)) 109 if (NILP (b->line_number_cache))
107 return; 110 return;
108 /* Optimization: if BUF_BEG == BUF_BEGV (as is the case after Fwiden 111 /* Optimization: if BUF_BEG == BUF_BEGV (as is the case after Fwiden
109 and save_restriction_restore), don't bother calling scan_buffer. */ 112 and save_restriction_restore), don't bother calling scan_buffer. */
110 if (BUF_BEG (b) == BUF_BEGV (b)) 113 if (BUF_BEG (b) == BUF_BEGV (b))
111 { 114 {
112 LINE_NUMBER_BEGV (b) = Qzero; 115 LINE_NUMBER_BEGV (b) = Qzero;
113 return; 116 return;
114 } 117 }
115 /* Count the newlines between beginning of buffer and beginning of 118 /* Calculating the line number of BUF_BEGV here is a bad idea,
116 the visible portion of the buffer. */ 119 because there is absolutely no reason to do it before the next
117 scan_buffer (b, '\n', BUF_BEG (b), BUF_BEGV (b), lots, 120 redisplay. We simply mark it as dirty instead. */
118 (int *)&shortage, 0); 121 LINE_NUMBER_BEGV (b) = make_int (-1);
119 LINE_NUMBER_BEGV (b) = make_int (lots - shortage);
120 } 122 }
121 123
122 /* Invalidate the line number cache positions that lie after POS. */ 124 /* Invalidate the line number cache positions that lie after POS. */
123 static void 125 static void
124 invalidate_line_number_cache (struct buffer *b, Bufpos pos) 126 invalidate_line_number_cache (struct buffer *b, Bufpos pos)
129 131
130 for (i = 0; i < LINE_NUMBER_RING_SIZE; i++) 132 for (i = 0; i < LINE_NUMBER_RING_SIZE; i++)
131 { 133 {
132 if (!CONSP (ring[i])) 134 if (!CONSP (ring[i]))
133 break; 135 break;
134 if (marker_position (XCAR (ring[i])) > pos) 136 /* As the marker stays behind the insertions, this check might
137 as well be >=. However, Finsert_before_markers can move the
138 marker anyway, which bites in shell buffers. */
139 if (marker_position (XCAR (ring[i])) >= pos)
135 { 140 {
136 /* Get the marker out of the way. */ 141 /* Get the marker out of the way. */
137 Fset_marker (XCAR (ring[i]), Qnil, lisp_buffer); 142 Fset_marker (XCAR (ring[i]), Qnil, lisp_buffer);
138 /* ...and shift the ring elements, up to the first nil. */ 143 /* ...and shift the ring elements, up to the first nil. */
139 for (j = i; !NILP (ring[j]) && j < LINE_NUMBER_RING_SIZE - 1; j++) 144 for (j = i; !NILP (ring[j]) && j < LINE_NUMBER_RING_SIZE - 1; j++)
140 ring[j] = ring[j + 1]; 145 ring[j] = ring[j + 1];
141 ring[j] = Qnil; 146 ring[j] = Qnil;
142 /* Must reevaluate the thing at position i. */ 147 /* Must recheck position i. */
143 i--; 148 i--;
144 } 149 }
145 } 150 }
146 } 151 }
147 152
184 else 189 else
185 { 190 {
186 int shortage; 191 int shortage;
187 scan_buffer (b, '\n', from, to, 1, &shortage, 0); 192 scan_buffer (b, '\n', from, to, 1, &shortage, 0);
188 if (!shortage) 193 if (!shortage)
189 /* The same as above applies. */
190 invalidate_line_number_cache (b, from); 194 invalidate_line_number_cache (b, from);
191 } 195 }
192 } 196 }
193 197
194 198
195 /* Get the nearest known position we know the line number of 199 /* Get the nearest known position we know the line number of
196 (i.e. BUF_BEGV, and cached positions). The return position will be 200 (i.e. BUF_BEGV, and cached positions). The return position will be
197 either closer than BEG, or BEG. 201 either closer than BEG, or BEG. The line of this known position
202 will be stored in LINE.
198 203
199 *LINE should be initialized to the line number of BEG (normally, 204 *LINE should be initialized to the line number of BEG (normally,
200 BEG will be BUF_BEGV, and *LINE will be XINT (LINE_NUMBER_BEGV). 205 BEG will be BUF_BEGV, and *LINE will be XINT (LINE_NUMBER_BEGV).
201 This will initialize the cache, if necessary. */ 206 This will initialize the cache, if necessary. */
202 static void 207 static void
243 marker = Fmake_marker (); 248 marker = Fmake_marker ();
244 Fset_marker (marker, make_int (pos), make_buffer (b)); 249 Fset_marker (marker, make_int (pos), make_buffer (b));
245 ring[0] = Fcons (marker, make_int (line)); 250 ring[0] = Fcons (marker, make_int (line));
246 } 251 }
247 252
248 /* Calculate the buffer line number. If CACHEP is non-zero, 253 /* Calculate the line number in buffer B at position POS. If CACHEP
249 initialize the line-number cache for future use. The line number 254 is non-zero, initialize and facilitate the line-number cache. The
250 of the first line is 0. If narrowing is in effect, count the lines 255 line number of the first line is 0. If narrowing is in effect,
251 from the beginning of the visible portion of the buffer. 256 count the lines are counted from the beginning of the visible
257 portion of the buffer.
252 258
253 The cache works as follows: To calculate the line number, we need 259 The cache works as follows: To calculate the line number, we need
254 two positions: position of point (POS) and the position from which 260 two positions: position of point (POS) and the position from which
255 to count newlines (BEG). We start by setting BEG to BUF_BEGV. If 261 to count newlines (BEG). We start by setting BEG to BUF_BEGV. If
256 this would require too much searching (i.e. pos - BUF_BEGV > 262 this would require too much searching (i.e. pos - BUF_BEGV >
263 EMACS_INT 269 EMACS_INT
264 buffer_line_number (struct buffer *b, Bufpos pos, int cachep) 270 buffer_line_number (struct buffer *b, Bufpos pos, int cachep)
265 { 271 {
266 Bufpos beg = BUF_BEGV (b); 272 Bufpos beg = BUF_BEGV (b);
267 EMACS_INT cached_lines = 0; 273 EMACS_INT cached_lines = 0;
268 EMACS_INT lots = 999999999;
269 EMACS_INT shortage, line; 274 EMACS_INT shortage, line;
275
276 if ((pos > beg ? pos - beg : beg - pos) <= LINE_NUMBER_FAR)
277 cachep = 0;
270 278
271 if (cachep) 279 if (cachep)
272 { 280 {
273 if (NILP (b->line_number_cache)) 281 if (NILP (b->line_number_cache))
274 allocate_line_number_cache (b); 282 allocate_line_number_cache (b);
283 /* If we don't know the line number of BUF_BEGV, calculate it now. */
284 if (XINT (LINE_NUMBER_BEGV (b)) == -1)
285 {
286 LINE_NUMBER_BEGV (b) = Qzero;
287 /* #### This has a side-effect of changing the cache. */
288 LINE_NUMBER_BEGV (b) =
289 make_int (buffer_line_number (b, BUF_BEGV (b), 1));
290 }
275 cached_lines = XINT (LINE_NUMBER_BEGV (b)); 291 cached_lines = XINT (LINE_NUMBER_BEGV (b));
276 get_nearest_line_number (b, &beg, pos, &cached_lines); 292 get_nearest_line_number (b, &beg, pos, &cached_lines);
277 } 293 }
278 294
279 scan_buffer (b, '\n', beg, pos, pos > beg ? lots : -lots, 295 /* An EMACS_MAXINT would be cool to have. */
296 #define LOTS 999999999
297
298 scan_buffer (b, '\n', beg, pos, pos > beg ? LOTS : -LOTS,
280 (int *)&shortage, 0); 299 (int *)&shortage, 0);
281 300
282 line = lots - shortage; 301 line = LOTS - shortage;
283 if (beg > pos) 302 if (beg > pos)
284 line = -line; 303 line = -line;
285 line += cached_lines; 304 line += cached_lines;
286 305
287 if (cachep) 306 if (cachep)
289 /* If too far, update the cache. */ 308 /* If too far, update the cache. */
290 if ((pos > beg ? pos - beg : beg - pos) > LINE_NUMBER_FAR) 309 if ((pos > beg ? pos - beg : beg - pos) > LINE_NUMBER_FAR)
291 add_line_number (b, pos, line); 310 add_line_number (b, pos, line);
292 /* Account for narrowing. If CACHEP is nil, this is 311 /* Account for narrowing. If CACHEP is nil, this is
293 unnecessary, because we counted from BUF_BEGV anyway. */ 312 unnecessary, because we counted from BUF_BEGV anyway. */
294 if (cachep) 313 line -= XINT (LINE_NUMBER_BEGV (b));
295 line -= XINT (LINE_NUMBER_BEGV (b));
296 } 314 }
297 315
298 return line; 316 return line;
299 } 317 }
300 318