annotate src/line-number.c @ 406:b8cc9ab3f761 r21-2-33

Import from CVS: tag r21-2-33
author cvs
date Mon, 13 Aug 2007 11:17:09 +0200
parents 2f8bb876ab1d
children 697ef44129c6
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
219
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
1 /* Line number cache.
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
2 Copyright (C) 1997 Free Software Foundation, Inc.
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
3
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
4 This file is part of XEmacs.
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
5
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
6 XEmacs is free software; you can redistribute it and/or modify it
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
7 under the terms of the GNU General Public License as published by the
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
8 Free Software Foundation; either version 2, or (at your option) any
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
9 later version.
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
10
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
14 for more details.
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
15
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
17 along with XEmacs; see the file COPYING. If not, write to
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
19 Boston, MA 02111-1307, USA. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
20
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
21 /* Synched up with: Not in FSF. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
22
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
23 /* To calculate the line numbers, redisplay must count the newlines
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
24 from a known position. This used to be BUF_BEGV, but this made the
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
25 line numbering extremely slow for large buffers, because Emacs had
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
26 to rescan the whole buffer at each redisplay.
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
27
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
28 To make line numbering efficient, we maintain a buffer-local cache
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
29 of recently used positions and their line numbers. The cache is
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
30 implemented as a small ring of cache positions. A cache position
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
31 is either nil or a cons of a buffer position (marker) and the
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
32 corresponding line number.
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
33
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
34 When calculating the line numbers, this cache is consulted if it
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
35 would otherwise take too much time to count the newlines in the
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
36 buffer (see the comment to buffer_line_number().)
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
37
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
38 Insertion and deletions that contain/delete newlines invalidate the
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
39 cached positions after the insertion point. This guarantees
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
40 relatively fast line numbers caching (even in buffers where point
219
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
41 moves a lot), and low memory usage. All of this is done only in
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
42 the buffers where the cache is actually initialized -- i.e. where
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
43 line-numbering is on, and you move the point farther than
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
44 LINE_NUMBER_FAR from the beginning of buffer. In this sense, the
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
45 cache is lazy -- if you don't use it, you don't pay for it.
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
46
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
47 NOTE: line-number cache should not be confused with line-start
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
48 cache. Line-start cache (a part of redisplay) works with the
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
49 display lines, whereas this works with the buffer lines (literally
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
50 counting the newlines). */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
51
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
52 #include <config.h>
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
53 #include "lisp.h"
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
54 #include "buffer.h"
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
55
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
56 #include "line-number.h"
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
57
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
58 /* #### The following three values could stand more exploration for
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
59 best performance. */
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
60
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
61 /* Size of the ring. The current code expects this to be a small
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
62 number. If you make it larger, you should probably optimize the
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
63 code below to keep it sorted. */
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
64 #define LINE_NUMBER_RING_SIZE 8
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
65
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
66 /* How much traversal has to be exceeded for two points to be
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
67 considered "far" from each other. When two points are far, cache
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
68 will be used. */
298
70ad99077275 Import from CVS: tag r21-0b47
cvs
parents: 286
diff changeset
69 #define LINE_NUMBER_FAR 16384
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
70
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
71 /* How large a string has to be to give up searching it for newlines,
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
72 before change. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
73 #define LINE_NUMBER_LARGE_STRING 256
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
74
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
75 /* To be used only when you *know* the cache has been allocated! */
373
6240c7796c7a Import from CVS: tag r21-2b2
cvs
parents: 298
diff changeset
76 #define LINE_NUMBER_RING(b) (XCAR ((b)->text->line_number_cache))
6240c7796c7a Import from CVS: tag r21-2b2
cvs
parents: 298
diff changeset
77 #define LINE_NUMBER_BEGV(b) (XCDR ((b)->text->line_number_cache))
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
78
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
79
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
80 /* Initialize the cache. Cache is (in pseudo-BNF):
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
81
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
82 CACHE = nil | INITIALIZED-CACHE
380
8626e4521993 Import from CVS: tag r21-2-5
cvs
parents: 373
diff changeset
83 INITIALIZED-CACHE = cons (RING, BEGV-LINE)
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
84 RING = vector (*RING-ELEMENT)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
85 RING-ELEMENT = nil | RING-PAIR
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
86 RING-PAIR = cons (marker, integer)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
87 BEGV-LINE = integer
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
88
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
89 Line number cache should never, ever, be visible to Lisp (because
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
90 destructively modifying its elements can cause crashes.) Debug it
373
6240c7796c7a Import from CVS: tag r21-2b2
cvs
parents: 298
diff changeset
91 using debug_print (current_buffer->text->last_number_cache). */
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
92 static void
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
93 allocate_line_number_cache (struct buffer *b)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
94 {
373
6240c7796c7a Import from CVS: tag r21-2b2
cvs
parents: 298
diff changeset
95 b->text->line_number_cache = Fcons (make_vector (LINE_NUMBER_RING_SIZE, Qnil),
6240c7796c7a Import from CVS: tag r21-2b2
cvs
parents: 298
diff changeset
96 Qzero);
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
97 narrow_line_number_cache (b);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
98 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
99
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
100 /* Flag LINE_NUMBER_BEGV (b) as dirty. Do it only if the line number
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
101 cache is already initialized. */
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
102 void
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
103 narrow_line_number_cache (struct buffer *b)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
104 {
373
6240c7796c7a Import from CVS: tag r21-2b2
cvs
parents: 298
diff changeset
105 if (NILP (b->text->line_number_cache))
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
106 return;
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
107
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
108 if (BUF_BEG (b) == BUF_BEGV (b))
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
109 /* The is the case Fwiden and save_restriction_restore. Since we
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
110 know the correct value, we can update it now. */
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
111 LINE_NUMBER_BEGV (b) = Qzero;
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
112 else
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
113 /* Calculating the line number of BUF_BEGV here is a bad idea,
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
114 because there is absolutely no reason to do it before the next
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
115 redisplay. We simply mark it as dirty instead. */
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
116 LINE_NUMBER_BEGV (b) = make_int (-1);
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
117 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
118
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
119 /* Invalidate the line number cache positions that lie after POS. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
120 static void
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
121 invalidate_line_number_cache (struct buffer *b, Bufpos pos)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
122 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
123 EMACS_INT i, j;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
124 Lisp_Object *ring = XVECTOR_DATA (LINE_NUMBER_RING (b));
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
125
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
126 for (i = 0; i < LINE_NUMBER_RING_SIZE; i++)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
127 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
128 if (!CONSP (ring[i]))
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
129 break;
219
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
130 /* As the marker stays behind the insertions, this check might
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
131 as well be `>'. However, Finsert_before_markers can advance
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
132 the marker anyway, which bites in shell buffers.
241
f955c73f5258 Import from CVS: tag r20-5b19
cvs
parents: 219
diff changeset
133
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
134 #### This forces recreation of the cached marker (and
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
135 recalculation of newlines) every time a newline is inserted
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
136 at point, which is way losing. Isn't there a way to make a
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
137 marker impervious to Finsert_before_markers()?? Maybe I
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
138 should convert the code to use extents. */
219
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
139 if (marker_position (XCAR (ring[i])) >= pos)
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
140 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
141 /* Get the marker out of the way. */
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
142 Fset_marker (XCAR (ring[i]), Qnil, Qnil);
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
143 /* ...and shift the ring elements, up to the first nil. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
144 for (j = i; !NILP (ring[j]) && j < LINE_NUMBER_RING_SIZE - 1; j++)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
145 ring[j] = ring[j + 1];
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
146 ring[j] = Qnil;
219
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
147 /* Must recheck position i. */
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
148 i--;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
149 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
150 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
151 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
152
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
153 /* Invalidate the cache positions after POS, if the string to be
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
154 inserted contains a newline. If the string is too large (larger
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
155 than LINE_NUMBER_LARGE_STRING), invalidate the cache positions
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
156 after POS without prior search.
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
157
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
158 This will do nothing if the cache is uninitialized. */
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
159 void
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
160 insert_invalidate_line_number_cache (struct buffer *b, Bufpos pos,
398
74fd4e045ea6 Import from CVS: tag r21-2-29
cvs
parents: 380
diff changeset
161 const Bufbyte *nonreloc, Bytecount length)
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
162 {
373
6240c7796c7a Import from CVS: tag r21-2b2
cvs
parents: 298
diff changeset
163 if (NILP (b->text->line_number_cache))
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
164 return;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
165
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
166 if (length > LINE_NUMBER_LARGE_STRING
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
167 ||
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
168 /* We could also count how many newlines there are in the string
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
169 and update the cache accordingly, but it would be too much
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
170 work for too little gain. */
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
171 memchr ((void *)nonreloc, '\n', (size_t) length))
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
172 invalidate_line_number_cache (b, pos);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
173 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
174
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
175 /* Invalidate the cache positions after FROM, if the region to be
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
176 deleted contains a newline. If the region-to-be-deleted is larger
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
177 than LINE_NUMBER_LARGE_STRING, invalidate the cache positions after
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
178 FROM without unconditionally.
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
179
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
180 This will do nothing if the cache is uninitialized. */
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
181 void
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
182 delete_invalidate_line_number_cache (struct buffer *b, Bufpos from, Bufpos to)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
183 {
373
6240c7796c7a Import from CVS: tag r21-2b2
cvs
parents: 298
diff changeset
184 if (NILP (b->text->line_number_cache))
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
185 return;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
186
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
187 if ((to - from) > LINE_NUMBER_LARGE_STRING)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
188 invalidate_line_number_cache (b, from);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
189 else
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
190 {
286
57709be46d1b Import from CVS: tag r21-0b41
cvs
parents: 284
diff changeset
191 EMACS_INT shortage;
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
192 scan_buffer (b, '\n', from, to, 1, &shortage, 0);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
193 if (!shortage)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
194 invalidate_line_number_cache (b, from);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
195 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
196 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
197
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
198 /* Get the nearest known position we know the line number of
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
199 (i.e. BUF_BEGV, and cached positions). The return position will be
219
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
200 either closer than BEG, or BEG. The line of this known position
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
201 will be stored in LINE.
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
202
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
203 *LINE should be initialized to the line number of BEG (normally,
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
204 BEG will be BUF_BEGV, and *LINE will be XINT (LINE_NUMBER_BEGV).
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
205 This will initialize the cache, if necessary. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
206 static void
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
207 get_nearest_line_number (struct buffer *b, Bufpos *beg, Bufpos pos,
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
208 EMACS_INT *line)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
209 {
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
210 EMACS_INT i;
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
211 Lisp_Object *ring = XVECTOR_DATA (LINE_NUMBER_RING (b));
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
212 Charcount length = pos - *beg;
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
213
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
214 if (length < 0)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
215 length = -length;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
216
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
217 /* Find the ring entry closest to POS, if it is closer than BEG. */
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
218 for (i = 0; i < LINE_NUMBER_RING_SIZE && CONSP (ring[i]); i++)
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
219 {
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
220 Bufpos newpos = marker_position (XCAR (ring[i]));
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
221 Charcount howfar = newpos - pos;
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
222 if (howfar < 0)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
223 howfar = -howfar;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
224 if (howfar < length)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
225 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
226 length = howfar;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
227 *beg = newpos;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
228 *line = XINT (XCDR (ring[i]));
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
229 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
230 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
231 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
232
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
233 /* Add a (POS . LINE) pair to the ring, and rotate it. */
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
234 static void
298
70ad99077275 Import from CVS: tag r21-0b47
cvs
parents: 286
diff changeset
235 add_position_to_cache (struct buffer *b, Bufpos pos, EMACS_INT line)
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
236 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
237 Lisp_Object *ring = XVECTOR_DATA (LINE_NUMBER_RING (b));
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
238 int i = LINE_NUMBER_RING_SIZE - 1;
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
239
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
240 /* Set the last marker in the ring to point nowhere. */
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
241 if (CONSP (ring[i]))
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
242 Fset_marker (XCAR (ring[i]), Qnil, Qnil);
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
243
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
244 /* Rotate the ring... */
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
245 for (; i > 0; i--)
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
246 ring[i] = ring[i - 1];
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
247
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
248 /* ...and update it. */
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
249 ring[0] = Fcons (Fset_marker (Fmake_marker (), make_int (pos),
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
250 make_buffer (b)),
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
251 make_int (line));
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
252 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
253
219
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
254 /* Calculate the line number in buffer B at position POS. If CACHEP
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
255 is non-zero, initialize and facilitate the line-number cache. The
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
256 line number of the first line is 0. If narrowing is in effect,
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
257 count the lines are counted from the beginning of the visible
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
258 portion of the buffer.
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
259
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
260 The cache works as follows: To calculate the line number, we need
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
261 two positions: position of point (POS) and the position from which
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
262 to count newlines (BEG). We start by setting BEG to BUF_BEGV. If
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
263 this would require too much searching (i.e. pos - BUF_BEGV >
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
264 LINE_NUMBER_FAR), try to find a closer position in the ring. If it
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
265 is found, use that position for BEG, and increment the line number
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
266 appropriately.
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
267
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
268 If the calculation (with or without the cache lookup) required more
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
269 than LINE_NUMBER_FAR characters of traversal, update the cache. */
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
270 EMACS_INT
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
271 buffer_line_number (struct buffer *b, Bufpos pos, int cachep)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
272 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
273 Bufpos beg = BUF_BEGV (b);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
274 EMACS_INT cached_lines = 0;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
275 EMACS_INT shortage, line;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
276
219
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
277 if ((pos > beg ? pos - beg : beg - pos) <= LINE_NUMBER_FAR)
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
278 cachep = 0;
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
279
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
280 if (cachep)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
281 {
373
6240c7796c7a Import from CVS: tag r21-2b2
cvs
parents: 298
diff changeset
282 if (NILP (b->text->line_number_cache))
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
283 allocate_line_number_cache (b);
219
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
284 /* If we don't know the line number of BUF_BEGV, calculate it now. */
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
285 if (XINT (LINE_NUMBER_BEGV (b)) == -1)
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
286 {
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
287 LINE_NUMBER_BEGV (b) = Qzero;
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
288 /* #### This has a side-effect of changing the cache. */
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
289 LINE_NUMBER_BEGV (b) =
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
290 make_int (buffer_line_number (b, BUF_BEGV (b), 1));
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
291 }
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
292 cached_lines = XINT (LINE_NUMBER_BEGV (b));
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
293 get_nearest_line_number (b, &beg, pos, &cached_lines);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
294 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
295
406
b8cc9ab3f761 Import from CVS: tag r21-2-33
cvs
parents: 404
diff changeset
296 scan_buffer (b, '\n', beg, pos, pos > beg ? EMACS_INT_MAX : -EMACS_INT_MAX,
298
70ad99077275 Import from CVS: tag r21-0b47
cvs
parents: 286
diff changeset
297 &shortage, 0);
219
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
298
298
70ad99077275 Import from CVS: tag r21-0b47
cvs
parents: 286
diff changeset
299 line = EMACS_INT_MAX - shortage;
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
300 if (beg > pos)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
301 line = -line;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
302 line += cached_lines;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
303
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
304 if (cachep)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
305 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
306 /* If too far, update the cache. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
307 if ((pos > beg ? pos - beg : beg - pos) > LINE_NUMBER_FAR)
284
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
308 add_position_to_cache (b, pos, line);
558f606b08ae Import from CVS: tag r21-0b40
cvs
parents: 241
diff changeset
309 /* Account for narrowing. If cache is not used, this is
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
310 unnecessary, because we counted from BUF_BEGV anyway. */
219
262b8bb4a523 Import from CVS: tag r20-4b8
cvs
parents: 211
diff changeset
311 line -= XINT (LINE_NUMBER_BEGV (b));
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
312 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
313
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
314 return line;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
315 }