annotate src/line-number.c @ 211:78478c60bfcd r20-4b4

Import from CVS: tag r20-4b4
author cvs
date Mon, 13 Aug 2007 10:05:51 +0200
parents
children 262b8bb4a523
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
211
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
1 /* Line number cache routines.
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
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
25 redisplay extremely slow for large buffers, because Emacs must
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
26 rescan the whole buffer at each redisplay, just to count the
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
27 newlines.
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
28
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
29 To make line numbering efficient, we maintain a simple-minded
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
30 cache. Each buffer contains a small ring of known positions, each
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
31 element of the ring being a Lisp_Object -- either nil or a cons of
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
32 a buffer position and the line number (beginning with 0).
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
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
36 buffer (see the comment to window_line_number.)
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
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
41 moves a lot), and low memory usage.
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
42
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
43 NOTE: line-number cache should not be confused with line-start
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
44 cache. Line-start cache (a part of redisplay) works with the
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
45 display lines, whereas this works with the buffer lines (literally
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
46 counting the newlines). */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
47
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
48 #include <config.h>
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
49 #include "lisp.h"
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
50 #include "buffer.h"
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
51 #include "insdel.h"
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
52
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
53 #include "line-number.h"
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
54
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
55
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
56 /* #### The following three values could use some tweaking, to get the
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
57 best performance. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
58
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
59 /* Size of the ring. The current code expects this to be a small
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
60 number. If you make it much bigger, you should probably tr yto
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
61 optimize the various routines to keep it sorted. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
62 #define LINE_NUMBER_RING_SIZE 8
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
63
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
64 /* How much traversal has to be exceeded for two points to be
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
65 considered "far" from each other. When two points are far, cache
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
66 will be used. You can set this to a small value for debugging
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
67 purposes. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
68 #define LINE_NUMBER_FAR 16384
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
69
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
70 /* 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
71 before change. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
72 #define LINE_NUMBER_LARGE_STRING 256
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
73
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
74 /* To be used only when you *know* the cache has been allocated! */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
75 #define LINE_NUMBER_RING(b) (XCAR ((b)->line_number_cache))
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
76 #define LINE_NUMBER_BEGV(b) (XCDR ((b)->line_number_cache))
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
77
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
78
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
79 /* Initialize the cache. Cache is (in pseudo-BNF):
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
80
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
81 CACHE = nil | INITIALIZED-CACHE
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
82 INITITIALIZED-CACHE = cons (RING, BEGV-LINE)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
83 RING = vector (*RING-ELEMENT)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
84 RING-ELEMENT = nil | RING-PAIR
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
85 RING-PAIR = cons (marker, integer)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
86 BEGV-LINE = integer
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
87
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
88 Line number cache should never, ever, be visible to Lisp (because
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
89 destructively modifying its elements can cause crashes.) Debug it
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
90 using debug_print (current_buffer->last_number_cache). */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
91 static void
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
92 allocate_line_number_cache (struct buffer *b)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
93 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
94 b->line_number_cache = Fcons (make_vector (LINE_NUMBER_RING_SIZE, Qnil),
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
95 Qzero);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
96 narrow_line_number_cache (b);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
97 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
98
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
99 /* Update line_number_begv. Do it only if the line number cache is
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
100 already initialized. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
101 void
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
102 narrow_line_number_cache (struct buffer *b)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
103 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
104 EMACS_INT lots = 999999999, shortage;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
105
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
106 if (NILP (b->line_number_cache))
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
107 return;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
108 /* Optimization: if BUF_BEG == BUF_BEGV (as is the case after Fwiden
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
109 and save_restriction_restore), don't bother calling scan_buffer. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
110 if (BUF_BEG (b) == BUF_BEGV (b))
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
111 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
112 LINE_NUMBER_BEGV (b) = Qzero;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
113 return;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
114 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
115 /* Count the newlines between beginning of buffer and beginning of
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
116 the visible portion of the buffer. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
117 scan_buffer (b, '\n', BUF_BEG (b), BUF_BEGV (b), lots,
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
118 (int *)&shortage, 0);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
119 LINE_NUMBER_BEGV (b) = make_int (lots - shortage);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
120 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
121
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
122 /* Invalidate the line number cache positions that lie after POS. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
123 static void
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
124 invalidate_line_number_cache (struct buffer *b, Bufpos pos)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
125 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
126 EMACS_INT i, j;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
127 Lisp_Object *ring = XVECTOR_DATA (LINE_NUMBER_RING (b));
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
128 Lisp_Object lisp_buffer = make_buffer (b);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
129
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
130 for (i = 0; i < LINE_NUMBER_RING_SIZE; i++)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
131 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
132 if (!CONSP (ring[i]))
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
133 break;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
134 if (marker_position (XCAR (ring[i])) > pos)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
135 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
136 /* Get the marker out of the way. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
137 Fset_marker (XCAR (ring[i]), Qnil, lisp_buffer);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
138 /* ...and shift the ring elements, up to the first nil. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
139 for (j = i; !NILP (ring[j]) && j < LINE_NUMBER_RING_SIZE - 1; j++)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
140 ring[j] = ring[j + 1];
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
141 ring[j] = Qnil;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
142 /* Must reevaluate the thing at position i. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
143 i--;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
144 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
145 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
146 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
147
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
148 /* Invalidate the cache positions after POS, if the string to be
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
149 inserted contains a newline. If the string is too large (larger
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
150 than LINE_NUMBER_LARGE_STRING), invalidate the cache positions
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
151 after POS without prior search.
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
152
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
153 This will do nothing, if cache is uninitialized. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
154 void
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
155 insert_invalidate_line_number_cache (struct buffer *b, Bufpos pos,
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
156 CONST Bufbyte *nonreloc, Bytecount length)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
157 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
158 if (NILP (b->line_number_cache))
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
159 return;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
160
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
161 if (length > LINE_NUMBER_LARGE_STRING
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
162 ||
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
163 /* We could also count how many newlines are in the string, and
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
164 update the cache accordingly, but it would be too much work
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
165 for too little gain. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
166 memchr ((void *)nonreloc, '\n', (size_t) length))
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
167 invalidate_line_number_cache (b, pos);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
168 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
169
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
170 /* Invalidate the cache positions after FROM, if the region to be
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
171 deleted contains a newline. If the region is too large (larger
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
172 than LINE_NUMBER_LARGE_STRING), invalidate the cache positions
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
173 after FROM without prior search.
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
174
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
175 This will do nothing, if cache is uninitialized. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
176 void
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
177 delete_invalidate_line_number_cache (struct buffer *b, Bufpos from, Bufpos to)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
178 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
179 if (NILP (b->line_number_cache))
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
180 return;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
181
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
182 if ((to - from) > LINE_NUMBER_LARGE_STRING)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
183 invalidate_line_number_cache (b, from);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
184 else
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
185 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
186 int shortage;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
187 scan_buffer (b, '\n', from, to, 1, &shortage, 0);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
188 if (!shortage)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
189 /* The same as above applies. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
190 invalidate_line_number_cache (b, from);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
191 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
192 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
193
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
194
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
195 /* Get the nearest known position we know the line number of
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
196 (i.e. BUF_BEGV, and cached positions). The return position will be
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
197 either closer than BEG, or BEG.
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
198
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
199 *LINE should be initialized to the line number of BEG (normally,
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
200 BEG will be BUF_BEGV, and *LINE will be XINT (LINE_NUMBER_BEGV).
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
201 This will initialize the cache, if necessary. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
202 static void
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
203 get_nearest_line_number (struct buffer *b, Bufpos *beg, Bufpos pos,
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
204 EMACS_INT *line)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
205 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
206 Lisp_Object *ring = XVECTOR_DATA (LINE_NUMBER_RING (b));
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
207 EMACS_INT i;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
208 Charcount length, howfar;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
209 Bufpos newpos;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
210
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
211 length = pos - *beg;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
212 if (length < 0)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
213 length = -length;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
214
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
215 /* Look for the nearest match. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
216 for (i = 0; i < LINE_NUMBER_RING_SIZE; i++)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
217 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
218 if (!CONSP (ring[i]))
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
219 break;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
220 newpos = marker_position (XCAR (ring[i]));
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
221 howfar = newpos - pos;
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
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
233 /* Add a (pos, line) pair to the ring, and rotate it. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
234 static void
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
235 add_line_number (struct buffer *b, Bufpos pos, int line)
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));
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
238 Lisp_Object marker;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
239 int i;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
240
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
241 for (i = LINE_NUMBER_RING_SIZE - 1; i > 0; i--)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
242 ring[i] = ring[i - 1];
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
243 marker = Fmake_marker ();
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
244 Fset_marker (marker, make_int (pos), make_buffer (b));
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
245 ring[0] = Fcons (marker, make_int (line));
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
246 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
247
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
248 /* Calculate the buffer line number. If CACHEP is non-zero,
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
249 initialize the line-number cache for future use. The line number
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
250 of the first line is 0. If narrowing is in effect, count the lines
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
251 from the beginning of the visible portion of the buffer.
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
252
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
253 The cache works as follows: To calculate the line number, we need
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
254 two positions: position of point (POS) and the position from which
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
255 to count newlines (BEG). We start by setting BEG to BUF_BEGV. If
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
256 this would require too much searching (i.e. pos - BUF_BEGV >
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
257 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
258 is found, use that position for BEG, and increment the line number
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
259 appropriately.
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
260
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
261 If the calculation (with or without the cache lookup) required more
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
262 than LINE_NUMBER_FAR bytes of traversal, update the cache. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
263 EMACS_INT
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
264 buffer_line_number (struct buffer *b, Bufpos pos, int cachep)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
265 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
266 Bufpos beg = BUF_BEGV (b);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
267 EMACS_INT cached_lines = 0;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
268 EMACS_INT lots = 999999999;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
269 EMACS_INT shortage, line;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
270
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
271 if (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 if (NILP (b->line_number_cache))
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
274 allocate_line_number_cache (b);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
275 cached_lines = XINT (LINE_NUMBER_BEGV (b));
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
276 get_nearest_line_number (b, &beg, pos, &cached_lines);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
277 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
278
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
279 scan_buffer (b, '\n', beg, pos, pos > beg ? lots : -lots,
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
280 (int *)&shortage, 0);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
281
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
282 line = lots - shortage;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
283 if (beg > pos)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
284 line = -line;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
285 line += cached_lines;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
286
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
287 if (cachep)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
288 {
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
289 /* If too far, update the cache. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
290 if ((pos > beg ? pos - beg : beg - pos) > LINE_NUMBER_FAR)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
291 add_line_number (b, pos, line);
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
292 /* Account for narrowing. If CACHEP is nil, this is
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
293 unnecessary, because we counted from BUF_BEGV anyway. */
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
294 if (cachep)
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
295 line -= XINT (LINE_NUMBER_BEGV (b));
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
296 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
297
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
298 return line;
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
299 }
78478c60bfcd Import from CVS: tag r20-4b4
cvs
parents:
diff changeset
300