314
|
1 /* Updating of data structures for redisplay.
|
26088
b7aa6ac26872
Add support for large files, 64-bit Solaris, system locale codings.
Paul Eggert <eggert@twinsun.com>
diff
changeset
|
2 Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 1999
|
18853
|
3 Free Software Foundation, Inc.
|
314
|
4
|
|
5 This file is part of GNU Emacs.
|
|
6
|
|
7 GNU Emacs is free software; you can redistribute it and/or modify
|
|
8 it under the terms of the GNU General Public License as published by
|
1777
|
9 the Free Software Foundation; either version 2, or (at your option)
|
314
|
10 any later version.
|
|
11
|
|
12 GNU Emacs is distributed in the hope that it will be useful,
|
|
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15 GNU General Public License for more details.
|
|
16
|
|
17 You should have received a copy of the GNU General Public License
|
|
18 along with GNU Emacs; see the file COPYING. If not, write to
|
14186
|
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
20 Boston, MA 02111-1307, USA. */
|
314
|
21
|
26088
b7aa6ac26872
Add support for large files, 64-bit Solaris, system locale codings.
Paul Eggert <eggert@twinsun.com>
diff
changeset
|
22 #include <config.h>
|
314
|
23 #include <signal.h>
|
7900
|
24 #include <stdio.h>
|
314
|
25 #include <ctype.h>
|
|
26
|
21514
|
27 #ifdef HAVE_UNISTD_H
|
|
28 #include <unistd.h>
|
|
29 #endif
|
|
30
|
3525
|
31 #include "lisp.h"
|
314
|
32 #include "termchar.h"
|
|
33 #include "termopts.h"
|
2198
|
34 #include "termhooks.h"
|
13526
|
35 /* cm.h must come after dispextern.h on Windows. */
|
13408
|
36 #include "dispextern.h"
|
|
37 #include "cm.h"
|
314
|
38 #include "buffer.h"
|
17015
|
39 #include "charset.h"
|
764
|
40 #include "frame.h"
|
314
|
41 #include "window.h"
|
|
42 #include "commands.h"
|
|
43 #include "disptab.h"
|
|
44 #include "indent.h"
|
4384
|
45 #include "intervals.h"
|
15065
|
46 #include "blockinput.h"
|
21514
|
47 #include "process.h"
|
|
48 #include "keyboard.h"
|
314
|
49
|
17015
|
50 /* I don't know why DEC Alpha OSF1 fail to compile this file if we
|
|
51 include the following file. */
|
|
52 /* #include "systty.h" */
|
12917
|
53 #include "syssignal.h"
|
554
|
54
|
314
|
55 #ifdef HAVE_X_WINDOWS
|
|
56 #include "xterm.h"
|
25012
|
57 #endif /* HAVE_X_WINDOWS */
|
314
|
58
|
13408
|
59 #ifdef HAVE_NTGUI
|
|
60 #include "w32term.h"
|
|
61 #endif /* HAVE_NTGUI */
|
|
62
|
25012
|
63 /* Include systime.h after xterm.h to avoid double inclusion of time.h. */
|
|
64
|
7808
|
65 #include "systime.h"
|
7558
|
66 #include <errno.h>
|
|
67
|
25012
|
68 /* To get the prototype for `sleep'. */
|
|
69
|
|
70 #ifdef HAVE_UNISTD_H
|
|
71 #include <unistd.h>
|
|
72 #endif
|
|
73
|
314
|
74 #define max(a, b) ((a) > (b) ? (a) : (b))
|
|
75 #define min(a, b) ((a) < (b) ? (a) : (b))
|
|
76
|
|
77 /* Get number of chars of output now in the buffer of a stdio stream.
|
25012
|
78 This ought to be built in in stdio, but it isn't. Some s- files
|
|
79 override this because their stdio internals differ. */
|
|
80
|
5214
c4bf07b226be
(PENDING_OUTPUT_COUNT) [__GNU_LIBRARY__]: Alternate definition for the GNU
Roland McGrath <roland@gnu.org>
diff
changeset
|
81 #ifdef __GNU_LIBRARY__
|
25012
|
82
|
|
83 /* The s- file might have overridden the definition with one that
|
|
84 works for the system's C library. But we are using the GNU C
|
|
85 library, so this is the right definition for every system. */
|
|
86
|
7558
|
87 #ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT
|
|
88 #define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT
|
|
89 #else
|
7443
a9cb818e5316
[__GNU_LIBRARY__]: Redefine PENDING_OUTPUT_COUNT even if already defined.
Roland McGrath <roland@gnu.org>
diff
changeset
|
90 #undef PENDING_OUTPUT_COUNT
|
5214
c4bf07b226be
(PENDING_OUTPUT_COUNT) [__GNU_LIBRARY__]: Alternate definition for the GNU
Roland McGrath <roland@gnu.org>
diff
changeset
|
91 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
|
7558
|
92 #endif
|
|
93 #else /* not __GNU_LIBRARY__ */
|
26088
b7aa6ac26872
Add support for large files, 64-bit Solaris, system locale codings.
Paul Eggert <eggert@twinsun.com>
diff
changeset
|
94 #if !defined (PENDING_OUTPUT_COUNT) && HAVE_STDIO_EXT_H && HAVE___FPENDING
|
b7aa6ac26872
Add support for large files, 64-bit Solaris, system locale codings.
Paul Eggert <eggert@twinsun.com>
diff
changeset
|
95 #include <stdio_ext.h>
|
b7aa6ac26872
Add support for large files, 64-bit Solaris, system locale codings.
Paul Eggert <eggert@twinsun.com>
diff
changeset
|
96 #define PENDING_OUTPUT_COUNT(FILE) __fpending (FILE)
|
b7aa6ac26872
Add support for large files, 64-bit Solaris, system locale codings.
Paul Eggert <eggert@twinsun.com>
diff
changeset
|
97 #endif
|
7443
a9cb818e5316
[__GNU_LIBRARY__]: Redefine PENDING_OUTPUT_COUNT even if already defined.
Roland McGrath <roland@gnu.org>
diff
changeset
|
98 #ifndef PENDING_OUTPUT_COUNT
|
314
|
99 #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
|
|
100 #endif
|
25012
|
101 #endif /* not __GNU_LIBRARY__ */
|
|
102
|
|
103
|
|
104 /* Structure to pass dimensions around. Used for character bounding
|
|
105 boxes, glyph matrix dimensions and alike. */
|
|
106
|
|
107 struct dim
|
|
108 {
|
|
109 int width;
|
|
110 int height;
|
|
111 };
|
|
112
|
|
113
|
|
114 /* Function prototypes. */
|
|
115
|
25186
|
116 static void redraw_overlapping_rows P_ ((struct window *, int));
|
|
117 static void redraw_overlapped_rows P_ ((struct window *, int));
|
25012
|
118 static int count_blanks P_ ((struct glyph *, int));
|
|
119 static int count_match P_ ((struct glyph *, struct glyph *,
|
|
120 struct glyph *, struct glyph *));
|
|
121 static unsigned line_draw_cost P_ ((struct glyph_matrix *, int));
|
|
122 static void update_frame_line P_ ((struct frame *, int));
|
|
123 static struct dim allocate_matrices_for_frame_redisplay
|
|
124 P_ ((Lisp_Object, int, int, struct dim, int, int *));
|
|
125 static void allocate_matrices_for_window_redisplay P_ ((struct window *,
|
|
126 struct dim));
|
|
127 static int realloc_glyph_pool P_ ((struct glyph_pool *, struct dim));
|
|
128 static void adjust_frame_glyphs P_ ((struct frame *));
|
|
129 struct glyph_matrix *new_glyph_matrix P_ ((struct glyph_pool *));
|
|
130 static void free_glyph_matrix P_ ((struct glyph_matrix *));
|
|
131 static void adjust_glyph_matrix P_ ((struct window *, struct glyph_matrix *,
|
|
132 int, int, struct dim));
|
25345
|
133 static void change_frame_size_1 P_ ((struct frame *, int, int, int, int, int));
|
25012
|
134 static void swap_glyphs_in_rows P_ ((struct glyph_row *, struct glyph_row *));
|
|
135 static void swap_glyph_pointers P_ ((struct glyph_row *, struct glyph_row *));
|
|
136 static int glyph_row_slice_p P_ ((struct glyph_row *, struct glyph_row *));
|
|
137 static void fill_up_frame_row_with_spaces P_ ((struct glyph_row *, int));
|
|
138 static void build_frame_matrix_from_window_tree P_ ((struct glyph_matrix *,
|
|
139 struct window *));
|
|
140 static void build_frame_matrix_from_leaf_window P_ ((struct glyph_matrix *,
|
|
141 struct window *));
|
|
142 static struct glyph_pool *new_glyph_pool P_ ((void));
|
|
143 static void free_glyph_pool P_ ((struct glyph_pool *));
|
|
144 static void adjust_frame_glyphs_initially P_ ((void));
|
|
145 static void adjust_frame_message_buffer P_ ((struct frame *));
|
|
146 static void adjust_decode_mode_spec_buffer P_ ((struct frame *));
|
|
147 static void fill_up_glyph_row_with_spaces P_ ((struct glyph_row *));
|
|
148 static void build_frame_matrix P_ ((struct frame *));
|
|
149 void clear_current_matrices P_ ((struct frame *));
|
|
150 void scroll_glyph_matrix_range P_ ((struct glyph_matrix *, int, int,
|
|
151 int, int));
|
|
152 static void clear_window_matrices P_ ((struct window *, int));
|
|
153 static void fill_up_glyph_row_area_with_spaces P_ ((struct glyph_row *, int));
|
|
154 static int scrolling_window P_ ((struct window *, int));
|
25186
|
155 static int update_window_line P_ ((struct window *, int));
|
25012
|
156 static void update_marginal_area P_ ((struct window *, int, int));
|
25186
|
157 static int update_text_area P_ ((struct window *, int));
|
25012
|
158 static void make_current P_ ((struct glyph_matrix *, struct glyph_matrix *,
|
|
159 int));
|
|
160 static void mirror_make_current P_ ((struct window *, int));
|
|
161 void check_window_matrix_pointers P_ ((struct window *));
|
25345
|
162 #if GLYPH_DEBUG
|
25012
|
163 static void check_matrix_pointers P_ ((struct glyph_matrix *,
|
|
164 struct glyph_matrix *));
|
25345
|
165 #endif
|
25012
|
166 static void mirror_line_dance P_ ((struct window *, int, int, int *, char *));
|
|
167 static int update_window_tree P_ ((struct window *, int));
|
|
168 static int update_window P_ ((struct window *, int));
|
|
169 static int update_frame_1 P_ ((struct frame *, int, int));
|
|
170 static void set_window_cursor_after_update P_ ((struct window *));
|
|
171 static int row_equal_p P_ ((struct window *, struct glyph_row *,
|
|
172 struct glyph_row *));
|
|
173 static void adjust_frame_glyphs_for_window_redisplay P_ ((struct frame *));
|
|
174 static void adjust_frame_glyphs_for_frame_redisplay P_ ((struct frame *));
|
|
175 static void reverse_rows P_ ((struct glyph_matrix *, int, int));
|
|
176 static int margin_glyphs_to_reserve P_ ((struct window *, int, Lisp_Object));
|
27855
|
177 static void sync_window_with_frame_matrix_rows P_ ((struct window *));
|
|
178 struct window *frame_row_to_window P_ ((struct window *, int));
|
25012
|
179
|
|
180
|
|
181
|
|
182 /* Non-zero means don't pause redisplay for pending input. (This is
|
|
183 for debugging and for a future implementation of EDT-like
|
|
184 scrolling. */
|
|
185
|
|
186 int redisplay_dont_pause;
|
10770
|
187
|
554
|
188 /* Nonzero upon entry to redisplay means do not assume anything about
|
764
|
189 current contents of actual terminal frame; clear and redraw it. */
|
314
|
190
|
764
|
191 int frame_garbaged;
|
314
|
192
|
25012
|
193 /* Nonzero means last display completed. Zero means it was preempted. */
|
314
|
194
|
|
195 int display_completed;
|
|
196
|
25012
|
197 /* Lisp variable visible-bell; enables use of screen-flash instead of
|
|
198 audible bell. */
|
314
|
199
|
|
200 int visible_bell;
|
|
201
|
764
|
202 /* Invert the color of the whole frame, at a low level. */
|
314
|
203
|
|
204 int inverse_video;
|
|
205
|
|
206 /* Line speed of the terminal. */
|
|
207
|
|
208 int baud_rate;
|
|
209
|
25012
|
210 /* Either nil or a symbol naming the window system under which Emacs
|
|
211 is running. */
|
314
|
212
|
|
213 Lisp_Object Vwindow_system;
|
|
214
|
|
215 /* Version number of X windows: 10, 11 or nil. */
|
25012
|
216
|
314
|
217 Lisp_Object Vwindow_system_version;
|
|
218
|
25012
|
219 /* Vector of glyph definitions. Indexed by glyph number, the contents
|
|
220 are a string which is how to output the glyph.
|
314
|
221
|
|
222 If Vglyph_table is nil, a glyph is output by using its low 8 bits
|
25012
|
223 as a character code.
|
|
224
|
|
225 This is an obsolete feature that is no longer used. The variable
|
|
226 is retained for compatibility. */
|
314
|
227
|
|
228 Lisp_Object Vglyph_table;
|
|
229
|
|
230 /* Display table to use for vectors that don't specify their own. */
|
|
231
|
|
232 Lisp_Object Vstandard_display_table;
|
|
233
|
25012
|
234 /* Nonzero means reading single-character input with prompt so put
|
|
235 cursor on mini-buffer after the prompt. positive means at end of
|
|
236 text in echo area; negative means at beginning of line. */
|
|
237
|
314
|
238 int cursor_in_echo_area;
|
13220
|
239
|
|
240 Lisp_Object Qdisplay_table;
|
25012
|
241
|
314
|
242
|
25012
|
243 /* The currently selected frame. In a single-frame version, this
|
25666
|
244 variable always equals the_only_frame. */
|
|
245
|
|
246 Lisp_Object selected_frame;
|
25012
|
247
|
|
248 /* A frame which is not just a mini-buffer, or 0 if there are no such
|
764
|
249 frames. This is usually the most recent such frame that was
|
9572
|
250 selected. In a single-frame version, this variable always holds
|
|
251 the address of the_only_frame. */
|
25012
|
252
|
|
253 struct frame *last_nonminibuf_frame;
|
|
254
|
|
255 /* Stdio stream being used for copy of all output. */
|
|
256
|
|
257 FILE *termscript;
|
|
258
|
|
259 /* Structure for info on cursor positioning. */
|
|
260
|
|
261 struct cm Wcm;
|
|
262
|
|
263 /* 1 means SIGWINCH happened when not safe. */
|
|
264
|
|
265 int delayed_size_change;
|
|
266
|
|
267 /* 1 means glyph initialization has been completed at startup. */
|
|
268
|
|
269 static int glyphs_initialized_initially_p;
|
|
270
|
|
271 /* Updated window if != 0. Set by update_window. */
|
|
272
|
|
273 struct window *updated_window;
|
|
274
|
|
275 /* Glyph row updated in update_window_line, and area that is updated. */
|
|
276
|
|
277 struct glyph_row *updated_row;
|
|
278 int updated_area;
|
|
279
|
|
280 /* A glyph for a space. */
|
|
281
|
|
282 struct glyph space_glyph;
|
|
283
|
|
284 /* Non-zero means update has been performed directly, so that there's
|
|
285 no need for redisplay_internal to do much work. Set by
|
|
286 direct_output_for_insert. */
|
|
287
|
|
288 int redisplay_performed_directly_p;
|
|
289
|
|
290 /* Counts of allocated structures. These counts serve to diagnose
|
|
291 memory leaks and double frees. */
|
|
292
|
|
293 int glyph_matrix_count;
|
|
294 int glyph_pool_count;
|
|
295
|
|
296 /* If non-null, the frame whose frame matrices are manipulated. If
|
|
297 null, window matrices are worked on. */
|
|
298
|
|
299 static struct frame *frame_matrix_frame;
|
|
300
|
|
301 /* Current interface for window-based redisplay. Set from init_xterm.
|
|
302 A null value means we are not using window-based redisplay. */
|
|
303
|
|
304 struct redisplay_interface *rif;
|
|
305
|
|
306 /* Non-zero means that fonts have been loaded since the last glyph
|
|
307 matrix adjustments. Redisplay must stop, and glyph matrices must
|
|
308 be adjusted when this flag becomes non-zero during display. The
|
|
309 reason fonts can be loaded so late is that fonts of fontsets are
|
|
310 loaded on demand. */
|
|
311
|
|
312 int fonts_changed_p;
|
|
313
|
|
314 /* Convert vpos and hpos from frame to window and vice versa.
|
|
315 This may only be used for terminal frames. */
|
|
316
|
|
317 #if GLYPH_DEBUG
|
|
318
|
|
319 static int window_to_frame_vpos P_ ((struct window *, int));
|
|
320 static int window_to_frame_hpos P_ ((struct window *, int));
|
|
321 #define WINDOW_TO_FRAME_VPOS(W, VPOS) window_to_frame_vpos ((W), (VPOS))
|
|
322 #define WINDOW_TO_FRAME_HPOS(W, HPOS) window_to_frame_hpos ((W), (HPOS))
|
|
323
|
|
324 #else /* GLYPH_DEBUG == 0 */
|
|
325
|
|
326 #define WINDOW_TO_FRAME_VPOS(W, VPOS) ((VPOS) + XFASTINT ((W)->top))
|
|
327 #define WINDOW_TO_FRAME_HPOS(W, HPOS) ((HPOS) + XFASTINT ((W)->left))
|
|
328
|
|
329 #endif /* GLYPH_DEBUG == 0 */
|
|
330
|
|
331
|
|
332 /* Like bcopy except never gets confused by overlap. Let this be the
|
|
333 first function defined in this file, or change emacs.c where the
|
|
334 address of this function is used. */
|
314
|
335
|
|
336 void
|
|
337 safe_bcopy (from, to, size)
|
|
338 char *from, *to;
|
|
339 int size;
|
|
340 {
|
1588
|
341 if (size <= 0 || from == to)
|
314
|
342 return;
|
|
343
|
1588
|
344 /* If the source and destination don't overlap, then bcopy can
|
|
345 handle it. If they do overlap, but the destination is lower in
|
|
346 memory than the source, we'll assume bcopy can handle that. */
|
|
347 if (to < from || from + size <= to)
|
|
348 bcopy (from, to, size);
|
|
349
|
|
350 /* Otherwise, we'll copy from the end. */
|
|
351 else
|
314
|
352 {
|
1588
|
353 register char *endf = from + size;
|
|
354 register char *endt = to + size;
|
314
|
355
|
|
356 /* If TO - FROM is large, then we should break the copy into
|
|
357 nonoverlapping chunks of TO - FROM bytes each. However, if
|
|
358 TO - FROM is small, then the bcopy function call overhead
|
|
359 makes this not worth it. The crossover point could be about
|
1588
|
360 anywhere. Since I don't think the obvious copy loop is too
|
|
361 bad, I'm trying to err in its favor. */
|
314
|
362 if (to - from < 64)
|
|
363 {
|
|
364 do
|
|
365 *--endt = *--endf;
|
|
366 while (endf != from);
|
|
367 }
|
|
368 else
|
|
369 {
|
1588
|
370 for (;;)
|
314
|
371 {
|
|
372 endt -= (to - from);
|
|
373 endf -= (to - from);
|
|
374
|
1588
|
375 if (endt < to)
|
|
376 break;
|
|
377
|
314
|
378 bcopy (endf, endt, to - from);
|
|
379 }
|
1588
|
380
|
|
381 /* If SIZE wasn't a multiple of TO - FROM, there will be a
|
25012
|
382 little left over. The amount left over is (endt + (to -
|
|
383 from)) - to, which is endt - from. */
|
314
|
384 bcopy (from, to, endt - from);
|
|
385 }
|
|
386 }
|
|
387 }
|
|
388
|
25012
|
389
|
|
390
|
|
391 /***********************************************************************
|
|
392 Glyph Matrices
|
|
393 ***********************************************************************/
|
|
394
|
|
395 /* Allocate and return a glyph_matrix structure. POOL is the glyph
|
|
396 pool from which memory for the matrix should be allocated, or null
|
|
397 for window-based redisplay where no glyph pools are used. The
|
|
398 member `pool' of the glyph matrix structure returned is set to
|
|
399 POOL, the structure is otherwise zeroed. */
|
|
400
|
|
401 struct glyph_matrix *
|
|
402 new_glyph_matrix (pool)
|
|
403 struct glyph_pool *pool;
|
|
404 {
|
|
405 struct glyph_matrix *result;
|
|
406
|
|
407 /* Allocate and clear. */
|
|
408 result = (struct glyph_matrix *) xmalloc (sizeof *result);
|
|
409 bzero (result, sizeof *result);
|
|
410
|
|
411 /* Increment number of allocated matrices. This count is used
|
|
412 to detect memory leaks. */
|
|
413 ++glyph_matrix_count;
|
|
414
|
|
415 /* Set pool and return. */
|
|
416 result->pool = pool;
|
|
417 return result;
|
|
418 }
|
|
419
|
|
420
|
|
421 /* Free glyph matrix MATRIX. Passing in a null MATRIX is allowed.
|
|
422
|
|
423 The global counter glyph_matrix_count is decremented when a matrix
|
|
424 is freed. If the count gets negative, more structures were freed
|
|
425 than allocated, i.e. one matrix was freed more than once or a bogus
|
|
426 pointer was passed to this function.
|
|
427
|
|
428 If MATRIX->pool is null, this means that the matrix manages its own
|
|
429 glyph memory---this is done for matrices on X frames. Freeing the
|
|
430 matrix also frees the glyph memory in this case. */
|
|
431
|
|
432 static void
|
|
433 free_glyph_matrix (matrix)
|
|
434 struct glyph_matrix *matrix;
|
|
435 {
|
|
436 if (matrix)
|
|
437 {
|
|
438 int i;
|
|
439
|
|
440 /* Detect the case that more matrices are freed than were
|
|
441 allocated. */
|
|
442 if (--glyph_matrix_count < 0)
|
|
443 abort ();
|
|
444
|
|
445 /* Free glyph memory if MATRIX owns it. */
|
|
446 if (matrix->pool == NULL)
|
|
447 for (i = 0; i < matrix->rows_allocated; ++i)
|
|
448 xfree (matrix->rows[i].glyphs[LEFT_MARGIN_AREA]);
|
|
449
|
|
450 /* Free row structures and the matrix itself. */
|
|
451 xfree (matrix->rows);
|
|
452 xfree (matrix);
|
|
453 }
|
|
454 }
|
|
455
|
|
456
|
|
457 /* Return the number of glyphs to reserve for a marginal area of
|
|
458 window W. TOTAL_GLYPHS is the number of glyphs in a complete
|
|
459 display line of window W. MARGIN gives the width of the marginal
|
|
460 area in canonical character units. MARGIN should be an integer
|
|
461 or a float. */
|
|
462
|
|
463 static int
|
|
464 margin_glyphs_to_reserve (w, total_glyphs, margin)
|
|
465 struct window *w;
|
|
466 int total_glyphs;
|
|
467 Lisp_Object margin;
|
|
468 {
|
|
469 int n;
|
|
470
|
|
471 if (NUMBERP (margin))
|
|
472 {
|
|
473 int width = XFASTINT (w->width);
|
|
474 double d = max (0, XFLOATINT (margin));
|
|
475 d = min (width / 2 - 1, d);
|
|
476 n = (int) ((double) total_glyphs / width * d);
|
|
477 }
|
|
478 else
|
|
479 n = 0;
|
|
480
|
|
481 return n;
|
|
482 }
|
|
483
|
|
484
|
|
485 /* Adjust glyph matrix MATRIX on window W or on a frame to changed
|
|
486 window sizes.
|
|
487
|
|
488 W is null if the function is called for a frame glyph matrix.
|
|
489 Otherwise it is the window MATRIX is a member of. X and Y are the
|
|
490 indices of the first column and row of MATRIX within the frame
|
|
491 matrix, if such a matrix exists. They are zero for purely
|
|
492 window-based redisplay. DIM is the needed size of the matrix.
|
|
493
|
|
494 In window-based redisplay, where no frame matrices exist, glyph
|
|
495 matrices manage their own glyph storage. Otherwise, they allocate
|
|
496 storage from a common frame glyph pool which can be found in
|
|
497 MATRIX->pool.
|
|
498
|
|
499 The reason for this memory management strategy is to avoid complete
|
|
500 frame redraws if possible. When we allocate from a common pool, a
|
|
501 change of the location or size of a sub-matrix within the pool
|
|
502 requires a complete redisplay of the frame because we cannot easily
|
|
503 make sure that the current matrices of all windows still agree with
|
|
504 what is displayed on the screen. While this is usually fast, it
|
|
505 leads to screen flickering. */
|
|
506
|
|
507 static void
|
|
508 adjust_glyph_matrix (w, matrix, x, y, dim)
|
|
509 struct window *w;
|
|
510 struct glyph_matrix *matrix;
|
|
511 int x, y;
|
|
512 struct dim dim;
|
|
513 {
|
|
514 int i;
|
|
515 int new_rows;
|
|
516 int marginal_areas_changed_p = 0;
|
25546
|
517 int header_line_changed_p = 0;
|
|
518 int header_line_p = 0;
|
25012
|
519 int left = -1, right = -1;
|
|
520 int window_x, window_y, window_width, window_height;
|
|
521
|
|
522 /* See if W had a top line that has disappeared now, or vice versa. */
|
|
523 if (w)
|
|
524 {
|
25546
|
525 header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
|
|
526 header_line_changed_p = header_line_p != matrix->header_line_p;
|
25012
|
527 }
|
25546
|
528 matrix->header_line_p = header_line_p;
|
25012
|
529
|
|
530 /* Do nothing if MATRIX' size, position, vscroll, and marginal areas
|
|
531 haven't changed. This optimization is important because preserving
|
|
532 the matrix means preventing redisplay. */
|
|
533 if (matrix->pool == NULL)
|
|
534 {
|
|
535 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
|
|
536 left = margin_glyphs_to_reserve (w, dim.width, w->left_margin_width);
|
|
537 right = margin_glyphs_to_reserve (w, dim.width, w->right_margin_width);
|
|
538 xassert (left >= 0 && right >= 0);
|
|
539 marginal_areas_changed_p = (left != matrix->left_margin_glyphs
|
|
540 || right != matrix->right_margin_glyphs);
|
|
541
|
|
542 if (!marginal_areas_changed_p
|
|
543 && !fonts_changed_p
|
25546
|
544 && !header_line_changed_p
|
25012
|
545 && matrix->window_top_y == XFASTINT (w->top)
|
|
546 && matrix->window_height == window_height
|
|
547 && matrix->window_vscroll == w->vscroll
|
|
548 && matrix->window_width == window_width)
|
|
549 return;
|
|
550 }
|
|
551
|
|
552 /* Enlarge MATRIX->rows if necessary. New rows are cleared. */
|
|
553 if (matrix->rows_allocated < dim.height)
|
|
554 {
|
|
555 int size = dim.height * sizeof (struct glyph_row);
|
|
556 new_rows = dim.height - matrix->rows_allocated;
|
|
557 matrix->rows = (struct glyph_row *) xrealloc (matrix->rows, size);
|
|
558 bzero (matrix->rows + matrix->rows_allocated,
|
|
559 new_rows * sizeof *matrix->rows);
|
|
560 matrix->rows_allocated = dim.height;
|
|
561 }
|
|
562 else
|
|
563 new_rows = 0;
|
|
564
|
|
565 /* If POOL is not null, MATRIX is a frame matrix or a window matrix
|
|
566 on a frame not using window-based redisplay. Set up pointers for
|
|
567 each row into the glyph pool. */
|
|
568 if (matrix->pool)
|
|
569 {
|
|
570 xassert (matrix->pool->glyphs);
|
|
571
|
|
572 if (w)
|
|
573 {
|
|
574 left = margin_glyphs_to_reserve (w, dim.width,
|
|
575 w->left_margin_width);
|
|
576 right = margin_glyphs_to_reserve (w, dim.width,
|
|
577 w->right_margin_width);
|
|
578 }
|
|
579 else
|
|
580 left = right = 0;
|
|
581
|
|
582 for (i = 0; i < dim.height; ++i)
|
|
583 {
|
|
584 struct glyph_row *row = &matrix->rows[i];
|
|
585
|
|
586 row->glyphs[LEFT_MARGIN_AREA]
|
|
587 = (matrix->pool->glyphs
|
|
588 + (y + i) * matrix->pool->ncolumns
|
|
589 + x);
|
|
590
|
|
591 if (w == NULL
|
|
592 || row == matrix->rows + dim.height - 1
|
25546
|
593 || (row == matrix->rows && matrix->header_line_p))
|
25012
|
594 {
|
|
595 row->glyphs[TEXT_AREA]
|
|
596 = row->glyphs[LEFT_MARGIN_AREA];
|
|
597 row->glyphs[RIGHT_MARGIN_AREA]
|
|
598 = row->glyphs[TEXT_AREA] + dim.width;
|
|
599 row->glyphs[LAST_AREA]
|
|
600 = row->glyphs[RIGHT_MARGIN_AREA];
|
|
601 }
|
|
602 else
|
|
603 {
|
|
604 row->glyphs[TEXT_AREA]
|
|
605 = row->glyphs[LEFT_MARGIN_AREA] + left;
|
|
606 row->glyphs[RIGHT_MARGIN_AREA]
|
|
607 = row->glyphs[TEXT_AREA] + dim.width - left - right;
|
|
608 row->glyphs[LAST_AREA]
|
|
609 = row->glyphs[LEFT_MARGIN_AREA] + dim.width;
|
|
610 }
|
|
611 }
|
|
612
|
|
613 matrix->left_margin_glyphs = left;
|
|
614 matrix->right_margin_glyphs = right;
|
|
615 }
|
|
616 else
|
|
617 {
|
|
618 /* If MATRIX->pool is null, MATRIX is responsible for managing
|
|
619 its own memory. Allocate glyph memory from the heap. */
|
|
620 if (dim.width > matrix->matrix_w
|
|
621 || new_rows
|
25546
|
622 || header_line_changed_p
|
25012
|
623 || marginal_areas_changed_p)
|
|
624 {
|
|
625 struct glyph_row *row = matrix->rows;
|
|
626 struct glyph_row *end = row + matrix->rows_allocated;
|
|
627
|
|
628 while (row < end)
|
|
629 {
|
|
630 row->glyphs[LEFT_MARGIN_AREA]
|
|
631 = (struct glyph *) xrealloc (row->glyphs[LEFT_MARGIN_AREA],
|
|
632 (dim.width
|
|
633 * sizeof (struct glyph)));
|
|
634
|
|
635 /* The mode line never has marginal areas. */
|
|
636 if (row == matrix->rows + dim.height - 1
|
25546
|
637 || (row == matrix->rows && matrix->header_line_p))
|
25012
|
638 {
|
|
639 row->glyphs[TEXT_AREA]
|
|
640 = row->glyphs[LEFT_MARGIN_AREA];
|
|
641 row->glyphs[RIGHT_MARGIN_AREA]
|
|
642 = row->glyphs[TEXT_AREA] + dim.width;
|
|
643 row->glyphs[LAST_AREA]
|
|
644 = row->glyphs[RIGHT_MARGIN_AREA];
|
|
645 }
|
|
646 else
|
|
647 {
|
|
648 row->glyphs[TEXT_AREA]
|
|
649 = row->glyphs[LEFT_MARGIN_AREA] + left;
|
|
650 row->glyphs[RIGHT_MARGIN_AREA]
|
|
651 = row->glyphs[TEXT_AREA] + dim.width - left - right;
|
|
652 row->glyphs[LAST_AREA]
|
|
653 = row->glyphs[LEFT_MARGIN_AREA] + dim.width;
|
|
654 }
|
|
655 ++row;
|
|
656 }
|
|
657 }
|
|
658
|
|
659 xassert (left >= 0 && right >= 0);
|
|
660 matrix->left_margin_glyphs = left;
|
|
661 matrix->right_margin_glyphs = right;
|
|
662 }
|
|
663
|
|
664 /* Number of rows to be used by MATRIX. */
|
|
665 matrix->nrows = dim.height;
|
|
666
|
|
667 /* Mark rows in a current matrix of a window as not having valid
|
|
668 contents. It's important to not do this for desired matrices.
|
|
669 When Emacs starts, it may already be building desired matrices
|
|
670 when this function runs. */
|
|
671 if (w && matrix == w->current_matrix)
|
|
672 {
|
|
673 /* Optimize the case that only the height has changed (C-x 2,
|
|
674 upper window). Invalidate all rows that are no longer part
|
|
675 of the window. */
|
|
676 if (!marginal_areas_changed_p
|
|
677 && matrix->window_top_y == XFASTINT (w->top)
|
|
678 && matrix->window_width == window_width)
|
|
679 {
|
|
680 i = 0;
|
|
681 while (matrix->rows[i].enabled_p
|
|
682 && (MATRIX_ROW_BOTTOM_Y (matrix->rows + i)
|
|
683 < matrix->window_height))
|
|
684 ++i;
|
|
685
|
|
686 /* Window end is invalid, if inside of the rows that
|
|
687 are invalidated. */
|
|
688 if (INTEGERP (w->window_end_vpos)
|
|
689 && XFASTINT (w->window_end_vpos) >= i)
|
|
690 w->window_end_valid = Qnil;
|
|
691
|
|
692 while (i < matrix->nrows)
|
|
693 matrix->rows[i++].enabled_p = 0;
|
|
694 }
|
|
695 else
|
|
696 {
|
|
697 for (i = 0; i < matrix->nrows; ++i)
|
|
698 matrix->rows[i].enabled_p = 0;
|
|
699 }
|
|
700 }
|
|
701
|
|
702 /* Remember last values to be able to optimize frame redraws. */
|
|
703 matrix->matrix_x = x;
|
|
704 matrix->matrix_y = y;
|
|
705 matrix->matrix_w = dim.width;
|
|
706 matrix->matrix_h = dim.height;
|
|
707
|
|
708 /* Record the top y location and height of W at the time the matrix
|
|
709 was last adjusted. This is used to optimize redisplay above. */
|
|
710 if (w)
|
|
711 {
|
|
712 matrix->window_top_y = XFASTINT (w->top);
|
|
713 matrix->window_height = window_height;
|
|
714 matrix->window_width = window_width;
|
|
715 matrix->window_vscroll = w->vscroll;
|
|
716 }
|
|
717 }
|
|
718
|
|
719
|
|
720 /* Reverse the contents of rows in MATRIX between START and END. The
|
|
721 contents of the row at END - 1 end up at START, END - 2 at START +
|
|
722 1 etc. This is part of the implementation of rotate_matrix (see
|
|
723 below). */
|
314
|
724
|
|
725 static void
|
25012
|
726 reverse_rows (matrix, start, end)
|
|
727 struct glyph_matrix *matrix;
|
|
728 int start, end;
|
314
|
729 {
|
25012
|
730 int i, j;
|
|
731
|
|
732 for (i = start, j = end - 1; i < j; ++i, --j)
|
|
733 {
|
|
734 /* Non-ISO HP/UX compiler doesn't like auto struct
|
|
735 initialization. */
|
|
736 struct glyph_row temp;
|
|
737 temp = matrix->rows[i];
|
|
738 matrix->rows[i] = matrix->rows[j];
|
|
739 matrix->rows[j] = temp;
|
|
740 }
|
314
|
741 }
|
|
742
|
25012
|
743
|
|
744 /* Rotate the contents of rows in MATRIX in the range FIRST .. LAST -
|
|
745 1 by BY positions. BY < 0 means rotate left, i.e. towards lower
|
|
746 indices. (Note: this does not copy glyphs, only glyph pointers in
|
|
747 row structures are moved around).
|
|
748
|
|
749 The algorithm used for rotating the vector was, I believe, first
|
|
750 described by Kernighan. See the vector R as consisting of two
|
|
751 sub-vectors AB, where A has length BY for BY >= 0. The result
|
|
752 after rotating is then BA. Reverse both sub-vectors to get ArBr
|
|
753 and reverse the result to get (ArBr)r which is BA. Similar for
|
|
754 rotating right. */
|
|
755
|
|
756 void
|
|
757 rotate_matrix (matrix, first, last, by)
|
|
758 struct glyph_matrix *matrix;
|
|
759 int first, last, by;
|
314
|
760 {
|
25012
|
761 if (by < 0)
|
|
762 {
|
|
763 /* Up (rotate left, i.e. towards lower indices). */
|
|
764 by = -by;
|
|
765 reverse_rows (matrix, first, first + by);
|
|
766 reverse_rows (matrix, first + by, last);
|
|
767 reverse_rows (matrix, first, last);
|
|
768 }
|
|
769 else if (by > 0)
|
314
|
770 {
|
25012
|
771 /* Down (rotate right, i.e. towards higher indices). */
|
|
772 reverse_rows (matrix, last - by, last);
|
|
773 reverse_rows (matrix, first, last - by);
|
|
774 reverse_rows (matrix, first, last);
|
314
|
775 }
|
25012
|
776 }
|
|
777
|
|
778
|
|
779 /* Increment buffer positions in glyph rows of MATRIX. Do it for rows
|
|
780 with indices START <= index < END. Increment positions by DELTA/
|
|
781 DELTA_BYTES. */
|
|
782
|
|
783 void
|
28708
|
784 increment_matrix_positions (matrix, start, end, delta, delta_bytes)
|
25012
|
785 struct glyph_matrix *matrix;
|
|
786 int start, end, delta, delta_bytes;
|
|
787 {
|
|
788 /* Check that START and END are reasonable values. */
|
|
789 xassert (start >= 0 && start <= matrix->nrows);
|
|
790 xassert (end >= 0 && end <= matrix->nrows);
|
|
791 xassert (start <= end);
|
|
792
|
|
793 for (; start < end; ++start)
|
28708
|
794 increment_row_positions (matrix->rows + start, delta, delta_bytes);
|
25012
|
795 }
|
|
796
|
|
797
|
|
798 /* Enable a range of rows in glyph matrix MATRIX. START and END are
|
|
799 the row indices of the first and last + 1 row to enable. If
|
|
800 ENABLED_P is non-zero, enabled_p flags in rows will be set to 1. */
|
|
801
|
|
802 void
|
|
803 enable_glyph_matrix_rows (matrix, start, end, enabled_p)
|
|
804 struct glyph_matrix *matrix;
|
|
805 int start, end;
|
|
806 int enabled_p;
|
|
807 {
|
|
808 xassert (start <= end);
|
|
809 xassert (start >= 0 && start < matrix->nrows);
|
|
810 xassert (end >= 0 && end <= matrix->nrows);
|
|
811
|
|
812 for (; start < end; ++start)
|
|
813 matrix->rows[start].enabled_p = enabled_p != 0;
|
|
814 }
|
|
815
|
|
816
|
|
817 /* Clear MATRIX.
|
|
818
|
|
819 This empties all rows in MATRIX by setting the enabled_p flag for
|
|
820 all rows of the matrix to zero. The function prepare_desired_row
|
|
821 will eventually really clear a row when it sees one with a zero
|
|
822 enabled_p flag.
|
|
823
|
|
824 Resets update hints to defaults value. The only update hint
|
|
825 currently present is the flag MATRIX->no_scrolling_p. */
|
|
826
|
|
827 void
|
|
828 clear_glyph_matrix (matrix)
|
|
829 struct glyph_matrix *matrix;
|
|
830 {
|
|
831 if (matrix)
|
314
|
832 {
|
25012
|
833 enable_glyph_matrix_rows (matrix, 0, matrix->nrows, 0);
|
|
834 matrix->no_scrolling_p = 0;
|
314
|
835 }
|
|
836 }
|
25012
|
837
|
|
838
|
|
839 /* Shift part of the glyph matrix MATRIX of window W up or down.
|
|
840 Increment y-positions in glyph rows between START and END by DY,
|
|
841 and recompute their visible height. */
|
|
842
|
|
843 void
|
|
844 shift_glyph_matrix (w, matrix, start, end, dy)
|
|
845 struct window *w;
|
|
846 struct glyph_matrix *matrix;
|
|
847 int start, end, dy;
|
|
848 {
|
|
849 int min_y, max_y;
|
|
850
|
|
851 xassert (start <= end);
|
|
852 xassert (start >= 0 && start < matrix->nrows);
|
|
853 xassert (end >= 0 && end <= matrix->nrows);
|
|
854
|
25546
|
855 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
|
25012
|
856 max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w);
|
|
857
|
|
858 for (; start < end; ++start)
|
|
859 {
|
|
860 struct glyph_row *row = &matrix->rows[start];
|
|
861
|
|
862 row->y += dy;
|
|
863
|
|
864 if (row->y < min_y)
|
|
865 row->visible_height = row->height - (min_y - row->y);
|
|
866 else if (row->y + row->height > max_y)
|
|
867 row->visible_height = row->height - (row->y + row->height - max_y);
|
|
868 else
|
|
869 row->visible_height = row->height;
|
|
870 }
|
|
871 }
|
|
872
|
|
873
|
|
874 /* Mark all rows in current matrices of frame F as invalid. Marking
|
|
875 invalid is done by setting enabled_p to zero for all rows in a
|
|
876 current matrix. */
|
|
877
|
|
878 void
|
|
879 clear_current_matrices (f)
|
|
880 register struct frame *f;
|
|
881 {
|
|
882 /* Clear frame current matrix, if we have one. */
|
|
883 if (f->current_matrix)
|
|
884 clear_glyph_matrix (f->current_matrix);
|
|
885
|
|
886 /* Clear the matrix of the menu bar window, if such a window exists.
|
|
887 The menu bar window is currently used to display menus on X when
|
|
888 no toolkit support is compiled in. */
|
|
889 if (WINDOWP (f->menu_bar_window))
|
|
890 clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix);
|
|
891
|
25544
|
892 /* Clear the matrix of the tool-bar window, if any. */
|
|
893 if (WINDOWP (f->tool_bar_window))
|
|
894 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
|
25012
|
895
|
|
896 /* Clear current window matrices. */
|
|
897 xassert (WINDOWP (FRAME_ROOT_WINDOW (f)));
|
|
898 clear_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)), 0);
|
|
899 }
|
|
900
|
|
901
|
|
902 /* Clear out all display lines of F for a coming redisplay. */
|
314
|
903
|
21514
|
904 void
|
25012
|
905 clear_desired_matrices (f)
|
|
906 register struct frame *f;
|
314
|
907 {
|
25012
|
908 if (f->desired_matrix)
|
|
909 clear_glyph_matrix (f->desired_matrix);
|
|
910
|
|
911 if (WINDOWP (f->menu_bar_window))
|
|
912 clear_glyph_matrix (XWINDOW (f->menu_bar_window)->desired_matrix);
|
|
913
|
25544
|
914 if (WINDOWP (f->tool_bar_window))
|
|
915 clear_glyph_matrix (XWINDOW (f->tool_bar_window)->desired_matrix);
|
25012
|
916
|
|
917 /* Do it for window matrices. */
|
|
918 xassert (WINDOWP (FRAME_ROOT_WINDOW (f)));
|
|
919 clear_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)), 1);
|
|
920 }
|
|
921
|
|
922
|
|
923 /* Clear matrices in window tree rooted in W. If DESIRED_P is
|
|
924 non-zero clear desired matrices, otherwise clear current matrices. */
|
|
925
|
|
926 static void
|
|
927 clear_window_matrices (w, desired_p)
|
|
928 struct window *w;
|
|
929 int desired_p;
|
|
930 {
|
|
931 while (w)
|
314
|
932 {
|
25012
|
933 if (!NILP (w->hchild))
|
|
934 {
|
|
935 xassert (WINDOWP (w->hchild));
|
|
936 clear_window_matrices (XWINDOW (w->hchild), desired_p);
|
|
937 }
|
|
938 else if (!NILP (w->vchild))
|
314
|
939 {
|
25012
|
940 xassert (WINDOWP (w->vchild));
|
|
941 clear_window_matrices (XWINDOW (w->vchild), desired_p);
|
|
942 }
|
|
943 else
|
|
944 {
|
|
945 if (desired_p)
|
|
946 clear_glyph_matrix (w->desired_matrix);
|
|
947 else
|
314
|
948 {
|
25012
|
949 clear_glyph_matrix (w->current_matrix);
|
|
950 w->window_end_valid = Qnil;
|
314
|
951 }
|
25012
|
952 }
|
|
953
|
|
954 w = NILP (w->next) ? 0 : XWINDOW (w->next);
|
|
955 }
|
|
956 }
|
|
957
|
|
958
|
|
959
|
|
960 /***********************************************************************
|
|
961 Glyph Rows
|
|
962
|
|
963 See dispextern.h for an overall explanation of glyph rows.
|
|
964 ***********************************************************************/
|
|
965
|
|
966 /* Clear glyph row ROW. Do it in a way that makes it robust against
|
|
967 changes in the glyph_row structure, i.e. addition or removal of
|
|
968 structure members. */
|
|
969
|
|
970 void
|
|
971 clear_glyph_row (row)
|
|
972 struct glyph_row *row;
|
|
973 {
|
|
974 struct glyph *p[1 + LAST_AREA];
|
|
975 static struct glyph_row null_row;
|
|
976
|
|
977 /* Save pointers. */
|
|
978 p[LEFT_MARGIN_AREA] = row->glyphs[LEFT_MARGIN_AREA];
|
|
979 p[TEXT_AREA] = row->glyphs[TEXT_AREA];
|
|
980 p[RIGHT_MARGIN_AREA] = row->glyphs[RIGHT_MARGIN_AREA];
|
|
981 p[LAST_AREA] = row->glyphs[LAST_AREA];
|
|
982
|
|
983 /* Clear. */
|
|
984 *row = null_row;
|
|
985
|
|
986 /* Restore pointers. */
|
|
987 row->glyphs[LEFT_MARGIN_AREA] = p[LEFT_MARGIN_AREA];
|
|
988 row->glyphs[TEXT_AREA] = p[TEXT_AREA];
|
|
989 row->glyphs[RIGHT_MARGIN_AREA] = p[RIGHT_MARGIN_AREA];
|
|
990 row->glyphs[LAST_AREA] = p[LAST_AREA];
|
|
991 }
|
|
992
|
|
993
|
|
994 /* Make ROW an empty, enabled row of canonical character height,
|
|
995 in window W starting at y-position Y. */
|
|
996
|
|
997 void
|
|
998 blank_row (w, row, y)
|
|
999 struct window *w;
|
|
1000 struct glyph_row *row;
|
|
1001 int y;
|
|
1002 {
|
|
1003 int min_y, max_y;
|
|
1004
|
25546
|
1005 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
|
25012
|
1006 max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w);
|
|
1007
|
|
1008 clear_glyph_row (row);
|
|
1009 row->y = y;
|
25186
|
1010 row->ascent = row->phys_ascent = 0;
|
|
1011 row->height = row->phys_height = CANON_Y_UNIT (XFRAME (w->frame));
|
25012
|
1012
|
|
1013 if (row->y < min_y)
|
|
1014 row->visible_height = row->height - (min_y - row->y);
|
|
1015 else if (row->y + row->height > max_y)
|
|
1016 row->visible_height = row->height - (row->y + row->height - max_y);
|
|
1017 else
|
|
1018 row->visible_height = row->height;
|
|
1019
|
|
1020 row->enabled_p = 1;
|
|
1021 }
|
|
1022
|
|
1023
|
|
1024 /* Increment buffer positions in glyph row ROW. DELTA and DELTA_BYTES
|
|
1025 are the amounts by which to change positions. Note that the first
|
|
1026 glyph of the text area of a row can have a buffer position even if
|
|
1027 the used count of the text area is zero. Such rows display line
|
|
1028 ends. */
|
|
1029
|
|
1030 void
|
28708
|
1031 increment_row_positions (row, delta, delta_bytes)
|
25012
|
1032 struct glyph_row *row;
|
|
1033 int delta, delta_bytes;
|
|
1034 {
|
|
1035 int area, i;
|
|
1036
|
|
1037 /* Increment start and end positions. */
|
|
1038 MATRIX_ROW_START_CHARPOS (row) += delta;
|
|
1039 MATRIX_ROW_START_BYTEPOS (row) += delta_bytes;
|
|
1040 MATRIX_ROW_END_CHARPOS (row) += delta;
|
|
1041 MATRIX_ROW_END_BYTEPOS (row) += delta_bytes;
|
|
1042
|
|
1043 /* Increment positions in glyphs. */
|
|
1044 for (area = 0; area < LAST_AREA; ++area)
|
|
1045 for (i = 0; i < row->used[area]; ++i)
|
|
1046 if (BUFFERP (row->glyphs[area][i].object)
|
|
1047 && row->glyphs[area][i].charpos > 0)
|
|
1048 row->glyphs[area][i].charpos += delta;
|
|
1049
|
|
1050 /* Capture the case of rows displaying a line end. */
|
|
1051 if (row->used[TEXT_AREA] == 0
|
|
1052 && MATRIX_ROW_DISPLAYS_TEXT_P (row))
|
|
1053 row->glyphs[TEXT_AREA]->charpos += delta;
|
|
1054 }
|
|
1055
|
|
1056
|
|
1057 /* Swap glyphs between two glyph rows A and B. This exchanges glyph
|
|
1058 contents, i.e. glyph structure contents are exchanged between A and
|
|
1059 B without changing glyph pointers in A and B. */
|
|
1060
|
|
1061 static void
|
|
1062 swap_glyphs_in_rows (a, b)
|
|
1063 struct glyph_row *a, *b;
|
|
1064 {
|
|
1065 int area;
|
|
1066
|
|
1067 for (area = 0; area < LAST_AREA; ++area)
|
|
1068 {
|
|
1069 /* Number of glyphs to swap. */
|
|
1070 int max_used = max (a->used[area], b->used[area]);
|
|
1071
|
|
1072 /* Start of glyphs in area of row A. */
|
|
1073 struct glyph *glyph_a = a->glyphs[area];
|
|
1074
|
|
1075 /* End + 1 of glyphs in area of row A. */
|
|
1076 struct glyph *glyph_a_end = a->glyphs[max_used];
|
|
1077
|
|
1078 /* Start of glyphs in area of row B. */
|
|
1079 struct glyph *glyph_b = b->glyphs[area];
|
|
1080
|
|
1081 while (glyph_a < glyph_a_end)
|
|
1082 {
|
|
1083 /* Non-ISO HP/UX compiler doesn't like auto struct
|
|
1084 initialization. */
|
|
1085 struct glyph temp;
|
|
1086 temp = *glyph_a;
|
|
1087 *glyph_a = *glyph_b;
|
|
1088 *glyph_b = temp;
|
|
1089 ++glyph_a;
|
|
1090 ++glyph_b;
|
314
|
1091 }
|
|
1092 }
|
|
1093 }
|
25012
|
1094
|
|
1095
|
|
1096 /* Exchange pointers to glyph memory between glyph rows A and B. */
|
|
1097
|
|
1098 static INLINE void
|
|
1099 swap_glyph_pointers (a, b)
|
|
1100 struct glyph_row *a, *b;
|
|
1101 {
|
|
1102 int i;
|
|
1103 for (i = 0; i < LAST_AREA + 1; ++i)
|
|
1104 {
|
|
1105 struct glyph *temp = a->glyphs[i];
|
|
1106 a->glyphs[i] = b->glyphs[i];
|
|
1107 b->glyphs[i] = temp;
|
|
1108 }
|
|
1109 }
|
|
1110
|
|
1111
|
|
1112 /* Copy glyph row structure FROM to glyph row structure TO, except
|
|
1113 that glyph pointers in the structures are left unchanged. */
|
|
1114
|
|
1115 INLINE void
|
|
1116 copy_row_except_pointers (to, from)
|
|
1117 struct glyph_row *to, *from;
|
|
1118 {
|
|
1119 struct glyph *pointers[1 + LAST_AREA];
|
|
1120
|
|
1121 /* Save glyph pointers of TO. */
|
|
1122 bcopy (to->glyphs, pointers, sizeof to->glyphs);
|
|
1123
|
|
1124 /* Do a structure assignment. */
|
|
1125 *to = *from;
|
|
1126
|
|
1127 /* Restore original pointers of TO. */
|
|
1128 bcopy (pointers, to->glyphs, sizeof to->glyphs);
|
|
1129 }
|
|
1130
|
|
1131
|
|
1132 /* Copy contents of glyph row FROM to glyph row TO. Glyph pointers in
|
|
1133 TO and FROM are left unchanged. Glyph contents are copied from the
|
|
1134 glyph memory of FROM to the glyph memory of TO. Increment buffer
|
|
1135 positions in row TO by DELTA/ DELTA_BYTES. */
|
|
1136
|
|
1137 void
|
|
1138 copy_glyph_row_contents (to, from, delta, delta_bytes)
|
|
1139 struct glyph_row *to, *from;
|
|
1140 int delta, delta_bytes;
|
|
1141 {
|
|
1142 int area;
|
|
1143
|
|
1144 /* This is like a structure assignment TO = FROM, except that
|
|
1145 glyph pointers in the rows are left unchanged. */
|
|
1146 copy_row_except_pointers (to, from);
|
|
1147
|
|
1148 /* Copy glyphs from FROM to TO. */
|
|
1149 for (area = 0; area < LAST_AREA; ++area)
|
|
1150 if (from->used[area])
|
|
1151 bcopy (from->glyphs[area], to->glyphs[area],
|
|
1152 from->used[area] * sizeof (struct glyph));
|
|
1153
|
|
1154 /* Increment buffer positions in TO by DELTA. */
|
28708
|
1155 increment_row_positions (to, delta, delta_bytes);
|
25012
|
1156 }
|
|
1157
|
|
1158
|
|
1159 /* Assign glyph row FROM to glyph row TO. This works like a structure
|
|
1160 assignment TO = FROM, except that glyph pointers are not copied but
|
|
1161 exchanged between TO and FROM. Pointers must be exchanged to avoid
|
|
1162 a memory leak. */
|
|
1163
|
|
1164 static INLINE void
|
|
1165 assign_row (to, from)
|
|
1166 struct glyph_row *to, *from;
|
|
1167 {
|
|
1168 swap_glyph_pointers (to, from);
|
|
1169 copy_row_except_pointers (to, from);
|
|
1170 }
|
|
1171
|
|
1172
|
|
1173 /* Test whether the glyph memory of the glyph row WINDOW_ROW, which is
|
|
1174 a row in a window matrix, is a slice of the glyph memory of the
|
|
1175 glyph row FRAME_ROW which is a row in a frame glyph matrix. Value
|
|
1176 is non-zero if the glyph memory of WINDOW_ROW is part of the glyph
|
|
1177 memory of FRAME_ROW. */
|
|
1178
|
|
1179 static int
|
|
1180 glyph_row_slice_p (window_row, frame_row)
|
|
1181 struct glyph_row *window_row, *frame_row;
|
|
1182 {
|
|
1183 struct glyph *window_glyph_start = window_row->glyphs[0];
|
|
1184 struct glyph *frame_glyph_start = frame_row->glyphs[0];
|
|
1185 struct glyph *frame_glyph_end = frame_row->glyphs[LAST_AREA];
|
|
1186
|
|
1187 return (frame_glyph_start <= window_glyph_start
|
|
1188 && window_glyph_start < frame_glyph_end);
|
|
1189 }
|
|
1190
|
|
1191
|
|
1192 /* Find the row in the window glyph matrix WINDOW_MATRIX being a slice
|
|
1193 of ROW in the frame matrix FRAME_MATRIX. Value is null if no row
|
|
1194 in WINDOW_MATRIX is found satisfying the condition. */
|
|
1195
|
|
1196 static struct glyph_row *
|
|
1197 find_glyph_row_slice (window_matrix, frame_matrix, row)
|
|
1198 struct glyph_matrix *window_matrix, *frame_matrix;
|
|
1199 int row;
|
|
1200 {
|
|
1201 int i;
|
|
1202
|
|
1203 xassert (row >= 0 && row < frame_matrix->nrows);
|
|
1204
|
|
1205 for (i = 0; i < window_matrix->nrows; ++i)
|
|
1206 if (glyph_row_slice_p (window_matrix->rows + i,
|
|
1207 frame_matrix->rows + row))
|
|
1208 break;
|
|
1209
|
|
1210 return i < window_matrix->nrows ? window_matrix->rows + i : 0;
|
|
1211 }
|
|
1212
|
|
1213
|
|
1214 /* Prepare ROW for display. Desired rows are cleared lazily,
|
|
1215 i.e. they are only marked as to be cleared by setting their
|
|
1216 enabled_p flag to zero. When a row is to be displayed, a prior
|
|
1217 call to this function really clears it. */
|
|
1218
|
|
1219 void
|
|
1220 prepare_desired_row (row)
|
|
1221 struct glyph_row *row;
|
|
1222 {
|
|
1223 if (!row->enabled_p)
|
|
1224 {
|
|
1225 clear_glyph_row (row);
|
|
1226 row->enabled_p = 1;
|
|
1227 }
|
|
1228 }
|
|
1229
|
|
1230
|
|
1231 /* Return a hash code for glyph row ROW. */
|
|
1232
|
|
1233 int
|
|
1234 line_hash_code (row)
|
|
1235 struct glyph_row *row;
|
|
1236 {
|
|
1237 int hash = 0;
|
|
1238
|
|
1239 if (row->enabled_p)
|
|
1240 {
|
|
1241 if (row->inverse_p)
|
|
1242 {
|
|
1243 /* Give all highlighted lines the same hash code
|
|
1244 so as to encourage scrolling to leave them in place. */
|
|
1245 hash = -1;
|
|
1246 }
|
|
1247 else
|
|
1248 {
|
|
1249 struct glyph *glyph = row->glyphs[TEXT_AREA];
|
|
1250 struct glyph *end = glyph + row->used[TEXT_AREA];
|
|
1251
|
|
1252 while (glyph < end)
|
|
1253 {
|
26998
|
1254 int c = glyph->u.ch;
|
|
1255 int face_id = glyph->face_id;
|
25012
|
1256 if (must_write_spaces)
|
26998
|
1257 c -= SPACEGLYPH;
|
|
1258 hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c;
|
|
1259 hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id;
|
25012
|
1260 ++glyph;
|
|
1261 }
|
|
1262
|
|
1263 if (hash == 0)
|
|
1264 hash = 1;
|
|
1265 }
|
|
1266 }
|
|
1267
|
|
1268 return hash;
|
|
1269 }
|
|
1270
|
|
1271
|
|
1272 /* Return the cost of drawing line VPOS In MATRIX. The cost equals
|
|
1273 the number of characters in the line. If must_write_spaces is
|
|
1274 zero, leading and trailing spaces are ignored. */
|
|
1275
|
|
1276 static unsigned int
|
|
1277 line_draw_cost (matrix, vpos)
|
|
1278 struct glyph_matrix *matrix;
|
|
1279 int vpos;
|
|
1280 {
|
|
1281 struct glyph_row *row = matrix->rows + vpos;
|
|
1282 struct glyph *beg = row->glyphs[TEXT_AREA];
|
|
1283 struct glyph *end = beg + row->used[TEXT_AREA];
|
|
1284 int len;
|
|
1285 Lisp_Object *glyph_table_base = GLYPH_TABLE_BASE;
|
|
1286 int glyph_table_len = GLYPH_TABLE_LENGTH;
|
|
1287
|
|
1288 /* Ignore trailing and leading spaces if we can. */
|
|
1289 if (!must_write_spaces)
|
|
1290 {
|
|
1291 /* Skip from the end over trailing spaces. */
|
|
1292 while (end != beg && CHAR_GLYPH_SPACE_P (*end))
|
|
1293 --end;
|
|
1294
|
|
1295 /* All blank line. */
|
|
1296 if (end == beg)
|
|
1297 return 0;
|
|
1298
|
|
1299 /* Skip over leading spaces. */
|
|
1300 while (CHAR_GLYPH_SPACE_P (*beg))
|
|
1301 ++beg;
|
|
1302 }
|
|
1303
|
|
1304 /* If we don't have a glyph-table, each glyph is one character,
|
|
1305 so return the number of glyphs. */
|
|
1306 if (glyph_table_base == 0)
|
|
1307 len = end - beg;
|
|
1308 else
|
|
1309 {
|
|
1310 /* Otherwise, scan the glyphs and accumulate their total length
|
|
1311 in LEN. */
|
|
1312 len = 0;
|
|
1313 while (beg < end)
|
|
1314 {
|
|
1315 GLYPH g = GLYPH_FROM_CHAR_GLYPH (*beg);
|
|
1316
|
26998
|
1317 if (g < 0
|
|
1318 || GLYPH_SIMPLE_P (glyph_table_base, glyph_table_len, g))
|
25012
|
1319 len += 1;
|
|
1320 else
|
|
1321 len += GLYPH_LENGTH (glyph_table_base, g);
|
|
1322
|
|
1323 ++beg;
|
|
1324 }
|
|
1325 }
|
|
1326
|
|
1327 return len;
|
|
1328 }
|
|
1329
|
|
1330
|
|
1331 /* Test two glyph rows A and B for equality. Value is non-zero if A
|
|
1332 and B have equal contents. W is the window to which the glyphs
|
|
1333 rows A and B belong. It is needed here to test for partial row
|
|
1334 visibility. */
|
|
1335
|
|
1336 static INLINE int
|
|
1337 row_equal_p (w, a, b)
|
|
1338 struct window *w;
|
|
1339 struct glyph_row *a, *b;
|
|
1340 {
|
|
1341 if (a == b)
|
|
1342 return 1;
|
|
1343 else if (a->hash != b->hash)
|
|
1344 return 0;
|
|
1345 else
|
|
1346 {
|
|
1347 struct glyph *a_glyph, *b_glyph, *a_end;
|
|
1348 int area;
|
|
1349
|
|
1350 /* Compare glyphs. */
|
|
1351 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
|
|
1352 {
|
|
1353 if (a->used[area] != b->used[area])
|
|
1354 return 0;
|
|
1355
|
|
1356 a_glyph = a->glyphs[area];
|
|
1357 a_end = a_glyph + a->used[area];
|
|
1358 b_glyph = b->glyphs[area];
|
|
1359
|
|
1360 while (a_glyph < a_end
|
|
1361 && GLYPH_EQUAL_P (a_glyph, b_glyph))
|
|
1362 ++a_glyph, ++b_glyph;
|
|
1363
|
|
1364 if (a_glyph != a_end)
|
|
1365 return 0;
|
|
1366 }
|
|
1367
|
|
1368 if (a->truncated_on_left_p != b->truncated_on_left_p
|
|
1369 || a->inverse_p != b->inverse_p
|
|
1370 || a->fill_line_p != b->fill_line_p
|
|
1371 || a->truncated_on_right_p != b->truncated_on_right_p
|
|
1372 || a->overlay_arrow_p != b->overlay_arrow_p
|
|
1373 || a->continued_p != b->continued_p
|
|
1374 || a->indicate_empty_line_p != b->indicate_empty_line_p
|
25186
|
1375 || a->overlapped_p != b->overlapped_p
|
25012
|
1376 || (MATRIX_ROW_CONTINUATION_LINE_P (a)
|
|
1377 != MATRIX_ROW_CONTINUATION_LINE_P (b))
|
|
1378 /* Different partially visible characters on left margin. */
|
|
1379 || a->x != b->x
|
|
1380 /* Different height. */
|
|
1381 || a->ascent != b->ascent
|
25186
|
1382 || a->phys_ascent != b->phys_ascent
|
|
1383 || a->phys_height != b->phys_height
|
25012
|
1384 || a->visible_height != b->visible_height)
|
|
1385 return 0;
|
|
1386 }
|
|
1387
|
|
1388 return 1;
|
|
1389 }
|
|
1390
|
|
1391
|
314
|
1392
|
25012
|
1393 /***********************************************************************
|
|
1394 Glyph Pool
|
|
1395
|
|
1396 See dispextern.h for an overall explanation of glyph pools.
|
|
1397 ***********************************************************************/
|
|
1398
|
|
1399 /* Allocate a glyph_pool structure. The structure returned is
|
|
1400 initialized with zeros. The global variable glyph_pool_count is
|
|
1401 incremented for each pool allocated. */
|
|
1402
|
|
1403 static struct glyph_pool *
|
|
1404 new_glyph_pool ()
|
|
1405 {
|
|
1406 struct glyph_pool *result;
|
|
1407
|
|
1408 /* Allocate a new glyph_pool and clear it. */
|
|
1409 result = (struct glyph_pool *) xmalloc (sizeof *result);
|
|
1410 bzero (result, sizeof *result);
|
|
1411
|
|
1412 /* For memory leak and double deletion checking. */
|
|
1413 ++glyph_pool_count;
|
|
1414
|
|
1415 return result;
|
|
1416 }
|
|
1417
|
|
1418
|
|
1419 /* Free a glyph_pool structure POOL. The function may be called with
|
|
1420 a null POOL pointer. The global variable glyph_pool_count is
|
|
1421 decremented with every pool structure freed. If this count gets
|
|
1422 negative, more structures were freed than allocated, i.e. one
|
|
1423 structure must have been freed more than once or a bogus pointer
|
|
1424 was passed to free_glyph_pool. */
|
|
1425
|
|
1426 static void
|
|
1427 free_glyph_pool (pool)
|
|
1428 struct glyph_pool *pool;
|
|
1429 {
|
|
1430 if (pool)
|
|
1431 {
|
|
1432 /* More freed than allocated? */
|
|
1433 --glyph_pool_count;
|
|
1434 xassert (glyph_pool_count >= 0);
|
|
1435
|
|
1436 xfree (pool->glyphs);
|
|
1437 xfree (pool);
|
|
1438 }
|
|
1439 }
|
|
1440
|
|
1441
|
|
1442 /* Enlarge a glyph pool POOL. MATRIX_DIM gives the number of rows and
|
|
1443 columns we need. This function never shrinks a pool. The only
|
|
1444 case in which this would make sense, would be when a frame's size
|
|
1445 is changed from a large value to a smaller one. But, if someone
|
|
1446 does it once, we can expect that he will do it again.
|
|
1447
|
|
1448 Value is non-zero if the pool changed in a way which makes
|
|
1449 re-adjusting window glyph matrices necessary. */
|
|
1450
|
|
1451 static int
|
|
1452 realloc_glyph_pool (pool, matrix_dim)
|
|
1453 struct glyph_pool *pool;
|
|
1454 struct dim matrix_dim;
|
|
1455 {
|
|
1456 int needed;
|
|
1457 int changed_p;
|
|
1458
|
|
1459 changed_p = (pool->glyphs == 0
|
|
1460 || matrix_dim.height != pool->nrows
|
|
1461 || matrix_dim.width != pool->ncolumns);
|
|
1462
|
|
1463 /* Enlarge the glyph pool. */
|
|
1464 needed = matrix_dim.width * matrix_dim.height;
|
|
1465 if (needed > pool->nglyphs)
|
|
1466 {
|
|
1467 int size = needed * sizeof (struct glyph);
|
|
1468
|
|
1469 if (pool->glyphs)
|
|
1470 pool->glyphs = (struct glyph *) xrealloc (pool->glyphs, size);
|
|
1471 else
|
|
1472 {
|
|
1473 pool->glyphs = (struct glyph *) xmalloc (size);
|
|
1474 bzero (pool->glyphs, size);
|
|
1475 }
|
|
1476
|
|
1477 pool->nglyphs = needed;
|
|
1478 }
|
|
1479
|
|
1480 /* Remember the number of rows and columns because (a) we use then
|
|
1481 to do sanity checks, and (b) the number of columns determines
|
|
1482 where rows in the frame matrix start---this must be available to
|
|
1483 determine pointers to rows of window sub-matrices. */
|
|
1484 pool->nrows = matrix_dim.height;
|
|
1485 pool->ncolumns = matrix_dim.width;
|
|
1486
|
|
1487 return changed_p;
|
|
1488 }
|
|
1489
|
|
1490
|
|
1491
|
|
1492 /***********************************************************************
|
|
1493 Debug Code
|
|
1494 ***********************************************************************/
|
|
1495
|
|
1496 #if GLYPH_DEBUG
|
|
1497
|
27855
|
1498
|
|
1499 /* Flush standard output. This is sometimes useful to call from
|
|
1500 the debugger. */
|
|
1501
|
|
1502 void
|
|
1503 flush_stdout ()
|
|
1504 {
|
|
1505 fflush (stdout);
|
|
1506 }
|
|
1507
|
|
1508
|
25012
|
1509 /* Check that no glyph pointers have been lost in MATRIX. If a
|
|
1510 pointer has been lost, e.g. by using a structure assignment between
|
|
1511 rows, at least one pointer must occur more than once in the rows of
|
|
1512 MATRIX. */
|
|
1513
|
|
1514 void
|
|
1515 check_matrix_pointer_lossage (matrix)
|
|
1516 struct glyph_matrix *matrix;
|
|
1517 {
|
|
1518 int i, j;
|
|
1519
|
|
1520 for (i = 0; i < matrix->nrows; ++i)
|
|
1521 for (j = 0; j < matrix->nrows; ++j)
|
|
1522 xassert (i == j
|
|
1523 || (matrix->rows[i].glyphs[TEXT_AREA]
|
|
1524 != matrix->rows[j].glyphs[TEXT_AREA]));
|
|
1525 }
|
|
1526
|
|
1527
|
|
1528 /* Get a pointer to glyph row ROW in MATRIX, with bounds checks. */
|
|
1529
|
|
1530 struct glyph_row *
|
|
1531 matrix_row (matrix, row)
|
|
1532 struct glyph_matrix *matrix;
|
|
1533 int row;
|
|
1534 {
|
|
1535 xassert (matrix && matrix->rows);
|
|
1536 xassert (row >= 0 && row < matrix->nrows);
|
|
1537
|
|
1538 /* That's really too slow for normal testing because this function
|
|
1539 is called almost everywhere. Although---it's still astonishingly
|
|
1540 fast, so it is valuable to have for debugging purposes. */
|
314
|
1541 #if 0
|
25012
|
1542 check_matrix_pointer_lossage (matrix);
|
|
1543 #endif
|
|
1544
|
|
1545 return matrix->rows + row;
|
|
1546 }
|
|
1547
|
|
1548
|
|
1549 #if 0 /* This function makes invalid assumptions when text is
|
|
1550 partially invisible. But it might come handy for debugging
|
|
1551 nevertheless. */
|
|
1552
|
|
1553 /* Check invariants that must hold for an up to date current matrix of
|
|
1554 window W. */
|
|
1555
|
|
1556 static void
|
|
1557 check_matrix_invariants (w)
|
314
|
1558 struct window *w;
|
|
1559 {
|
25012
|
1560 struct glyph_matrix *matrix = w->current_matrix;
|
|
1561 int yb = window_text_bottom_y (w);
|
|
1562 struct glyph_row *row = matrix->rows;
|
|
1563 struct glyph_row *last_text_row = NULL;
|
|
1564 struct buffer *saved = current_buffer;
|
|
1565 struct buffer *buffer = XBUFFER (w->buffer);
|
|
1566 int c;
|
|
1567
|
|
1568 /* This can sometimes happen for a fresh window. */
|
|
1569 if (matrix->nrows < 2)
|
|
1570 return;
|
|
1571
|
|
1572 set_buffer_temp (buffer);
|
|
1573
|
|
1574 /* Note: last row is always reserved for the mode line. */
|
|
1575 while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
|
|
1576 && MATRIX_ROW_BOTTOM_Y (row) < yb)
|
|
1577 {
|
|
1578 struct glyph_row *next = row + 1;
|
|
1579
|
|
1580 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
|
|
1581 last_text_row = row;
|
|
1582
|
|
1583 /* Check that character and byte positions are in sync. */
|
|
1584 xassert (MATRIX_ROW_START_BYTEPOS (row)
|
|
1585 == CHAR_TO_BYTE (MATRIX_ROW_START_CHARPOS (row)));
|
|
1586
|
|
1587 /* CHAR_TO_BYTE aborts when invoked for a position > Z. We can
|
|
1588 have such a position temporarily in case of a minibuffer
|
|
1589 displaying something like `[Sole completion]' at its end. */
|
|
1590 if (MATRIX_ROW_END_CHARPOS (row) < BUF_ZV (current_buffer))
|
|
1591 xassert (MATRIX_ROW_END_BYTEPOS (row)
|
|
1592 == CHAR_TO_BYTE (MATRIX_ROW_END_CHARPOS (row)));
|
|
1593
|
|
1594 /* Check that end position of `row' is equal to start position
|
|
1595 of next row. */
|
|
1596 if (next->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (next))
|
|
1597 {
|
|
1598 xassert (MATRIX_ROW_END_CHARPOS (row)
|
|
1599 == MATRIX_ROW_START_CHARPOS (next));
|
|
1600 xassert (MATRIX_ROW_END_BYTEPOS (row)
|
|
1601 == MATRIX_ROW_START_BYTEPOS (next));
|
|
1602 }
|
|
1603 row = next;
|
|
1604 }
|
|
1605
|
|
1606 xassert (w->current_matrix->nrows == w->desired_matrix->nrows);
|
|
1607 xassert (w->desired_matrix->rows != NULL);
|
|
1608 set_buffer_temp (saved);
|
|
1609 }
|
|
1610
|
|
1611 #endif /* 0 */
|
|
1612
|
|
1613 #endif /* GLYPH_DEBUG != 0 */
|
|
1614
|
|
1615
|
|
1616
|
|
1617 /**********************************************************************
|
|
1618 Allocating/ Adjusting Glyph Matrices
|
|
1619 **********************************************************************/
|
|
1620
|
|
1621 /* Allocate glyph matrices over a window tree for a frame-based
|
|
1622 redisplay
|
|
1623
|
|
1624 X and Y are column/row within the frame glyph matrix where
|
|
1625 sub-matrices for the window tree rooted at WINDOW must be
|
|
1626 allocated. CH_DIM contains the dimensions of the smallest
|
|
1627 character that could be used during display. DIM_ONLY_P non-zero
|
|
1628 means that the caller of this function is only interested in the
|
|
1629 result matrix dimension, and matrix adjustments should not be
|
|
1630 performed.
|
|
1631
|
|
1632 The function returns the total width/height of the sub-matrices of
|
|
1633 the window tree. If called on a frame root window, the computation
|
|
1634 will take the mini-buffer window into account.
|
|
1635
|
|
1636 *WINDOW_CHANGE_FLAGS is set to a bit mask with bits
|
|
1637
|
|
1638 NEW_LEAF_MATRIX set if any window in the tree did not have a
|
|
1639 glyph matrices yet, and
|
|
1640
|
|
1641 CHANGED_LEAF_MATRIX set if the dimension or location of a matrix of
|
|
1642 any window in the tree will be changed or have been changed (see
|
|
1643 DIM_ONLY_P).
|
|
1644
|
|
1645 *WINDOW_CHANGE_FLAGS must be initialized by the caller of this
|
|
1646 function.
|
|
1647
|
|
1648 Windows are arranged into chains of windows on the same level
|
|
1649 through the next fields of window structures. Such a level can be
|
|
1650 either a sequence of horizontally adjacent windows from left to
|
|
1651 right, or a sequence of vertically adjacent windows from top to
|
|
1652 bottom. Each window in a horizontal sequence can be either a leaf
|
|
1653 window or a vertical sequence; a window in a vertical sequence can
|
|
1654 be either a leaf or a horizontal sequence. All windows in a
|
|
1655 horizontal sequence have the same height, and all windows in a
|
|
1656 vertical sequence have the same width.
|
|
1657
|
|
1658 This function uses, for historical reasons, a more general
|
|
1659 algorithm to determine glyph matrix dimensions that would be
|
|
1660 necessary.
|
|
1661
|
|
1662 The matrix height of a horizontal sequence is determined by the
|
|
1663 maximum height of any matrix in the sequence. The matrix width of
|
|
1664 a horizontal sequence is computed by adding up matrix widths of
|
|
1665 windows in the sequence.
|
|
1666
|
|
1667 |<------- result width ------->|
|
|
1668 +---------+----------+---------+ ---
|
|
1669 | | | | |
|
|
1670 | | | |
|
|
1671 +---------+ | | result height
|
|
1672 | +---------+
|
|
1673 | | |
|
|
1674 +----------+ ---
|
|
1675
|
|
1676 The matrix width of a vertical sequence is the maximum matrix width
|
|
1677 of any window in the sequence. Its height is computed by adding up
|
|
1678 matrix heights of windows in the sequence.
|
|
1679
|
|
1680 |<---- result width -->|
|
|
1681 +---------+ ---
|
|
1682 | | |
|
|
1683 | | |
|
|
1684 +---------+--+ |
|
|
1685 | | |
|
|
1686 | | result height
|
|
1687 | |
|
|
1688 +------------+---------+ |
|
|
1689 | | |
|
|
1690 | | |
|
|
1691 +------------+---------+ --- */
|
|
1692
|
|
1693 /* Bit indicating that a new matrix will be allocated or has been
|
|
1694 allocated. */
|
|
1695
|
|
1696 #define NEW_LEAF_MATRIX (1 << 0)
|
|
1697
|
|
1698 /* Bit indicating that a matrix will or has changed its location or
|
|
1699 size. */
|
|
1700
|
|
1701 #define CHANGED_LEAF_MATRIX (1 << 1)
|
|
1702
|
|
1703 static struct dim
|
|
1704 allocate_matrices_for_frame_redisplay (window, x, y, ch_dim,
|
|
1705 dim_only_p, window_change_flags)
|
|
1706 Lisp_Object window;
|
|
1707 int x, y;
|
|
1708 struct dim ch_dim;
|
|
1709 int dim_only_p;
|
|
1710 int *window_change_flags;
|
|
1711 {
|
|
1712 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
|
|
1713 int x0 = x, y0 = y;
|
|
1714 int wmax = 0, hmax = 0;
|
|
1715 struct dim total;
|
|
1716 struct dim dim;
|
|
1717 struct window *w;
|
|
1718 int in_horz_combination_p;
|
|
1719
|
|
1720 /* What combination is WINDOW part of? Compute this once since the
|
|
1721 result is the same for all windows in the `next' chain. The
|
|
1722 special case of a root window (parent equal to nil) is treated
|
|
1723 like a vertical combination because a root window's `next'
|
|
1724 points to the mini-buffer window, if any, which is arranged
|
|
1725 vertically below other windows. */
|
|
1726 in_horz_combination_p
|
|
1727 = (!NILP (XWINDOW (window)->parent)
|
|
1728 && !NILP (XWINDOW (XWINDOW (window)->parent)->hchild));
|
|
1729
|
|
1730 /* For WINDOW and all windows on the same level. */
|
|
1731 do
|
|
1732 {
|
|
1733 w = XWINDOW (window);
|
|
1734
|
|
1735 /* Get the dimension of the window sub-matrix for W, depending
|
|
1736 on whether this a combination or a leaf window. */
|
|
1737 if (!NILP (w->hchild))
|
|
1738 dim = allocate_matrices_for_frame_redisplay (w->hchild, x, y, ch_dim,
|
|
1739 dim_only_p,
|
|
1740 window_change_flags);
|
|
1741 else if (!NILP (w->vchild))
|
|
1742 dim = allocate_matrices_for_frame_redisplay (w->vchild, x, y, ch_dim,
|
|
1743 dim_only_p,
|
|
1744 window_change_flags);
|
|
1745 else
|
|
1746 {
|
|
1747 /* If not already done, allocate sub-matrix structures. */
|
|
1748 if (w->desired_matrix == NULL)
|
|
1749 {
|
|
1750 w->desired_matrix = new_glyph_matrix (f->desired_pool);
|
|
1751 w->current_matrix = new_glyph_matrix (f->current_pool);
|
|
1752 *window_change_flags |= NEW_LEAF_MATRIX;
|
|
1753 }
|
|
1754
|
|
1755 /* Width and height MUST be chosen so that there are no
|
|
1756 holes in the frame matrix. */
|
28507
b6f06a755c7d
make_number/XINT/XUINT conversions; EQ/== fixes; ==Qnil -> NILP
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
1757 dim.width = XINT (w->width);
|
b6f06a755c7d
make_number/XINT/XUINT conversions; EQ/== fixes; ==Qnil -> NILP
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
1758 dim.height = XINT (w->height);
|
25012
|
1759
|
|
1760 /* Will matrix be re-allocated? */
|
|
1761 if (x != w->desired_matrix->matrix_x
|
|
1762 || y != w->desired_matrix->matrix_y
|
|
1763 || dim.width != w->desired_matrix->matrix_w
|
|
1764 || dim.height != w->desired_matrix->matrix_h
|
|
1765 || (margin_glyphs_to_reserve (w, dim.width,
|
|
1766 w->right_margin_width)
|
|
1767 != w->desired_matrix->left_margin_glyphs)
|
|
1768 || (margin_glyphs_to_reserve (w, dim.width,
|
|
1769 w->left_margin_width)
|
|
1770 != w->desired_matrix->right_margin_glyphs))
|
|
1771 *window_change_flags |= CHANGED_LEAF_MATRIX;
|
|
1772
|
|
1773 /* Actually change matrices, if allowed. Do not consider
|
|
1774 CHANGED_LEAF_MATRIX computed above here because the pool
|
|
1775 may have been changed which we don't now here. We trust
|
|
1776 that we only will be called with DIM_ONLY_P != 0 when
|
|
1777 necessary. */
|
|
1778 if (!dim_only_p)
|
|
1779 {
|
|
1780 adjust_glyph_matrix (w, w->desired_matrix, x, y, dim);
|
|
1781 adjust_glyph_matrix (w, w->current_matrix, x, y, dim);
|
|
1782 }
|
|
1783 }
|
|
1784
|
|
1785 /* If we are part of a horizontal combination, advance x for
|
|
1786 windows to the right of W; otherwise advance y for windows
|
|
1787 below W. */
|
|
1788 if (in_horz_combination_p)
|
|
1789 x += dim.width;
|
|
1790 else
|
|
1791 y += dim.height;
|
|
1792
|
|
1793 /* Remember maximum glyph matrix dimensions. */
|
|
1794 wmax = max (wmax, dim.width);
|
|
1795 hmax = max (hmax, dim.height);
|
|
1796
|
|
1797 /* Next window on same level. */
|
|
1798 window = w->next;
|
|
1799 }
|
|
1800 while (!NILP (window));
|
|
1801
|
|
1802 /* Set `total' to the total glyph matrix dimension of this window
|
|
1803 level. In a vertical combination, the width is the width of the
|
|
1804 widest window; the height is the y we finally reached, corrected
|
|
1805 by the y we started with. In a horizontal combination, the total
|
|
1806 height is the height of the tallest window, and the width is the
|
|
1807 x we finally reached, corrected by the x we started with. */
|
|
1808 if (in_horz_combination_p)
|
|
1809 {
|
|
1810 total.width = x - x0;
|
|
1811 total.height = hmax;
|
|
1812 }
|
|
1813 else
|
|
1814 {
|
|
1815 total.width = wmax;
|
|
1816 total.height = y - y0;
|
|
1817 }
|
|
1818
|
|
1819 return total;
|
|
1820 }
|
|
1821
|
|
1822
|
|
1823 /* Allocate window matrices for window-based redisplay. W is the
|
|
1824 window whose matrices must be allocated/reallocated. CH_DIM is the
|
|
1825 size of the smallest character that could potentially be used on W. */
|
|
1826
|
|
1827 static void
|
|
1828 allocate_matrices_for_window_redisplay (w, ch_dim)
|
|
1829 struct window *w;
|
|
1830 struct dim ch_dim;
|
|
1831 {
|
|
1832 struct frame *f = XFRAME (w->frame);
|
|
1833
|
|
1834 while (w)
|
314
|
1835 {
|
25012
|
1836 if (!NILP (w->vchild))
|
|
1837 allocate_matrices_for_window_redisplay (XWINDOW (w->vchild), ch_dim);
|
|
1838 else if (!NILP (w->hchild))
|
|
1839 allocate_matrices_for_window_redisplay (XWINDOW (w->hchild), ch_dim);
|
|
1840 else
|
314
|
1841 {
|
25012
|
1842 /* W is a leaf window. */
|
|
1843 int window_pixel_width = XFLOATINT (w->width) * CANON_X_UNIT (f);
|
|
1844 int window_pixel_height = window_box_height (w) + abs (w->vscroll);
|
|
1845 struct dim dim;
|
|
1846
|
|
1847 /* If matrices are not yet allocated, allocate them now. */
|
|
1848 if (w->desired_matrix == NULL)
|
314
|
1849 {
|
25012
|
1850 w->desired_matrix = new_glyph_matrix (NULL);
|
|
1851 w->current_matrix = new_glyph_matrix (NULL);
|
314
|
1852 }
|
25012
|
1853
|
|
1854 /* Compute number of glyphs needed in a glyph row. */
|
|
1855 dim.width = (((window_pixel_width + ch_dim.width - 1)
|
|
1856 / ch_dim.width)
|
|
1857 /* 2 partially visible columns in the text area. */
|
|
1858 + 2
|
|
1859 /* One partially visible column at the right
|
|
1860 edge of each marginal area. */
|
|
1861 + 1 + 1);
|
|
1862
|
|
1863 /* Compute number of glyph rows needed. */
|
|
1864 dim.height = (((window_pixel_height + ch_dim.height - 1)
|
|
1865 / ch_dim.height)
|
|
1866 /* One partially visible line at the top and
|
|
1867 bottom of the window. */
|
|
1868 + 2
|
|
1869 /* 2 for top and mode line. */
|
|
1870 + 2);
|
|
1871
|
|
1872 /* Change matrices. */
|
|
1873 adjust_glyph_matrix (w, w->desired_matrix, 0, 0, dim);
|
|
1874 adjust_glyph_matrix (w, w->current_matrix, 0, 0, dim);
|
|
1875 }
|
|
1876
|
|
1877 w = NILP (w->next) ? NULL : XWINDOW (w->next);
|
|
1878 }
|
|
1879 }
|
|
1880
|
|
1881
|
|
1882 /* Re-allocate/ re-compute glyph matrices on frame F. If F is null,
|
|
1883 do it for all frames; otherwise do it just for the given frame.
|
|
1884 This function must be called when a new frame is created, its size
|
|
1885 changes, or its window configuration changes. */
|
|
1886
|
|
1887 void
|
|
1888 adjust_glyphs (f)
|
|
1889 struct frame *f;
|
|
1890 {
|
25186
|
1891 /* Block input so that expose events and other events that access
|
|
1892 glyph matrices are not processed while we are changing them. */
|
|
1893 BLOCK_INPUT;
|
|
1894
|
25012
|
1895 if (f)
|
|
1896 adjust_frame_glyphs (f);
|
|
1897 else
|
|
1898 {
|
|
1899 Lisp_Object tail, lisp_frame;
|
|
1900
|
|
1901 FOR_EACH_FRAME (tail, lisp_frame)
|
|
1902 adjust_frame_glyphs (XFRAME (lisp_frame));
|
|
1903 }
|
25186
|
1904
|
|
1905 UNBLOCK_INPUT;
|
25012
|
1906 }
|
|
1907
|
|
1908
|
|
1909 /* Adjust frame glyphs when Emacs is initialized.
|
|
1910
|
|
1911 To be called from init_display.
|
|
1912
|
|
1913 We need a glyph matrix because redraw will happen soon.
|
|
1914 Unfortunately, window sizes on selected_frame are not yet set to
|
|
1915 meaningful values. I believe we can assume that there are only two
|
|
1916 windows on the frame---the mini-buffer and the root window. Frame
|
|
1917 height and width seem to be correct so far. So, set the sizes of
|
|
1918 windows to estimated values. */
|
|
1919
|
|
1920 static void
|
|
1921 adjust_frame_glyphs_initially ()
|
|
1922 {
|
25666
|
1923 struct frame *sf = SELECTED_FRAME ();
|
|
1924 struct window *root = XWINDOW (sf->root_window);
|
25012
|
1925 struct window *mini = XWINDOW (root->next);
|
25666
|
1926 int frame_height = FRAME_HEIGHT (sf);
|
|
1927 int frame_width = FRAME_WIDTH (sf);
|
|
1928 int top_margin = FRAME_TOP_MARGIN (sf);
|
25012
|
1929
|
|
1930 /* Do it for the root window. */
|
|
1931 XSETFASTINT (root->top, top_margin);
|
|
1932 XSETFASTINT (root->width, frame_width);
|
25666
|
1933 set_window_height (sf->root_window, frame_height - 1 - top_margin, 0);
|
25012
|
1934
|
|
1935 /* Do it for the mini-buffer window. */
|
|
1936 XSETFASTINT (mini->top, frame_height - 1);
|
|
1937 XSETFASTINT (mini->width, frame_width);
|
|
1938 set_window_height (root->next, 1, 0);
|
|
1939
|
25666
|
1940 adjust_frame_glyphs (sf);
|
25012
|
1941 glyphs_initialized_initially_p = 1;
|
|
1942 }
|
|
1943
|
|
1944
|
|
1945 /* Allocate/reallocate glyph matrices of a single frame F. */
|
|
1946
|
|
1947 static void
|
|
1948 adjust_frame_glyphs (f)
|
|
1949 struct frame *f;
|
|
1950 {
|
|
1951 if (FRAME_WINDOW_P (f))
|
|
1952 adjust_frame_glyphs_for_window_redisplay (f);
|
|
1953 else
|
|
1954 adjust_frame_glyphs_for_frame_redisplay (f);
|
|
1955
|
|
1956 /* Don't forget the message buffer and the buffer for
|
|
1957 decode_mode_spec. */
|
|
1958 adjust_frame_message_buffer (f);
|
|
1959 adjust_decode_mode_spec_buffer (f);
|
|
1960
|
|
1961 f->glyphs_initialized_p = 1;
|
|
1962 }
|
|
1963
|
|
1964
|
|
1965 /* Allocate/reallocate glyph matrices of a single frame F for
|
|
1966 frame-based redisplay. */
|
|
1967
|
|
1968 static void
|
|
1969 adjust_frame_glyphs_for_frame_redisplay (f)
|
|
1970 struct frame *f;
|
|
1971 {
|
|
1972 struct dim ch_dim;
|
|
1973 struct dim matrix_dim;
|
|
1974 int pool_changed_p;
|
|
1975 int window_change_flags;
|
|
1976 int top_window_y;
|
|
1977
|
|
1978 if (!FRAME_LIVE_P (f))
|
|
1979 return;
|
|
1980
|
|
1981 /* Determine the smallest character in any font for F. On
|
|
1982 console windows, all characters have dimension (1, 1). */
|
|
1983 ch_dim.width = ch_dim.height = 1;
|
|
1984
|
|
1985 top_window_y = FRAME_TOP_MARGIN (f);
|
|
1986
|
|
1987 /* Allocate glyph pool structures if not already done. */
|
|
1988 if (f->desired_pool == NULL)
|
|
1989 {
|
|
1990 f->desired_pool = new_glyph_pool ();
|
|
1991 f->current_pool = new_glyph_pool ();
|
|
1992 }
|
|
1993
|
|
1994 /* Allocate frames matrix structures if needed. */
|
|
1995 if (f->desired_matrix == NULL)
|
|
1996 {
|
|
1997 f->desired_matrix = new_glyph_matrix (f->desired_pool);
|
|
1998 f->current_matrix = new_glyph_matrix (f->current_pool);
|
|
1999 }
|
|
2000
|
|
2001 /* Compute window glyph matrices. (This takes the mini-buffer
|
|
2002 window into account). The result is the size of the frame glyph
|
|
2003 matrix needed. The variable window_change_flags is set to a bit
|
|
2004 mask indicating whether new matrices will be allocated or
|
|
2005 existing matrices change their size or location within the frame
|
|
2006 matrix. */
|
|
2007 window_change_flags = 0;
|
|
2008 matrix_dim
|
|
2009 = allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f),
|
|
2010 0, top_window_y,
|
|
2011 ch_dim, 1,
|
|
2012 &window_change_flags);
|
|
2013
|
|
2014 /* Add in menu bar lines, if any. */
|
|
2015 matrix_dim.height += top_window_y;
|
|
2016
|
|
2017 /* Enlarge pools as necessary. */
|
|
2018 pool_changed_p = realloc_glyph_pool (f->desired_pool, matrix_dim);
|
|
2019 realloc_glyph_pool (f->current_pool, matrix_dim);
|
|
2020
|
|
2021 /* Set up glyph pointers within window matrices. Do this only if
|
|
2022 absolutely necessary since it requires a frame redraw. */
|
|
2023 if (pool_changed_p || window_change_flags)
|
|
2024 {
|
|
2025 /* Do it for window matrices. */
|
|
2026 allocate_matrices_for_frame_redisplay (FRAME_ROOT_WINDOW (f),
|
|
2027 0, top_window_y, ch_dim, 0,
|
|
2028 &window_change_flags);
|
|
2029
|
|
2030 /* Size of frame matrices must equal size of frame. Note
|
|
2031 that we are called for X frames with window widths NOT equal
|
|
2032 to the frame width (from CHANGE_FRAME_SIZE_1). */
|
|
2033 xassert (matrix_dim.width == FRAME_WIDTH (f)
|
|
2034 && matrix_dim.height == FRAME_HEIGHT (f));
|
|
2035
|
|
2036 /* Resize frame matrices. */
|
|
2037 adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim);
|
|
2038 adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim);
|
|
2039
|
|
2040 /* Since location and size of sub-matrices within the pool may
|
|
2041 have changed, and current matrices don't have meaningful
|
|
2042 contents anymore, mark the frame garbaged. */
|
|
2043 SET_FRAME_GARBAGED (f);
|
|
2044 }
|
|
2045 }
|
|
2046
|
|
2047
|
|
2048 /* Allocate/reallocate glyph matrices of a single frame F for
|
|
2049 window-based redisplay. */
|
|
2050
|
|
2051 static void
|
|
2052 adjust_frame_glyphs_for_window_redisplay (f)
|
|
2053 struct frame *f;
|
|
2054 {
|
|
2055 struct dim ch_dim;
|
|
2056 struct window *w;
|
|
2057
|
|
2058 xassert (FRAME_WINDOW_P (f) && FRAME_LIVE_P (f));
|
|
2059
|
|
2060 /* Get minimum sizes. */
|
|
2061 #ifdef HAVE_WINDOW_SYSTEM
|
|
2062 ch_dim.width = FRAME_SMALLEST_CHAR_WIDTH (f);
|
|
2063 ch_dim.height = FRAME_SMALLEST_FONT_HEIGHT (f);
|
|
2064 #else
|
|
2065 ch_dim.width = ch_dim.height = 1;
|
|
2066 #endif
|
|
2067
|
|
2068 /* Allocate/reallocate window matrices. */
|
|
2069 allocate_matrices_for_window_redisplay (XWINDOW (FRAME_ROOT_WINDOW (f)),
|
|
2070 ch_dim);
|
|
2071
|
|
2072 /* Allocate/ reallocate matrices of the dummy window used to display
|
|
2073 the menu bar under X when no X toolkit support is available. */
|
|
2074 #ifndef USE_X_TOOLKIT
|
|
2075 {
|
|
2076 /* Allocate a dummy window if not already done. */
|
|
2077 if (NILP (f->menu_bar_window))
|
|
2078 {
|
|
2079 f->menu_bar_window = make_window ();
|
|
2080 w = XWINDOW (f->menu_bar_window);
|
|
2081 XSETFRAME (w->frame, f);
|
|
2082 w->pseudo_window_p = 1;
|
|
2083 }
|
|
2084 else
|
|
2085 w = XWINDOW (f->menu_bar_window);
|
|
2086
|
|
2087 /* Set window dimensions to frame dimensions and allocate or
|
|
2088 adjust glyph matrices of W. */
|
|
2089 XSETFASTINT (w->top, 0);
|
|
2090 XSETFASTINT (w->left, 0);
|
|
2091 XSETFASTINT (w->height, FRAME_MENU_BAR_LINES (f));
|
|
2092 XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f));
|
|
2093 allocate_matrices_for_window_redisplay (w, ch_dim);
|
|
2094 }
|
|
2095 #endif /* not USE_X_TOOLKIT */
|
|
2096
|
25544
|
2097 /* Allocate/ reallocate matrices of the tool bar window. If we
|
|
2098 don't have a tool bar window yet, make one. */
|
|
2099 if (NILP (f->tool_bar_window))
|
25012
|
2100 {
|
25544
|
2101 f->tool_bar_window = make_window ();
|
|
2102 w = XWINDOW (f->tool_bar_window);
|
25012
|
2103 XSETFRAME (w->frame, f);
|
|
2104 w->pseudo_window_p = 1;
|
|
2105 }
|
|
2106 else
|
25544
|
2107 w = XWINDOW (f->tool_bar_window);
|
25012
|
2108
|
|
2109 XSETFASTINT (w->top, FRAME_MENU_BAR_LINES (f));
|
|
2110 XSETFASTINT (w->left, 0);
|
25544
|
2111 XSETFASTINT (w->height, FRAME_TOOL_BAR_LINES (f));
|
25012
|
2112 XSETFASTINT (w->width, FRAME_WINDOW_WIDTH (f));
|
|
2113 allocate_matrices_for_window_redisplay (w, ch_dim);
|
|
2114 }
|
|
2115
|
|
2116
|
|
2117 /* Adjust/ allocate message buffer of frame F.
|
|
2118
|
|
2119 Note that the message buffer is never freed. Since I could not
|
|
2120 find a free in 19.34, I assume that freeing it would be
|
|
2121 problematic in some way and don't do it either.
|
|
2122
|
|
2123 (Implementation note: It should be checked if we can free it
|
|
2124 eventually without causing trouble). */
|
|
2125
|
|
2126 static void
|
|
2127 adjust_frame_message_buffer (f)
|
|
2128 struct frame *f;
|
|
2129 {
|
|
2130 int size = FRAME_MESSAGE_BUF_SIZE (f) + 1;
|
|
2131
|
|
2132 if (FRAME_MESSAGE_BUF (f))
|
|
2133 {
|
|
2134 char *buffer = FRAME_MESSAGE_BUF (f);
|
|
2135 char *new_buffer = (char *) xrealloc (buffer, size);
|
|
2136 FRAME_MESSAGE_BUF (f) = new_buffer;
|
|
2137 }
|
|
2138 else
|
|
2139 FRAME_MESSAGE_BUF (f) = (char *) xmalloc (size);
|
|
2140 }
|
|
2141
|
|
2142
|
|
2143 /* Re-allocate buffer for decode_mode_spec on frame F. */
|
|
2144
|
|
2145 static void
|
|
2146 adjust_decode_mode_spec_buffer (f)
|
|
2147 struct frame *f;
|
|
2148 {
|
|
2149 f->decode_mode_spec_buffer
|
|
2150 = (char *) xrealloc (f->decode_mode_spec_buffer,
|
|
2151 FRAME_MESSAGE_BUF_SIZE (f) + 1);
|
|
2152 }
|
|
2153
|
|
2154
|
|
2155
|
|
2156 /**********************************************************************
|
|
2157 Freeing Glyph Matrices
|
|
2158 **********************************************************************/
|
|
2159
|
|
2160 /* Free glyph memory for a frame F. F may be null. This function can
|
|
2161 be called for the same frame more than once. The root window of
|
|
2162 F may be nil when this function is called. This is the case when
|
|
2163 the function is called when F is destroyed. */
|
|
2164
|
|
2165 void
|
|
2166 free_glyphs (f)
|
|
2167 struct frame *f;
|
|
2168 {
|
|
2169 if (f && f->glyphs_initialized_p)
|
|
2170 {
|
27968
|
2171 /* Block interrupt input so that we don't get surprised by an X
|
|
2172 event while we're in an inconsistent state. */
|
|
2173 BLOCK_INPUT;
|
25012
|
2174 f->glyphs_initialized_p = 0;
|
|
2175
|
|
2176 /* Release window sub-matrices. */
|
|
2177 if (!NILP (f->root_window))
|
|
2178 free_window_matrices (XWINDOW (f->root_window));
|
|
2179
|
|
2180 /* Free the dummy window for menu bars without X toolkit and its
|
|
2181 glyph matrices. */
|
|
2182 if (!NILP (f->menu_bar_window))
|
|
2183 {
|
|
2184 struct window *w = XWINDOW (f->menu_bar_window);
|
|
2185 free_glyph_matrix (w->desired_matrix);
|
|
2186 free_glyph_matrix (w->current_matrix);
|
|
2187 w->desired_matrix = w->current_matrix = NULL;
|
|
2188 f->menu_bar_window = Qnil;
|
|
2189 }
|
|
2190
|
25544
|
2191 /* Free the tool bar window and its glyph matrices. */
|
|
2192 if (!NILP (f->tool_bar_window))
|
25012
|
2193 {
|
25544
|
2194 struct window *w = XWINDOW (f->tool_bar_window);
|
25012
|
2195 free_glyph_matrix (w->desired_matrix);
|
|
2196 free_glyph_matrix (w->current_matrix);
|
|
2197 w->desired_matrix = w->current_matrix = NULL;
|
25544
|
2198 f->tool_bar_window = Qnil;
|
25012
|
2199 }
|
|
2200
|
|
2201 /* Release frame glyph matrices. Reset fields to zero in
|
|
2202 case we are called a second time. */
|
|
2203 if (f->desired_matrix)
|
|
2204 {
|
|
2205 free_glyph_matrix (f->desired_matrix);
|
|
2206 free_glyph_matrix (f->current_matrix);
|
|
2207 f->desired_matrix = f->current_matrix = NULL;
|
|
2208 }
|
|
2209
|
|
2210 /* Release glyph pools. */
|
|
2211 if (f->desired_pool)
|
|
2212 {
|
|
2213 free_glyph_pool (f->desired_pool);
|
|
2214 free_glyph_pool (f->current_pool);
|
|
2215 f->desired_pool = f->current_pool = NULL;
|
314
|
2216 }
|
27968
|
2217
|
|
2218 UNBLOCK_INPUT;
|
314
|
2219 }
|
|
2220 }
|
|
2221
|
25012
|
2222
|
|
2223 /* Free glyph sub-matrices in the window tree rooted at W. This
|
|
2224 function may be called with a null pointer, and it may be called on
|
|
2225 the same tree more than once. */
|
|
2226
|
|
2227 void
|
|
2228 free_window_matrices (w)
|
|
2229 struct window *w;
|
|
2230 {
|
|
2231 while (w)
|
|
2232 {
|
|
2233 if (!NILP (w->hchild))
|
|
2234 free_window_matrices (XWINDOW (w->hchild));
|
|
2235 else if (!NILP (w->vchild))
|
|
2236 free_window_matrices (XWINDOW (w->vchild));
|
|
2237 else
|
|
2238 {
|
|
2239 /* This is a leaf window. Free its memory and reset fields
|
|
2240 to zero in case this function is called a second time for
|
|
2241 W. */
|
|
2242 free_glyph_matrix (w->current_matrix);
|
|
2243 free_glyph_matrix (w->desired_matrix);
|
|
2244 w->current_matrix = w->desired_matrix = NULL;
|
|
2245 }
|
|
2246
|
|
2247 /* Next window on same level. */
|
|
2248 w = NILP (w->next) ? 0 : XWINDOW (w->next);
|
|
2249 }
|
|
2250 }
|
|
2251
|
|
2252
|
|
2253 /* Check glyph memory leaks. This function is called from
|
|
2254 shut_down_emacs. Note that frames are not destroyed when Emacs
|
|
2255 exits. We therefore free all glyph memory for all active frames
|
|
2256 explicitly and check that nothing is left allocated. */
|
6620
|
2257
|
|
2258 void
|
25012
|
2259 check_glyph_memory ()
|
6620
|
2260 {
|
25012
|
2261 Lisp_Object tail, frame;
|
|
2262
|
|
2263 /* Free glyph memory for all frames. */
|
|
2264 FOR_EACH_FRAME (tail, frame)
|
|
2265 free_glyphs (XFRAME (frame));
|
|
2266
|
|
2267 /* Check that nothing is left allocated. */
|
|
2268 if (glyph_matrix_count)
|
|
2269 abort ();
|
|
2270 if (glyph_pool_count)
|
|
2271 abort ();
|
|
2272 }
|
|
2273
|
|
2274
|
|
2275
|
|
2276 /**********************************************************************
|
|
2277 Building a Frame Matrix
|
|
2278 **********************************************************************/
|
|
2279
|
|
2280 /* Most of the redisplay code works on glyph matrices attached to
|
|
2281 windows. This is a good solution most of the time, but it is not
|
|
2282 suitable for terminal code. Terminal output functions cannot rely
|
|
2283 on being able to set an arbitrary terminal window. Instead they
|
|
2284 must be provided with a view of the whole frame, i.e. the whole
|
|
2285 screen. We build such a view by constructing a frame matrix from
|
|
2286 window matrices in this section.
|
|
2287
|
|
2288 Windows that must be updated have their must_be_update_p flag set.
|
|
2289 For all such windows, their desired matrix is made part of the
|
|
2290 desired frame matrix. For other windows, their current matrix is
|
|
2291 made part of the desired frame matrix.
|
|
2292
|
|
2293 +-----------------+----------------+
|
|
2294 | desired | desired |
|
|
2295 | | |
|
|
2296 +-----------------+----------------+
|
|
2297 | current |
|
|
2298 | |
|
|
2299 +----------------------------------+
|
|
2300
|
|
2301 Desired window matrices can be made part of the frame matrix in a
|
|
2302 cheap way: We exploit the fact that the desired frame matrix and
|
|
2303 desired window matrices share their glyph memory. This is not
|
|
2304 possible for current window matrices. Their glyphs are copied to
|
|
2305 the desired frame matrix. The latter is equivalent to
|
|
2306 preserve_other_columns in the old redisplay.
|
|
2307
|
|
2308 Used glyphs counters for frame matrix rows are the result of adding
|
|
2309 up glyph lengths of the window matrices. A line in the frame
|
|
2310 matrix is enabled, if a corresponding line in a window matrix is
|
|
2311 enabled.
|
|
2312
|
|
2313 After building the desired frame matrix, it will be passed to
|
|
2314 terminal code, which will manipulate both the desired and current
|
|
2315 frame matrix. Changes applied to the frame's current matrix have
|
|
2316 to be visible in current window matrices afterwards, of course.
|
|
2317
|
|
2318 This problem is solved like this:
|
|
2319
|
|
2320 1. Window and frame matrices share glyphs. Window matrices are
|
|
2321 constructed in a way that their glyph contents ARE the glyph
|
|
2322 contents needed in a frame matrix. Thus, any modification of
|
|
2323 glyphs done in terminal code will be reflected in window matrices
|
|
2324 automatically.
|
|
2325
|
|
2326 2. Exchanges of rows in a frame matrix done by terminal code are
|
|
2327 intercepted by hook functions so that corresponding row operations
|
|
2328 on window matrices can be performed. This is necessary because we
|
|
2329 use pointers to glyphs in glyph row structures. To satisfy the
|
|
2330 assumption of point 1 above that glyphs are updated implicitly in
|
|
2331 window matrices when they are manipulated via the frame matrix,
|
|
2332 window and frame matrix must of course agree where to find the
|
|
2333 glyphs for their rows. Possible manipulations that must be
|
|
2334 mirrored are assignments of rows of the desired frame matrix to the
|
|
2335 current frame matrix and scrolling the current frame matrix. */
|
|
2336
|
|
2337 /* Build frame F's desired matrix from window matrices. Only windows
|
|
2338 which have the flag must_be_updated_p set have to be updated. Menu
|
|
2339 bar lines of a frame are not covered by window matrices, so make
|
|
2340 sure not to touch them in this function. */
|
|
2341
|
|
2342 static void
|
|
2343 build_frame_matrix (f)
|
|
2344 struct frame *f;
|
|
2345 {
|
6620
|
2346 int i;
|
|
2347
|
25012
|
2348 /* F must have a frame matrix when this function is called. */
|
|
2349 xassert (!FRAME_WINDOW_P (f));
|
|
2350
|
|
2351 /* Clear all rows in the frame matrix covered by window matrices.
|
|
2352 Menu bar lines are not covered by windows. */
|
|
2353 for (i = FRAME_TOP_MARGIN (f); i < f->desired_matrix->nrows; ++i)
|
|
2354 clear_glyph_row (MATRIX_ROW (f->desired_matrix, i));
|
|
2355
|
|
2356 /* Build the matrix by walking the window tree. */
|
|
2357 build_frame_matrix_from_window_tree (f->desired_matrix,
|
|
2358 XWINDOW (FRAME_ROOT_WINDOW (f)));
|
|
2359 }
|
|
2360
|
|
2361
|
|
2362 /* Walk a window tree, building a frame matrix MATRIX from window
|
|
2363 matrices. W is the root of a window tree. */
|
|
2364
|
|
2365 static void
|
|
2366 build_frame_matrix_from_window_tree (matrix, w)
|
|
2367 struct glyph_matrix *matrix;
|
|
2368 struct window *w;
|
|
2369 {
|
|
2370 while (w)
|
6620
|
2371 {
|
25012
|
2372 if (!NILP (w->hchild))
|
|
2373 build_frame_matrix_from_window_tree (matrix, XWINDOW (w->hchild));
|
|
2374 else if (!NILP (w->vchild))
|
|
2375 build_frame_matrix_from_window_tree (matrix, XWINDOW (w->vchild));
|
|
2376 else
|
|
2377 build_frame_matrix_from_leaf_window (matrix, w);
|
|
2378
|
|
2379 w = NILP (w->next) ? 0 : XWINDOW (w->next);
|
6620
|
2380 }
|
|
2381 }
|
6642
|
2382
|
25012
|
2383
|
|
2384 /* Add a window's matrix to a frame matrix. FRAME_MATRIX is the
|
|
2385 desired frame matrix built. W is a leaf window whose desired or
|
|
2386 current matrix is to be added to FRAME_MATRIX. W's flag
|
|
2387 must_be_updated_p determines which matrix it contributes to
|
|
2388 FRAME_MATRIX. If must_be_updated_p is non-zero, W's desired matrix
|
|
2389 is added to FRAME_MATRIX, otherwise W's current matrix is added.
|
|
2390 Adding a desired matrix means setting up used counters and such in
|
|
2391 frame rows, while adding a current window matrix to FRAME_MATRIX
|
|
2392 means copying glyphs. The latter case corresponds to
|
|
2393 preserve_other_columns in the old redisplay. */
|
|
2394
|
|
2395 static void
|
|
2396 build_frame_matrix_from_leaf_window (frame_matrix, w)
|
|
2397 struct glyph_matrix *frame_matrix;
|
6642
|
2398 struct window *w;
|
|
2399 {
|
25012
|
2400 struct glyph_matrix *window_matrix;
|
|
2401 int window_y, frame_y;
|
|
2402 /* If non-zero, a glyph to insert at the right border of W. */
|
|
2403 GLYPH right_border_glyph = 0;
|
|
2404
|
|
2405 /* Set window_matrix to the matrix we have to add to FRAME_MATRIX. */
|
|
2406 if (w->must_be_updated_p)
|
|
2407 {
|
|
2408 window_matrix = w->desired_matrix;
|
|
2409
|
|
2410 /* Decide whether we want to add a vertical border glyph. */
|
|
2411 if (!WINDOW_RIGHTMOST_P (w))
|
|
2412 {
|
|
2413 struct Lisp_Char_Table *dp = window_display_table (w);
|
|
2414 right_border_glyph = (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
|
|
2415 ? XINT (DISP_BORDER_GLYPH (dp))
|
|
2416 : '|');
|
|
2417 }
|
|
2418 }
|
|
2419 else
|
|
2420 window_matrix = w->current_matrix;
|
|
2421
|
|
2422 /* For all rows in the window matrix and corresponding rows in the
|
|
2423 frame matrix. */
|
|
2424 window_y = 0;
|
|
2425 frame_y = window_matrix->matrix_y;
|
|
2426 while (window_y < window_matrix->nrows)
|
6642
|
2427 {
|
25012
|
2428 struct glyph_row *frame_row = frame_matrix->rows + frame_y;
|
|
2429 struct glyph_row *window_row = window_matrix->rows + window_y;
|
|
2430
|
|
2431 /* Fill up the frame row with spaces up to the left margin of the
|
|
2432 window row. */
|
|
2433 fill_up_frame_row_with_spaces (frame_row, window_matrix->matrix_x);
|
|
2434
|
|
2435 /* Fill up areas in the window matrix row with spaces. */
|
|
2436 fill_up_glyph_row_with_spaces (window_row);
|
|
2437
|
|
2438 if (window_matrix == w->current_matrix)
|
6682
|
2439 {
|
25012
|
2440 /* We have to copy W's current matrix. Copy window
|
|
2441 row to frame row. */
|
|
2442 bcopy (window_row->glyphs[0],
|
|
2443 frame_row->glyphs[TEXT_AREA] + window_matrix->matrix_x,
|
|
2444 window_matrix->matrix_w * sizeof (struct glyph));
|
|
2445 }
|
|
2446 else
|
|
2447 {
|
|
2448 /* Copy W's desired matrix. */
|
|
2449
|
|
2450 /* Maybe insert a vertical border between horizontally adjacent
|
|
2451 windows. */
|
|
2452 if (right_border_glyph)
|
|
2453 {
|
|
2454 struct glyph *border = window_row->glyphs[LAST_AREA] - 1;
|
|
2455 SET_CHAR_GLYPH_FROM_GLYPH (*border, right_border_glyph);
|
|
2456 }
|
|
2457
|
27855
|
2458 #if 0 /* This shouldn't be necessary. Let's check it. */
|
25012
|
2459 /* Due to hooks installed, it normally doesn't happen that
|
|
2460 window rows and frame rows of the same matrix are out of
|
|
2461 sync, i.e. have a different understanding of where to
|
|
2462 find glyphs for the row. The following is a safety-belt
|
|
2463 that doesn't cost much and makes absolutely sure that
|
|
2464 window and frame matrices are in sync. */
|
|
2465 if (!glyph_row_slice_p (window_row, frame_row))
|
6682
|
2466 {
|
25012
|
2467 /* Find the row in the window being a slice. There
|
|
2468 should exist one from program logic. */
|
|
2469 struct glyph_row *slice_row
|
|
2470 = find_glyph_row_slice (window_matrix, frame_matrix, frame_y);
|
|
2471 xassert (slice_row != 0);
|
|
2472
|
|
2473 /* Exchange glyphs between both window rows. */
|
|
2474 swap_glyphs_in_rows (window_row, slice_row);
|
|
2475
|
|
2476 /* Exchange pointers between both rows. */
|
|
2477 swap_glyph_pointers (window_row, slice_row);
|
6682
|
2478 }
|
27855
|
2479 #endif
|
|
2480
|
|
2481 /* Window row window_y must be a slice of frame row
|
|
2482 frame_y. */
|
25012
|
2483 xassert (glyph_row_slice_p (window_row, frame_row));
|
27855
|
2484
|
25012
|
2485 /* If rows are in sync, we don't have to copy glyphs because
|
|
2486 frame and window share glyphs. */
|
25241
|
2487
|
|
2488 #if GLYPH_DEBUG
|
|
2489 strcpy (w->current_matrix->method, w->desired_matrix->method);
|
|
2490 #endif
|
25012
|
2491 }
|
|
2492
|
|
2493 /* Set number of used glyphs in the frame matrix. Since we fill
|
|
2494 up with spaces, and visit leaf windows from left to right it
|
|
2495 can be done simply. */
|
|
2496 frame_row->used[TEXT_AREA]
|
|
2497 = window_matrix->matrix_x + window_matrix->matrix_w;
|
|
2498
|
|
2499 /* Or in flags. */
|
|
2500 frame_row->enabled_p |= window_row->enabled_p;
|
|
2501 frame_row->inverse_p |= window_row->inverse_p;
|
|
2502
|
|
2503 /* Next row. */
|
|
2504 ++window_y;
|
|
2505 ++frame_y;
|
|
2506 }
|
|
2507 }
|
|
2508
|
|
2509
|
|
2510 /* Add spaces to a glyph row ROW in a window matrix.
|
|
2511
|
|
2512 Each row has the form:
|
|
2513
|
|
2514 +---------+-----------------------------+------------+
|
|
2515 | left | text | right |
|
|
2516 +---------+-----------------------------+------------+
|
|
2517
|
|
2518 Left and right marginal areas are optional. This function adds
|
|
2519 spaces to areas so that there are no empty holes between areas.
|
|
2520 In other words: If the right area is not empty, the text area
|
|
2521 is filled up with spaces up to the right area. If the text area
|
|
2522 is not empty, the left area is filled up.
|
|
2523
|
|
2524 To be called for frame-based redisplay, only. */
|
|
2525
|
|
2526 static void
|
|
2527 fill_up_glyph_row_with_spaces (row)
|
|
2528 struct glyph_row *row;
|
|
2529 {
|
|
2530 fill_up_glyph_row_area_with_spaces (row, LEFT_MARGIN_AREA);
|
|
2531 fill_up_glyph_row_area_with_spaces (row, TEXT_AREA);
|
|
2532 fill_up_glyph_row_area_with_spaces (row, RIGHT_MARGIN_AREA);
|
|
2533 }
|
|
2534
|
|
2535
|
|
2536 /* Fill area AREA of glyph row ROW with spaces. To be called for
|
|
2537 frame-based redisplay only. */
|
|
2538
|
|
2539 static void
|
|
2540 fill_up_glyph_row_area_with_spaces (row, area)
|
|
2541 struct glyph_row *row;
|
|
2542 int area;
|
|
2543 {
|
|
2544 if (row->glyphs[area] < row->glyphs[area + 1])
|
|
2545 {
|
|
2546 struct glyph *end = row->glyphs[area + 1];
|
|
2547 struct glyph *text = row->glyphs[area] + row->used[area];
|
|
2548
|
|
2549 while (text < end)
|
|
2550 *text++ = space_glyph;
|
|
2551 row->used[area] = text - row->glyphs[area];
|
|
2552 }
|
|
2553 }
|
|
2554
|
|
2555
|
|
2556 /* Add spaces to the end of ROW in a frame matrix until index UPTO is
|
|
2557 reached. In frame matrices only one area, TEXT_AREA, is used. */
|
|
2558
|
|
2559 static void
|
|
2560 fill_up_frame_row_with_spaces (row, upto)
|
|
2561 struct glyph_row *row;
|
|
2562 int upto;
|
|
2563 {
|
|
2564 int i = row->used[TEXT_AREA];
|
|
2565 struct glyph *glyph = row->glyphs[TEXT_AREA];
|
|
2566
|
|
2567 while (i < upto)
|
|
2568 glyph[i++] = space_glyph;
|
|
2569
|
|
2570 row->used[TEXT_AREA] = i;
|
|
2571 }
|
|
2572
|
|
2573
|
|
2574
|
|
2575 /**********************************************************************
|
|
2576 Mirroring operations on frame matrices in window matrices
|
|
2577 **********************************************************************/
|
|
2578
|
|
2579 /* Set frame being updated via frame-based redisplay to F. This
|
|
2580 function must be called before updates to make explicit that we are
|
|
2581 working on frame matrices or not. */
|
|
2582
|
|
2583 static INLINE void
|
|
2584 set_frame_matrix_frame (f)
|
|
2585 struct frame *f;
|
|
2586 {
|
|
2587 frame_matrix_frame = f;
|
|
2588 }
|
|
2589
|
|
2590
|
|
2591 /* Make sure glyph row ROW in CURRENT_MATRIX is up to date.
|
|
2592 DESIRED_MATRIX is the desired matrix corresponding to
|
|
2593 CURRENT_MATRIX. The update is done by exchanging glyph pointers
|
|
2594 between rows in CURRENT_MATRIX and DESIRED_MATRIX. If
|
|
2595 frame_matrix_frame is non-null, this indicates that the exchange is
|
|
2596 done in frame matrices, and that we have to perform analogous
|
|
2597 operations in window matrices of frame_matrix_frame. */
|
|
2598
|
|
2599 static INLINE void
|
|
2600 make_current (desired_matrix, current_matrix, row)
|
|
2601 struct glyph_matrix *desired_matrix, *current_matrix;
|
|
2602 int row;
|
|
2603 {
|
|
2604 struct glyph_row *current_row = MATRIX_ROW (current_matrix, row);
|
|
2605 struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row);
|
|
2606
|
|
2607 /* Do current_row = desired_row. This exchanges glyph pointers
|
|
2608 between both rows, and does a structure assignment otherwise. */
|
|
2609 assign_row (current_row, desired_row);
|
|
2610
|
|
2611 /* Enable current_row to mark it as valid. */
|
|
2612 current_row->enabled_p = 1;
|
|
2613
|
|
2614 /* If we are called on frame matrices, perform analogous operations
|
|
2615 for window matrices. */
|
|
2616 if (frame_matrix_frame)
|
|
2617 mirror_make_current (XWINDOW (frame_matrix_frame->root_window), row);
|
|
2618 }
|
|
2619
|
|
2620
|
|
2621 /* W is the root of a window tree. FRAME_ROW is the index of a row in
|
|
2622 W's frame which has been made current (by swapping pointers between
|
|
2623 current and desired matrix). Perform analogous operations in the
|
|
2624 matrices of leaf windows in the window tree rooted at W. */
|
|
2625
|
|
2626 static void
|
|
2627 mirror_make_current (w, frame_row)
|
|
2628 struct window *w;
|
|
2629 int frame_row;
|
|
2630 {
|
|
2631 while (w)
|
|
2632 {
|
|
2633 if (!NILP (w->hchild))
|
|
2634 mirror_make_current (XWINDOW (w->hchild), frame_row);
|
|
2635 else if (!NILP (w->vchild))
|
|
2636 mirror_make_current (XWINDOW (w->vchild), frame_row);
|
|
2637 else
|
|
2638 {
|
|
2639 /* Row relative to window W. Don't use FRAME_TO_WINDOW_VPOS
|
|
2640 here because the checks performed in debug mode there
|
|
2641 will not allow the conversion. */
|
|
2642 int row = frame_row - w->desired_matrix->matrix_y;
|
|
2643
|
|
2644 /* If FRAME_ROW is within W, assign the desired row to the
|
|
2645 current row (exchanging glyph pointers). */
|
|
2646 if (row >= 0 && row < w->desired_matrix->matrix_h)
|
6682
|
2647 {
|
25012
|
2648 struct glyph_row *current_row
|
|
2649 = MATRIX_ROW (w->current_matrix, row);
|
|
2650 struct glyph_row *desired_row
|
|
2651 = MATRIX_ROW (w->desired_matrix, row);
|
25241
|
2652
|
|
2653 if (desired_row->enabled_p)
|
|
2654 assign_row (current_row, desired_row);
|
|
2655 else
|
|
2656 swap_glyph_pointers (desired_row, current_row);
|
25012
|
2657 current_row->enabled_p = 1;
|
6682
|
2658 }
|
|
2659 }
|
25012
|
2660
|
|
2661 w = NILP (w->next) ? 0 : XWINDOW (w->next);
|
6642
|
2662 }
|
|
2663 }
|
25012
|
2664
|
|
2665
|
|
2666 /* Perform row dance after scrolling. We are working on the range of
|
|
2667 lines UNCHANGED_AT_TOP + 1 to UNCHANGED_AT_TOP + NLINES (not
|
|
2668 including) in MATRIX. COPY_FROM is a vector containing, for each
|
|
2669 row I in the range 0 <= I < NLINES, the index of the original line
|
|
2670 to move to I. This index is relative to the row range, i.e. 0 <=
|
|
2671 index < NLINES. RETAINED_P is a vector containing zero for each
|
|
2672 row 0 <= I < NLINES which is empty.
|
|
2673
|
|
2674 This function is called from do_scrolling and do_direct_scrolling. */
|
|
2675
|
|
2676 void
|
|
2677 mirrored_line_dance (matrix, unchanged_at_top, nlines, copy_from,
|
|
2678 retained_p)
|
|
2679 struct glyph_matrix *matrix;
|
|
2680 int unchanged_at_top, nlines;
|
|
2681 int *copy_from;
|
|
2682 char *retained_p;
|
|
2683 {
|
|
2684 /* A copy of original rows. */
|
|
2685 struct glyph_row *old_rows;
|
|
2686
|
|
2687 /* Rows to assign to. */
|
|
2688 struct glyph_row *new_rows = MATRIX_ROW (matrix, unchanged_at_top);
|
|
2689
|
|
2690 int i;
|
|
2691
|
|
2692 /* Make a copy of the original rows. */
|
|
2693 old_rows = (struct glyph_row *) alloca (nlines * sizeof *old_rows);
|
|
2694 bcopy (new_rows, old_rows, nlines * sizeof *old_rows);
|
|
2695
|
|
2696 /* Assign new rows, maybe clear lines. */
|
|
2697 for (i = 0; i < nlines; ++i)
|
|
2698 {
|
|
2699 int enabled_before_p = new_rows[i].enabled_p;
|
|
2700
|
|
2701 xassert (i + unchanged_at_top < matrix->nrows);
|
|
2702 xassert (unchanged_at_top + copy_from[i] < matrix->nrows);
|
|
2703 new_rows[i] = old_rows[copy_from[i]];
|
|
2704 new_rows[i].enabled_p = enabled_before_p;
|
|
2705
|
|
2706 /* RETAINED_P is zero for empty lines. */
|
|
2707 if (!retained_p[copy_from[i]])
|
|
2708 new_rows[i].enabled_p = 0;
|
|
2709 }
|
|
2710
|
|
2711 /* Do the same for window matrices, if MATRIX Is a frame matrix. */
|
|
2712 if (frame_matrix_frame)
|
|
2713 mirror_line_dance (XWINDOW (frame_matrix_frame->root_window),
|
|
2714 unchanged_at_top, nlines, copy_from, retained_p);
|
|
2715 }
|
|
2716
|
|
2717
|
27855
|
2718 /* Synchronize glyph pointers in the current matrix of window W with
|
|
2719 the current frame matrix. W must be full-width, and be on a tty
|
|
2720 frame. */
|
|
2721
|
|
2722 static void
|
|
2723 sync_window_with_frame_matrix_rows (w)
|
|
2724 struct window *w;
|
|
2725 {
|
|
2726 struct frame *f = XFRAME (w->frame);
|
|
2727 struct glyph_row *window_row, *window_row_end, *frame_row;
|
|
2728
|
|
2729 /* Preconditions: W must be a leaf window and full-width. Its frame
|
|
2730 must have a frame matrix. */
|
|
2731 xassert (NILP (w->hchild) && NILP (w->vchild));
|
|
2732 xassert (WINDOW_FULL_WIDTH_P (w));
|
|
2733 xassert (!FRAME_WINDOW_P (f));
|
|
2734
|
|
2735 /* If W is a full-width window, glyph pointers in W's current matrix
|
|
2736 have, by definition, to be the same as glyph pointers in the
|
|
2737 corresponding frame matrix. */
|
|
2738 window_row = w->current_matrix->rows;
|
|
2739 window_row_end = window_row + w->current_matrix->nrows;
|
|
2740 frame_row = f->current_matrix->rows + XFASTINT (w->top);
|
|
2741 while (window_row < window_row_end)
|
|
2742 {
|
|
2743 int area;
|
|
2744
|
|
2745 for (area = LEFT_MARGIN_AREA; area <= LAST_AREA; ++area)
|
|
2746 window_row->glyphs[area] = frame_row->glyphs[area];
|
|
2747
|
|
2748 ++window_row, ++frame_row;
|
|
2749 }
|
|
2750 }
|
|
2751
|
|
2752
|
|
2753 /* Return the window in the window tree rooted in W containing frame
|
|
2754 row ROW. Value is null if none is found. */
|
|
2755
|
|
2756 struct window *
|
|
2757 frame_row_to_window (w, row)
|
|
2758 struct window *w;
|
|
2759 int row;
|
|
2760 {
|
|
2761 struct window *found = NULL;
|
|
2762
|
|
2763 while (w && !found)
|
|
2764 {
|
|
2765 if (!NILP (w->hchild))
|
|
2766 found = frame_row_to_window (XWINDOW (w->hchild), row);
|
|
2767 else if (!NILP (w->vchild))
|
|
2768 found = frame_row_to_window (XWINDOW (w->vchild), row);
|
|
2769 else if (row >= XFASTINT (w->top)
|
|
2770 && row < XFASTINT (w->top) + XFASTINT (w->height))
|
|
2771 found = w;
|
|
2772
|
|
2773 w = NILP (w->next) ? 0 : XWINDOW (w->next);
|
|
2774 }
|
|
2775
|
|
2776 return found;
|
|
2777 }
|
|
2778
|
|
2779
|
25012
|
2780 /* Perform a line dance in the window tree rooted at W, after
|
|
2781 scrolling a frame matrix in mirrored_line_dance.
|
|
2782
|
|
2783 We are working on the range of lines UNCHANGED_AT_TOP + 1 to
|
|
2784 UNCHANGED_AT_TOP + NLINES (not including) in W's frame matrix.
|
|
2785 COPY_FROM is a vector containing, for each row I in the range 0 <=
|
|
2786 I < NLINES, the index of the original line to move to I. This
|
|
2787 index is relative to the row range, i.e. 0 <= index < NLINES.
|
|
2788 RETAINED_P is a vector containing zero for each row 0 <= I < NLINES
|
|
2789 which is empty. */
|
|
2790
|
|
2791 static void
|
|
2792 mirror_line_dance (w, unchanged_at_top, nlines, copy_from, retained_p)
|
|
2793 struct window *w;
|
|
2794 int unchanged_at_top, nlines;
|
|
2795 int *copy_from;
|
|
2796 char *retained_p;
|
|
2797 {
|
|
2798 while (w)
|
|
2799 {
|
|
2800 if (!NILP (w->hchild))
|
|
2801 mirror_line_dance (XWINDOW (w->hchild), unchanged_at_top,
|
|
2802 nlines, copy_from, retained_p);
|
|
2803 else if (!NILP (w->vchild))
|
|
2804 mirror_line_dance (XWINDOW (w->vchild), unchanged_at_top,
|
|
2805 nlines, copy_from, retained_p);
|
|
2806 else
|
|
2807 {
|
|
2808 /* W is a leaf window, and we are working on its current
|
|
2809 matrix m. */
|
|
2810 struct glyph_matrix *m = w->current_matrix;
|
27855
|
2811 int i, sync_p = 0;
|
25012
|
2812 struct glyph_row *old_rows;
|
|
2813
|
|
2814 /* Make a copy of the original rows of matrix m. */
|
|
2815 old_rows = (struct glyph_row *) alloca (m->nrows * sizeof *old_rows);
|
|
2816 bcopy (m->rows, old_rows, m->nrows * sizeof *old_rows);
|
|
2817
|
|
2818 for (i = 0; i < nlines; ++i)
|
|
2819 {
|
|
2820 /* Frame relative line assigned to. */
|
|
2821 int frame_to = i + unchanged_at_top;
|
|
2822
|
|
2823 /* Frame relative line assigned. */
|
|
2824 int frame_from = copy_from[i] + unchanged_at_top;
|
|
2825
|
|
2826 /* Window relative line assigned to. */
|
|
2827 int window_to = frame_to - m->matrix_y;
|
|
2828
|
|
2829 /* Window relative line assigned. */
|
|
2830 int window_from = frame_from - m->matrix_y;
|
|
2831
|
|
2832 /* Is assigned line inside window? */
|
|
2833 int from_inside_window_p
|
|
2834 = window_from >= 0 && window_from < m->matrix_h;
|
|
2835
|
27855
|
2836 /* Is assigned to line inside window? */
|
|
2837 int to_inside_window_p
|
|
2838 = window_to >= 0 && window_to < m->matrix_h;
|
|
2839
|
|
2840 if (from_inside_window_p && to_inside_window_p)
|
25012
|
2841 {
|
|
2842 /* Enabled setting before assignment. */
|
|
2843 int enabled_before_p;
|
|
2844
|
|
2845 /* Do the assignment. The enabled_p flag is saved
|
|
2846 over the assignment because the old redisplay did
|
|
2847 that. */
|
|
2848 enabled_before_p = m->rows[window_to].enabled_p;
|
|
2849 m->rows[window_to] = old_rows[window_from];
|
|
2850 m->rows[window_to].enabled_p = enabled_before_p;
|
|
2851
|
|
2852 /* If frame line is empty, window line is empty, too. */
|
|
2853 if (!retained_p[copy_from[i]])
|
|
2854 m->rows[window_to].enabled_p = 0;
|
|
2855 }
|
27855
|
2856 else if (to_inside_window_p)
|
|
2857 {
|
|
2858 /* A copy between windows. This is an infrequent
|
|
2859 case not worth optimizing. */
|
|
2860 struct frame *f = XFRAME (w->frame);
|
|
2861 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
|
|
2862 struct window *w2;
|
|
2863 struct glyph_matrix *m2;
|
|
2864 int m2_from;
|
|
2865
|
|
2866 w2 = frame_row_to_window (root, frame_to);
|
|
2867 m2 = w2->current_matrix;
|
|
2868 m2_from = frame_from - m2->matrix_y;
|
|
2869 copy_row_except_pointers (m->rows + window_to,
|
|
2870 m2->rows + m2_from);
|
|
2871
|
|
2872 /* If frame line is empty, window line is empty, too. */
|
|
2873 if (!retained_p[copy_from[i]])
|
|
2874 m->rows[window_to].enabled_p = 0;
|
|
2875 sync_p = 1;
|
|
2876 }
|
|
2877 else if (from_inside_window_p)
|
|
2878 sync_p = 1;
|
25012
|
2879 }
|
27855
|
2880
|
|
2881 /* If there was a copy between windows, make sure glyph
|
|
2882 pointers are in sync with the frame matrix. */
|
|
2883 if (sync_p)
|
|
2884 sync_window_with_frame_matrix_rows (w);
|
25012
|
2885
|
|
2886 /* Check that no pointers are lost. */
|
|
2887 CHECK_MATRIX (m);
|
|
2888 }
|
|
2889
|
|
2890 /* Next window on same level. */
|
|
2891 w = NILP (w->next) ? 0 : XWINDOW (w->next);
|
|
2892 }
|
|
2893 }
|
|
2894
|
|
2895
|
|
2896 #if GLYPH_DEBUG
|
|
2897
|
|
2898 /* Check that window and frame matrices agree about their
|
|
2899 understanding where glyphs of the rows are to find. For each
|
|
2900 window in the window tree rooted at W, check that rows in the
|
|
2901 matrices of leaf window agree with their frame matrices about
|
|
2902 glyph pointers. */
|
314
|
2903
|
21514
|
2904 void
|
25012
|
2905 check_window_matrix_pointers (w)
|
314
|
2906 struct window *w;
|
|
2907 {
|
25012
|
2908 while (w)
|
|
2909 {
|
|
2910 if (!NILP (w->hchild))
|
|
2911 check_window_matrix_pointers (XWINDOW (w->hchild));
|
|
2912 else if (!NILP (w->vchild))
|
|
2913 check_window_matrix_pointers (XWINDOW (w->vchild));
|
|
2914 else
|
|
2915 {
|
|
2916 struct frame *f = XFRAME (w->frame);
|
|
2917 check_matrix_pointers (w->desired_matrix, f->desired_matrix);
|
|
2918 check_matrix_pointers (w->current_matrix, f->current_matrix);
|
|
2919 }
|
|
2920
|
|
2921 w = NILP (w->next) ? 0 : XWINDOW (w->next);
|
|
2922 }
|
|
2923 }
|
|
2924
|
|
2925
|
|
2926 /* Check that window rows are slices of frame rows. WINDOW_MATRIX is
|
|
2927 a window and FRAME_MATRIX is the corresponding frame matrix. For
|
|
2928 each row in WINDOW_MATRIX check that it's a slice of the
|
|
2929 corresponding frame row. If it isn't, abort. */
|
|
2930
|
|
2931 static void
|
|
2932 check_matrix_pointers (window_matrix, frame_matrix)
|
|
2933 struct glyph_matrix *window_matrix, *frame_matrix;
|
|
2934 {
|
|
2935 /* Row number in WINDOW_MATRIX. */
|
|
2936 int i = 0;
|
|
2937
|
|
2938 /* Row number corresponding to I in FRAME_MATRIX. */
|
|
2939 int j = window_matrix->matrix_y;
|
|
2940
|
|
2941 /* For all rows check that the row in the window matrix is a
|
|
2942 slice of the row in the frame matrix. If it isn't we didn't
|
|
2943 mirror an operation on the frame matrix correctly. */
|
|
2944 while (i < window_matrix->nrows)
|
|
2945 {
|
|
2946 if (!glyph_row_slice_p (window_matrix->rows + i,
|
|
2947 frame_matrix->rows + j))
|
|
2948 abort ();
|
|
2949 ++i, ++j;
|
|
2950 }
|
|
2951 }
|
|
2952
|
|
2953 #endif /* GLYPH_DEBUG != 0 */
|
|
2954
|
|
2955
|
|
2956
|
|
2957 /**********************************************************************
|
|
2958 VPOS and HPOS translations
|
|
2959 **********************************************************************/
|
|
2960
|
|
2961 #if GLYPH_DEBUG
|
|
2962
|
|
2963 /* Translate vertical position VPOS which is relative to window W to a
|
|
2964 vertical position relative to W's frame. */
|
|
2965
|
|
2966 static int
|
|
2967 window_to_frame_vpos (w, vpos)
|
|
2968 struct window *w;
|
|
2969 int vpos;
|
|
2970 {
|
|
2971 struct frame *f = XFRAME (w->frame);
|
|
2972
|
|
2973 xassert (!FRAME_WINDOW_P (f));
|
|
2974 xassert (vpos >= 0 && vpos <= w->desired_matrix->nrows);
|
|
2975 vpos += XFASTINT (w->top);
|
|
2976 xassert (vpos >= 0 && vpos <= FRAME_HEIGHT (f));
|
|
2977 return vpos;
|
|
2978 }
|
|
2979
|
|
2980
|
|
2981 /* Translate horizontal position HPOS which is relative to window W to
|
|
2982 a vertical position relative to W's frame. */
|
|
2983
|
|
2984 static int
|
|
2985 window_to_frame_hpos (w, hpos)
|
|
2986 struct window *w;
|
|
2987 int hpos;
|
|
2988 {
|
|
2989 struct frame *f = XFRAME (w->frame);
|
|
2990
|
|
2991 xassert (!FRAME_WINDOW_P (f));
|
|
2992 hpos += XFASTINT (w->left);
|
|
2993 return hpos;
|
314
|
2994 }
|
25012
|
2995
|
|
2996 #endif /* GLYPH_DEBUG */
|
|
2997
|
|
2998
|
314
|
2999
|
25012
|
3000 /**********************************************************************
|
|
3001 Redrawing Frames
|
|
3002 **********************************************************************/
|
|
3003
|
|
3004 DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
|
|
3005 "Clear frame FRAME and output again what is supposed to appear on it.")
|
|
3006 (frame)
|
|
3007 Lisp_Object frame;
|
|
3008 {
|
|
3009 struct frame *f;
|
|
3010
|
|
3011 CHECK_LIVE_FRAME (frame, 0);
|
|
3012 f = XFRAME (frame);
|
|
3013
|
|
3014 /* Ignore redraw requests, if frame has no glyphs yet.
|
|
3015 (Implementation note: It still has to be checked why we are
|
|
3016 called so early here). */
|
|
3017 if (!glyphs_initialized_initially_p)
|
|
3018 return Qnil;
|
|
3019
|
|
3020 update_begin (f);
|
|
3021 if (FRAME_MSDOS_P (f))
|
|
3022 set_terminal_modes ();
|
|
3023 clear_frame ();
|
|
3024 clear_current_matrices (f);
|
|
3025 update_end (f);
|
|
3026 fflush (stdout);
|
|
3027 windows_or_buffers_changed++;
|
|
3028 /* Mark all windows as inaccurate, so that every window will have
|
|
3029 its redisplay done. */
|
|
3030 mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
|
|
3031 set_window_update_flags (XWINDOW (FRAME_ROOT_WINDOW (f)), 1);
|
|
3032 f->garbaged = 0;
|
|
3033 return Qnil;
|
|
3034 }
|
|
3035
|
|
3036
|
|
3037 /* Redraw frame F. This is nothing more than a call to the Lisp
|
|
3038 function redraw-frame. */
|
|
3039
|
|
3040 void
|
|
3041 redraw_frame (f)
|
|
3042 struct frame *f;
|
|
3043 {
|
|
3044 Lisp_Object frame;
|
|
3045 XSETFRAME (frame, f);
|
|
3046 Fredraw_frame (frame);
|
|
3047 }
|
|
3048
|
|
3049
|
|
3050 DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
|
|
3051 "Clear and redisplay all visible frames.")
|
|
3052 ()
|
|
3053 {
|
|
3054 Lisp_Object tail, frame;
|
|
3055
|
|
3056 FOR_EACH_FRAME (tail, frame)
|
|
3057 if (FRAME_VISIBLE_P (XFRAME (frame)))
|
|
3058 Fredraw_frame (frame);
|
|
3059
|
|
3060 return Qnil;
|
|
3061 }
|
|
3062
|
|
3063
|
|
3064 /* This is used when frame_garbaged is set. Call Fredraw_frame on all
|
|
3065 visible frames marked as garbaged. */
|
|
3066
|
|
3067 void
|
|
3068 redraw_garbaged_frames ()
|
|
3069 {
|
|
3070 Lisp_Object tail, frame;
|
|
3071
|
|
3072 FOR_EACH_FRAME (tail, frame)
|
|
3073 if (FRAME_VISIBLE_P (XFRAME (frame))
|
|
3074 && FRAME_GARBAGED_P (XFRAME (frame)))
|
|
3075 Fredraw_frame (frame);
|
|
3076 }
|
|
3077
|
|
3078
|
|
3079
|
|
3080 /***********************************************************************
|
|
3081 Direct Operations
|
|
3082 ***********************************************************************/
|
|
3083
|
|
3084 /* Try to update display and current glyph matrix directly.
|
|
3085
|
|
3086 This function is called after a character G has been inserted into
|
|
3087 current_buffer. It tries to update the current glyph matrix and
|
|
3088 perform appropriate screen output to reflect the insertion. If it
|
|
3089 succeeds, the global flag redisplay_performed_directly_p will be
|
|
3090 set to 1, and thereby prevent the more costly general redisplay
|
|
3091 from running (see redisplay_internal).
|
|
3092
|
|
3093 This function is not called for `hairy' character insertions.
|
|
3094 In particular, it is not called when after or before change
|
|
3095 functions exist, like they are used by font-lock. See keyboard.c
|
|
3096 for details where this function is called. */
|
314
|
3097
|
|
3098 int
|
|
3099 direct_output_for_insert (g)
|
|
3100 int g;
|
|
3101 {
|
25666
|
3102 register struct frame *f = SELECTED_FRAME ();
|
25012
|
3103 struct window *w = XWINDOW (selected_window);
|
|
3104 struct it it, it2;
|
|
3105 struct glyph_row *glyph_row;
|
|
3106 struct glyph *glyphs, *glyph, *end;
|
|
3107 int n;
|
|
3108 /* Non-null means that Redisplay of W is based on window matrices. */
|
|
3109 int window_redisplay_p = FRAME_WINDOW_P (f);
|
|
3110 /* Non-null means we are in overwrite mode. */
|
|
3111 int overwrite_p = !NILP (current_buffer->overwrite_mode);
|
|
3112 int added_width;
|
|
3113 struct text_pos pos;
|
|
3114 int delta, delta_bytes;
|
|
3115
|
|
3116 /* Not done directly. */
|
|
3117 redisplay_performed_directly_p = 0;
|
|
3118
|
|
3119 /* Quickly give up for some common cases. */
|
|
3120 if (cursor_in_echo_area
|
|
3121 /* Give up if fonts have changed. */
|
|
3122 || fonts_changed_p
|
|
3123 /* Give up if face attributes have been changed. */
|
|
3124 || face_change_count
|
|
3125 /* Give up if cursor position not really known. */
|
314
|
3126 || !display_completed
|
25012
|
3127 /* Give up if buffer appears in two places. */
|
314
|
3128 || buffer_shared > 1
|
25012
|
3129 /* Give up if w is mini-buffer and a message is being displayed there */
|
25345
|
3130 || (MINI_WINDOW_P (w) && !NILP (echo_area_buffer[0]))
|
25012
|
3131 /* Give up for hscrolled mini-buffer because display of the prompt
|
|
3132 is handled specially there (see display_line). */
|
|
3133 || (MINI_WINDOW_P (w) && XFASTINT (w->hscroll))
|
|
3134 /* Give up if overwriting in the middle of a line. */
|
|
3135 || (overwrite_p
|
|
3136 && PT != ZV
|
|
3137 && FETCH_BYTE (PT) != '\n')
|
|
3138 /* Give up for tabs and line ends. */
|
|
3139 || g == '\t'
|
|
3140 || g == '\n'
|
|
3141 || g == '\r'
|
|
3142 /* Give up if unable to display the cursor in the window. */
|
|
3143 || w->cursor.vpos < 0
|
25186
|
3144 || (glyph_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos),
|
|
3145 /* Can't do it in a continued line because continuation
|
|
3146 lines would change. */
|
|
3147 (glyph_row->continued_p
|
|
3148 /* Can't use this method if the line overlaps others or is
|
|
3149 overlapped by others because these other lines would
|
|
3150 have to be redisplayed. */
|
|
3151 || glyph_row->overlapping_p
|
|
3152 || glyph_row->overlapped_p))
|
25012
|
3153 /* Can't do it for partial width windows on terminal frames
|
|
3154 because we can't clear to eol in such a window. */
|
|
3155 || (!window_redisplay_p && !WINDOW_FULL_WIDTH_P (w)))
|
|
3156 return 0;
|
|
3157
|
|
3158 /* Set up a display iterator structure for W. Glyphs will be
|
|
3159 produced in scratch_glyph_row. Current position is W's cursor
|
|
3160 position. */
|
|
3161 clear_glyph_row (&scratch_glyph_row);
|
|
3162 SET_TEXT_POS (pos, PT, PT_BYTE);
|
28361
|
3163 DEC_TEXT_POS (pos, !NILP (current_buffer->enable_multibyte_characters));
|
25012
|
3164 init_iterator (&it, w, CHARPOS (pos), BYTEPOS (pos), &scratch_glyph_row,
|
|
3165 DEFAULT_FACE_ID);
|
|
3166
|
|
3167 glyph_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
|
|
3168
|
|
3169 /* Give up if highlighting trailing whitespace and we have trailing
|
|
3170 whitespace in glyph_row. We would have to remove the trailing
|
|
3171 whitespace face in that case. */
|
25304
|
3172 if (!NILP (Vshow_trailing_whitespace)
|
25012
|
3173 && glyph_row->used[TEXT_AREA])
|
|
3174 {
|
|
3175 struct glyph *last;
|
|
3176
|
|
3177 last = glyph_row->glyphs[TEXT_AREA] + glyph_row->used[TEXT_AREA] - 1;
|
|
3178 if (last->type == STRETCH_GLYPH
|
|
3179 || (last->type == CHAR_GLYPH
|
26998
|
3180 && last->u.ch == ' '))
|
25012
|
3181 return 0;
|
|
3182 }
|
|
3183
|
|
3184 /* Give up if there are overlay strings at pos. This would fail
|
|
3185 if the overlay string has newlines in it. */
|
|
3186 if (STRINGP (it.string))
|
|
3187 return 0;
|
|
3188
|
|
3189 it.hpos = w->cursor.hpos;
|
|
3190 it.vpos = w->cursor.vpos;
|
|
3191 it.current_x = w->cursor.x + it.first_visible_x;
|
|
3192 it.current_y = w->cursor.y;
|
|
3193 it.end_charpos = PT;
|
|
3194 it.stop_charpos = min (PT, it.stop_charpos);
|
|
3195
|
|
3196 /* More than one display element may be returned for PT - 1 if
|
|
3197 (i) it's a control character which is translated into `\003' or
|
|
3198 `^C', or (ii) it has a display table entry, or (iii) it's a
|
|
3199 combination of both. */
|
|
3200 delta = delta_bytes = 0;
|
|
3201 while (get_next_display_element (&it))
|
|
3202 {
|
|
3203 PRODUCE_GLYPHS (&it);
|
|
3204
|
|
3205 /* Give up if glyph doesn't fit completely on the line. */
|
|
3206 if (it.current_x >= it.last_visible_x)
|
|
3207 return 0;
|
|
3208
|
|
3209 /* Give up if new glyph has different ascent or descent than
|
|
3210 the original row, or if it is not a character glyph. */
|
|
3211 if (glyph_row->ascent != it.ascent
|
|
3212 || glyph_row->height != it.ascent + it.descent
|
25186
|
3213 || glyph_row->phys_ascent != it.phys_ascent
|
|
3214 || glyph_row->phys_height != it.phys_ascent + it.phys_descent
|
25012
|
3215 || it.what != IT_CHARACTER)
|
|
3216 return 0;
|
|
3217
|
|
3218 delta += 1;
|
|
3219 delta_bytes += it.len;
|
|
3220 set_iterator_to_next (&it);
|
|
3221 }
|
|
3222
|
|
3223 /* Give up if we hit the right edge of the window. We would have
|
|
3224 to insert truncation or continuation glyphs. */
|
|
3225 added_width = it.current_x - (w->cursor.x + it.first_visible_x);
|
|
3226 if (glyph_row->pixel_width + added_width >= it.last_visible_x)
|
314
|
3227 return 0;
|
|
3228
|
25012
|
3229 /* Give up if there is a \t following in the line. */
|
|
3230 it2 = it;
|
|
3231 it2.end_charpos = ZV;
|
|
3232 it2.stop_charpos = min (it2.stop_charpos, ZV);
|
|
3233 while (get_next_display_element (&it2)
|
|
3234 && !ITERATOR_AT_END_OF_LINE_P (&it2))
|
|
3235 {
|
|
3236 if (it2.c == '\t')
|
|
3237 return 0;
|
|
3238 set_iterator_to_next (&it2);
|
|
3239 }
|
|
3240
|
|
3241 /* Number of new glyphs produced. */
|
|
3242 n = it.glyph_row->used[TEXT_AREA];
|
|
3243
|
|
3244 /* Start and end of glyphs in original row. */
|
|
3245 glyphs = glyph_row->glyphs[TEXT_AREA] + w->cursor.hpos;
|
|
3246 end = glyph_row->glyphs[1 + TEXT_AREA];
|
|
3247
|
|
3248 /* Make room for new glyphs, then insert them. */
|
|
3249 xassert (end - glyphs - n >= 0);
|
25781
|
3250 safe_bcopy ((char *) glyphs, (char *) (glyphs + n),
|
|
3251 (end - glyphs - n) * sizeof (*end));
|
25012
|
3252 bcopy (it.glyph_row->glyphs[TEXT_AREA], glyphs, n * sizeof *glyphs);
|
|
3253 glyph_row->used[TEXT_AREA] = min (glyph_row->used[TEXT_AREA] + n,
|
|
3254 end - glyph_row->glyphs[TEXT_AREA]);
|
|
3255
|
|
3256 /* Compute new line width. */
|
|
3257 glyph = glyph_row->glyphs[TEXT_AREA];
|
|
3258 end = glyph + glyph_row->used[TEXT_AREA];
|
|
3259 glyph_row->pixel_width = glyph_row->x;
|
|
3260 while (glyph < end)
|
|
3261 {
|
|
3262 glyph_row->pixel_width += glyph->pixel_width;
|
|
3263 ++glyph;
|
|
3264 }
|
|
3265
|
|
3266 /* Increment buffer positions for glyphs following the newly
|
|
3267 inserted ones. */
|
|
3268 for (glyph = glyphs + n; glyph < end; ++glyph)
|
26546
|
3269 if (glyph->charpos > 0 && BUFFERP (glyph->object))
|
25012
|
3270 glyph->charpos += delta;
|
|
3271
|
|
3272 if (MATRIX_ROW_END_CHARPOS (glyph_row) > 0)
|
|
3273 {
|
|
3274 MATRIX_ROW_END_CHARPOS (glyph_row) += delta;
|
|
3275 MATRIX_ROW_END_BYTEPOS (glyph_row) += delta_bytes;
|
|
3276 }
|
|
3277
|
|
3278 /* Adjust positions in lines following the one we are in. */
|
28708
|
3279 increment_matrix_positions (w->current_matrix,
|
|
3280 w->cursor.vpos + 1,
|
|
3281 w->current_matrix->nrows,
|
|
3282 delta, delta_bytes);
|
25012
|
3283
|
|
3284 glyph_row->contains_overlapping_glyphs_p
|
|
3285 |= it.glyph_row->contains_overlapping_glyphs_p;
|
|
3286
|
26591
|
3287 glyph_row->displays_text_p = 1;
|
|
3288 w->window_end_vpos = make_number (max (w->cursor.vpos,
|
|
3289 XFASTINT (w->window_end_vpos)));
|
|
3290
|
25304
|
3291 if (!NILP (Vshow_trailing_whitespace))
|
25012
|
3292 highlight_trailing_whitespace (it.f, glyph_row);
|
|
3293
|
|
3294 /* Write glyphs. If at end of row, we can simply call write_glyphs.
|
|
3295 In the middle, we have to insert glyphs. Note that this is now
|
|
3296 implemented for X frames. The implementation uses updated_window
|
|
3297 and updated_row. */
|
|
3298 updated_row = glyph_row;
|
|
3299 update_begin (f);
|
|
3300 if (rif)
|
|
3301 {
|
|
3302 rif->update_window_begin_hook (w);
|
|
3303
|
|
3304 if (glyphs == end - n)
|
|
3305 rif->write_glyphs (glyphs, n);
|
|
3306 else
|
|
3307 rif->insert_glyphs (glyphs, n);
|
|
3308 }
|
|
3309 else
|
|
3310 {
|
|
3311 if (glyphs == end - n)
|
|
3312 write_glyphs (glyphs, n);
|
|
3313 else
|
|
3314 insert_glyphs (glyphs, n);
|
|
3315 }
|
|
3316
|
|
3317 w->cursor.hpos += n;
|
|
3318 w->cursor.x = it.current_x - it.first_visible_x;
|
|
3319 xassert (w->cursor.hpos >= 0
|
|
3320 && w->cursor.hpos < w->desired_matrix->matrix_w);
|
|
3321
|
|
3322 /* How to set the cursor differs depending on whether we are
|
|
3323 using a frame matrix or a window matrix. Note that when
|
|
3324 a frame matrix is used, cursor_to expects frame coordinates,
|
|
3325 and the X and Y parameters are not used. */
|
|
3326 if (window_redisplay_p)
|
|
3327 rif->cursor_to (w->cursor.vpos, w->cursor.hpos,
|
|
3328 w->cursor.y, w->cursor.x);
|
|
3329 else
|
|
3330 {
|
|
3331 int x, y;
|
|
3332 x = (WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos)
|
|
3333 + (INTEGERP (w->left_margin_width)
|
|
3334 ? XFASTINT (w->left_margin_width)
|
|
3335 : 0));
|
|
3336 y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos);
|
|
3337 cursor_to (y, x);
|
|
3338 }
|
|
3339
|
|
3340 if (rif)
|
|
3341 rif->update_window_end_hook (w, 1);
|
|
3342 update_end (f);
|
|
3343 updated_row = NULL;
|
|
3344 fflush (stdout);
|
|
3345
|
|
3346 TRACE ((stderr, "direct output for insert\n"));
|
|
3347
|
25372
|
3348 UNCHANGED_MODIFIED = MODIFF;
|
|
3349 BEG_UNCHANGED = GPT - BEG;
|
16039
|
3350 XSETFASTINT (w->last_point, PT);
|
25012
|
3351 w->last_cursor = w->cursor;
|
9303
3115ae493c30
(direct_output_for_insert, direct_output_forward_char, change_frame_size,
Karl Heuer <kwzh@gnu.org>
diff
changeset
|
3352 XSETFASTINT (w->last_modified, MODIFF);
|
16195
e15e4bdcb8cc
(direct_output_for_insert): Set last_overlay_modified field in window.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
3353 XSETFASTINT (w->last_overlay_modified, OVERLAY_MODIFF);
|
314
|
3354
|
25012
|
3355 redisplay_performed_directly_p = 1;
|
314
|
3356 return 1;
|
|
3357 }
|
|
3358
|
25012
|
3359
|
|
3360 /* Perform a direct display update for moving PT by N positions
|
|
3361 left or right. N < 0 means a movement backwards. This function
|
|
3362 is currently only called for N == 1 or N == -1. */
|
|
3363
|
314
|
3364 int
|
|
3365 direct_output_forward_char (n)
|
|
3366 int n;
|
|
3367 {
|
25666
|
3368 struct frame *f = SELECTED_FRAME ();
|
25012
|
3369 struct window *w = XWINDOW (selected_window);
|
|
3370 struct glyph_row *row;
|
|
3371
|
26851
|
3372 /* Give up if point moved out of or into a composition. */
|
28507
b6f06a755c7d
make_number/XINT/XUINT conversions; EQ/== fixes; ==Qnil -> NILP
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
3373 if (check_point_in_composition (current_buffer, XINT (w->last_point),
|
26851
|
3374 current_buffer, PT))
|
|
3375 return 0;
|
|
3376
|
25012
|
3377 /* Give up if face attributes have been changed. */
|
|
3378 if (face_change_count)
|
17015
|
3379 return 0;
|
25012
|
3380
|
|
3381 /* Give up if current matrix is not up to date or we are
|
|
3382 displaying a message. */
|
|
3383 if (!display_completed || cursor_in_echo_area)
|
|
3384 return 0;
|
|
3385
|
|
3386 /* Give up if the buffer's direction is reversed. */
|
|
3387 if (!NILP (XBUFFER (w->buffer)->direction_reversed))
|
314
|
3388 return 0;
|
11096
cac0367b1794
(direct_output_forward_char): Don't use direct output at an overlay boundary.
Karl Heuer <kwzh@gnu.org>
diff
changeset
|
3389
|
2794
|
3390 /* Can't use direct output if highlighting a region. */
|
|
3391 if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
|
|
3392 return 0;
|
|
3393
|
25304
|
3394 /* Can't use direct output if highlighting trailing whitespace. */
|
|
3395 if (!NILP (Vshow_trailing_whitespace))
|
|
3396 return 0;
|
|
3397
|
25735
|
3398 /* Give up if we are showing a message or just cleared the message
|
|
3399 because we might need to resize the echo area window. */
|
|
3400 if (!NILP (echo_area_buffer[0]) || !NILP (echo_area_buffer[1]))
|
|
3401 return 0;
|
|
3402
|
|
3403 /* Give up if we don't know where the cursor is. */
|
|
3404 if (w->cursor.vpos < 0)
|
|
3405 return 0;
|
|
3406
|
25012
|
3407 row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
|
|
3408
|
|
3409 if (PT <= MATRIX_ROW_START_BYTEPOS (row)
|
|
3410 || PT >= MATRIX_ROW_END_BYTEPOS (row))
|
6069
07045ca8ff19
(direct_output_forward_char): Use Fget_char_property to test for invisibility.
Karl Heuer <kwzh@gnu.org>
diff
changeset
|
3411 return 0;
|
4384
|
3412
|
25012
|
3413 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
|
|
3414 w->last_cursor = w->cursor;
|
16039
|
3415 XSETFASTINT (w->last_point, PT);
|
25012
|
3416
|
|
3417 xassert (w->cursor.hpos >= 0
|
|
3418 && w->cursor.hpos < w->desired_matrix->matrix_w);
|
|
3419
|
|
3420 if (FRAME_WINDOW_P (f))
|
|
3421 rif->cursor_to (w->cursor.vpos, w->cursor.hpos,
|
|
3422 w->cursor.y, w->cursor.x);
|
|
3423 else
|
|
3424 {
|
|
3425 int x, y;
|
|
3426 x = (WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos)
|
|
3427 + (INTEGERP (w->left_margin_width)
|
|
3428 ? XFASTINT (w->left_margin_width)
|
|
3429 : 0));
|
|
3430 y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos);
|
|
3431 cursor_to (y, x);
|
|
3432 }
|
|
3433
|
314
|
3434 fflush (stdout);
|
25012
|
3435 redisplay_performed_directly_p = 1;
|
314
|
3436 return 1;
|
|
3437 }
|
25012
|
3438
|
|
3439
|
314
|
3440
|
25012
|
3441 /***********************************************************************
|
|
3442 Frame Update
|
|
3443 ***********************************************************************/
|
|
3444
|
|
3445 /* Update frame F based on the data in desired matrices.
|
|
3446
|
|
3447 If FORCE_P is non-zero, don't let redisplay be stopped by detecting
|
|
3448 pending input. If INHIBIT_HAIRY_ID_P is non-zero, don't try
|
|
3449 scrolling.
|
|
3450
|
|
3451 Value is non-zero if redisplay was stopped due to pending input. */
|
314
|
3452
|
|
3453 int
|
25012
|
3454 update_frame (f, force_p, inhibit_hairy_id_p)
|
|
3455 struct frame *f;
|
|
3456 int force_p;
|
|
3457 int inhibit_hairy_id_p;
|
|
3458 {
|
|
3459 /* 1 means display has been paused because of pending input. */
|
|
3460 int paused_p;
|
|
3461 struct window *root_window = XWINDOW (f->root_window);
|
|
3462
|
|
3463 if (FRAME_WINDOW_P (f))
|
|
3464 {
|
|
3465 /* We are working on window matrix basis. All windows whose
|
|
3466 flag must_be_updated_p is set have to be updated. */
|
|
3467
|
|
3468 /* Record that we are not working on frame matrices. */
|
|
3469 set_frame_matrix_frame (NULL);
|
|
3470
|
|
3471 /* Update all windows in the window tree of F, maybe stopping
|
|
3472 when pending input is detected. */
|
|
3473 update_begin (f);
|
|
3474
|
|
3475 /* Update the menu bar on X frames that don't have toolkit
|
|
3476 support. */
|
|
3477 if (WINDOWP (f->menu_bar_window))
|
|
3478 update_window (XWINDOW (f->menu_bar_window), 1);
|
|
3479
|
|
3480 /* Update the tool-bar window, if present. */
|
25544
|
3481 if (WINDOWP (f->tool_bar_window))
|
25012
|
3482 {
|
|
3483 Lisp_Object tem;
|
25544
|
3484 struct window *w = XWINDOW (f->tool_bar_window);
|
25012
|
3485
|
|
3486 /* Update tool-bar window. */
|
|
3487 if (w->must_be_updated_p)
|
|
3488 {
|
|
3489 update_window (w, 1);
|
|
3490 w->must_be_updated_p = 0;
|
|
3491
|
|
3492 /* Swap tool-bar strings. We swap because we want to
|
|
3493 reuse strings. */
|
25544
|
3494 tem = f->current_tool_bar_string;
|
|
3495 f->current_tool_bar_string = f->desired_tool_bar_string;
|
|
3496 f->desired_tool_bar_string = tem;
|
|
3497 f->n_current_tool_bar_items = f->n_desired_tool_bar_items;
|
25012
|
3498
|
|
3499 /* Swap tool-bar items. We swap because we want to
|
|
3500 reuse vectors. */
|
25544
|
3501 tem = f->current_tool_bar_items;
|
|
3502 f->current_tool_bar_items = f->desired_tool_bar_items;
|
|
3503 f->desired_tool_bar_items = tem;
|
25012
|
3504 }
|
|
3505 }
|
|
3506
|
|
3507
|
|
3508 /* Update windows. */
|
|
3509 paused_p = update_window_tree (root_window, force_p);
|
|
3510 update_end (f);
|
|
3511 display_completed = !paused_p;
|
|
3512
|
|
3513 /* The flush is a performance bottleneck under X. */
|
|
3514 #if 0
|
|
3515 rif->flush_display (f);
|
|
3516 #endif
|
|
3517 }
|
|
3518 else
|
|
3519 {
|
|
3520 /* We are working on frame matrix basis. Set the frame on whose
|
|
3521 frame matrix we operate. */
|
|
3522 set_frame_matrix_frame (f);
|
|
3523
|
|
3524 /* Build F's desired matrix from window matrices. For windows
|
|
3525 whose must_be_updated_p flag is set, desired matrices are
|
|
3526 made part of the desired frame matrix. For other windows,
|
|
3527 the current matrix is copied. */
|
|
3528 build_frame_matrix (f);
|
|
3529
|
|
3530 /* Do the update on the frame desired matrix. */
|
|
3531 paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p);
|
|
3532
|
|
3533 /* Check window matrices for lost pointers. */
|
|
3534 IF_DEBUG (check_window_matrix_pointers (root_window));
|
|
3535 }
|
|
3536
|
|
3537 /* Reset flags indicating that a window should be updated. */
|
|
3538 set_window_update_flags (root_window, 0);
|
|
3539 return paused_p;
|
|
3540 }
|
|
3541
|
|
3542
|
|
3543
|
|
3544 /************************************************************************
|
|
3545 Window-based updates
|
|
3546 ************************************************************************/
|
|
3547
|
|
3548 /* Perform updates in window tree rooted at W. FORCE_P non-zero means
|
|
3549 don't stop updating when input is pending. */
|
|
3550
|
|
3551 static int
|
|
3552 update_window_tree (w, force_p)
|
|
3553 struct window *w;
|
|
3554 int force_p;
|
|
3555 {
|
|
3556 int paused_p = 0;
|
|
3557
|
|
3558 while (w && !paused_p)
|
|
3559 {
|
|
3560 if (!NILP (w->hchild))
|
|
3561 paused_p |= update_window_tree (XWINDOW (w->hchild), force_p);
|
|
3562 else if (!NILP (w->vchild))
|
|
3563 paused_p |= update_window_tree (XWINDOW (w->vchild), force_p);
|
|
3564 else if (w->must_be_updated_p)
|
|
3565 paused_p |= update_window (w, force_p);
|
|
3566
|
|
3567 w = NILP (w->next) ? 0 : XWINDOW (w->next);
|
|
3568 }
|
|
3569
|
|
3570 return paused_p;
|
|
3571 }
|
|
3572
|
|
3573
|
|
3574 /* Update window W if its flag must_be_updated_p is non-zero. If
|
|
3575 FORCE_P is non-zero, don't stop updating if input is pending. */
|
|
3576
|
|
3577 void
|
|
3578 update_single_window (w, force_p)
|
|
3579 struct window *w;
|
|
3580 int force_p;
|
|
3581 {
|
|
3582 if (w->must_be_updated_p)
|
|
3583 {
|
|
3584 struct frame *f = XFRAME (WINDOW_FRAME (w));
|
|
3585
|
|
3586 /* Record that this is not a frame-based redisplay. */
|
|
3587 set_frame_matrix_frame (NULL);
|
|
3588
|
|
3589 /* Update W. */
|
|
3590 update_begin (f);
|
|
3591 update_window (w, force_p);
|
|
3592 update_end (f);
|
|
3593
|
|
3594 /* Reset flag in W. */
|
|
3595 w->must_be_updated_p = 0;
|
|
3596 }
|
|
3597 }
|
|
3598
|
|
3599
|
25186
|
3600 /* Redraw lines from the current matrix of window W that are
|
|
3601 overlapped by other rows. YB is bottom-most y-position in W. */
|
|
3602
|
|
3603 static void
|
|
3604 redraw_overlapped_rows (w, yb)
|
|
3605 struct window *w;
|
|
3606 int yb;
|
|
3607 {
|
|
3608 int i, bottom_y;
|
|
3609 struct glyph_row *row;
|
|
3610
|
|
3611 /* If rows overlapping others have been changed, the rows being
|
|
3612 overlapped have to be redrawn. This won't draw lines that have
|
|
3613 already been drawn in update_window_line because overlapped_p in
|
|
3614 desired rows is 0, so after row assignment overlapped_p in
|
|
3615 current rows is 0. */
|
|
3616 for (i = 0; i < w->current_matrix->nrows; ++i)
|
|
3617 {
|
|
3618 row = w->current_matrix->rows + i;
|
|
3619
|
|
3620 if (!row->enabled_p)
|
|
3621 break;
|
|
3622 else if (row->mode_line_p)
|
|
3623 continue;
|
|
3624
|
|
3625 if (row->overlapped_p)
|
|
3626 {
|
|
3627 enum glyph_row_area area;
|
|
3628
|
|
3629 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
|
|
3630 {
|
|
3631 updated_row = row;
|
|
3632 updated_area = area;
|
|
3633 rif->cursor_to (i, 0, row->y, area == TEXT_AREA ? row->x : 0);
|
|
3634 if (row->used[area])
|
|
3635 rif->write_glyphs (row->glyphs[area], row->used[area]);
|
|
3636 rif->clear_end_of_line (-1);
|
|
3637 }
|
|
3638
|
|
3639 row->overlapped_p = 0;
|
|
3640 }
|
|
3641
|
|
3642 bottom_y = MATRIX_ROW_BOTTOM_Y (row);
|
|
3643 if (bottom_y >= yb)
|
|
3644 break;
|
|
3645 }
|
|
3646 }
|
|
3647
|
|
3648
|
|
3649 /* Redraw lines from the current matrix of window W that overlap
|
|
3650 others. YB is bottom-most y-position in W. */
|
|
3651
|
|
3652 static void
|
|
3653 redraw_overlapping_rows (w, yb)
|
|
3654 struct window *w;
|
|
3655 int yb;
|
|
3656 {
|
|
3657 int i, bottom_y;
|
|
3658 struct glyph_row *row;
|
|
3659
|
|
3660 for (i = 0; i < w->current_matrix->nrows; ++i)
|
|
3661 {
|
|
3662 row = w->current_matrix->rows + i;
|
|
3663
|
|
3664 if (!row->enabled_p)
|
|
3665 break;
|
|
3666 else if (row->mode_line_p)
|
|
3667 continue;
|
|
3668
|
|
3669 bottom_y = MATRIX_ROW_BOTTOM_Y (row);
|
|
3670
|
|
3671 if (row->overlapping_p && i > 0 && bottom_y < yb)
|
|
3672 {
|
|
3673 if (row->used[LEFT_MARGIN_AREA])
|
|
3674 rif->fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
|
|
3675
|
|
3676 if (row->used[TEXT_AREA])
|
|
3677 rif->fix_overlapping_area (w, row, TEXT_AREA);
|
|
3678
|
|
3679 if (row->used[RIGHT_MARGIN_AREA])
|
|
3680 rif->fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
|
|
3681
|
|
3682 /* Record in neighbor rows that ROW overwrites part of their
|
|
3683 display. */
|
|
3684 if (row->phys_ascent > row->ascent && i > 0)
|
|
3685 MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p = 1;
|
|
3686 if ((row->phys_height - row->phys_ascent
|
|
3687 > row->height - row->ascent)
|
|
3688 && bottom_y < yb)
|
|
3689 MATRIX_ROW (w->current_matrix, i + 1)->overlapped_p = 1;
|
|
3690 }
|
|
3691
|
|
3692 if (bottom_y >= yb)
|
|
3693 break;
|
|
3694 }
|
|
3695 }
|
|
3696
|
|
3697
|
25012
|
3698 /* Update display of window W. FORCE_P non-zero means that we should
|
|
3699 not stop when detecting pending input. */
|
|
3700
|
|
3701 static int
|
|
3702 update_window (w, force_p)
|
|
3703 struct window *w;
|
|
3704 int force_p;
|
|
3705 {
|
|
3706 struct glyph_matrix *desired_matrix = w->desired_matrix;
|
|
3707 int paused_p;
|
|
3708 int preempt_count = baud_rate / 2400 + 1;
|
|
3709 extern int input_pending;
|
25345
|
3710 #if GLYPH_DEBUG
|
|
3711 struct frame *f = XFRAME (WINDOW_FRAME (w));
|
25012
|
3712 extern struct frame *updating_frame;
|
25345
|
3713 #endif
|
25012
|
3714
|
|
3715 /* Check that W's frame doesn't have glyph matrices. */
|
|
3716 xassert (FRAME_WINDOW_P (f));
|
|
3717 xassert (updating_frame != NULL);
|
|
3718
|
|
3719 /* Check pending input the first time so that we can quickly return. */
|
|
3720 if (redisplay_dont_pause)
|
|
3721 force_p = 1;
|
|
3722 else
|
|
3723 detect_input_pending ();
|
|
3724
|
|
3725 /* If forced to complete the update, or if no input is pending, do
|
|
3726 the update. */
|
|
3727 if (force_p || !input_pending)
|
|
3728 {
|
|
3729 struct glyph_row *row, *end;
|
|
3730 struct glyph_row *mode_line_row;
|
25546
|
3731 struct glyph_row *header_line_row = NULL;
|
25186
|
3732 int yb, changed_p = 0;
|
25012
|
3733
|
|
3734 rif->update_window_begin_hook (w);
|
|
3735 yb = window_text_bottom_y (w);
|
|
3736
|
|
3737 /* If window has a top line, update it before everything else.
|
|
3738 Adjust y-positions of other rows by the top line height. */
|
|
3739 row = desired_matrix->rows;
|
|
3740 end = row + desired_matrix->nrows - 1;
|
|
3741 if (row->mode_line_p)
|
25546
|
3742 header_line_row = row++;
|
25012
|
3743
|
|
3744 /* Update the mode line, if necessary. */
|
|
3745 mode_line_row = MATRIX_MODE_LINE_ROW (desired_matrix);
|
|
3746 if (mode_line_row->mode_line_p && mode_line_row->enabled_p)
|
|
3747 {
|
|
3748 mode_line_row->y = yb;
|
|
3749 update_window_line (w, MATRIX_ROW_VPOS (mode_line_row,
|
|
3750 desired_matrix));
|
25186
|
3751 changed_p = 1;
|
25012
|
3752 }
|
|
3753
|
|
3754 /* Find first enabled row. Optimizations in redisplay_internal
|
|
3755 may lead to an update with only one row enabled. There may
|
|
3756 be also completely empty matrices. */
|
|
3757 while (row < end && !row->enabled_p)
|
|
3758 ++row;
|
|
3759
|
|
3760 /* Try reusing part of the display by inserting/deleting lines. */
|
|
3761 if (row < end && !desired_matrix->no_scrolling_p)
|
|
3762 {
|
25546
|
3763 int rc = scrolling_window (w, header_line_row != NULL);
|
25012
|
3764 if (rc < 0)
|
|
3765 {
|
|
3766 /* All rows were found to be equal. */
|
|
3767 paused_p = 0;
|
|
3768 goto set_cursor;
|
|
3769 }
|
|
3770 else if (rc > 0)
|
|
3771 force_p = 1;
|
25186
|
3772 changed_p = 1;
|
25012
|
3773 }
|
|
3774
|
|
3775 /* Update the top mode line after scrolling because a new top
|
|
3776 line would otherwise overwrite lines at the top of the window
|
|
3777 that can be scrolled. */
|
25546
|
3778 if (header_line_row && header_line_row->enabled_p)
|
25012
|
3779 {
|
25546
|
3780 header_line_row->y = 0;
|
25012
|
3781 update_window_line (w, 0);
|
25186
|
3782 changed_p = 1;
|
25012
|
3783 }
|
|
3784
|
|
3785 /* Update the rest of the lines. */
|
|
3786 for (; row < end && (force_p || !input_pending); ++row)
|
|
3787 if (row->enabled_p
|
|
3788 /* A row can be completely invisible in case a desired
|
|
3789 matrix was built with a vscroll and then
|
|
3790 make_cursor_line_fully_visible shifts the matrix. */
|
|
3791 && row->visible_height > 0)
|
|
3792 {
|
|
3793 int vpos = MATRIX_ROW_VPOS (row, desired_matrix);
|
|
3794 int i;
|
|
3795
|
|
3796 /* We'll Have to play a little bit with when to
|
|
3797 detect_input_pending. If it's done too often,
|
|
3798 scrolling large windows with repeated scroll-up
|
|
3799 commands will too quickly pause redisplay. */
|
|
3800 if (!force_p && vpos % preempt_count == 0)
|
|
3801 detect_input_pending ();
|
|
3802
|
25186
|
3803 changed_p |= update_window_line (w, vpos);
|
25012
|
3804
|
|
3805 /* Mark all rows below the last visible one in the current
|
|
3806 matrix as invalid. This is necessary because of
|
|
3807 variable line heights. Consider the case of three
|
|
3808 successive redisplays, where the first displays 5
|
|
3809 lines, the second 3 lines, and the third 5 lines again.
|
|
3810 If the second redisplay wouldn't mark rows in the
|
|
3811 current matrix invalid, the third redisplay might be
|
|
3812 tempted to optimize redisplay based on lines displayed
|
|
3813 in the first redisplay. */
|
|
3814 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
|
|
3815 for (i = vpos + 1; i < w->current_matrix->nrows - 1; ++i)
|
|
3816 MATRIX_ROW (w->current_matrix, i)->enabled_p = 0;
|
|
3817 }
|
|
3818
|
|
3819 /* Was display preempted? */
|
|
3820 paused_p = row < end;
|
|
3821
|
|
3822 set_cursor:
|
|
3823
|
25186
|
3824 /* Fix the appearance of overlapping(overlapped rows. */
|
|
3825 if (rif->fix_overlapping_area
|
|
3826 && !w->pseudo_window_p
|
|
3827 && changed_p
|
|
3828 && !paused_p)
|
|
3829 {
|
|
3830 redraw_overlapped_rows (w, yb);
|
|
3831 redraw_overlapping_rows (w, yb);
|
|
3832 }
|
|
3833
|
25012
|
3834 if (!paused_p && !w->pseudo_window_p)
|
|
3835 {
|
|
3836 /* Make cursor visible at cursor position of W. */
|
|
3837 set_window_cursor_after_update (w);
|
|
3838
|
|
3839 #if 0
|
|
3840 /* Check that current matrix invariants are satisfied. This
|
|
3841 is for debugging only. See the comment around
|
|
3842 check_matrix_invariants. */
|
|
3843 IF_DEBUG (check_matrix_invariants (w));
|
|
3844 #endif
|
|
3845 }
|
|
3846
|
|
3847 #if GLYPH_DEBUG
|
|
3848 /* Remember the redisplay method used to display the matrix. */
|
|
3849 strcpy (w->current_matrix->method, w->desired_matrix->method);
|
|
3850 #endif
|
25186
|
3851
|
25012
|
3852 /* End of update of window W. */
|
|
3853 rif->update_window_end_hook (w, 1);
|
25186
|
3854
|
25012
|
3855 }
|
|
3856 else
|
|
3857 paused_p = 1;
|
|
3858
|
|
3859 clear_glyph_matrix (desired_matrix);
|
25186
|
3860
|
25012
|
3861 return paused_p;
|
|
3862 }
|
|
3863
|
|
3864
|
|
3865 /* Update the display of area AREA in window W, row number VPOS.
|
|
3866 AREA can be either LEFT_MARGIN_AREA or RIGHT_MARGIN_AREA. */
|
|
3867
|
|
3868 static void
|
|
3869 update_marginal_area (w, area, vpos)
|
|
3870 struct window *w;
|
|
3871 int area, vpos;
|
|
3872 {
|
|
3873 struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
|
|
3874
|
|
3875 /* Let functions in xterm.c know what area subsequent X positions
|
|
3876 will be relative to. */
|
|
3877 updated_area = area;
|
|
3878
|
|
3879 /* Set cursor to start of glyphs, write them, and clear to the end
|
|
3880 of the area. I don't think that something more sophisticated is
|
|
3881 necessary here, since marginal areas will not be the default. */
|
|
3882 rif->cursor_to (vpos, 0, desired_row->y, 0);
|
|
3883 if (desired_row->used[area])
|
|
3884 rif->write_glyphs (desired_row->glyphs[area], desired_row->used[area]);
|
|
3885 rif->clear_end_of_line (-1);
|
|
3886 }
|
|
3887
|
|
3888
|
25186
|
3889 /* Update the display of the text area of row VPOS in window W.
|
|
3890 Value is non-zero if display has changed. */
|
|
3891
|
|
3892 static int
|
25012
|
3893 update_text_area (w, vpos)
|
|
3894 struct window *w;
|
|
3895 int vpos;
|
314
|
3896 {
|
25012
|
3897 struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
|
|
3898 struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
|
25186
|
3899 int changed_p = 0;
|
25012
|
3900
|
|
3901 /* Let functions in xterm.c know what area subsequent X positions
|
|
3902 will be relative to. */
|
|
3903 updated_area = TEXT_AREA;
|
|
3904
|
|
3905 /* If rows are at different X or Y, or rows have different height,
|
|
3906 or the current row is marked invalid, write the entire line. */
|
|
3907 if (!current_row->enabled_p
|
|
3908 || desired_row->y != current_row->y
|
|
3909 || desired_row->ascent != current_row->ascent
|
25186
|
3910 || desired_row->phys_ascent != current_row->phys_ascent
|
|
3911 || desired_row->phys_height != current_row->phys_height
|
25012
|
3912 || desired_row->visible_height != current_row->visible_height
|
25186
|
3913 || current_row->overlapped_p
|
25012
|
3914 || current_row->x != desired_row->x)
|
|
3915 {
|
|
3916 rif->cursor_to (vpos, 0, desired_row->y, desired_row->x);
|
|
3917
|
|
3918 if (desired_row->used[TEXT_AREA])
|
|
3919 rif->write_glyphs (desired_row->glyphs[TEXT_AREA],
|
|
3920 desired_row->used[TEXT_AREA]);
|
|
3921
|
|
3922 /* Clear to end of window. */
|
|
3923 rif->clear_end_of_line (-1);
|
25186
|
3924 changed_p = 1;
|
25012
|
3925 }
|
|
3926 else
|
|
3927 {
|
|
3928 int stop, i, x;
|
|
3929 struct glyph *current_glyph = current_row->glyphs[TEXT_AREA];
|
|
3930 struct glyph *desired_glyph = desired_row->glyphs[TEXT_AREA];
|
|
3931
|
|
3932 /* If the desired row extends its face to the text area end,
|
|
3933 make sure we write at least one glyph, so that the face
|
|
3934 extension actually takes place. */
|
|
3935 int desired_stop_pos = (desired_row->used[TEXT_AREA]
|
|
3936 - (MATRIX_ROW_EXTENDS_FACE_P (desired_row)
|
|
3937 ? 1 : 0));
|
|
3938
|
|
3939 stop = min (current_row->used[TEXT_AREA], desired_stop_pos);
|
|
3940 i = 0;
|
|
3941 x = desired_row->x;
|
|
3942
|
|
3943 while (i < stop)
|
|
3944 {
|
|
3945 /* Skip over glyphs that both rows have in common. These
|
|
3946 don't have to be written. */
|
|
3947 while (i < stop
|
|
3948 && GLYPH_EQUAL_P (desired_glyph, current_glyph))
|
|
3949 {
|
|
3950 x += desired_glyph->pixel_width;
|
|
3951 ++desired_glyph, ++current_glyph, ++i;
|
|
3952 }
|
|
3953
|
|
3954 /* Consider the case that the current row contains "xxx ppp
|
|
3955 ggg" in italic Courier font, and the desired row is "xxx
|
|
3956 ggg". The character `p' has lbearing, `g' has not. The
|
|
3957 loop above will stop in front of the first `p' in the
|
|
3958 current row. If we would start writing glyphs there, we
|
|
3959 wouldn't erase the lbearing of the `p'. The rest of the
|
|
3960 lbearing problem is then taken care of by x_draw_glyphs. */
|
|
3961 if (current_row->contains_overlapping_glyphs_p
|
|
3962 && i > 0
|
|
3963 && i < current_row->used[TEXT_AREA]
|
|
3964 && current_row->used[TEXT_AREA] != desired_row->used[TEXT_AREA])
|
|
3965 {
|
|
3966 int left, right;
|
|
3967 rif->get_glyph_overhangs (current_glyph, XFRAME (w->frame),
|
|
3968 &left, &right);
|
|
3969 while (left > 0 && i > 0)
|
|
3970 {
|
|
3971 --i, --desired_glyph, --current_glyph;
|
|
3972 x -= desired_glyph->pixel_width;
|
|
3973 left -= desired_glyph->pixel_width;
|
|
3974 }
|
|
3975 }
|
|
3976
|
|
3977 /* Try to avoid writing the entire rest of the desired row
|
|
3978 by looking for a resync point. This mainly prevents
|
|
3979 mode line flickering in the case the mode line is in
|
|
3980 fixed-pitch font, which it usually will be. */
|
|
3981 if (i < desired_row->used[TEXT_AREA])
|
|
3982 {
|
|
3983 int start_x = x, start_hpos = i;
|
|
3984 struct glyph *start = desired_glyph;
|
|
3985 int current_x = x;
|
|
3986
|
|
3987 /* Find the next glyph that's equal again. */
|
|
3988 while (i < stop
|
|
3989 && !GLYPH_EQUAL_P (desired_glyph, current_glyph)
|
|
3990 && x == current_x)
|
|
3991 {
|
|
3992 x += desired_glyph->pixel_width;
|
|
3993 current_x += current_glyph->pixel_width;
|
|
3994 ++desired_glyph, ++current_glyph, ++i;
|
|
3995 }
|
|
3996
|
|
3997 if (i == start_hpos || x != current_x)
|
|
3998 {
|
|
3999 i = start_hpos;
|
|
4000 x = start_x;
|
|
4001 desired_glyph = start;
|
|
4002 break;
|
|
4003 }
|
|
4004
|
|
4005 rif->cursor_to (vpos, start_hpos, desired_row->y, start_x);
|
|
4006 rif->write_glyphs (start, i - start_hpos);
|
25186
|
4007 changed_p = 1;
|
25012
|
4008 }
|
|
4009 }
|
|
4010
|
|
4011 /* Write the rest. */
|
|
4012 if (i < desired_row->used[TEXT_AREA])
|
|
4013 {
|
|
4014 rif->cursor_to (vpos, i, desired_row->y, x);
|
|
4015 rif->write_glyphs (desired_glyph, desired_row->used[TEXT_AREA] - i);
|
25186
|
4016 changed_p = 1;
|
25012
|
4017 }
|
|
4018
|
|
4019 /* Maybe clear to end of line. */
|
|
4020 if (MATRIX_ROW_EXTENDS_FACE_P (desired_row))
|
|
4021 {
|
|
4022 /* If new row extends to the end of the text area, nothing
|
|
4023 has to be cleared, if and only if we did a write_glyphs
|
|
4024 above. This is made sure by setting desired_stop_pos
|
|
4025 appropriately above. */
|
|
4026 xassert (i < desired_row->used[TEXT_AREA]);
|
|
4027 }
|
|
4028 else if (MATRIX_ROW_EXTENDS_FACE_P (current_row))
|
|
4029 {
|
|
4030 /* If old row extends to the end of the text area, clear. */
|
|
4031 if (i >= desired_row->used[TEXT_AREA])
|
|
4032 rif->cursor_to (vpos, i, desired_row->y,
|
|
4033 desired_row->x + desired_row->pixel_width);
|
|
4034 rif->clear_end_of_line (-1);
|
25186
|
4035 changed_p = 1;
|
25012
|
4036 }
|
|
4037 else if (desired_row->pixel_width < current_row->pixel_width)
|
|
4038 {
|
|
4039 /* Otherwise clear to the end of the old row. Everything
|
|
4040 after that position should be clear already. */
|
|
4041 int x;
|
|
4042
|
|
4043 if (i >= desired_row->used[TEXT_AREA])
|
|
4044 rif->cursor_to (vpos, i, desired_row->y,
|
|
4045 desired_row->x + desired_row->pixel_width);
|
|
4046
|
|
4047 /* If cursor is displayed at the end of the line, make sure
|
|
4048 it's cleared. Nowadays we don't have a phys_cursor_glyph
|
|
4049 with which to erase the cursor (because this method
|
|
4050 doesn't work with lbearing/rbearing), so we must do it
|
|
4051 this way. */
|
|
4052 if (vpos == w->phys_cursor.vpos
|
|
4053 && w->phys_cursor.hpos >= desired_row->used[TEXT_AREA])
|
|
4054 {
|
|
4055 w->phys_cursor_on_p = 0;
|
|
4056 x = -1;
|
|
4057 }
|
|
4058 else
|
|
4059 x = current_row->x + current_row->pixel_width;
|
|
4060 rif->clear_end_of_line (x);
|
25186
|
4061 changed_p = 1;
|
25012
|
4062 }
|
|
4063 }
|
25186
|
4064
|
|
4065 return changed_p;
|
25012
|
4066 }
|
|
4067
|
|
4068
|
25186
|
4069 /* Update row VPOS in window W. Value is non-zero if display has been
|
|
4070 changed. */
|
|
4071
|
|
4072 static int
|
25012
|
4073 update_window_line (w, vpos)
|
|
4074 struct window *w;
|
|
4075 int vpos;
|
|
4076 {
|
|
4077 struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
|
|
4078 struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
|
25186
|
4079 int changed_p = 0;
|
25012
|
4080
|
|
4081 xassert (desired_row->enabled_p);
|
|
4082
|
|
4083 /* Set the row being updated. This is important to let xterm.c
|
|
4084 know what line height values are in effect. */
|
|
4085 updated_row = desired_row;
|
|
4086
|
|
4087 /* Update display of the left margin area, if there is one. */
|
|
4088 if (!desired_row->full_width_p
|
|
4089 && !NILP (w->left_margin_width))
|
25186
|
4090 {
|
|
4091 update_marginal_area (w, LEFT_MARGIN_AREA, vpos);
|
|
4092 changed_p = 1;
|
|
4093 }
|
25012
|
4094
|
|
4095 /* Update the display of the text area. */
|
25186
|
4096 changed_p |= update_text_area (w, vpos);
|
25012
|
4097
|
|
4098 /* Update display of the right margin area, if there is one. */
|
|
4099 if (!desired_row->full_width_p
|
|
4100 && !NILP (w->right_margin_width))
|
25186
|
4101 {
|
|
4102 changed_p = 1;
|
|
4103 update_marginal_area (w, RIGHT_MARGIN_AREA, vpos);
|
|
4104 }
|
25012
|
4105
|
|
4106 /* Draw truncation marks etc. */
|
|
4107 if (!current_row->enabled_p
|
|
4108 || desired_row->y != current_row->y
|
|
4109 || desired_row->visible_height != current_row->visible_height
|
|
4110 || desired_row->overlay_arrow_p != current_row->overlay_arrow_p
|
|
4111 || desired_row->truncated_on_left_p != current_row->truncated_on_left_p
|
|
4112 || desired_row->truncated_on_right_p != current_row->truncated_on_right_p
|
|
4113 || desired_row->continued_p != current_row->continued_p
|
|
4114 || desired_row->mode_line_p != current_row->mode_line_p
|
|
4115 || (desired_row->indicate_empty_line_p
|
|
4116 != current_row->indicate_empty_line_p)
|
|
4117 || (MATRIX_ROW_CONTINUATION_LINE_P (desired_row)
|
|
4118 != MATRIX_ROW_CONTINUATION_LINE_P (current_row)))
|
|
4119 rif->after_update_window_line_hook (desired_row);
|
|
4120
|
|
4121 /* Update current_row from desired_row. */
|
|
4122 make_current (w->desired_matrix, w->current_matrix, vpos);
|
|
4123 updated_row = NULL;
|
25186
|
4124 return changed_p;
|
25012
|
4125 }
|
|
4126
|
|
4127
|
|
4128 /* Set the cursor after an update of window W. This function may only
|
|
4129 be called from update_window. */
|
|
4130
|
|
4131 static void
|
|
4132 set_window_cursor_after_update (w)
|
|
4133 struct window *w;
|
|
4134 {
|
|
4135 struct frame *f = XFRAME (w->frame);
|
|
4136 int cx, cy, vpos, hpos;
|
|
4137
|
|
4138 /* Not intended for frame matrix updates. */
|
|
4139 xassert (FRAME_WINDOW_P (f));
|
|
4140
|
25345
|
4141 if (cursor_in_echo_area
|
|
4142 && !NILP (echo_area_buffer[0])
|
|
4143 /* If we are showing a message instead of the mini-buffer,
|
|
4144 show the cursor for the message instead. */
|
|
4145 && XWINDOW (minibuf_window) == w
|
|
4146 && EQ (minibuf_window, echo_area_window)
|
25012
|
4147 /* These cases apply only to the frame that contains
|
|
4148 the active mini-buffer window. */
|
|
4149 && FRAME_HAS_MINIBUF_P (f)
|
|
4150 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
|
|
4151 {
|
|
4152 cx = cy = vpos = hpos = 0;
|
|
4153
|
|
4154 if (cursor_in_echo_area >= 0)
|
|
4155 {
|
|
4156 /* If the mini-buffer is several lines high, find the last
|
|
4157 line that has any text on it. Note: either all lines
|
|
4158 are enabled or none. Otherwise we wouldn't be able to
|
|
4159 determine Y. */
|
25190
|
4160 struct glyph_row *row, *last_row;
|
|
4161 struct glyph *glyph;
|
|
4162 int yb = window_text_bottom_y (w);
|
|
4163
|
|
4164 last_row = NULL;
|
25345
|
4165 for (row = MATRIX_ROW (w->current_matrix, 0);
|
|
4166 row->enabled_p;
|
|
4167 ++row)
|
25012
|
4168 {
|
25190
|
4169 if (row->used[TEXT_AREA]
|
|
4170 && row->glyphs[TEXT_AREA][0].charpos >= 0)
|
|
4171 last_row = row;
|
|
4172
|
|
4173 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
|
|
4174 break;
|
25012
|
4175 }
|
25190
|
4176
|
25012
|
4177 if (last_row)
|
|
4178 {
|
25190
|
4179 struct glyph *start = row->glyphs[TEXT_AREA];
|
25345
|
4180 struct glyph *last = start + row->used[TEXT_AREA] - 1;
|
|
4181
|
|
4182 while (last > start && last->charpos < 0)
|
25190
|
4183 --last;
|
|
4184
|
|
4185 for (glyph = start; glyph < last; ++glyph)
|
|
4186 {
|
|
4187 cx += glyph->pixel_width;
|
|
4188 ++hpos;
|
|
4189 }
|
|
4190
|
25012
|
4191 cy = last_row->y;
|
25190
|
4192 vpos = MATRIX_ROW_VPOS (last_row, w->current_matrix);
|
25012
|
4193 }
|
|
4194 }
|
|
4195 }
|
|
4196 else
|
|
4197 {
|
|
4198 cx = w->cursor.x;
|
|
4199 cy = w->cursor.y;
|
|
4200 hpos = w->cursor.hpos;
|
|
4201 vpos = w->cursor.vpos;
|
|
4202 }
|
|
4203
|
|
4204 /* Window cursor can be out of sync for horizontally split windows. */
|
|
4205 hpos = max (0, hpos);
|
|
4206 hpos = min (w->current_matrix->matrix_w - 1, hpos);
|
|
4207 vpos = max (0, vpos);
|
|
4208 vpos = min (w->current_matrix->nrows - 1, vpos);
|
|
4209 rif->cursor_to (vpos, hpos, cy, cx);
|
|
4210 }
|
|
4211
|
|
4212
|
|
4213 /* Try to reuse part of the current display of W by scrolling lines.
|
25546
|
4214 HEADER_LINE_P non-zero means W has a top mode line.
|
25012
|
4215
|
|
4216 The algorithm is taken from Communications of the ACM, Apr78 "A
|
|
4217 Technique for Isolating Differences Between Files." It should take
|
|
4218 O(N) time.
|
|
4219
|
|
4220 A short outline of the steps of the algorithm
|
|
4221
|
|
4222 1. Skip lines equal at the start and end of both matrices.
|
|
4223
|
|
4224 2. Enter rows in the current and desired matrix into a symbol
|
|
4225 table, counting how often they appear in both matrices.
|
|
4226
|
|
4227 3. Rows that appear exactly once in both matrices serve as anchors,
|
|
4228 i.e. we assume that such lines are likely to have been moved.
|
|
4229
|
|
4230 4. Starting from anchor lines, extend regions to be scrolled both
|
|
4231 forward and backward.
|
|
4232
|
|
4233 Value is
|
|
4234
|
|
4235 -1 if all rows were found to be equal.
|
|
4236 0 to indicate that we did not scroll the display, or
|
|
4237 1 if we did scroll. */
|
|
4238
|
|
4239 static int
|
25546
|
4240 scrolling_window (w, header_line_p)
|
25012
|
4241 struct window *w;
|
25546
|
4242 int header_line_p;
|
25012
|
4243 {
|
|
4244 struct symbol
|
|
4245 {
|
|
4246 /* Number of occurrences of this line in old and new matrix. */
|
|
4247 short old_uses, new_uses;
|
|
4248
|
|
4249 /* Vpos of line in new matrix. */
|
|
4250 short new_line_number;
|
|
4251
|
|
4252 /* The line itself. */
|
|
4253 struct glyph_row *row;
|
|
4254
|
|
4255 /* Hash collision chain. */
|
|
4256 struct symbol *next;
|
|
4257 };
|
|
4258
|
|
4259 int SYMBOL_TABLE_SIZE = 101;
|
|
4260 struct symbol **table;
|
|
4261 struct symbol **old_line_syms, **new_line_syms;
|
|
4262 int i, j, first_old, first_new, last_old, last_new;
|
|
4263 struct symbol *sym;
|
|
4264 struct run **runs;
|
|
4265 int nruns;
|
|
4266 struct glyph_matrix *desired_matrix = w->desired_matrix;
|
|
4267 struct glyph_matrix *current_matrix = w->current_matrix;
|
|
4268 int yb = window_text_bottom_y (w);
|
|
4269
|
|
4270 /* Skip over rows equal at the start. */
|
25546
|
4271 i = header_line_p ? 1 : 0;
|
25012
|
4272 while (i < current_matrix->nrows - 1
|
|
4273 && MATRIX_ROW_ENABLED_P (current_matrix, i)
|
|
4274 && MATRIX_ROW_ENABLED_P (desired_matrix, i)
|
|
4275 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (desired_matrix, i)) < yb
|
|
4276 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i)) < yb
|
|
4277 && row_equal_p (w,
|
|
4278 MATRIX_ROW (desired_matrix, i),
|
|
4279 MATRIX_ROW (current_matrix, i)))
|
|
4280 {
|
|
4281 assign_row (MATRIX_ROW (current_matrix, i),
|
|
4282 MATRIX_ROW (desired_matrix, i));
|
|
4283 MATRIX_ROW (desired_matrix, i)->enabled_p = 0;
|
|
4284 ++i;
|
|
4285 }
|
|
4286
|
|
4287 /* Give up if some rows in the desired matrix are not enabled. */
|
|
4288 if (!MATRIX_ROW (desired_matrix, i)->enabled_p)
|
|
4289 return -1;
|
|
4290
|
|
4291 first_old = first_new = i;
|
|
4292
|
|
4293 /* Set last_new to the index + 1 of the last enabled row in the
|
|
4294 desired matrix. */
|
|
4295 i = first_new + 1;
|
|
4296 while (i < desired_matrix->nrows - 1
|
|
4297 && MATRIX_ROW (desired_matrix, i)->enabled_p
|
|
4298 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (desired_matrix, i)) < yb)
|
|
4299 ++i;
|
|
4300
|
|
4301 if (!MATRIX_ROW (desired_matrix, i)->enabled_p)
|
|
4302 return 0;
|
|
4303
|
|
4304 last_new = i;
|
|
4305
|
|
4306 /* Set last_old to the index + 1 of the last enabled row in the
|
|
4307 current matrix. We don't look at the enabled flag here because
|
|
4308 we plan to reuse part of the display even if other parts are
|
|
4309 disabled. */
|
|
4310 i = first_old + 1;
|
|
4311 while (i < current_matrix->nrows - 1
|
|
4312 && MATRIX_ROW_BOTTOM_Y (MATRIX_ROW (current_matrix, i)) < yb)
|
|
4313 ++i;
|
|
4314 last_old = i;
|
|
4315
|
|
4316 /* Skip over rows equal at the bottom. */
|
|
4317 i = last_new;
|
|
4318 j = last_old;
|
|
4319 while (i - 1 > first_new
|
|
4320 && j - 1 > first_old
|
|
4321 && MATRIX_ROW (current_matrix, i - 1)->enabled_p
|
|
4322 && (MATRIX_ROW (current_matrix, i - 1)->y
|
|
4323 == MATRIX_ROW (desired_matrix, j - 1)->y)
|
|
4324 && row_equal_p (w,
|
|
4325 MATRIX_ROW (desired_matrix, i - 1),
|
|
4326 MATRIX_ROW (current_matrix, j - 1)))
|
|
4327 --i, --j;
|
|
4328 last_new = i;
|
|
4329 last_old = j;
|
|
4330
|
|
4331 /* Nothing to do if all rows are equal. */
|
|
4332 if (last_new == first_new)
|
|
4333 return 0;
|
|
4334
|
|
4335 /* Allocate a hash table in which all rows will be inserted. */
|
|
4336 table = (struct symbol **) alloca (SYMBOL_TABLE_SIZE * sizeof *table);
|
|
4337 bzero (table, SYMBOL_TABLE_SIZE * sizeof *table);
|
|
4338
|
|
4339 /* For each row in the current matrix, record the symbol belonging
|
|
4340 to the row in OLD_LINE_SYMS. */
|
|
4341 old_line_syms = (struct symbol **) alloca (current_matrix->nrows
|
|
4342 * sizeof *old_line_syms);
|
|
4343 new_line_syms = (struct symbol **) alloca (desired_matrix->nrows
|
|
4344 * sizeof *new_line_syms);
|
|
4345
|
|
4346 #define ADDSYM(ROW) \
|
|
4347 do \
|
|
4348 { \
|
|
4349 struct glyph_row *row_ = (ROW); \
|
|
4350 int i_ = row_->hash % SYMBOL_TABLE_SIZE; \
|
|
4351 sym = table[i_]; \
|
|
4352 while (sym && !row_equal_p (w, sym->row, row_)) \
|
|
4353 sym = sym->next; \
|
|
4354 if (sym == NULL) \
|
|
4355 { \
|
|
4356 sym = (struct symbol *) alloca (sizeof *sym); \
|
|
4357 sym->row = row_; \
|
|
4358 sym->old_uses = sym->new_uses = 0; \
|
|
4359 sym->next = table[i_]; \
|
|
4360 table[i_] = sym; \
|
|
4361 } \
|
|
4362 } \
|
|
4363 while (0)
|
|
4364
|
|
4365 /* Add current rows to the symbol table. */
|
|
4366 for (i = first_old; i < last_old; ++i)
|
|
4367 {
|
|
4368 if (MATRIX_ROW (current_matrix, i)->enabled_p)
|
|
4369 {
|
|
4370 ADDSYM (MATRIX_ROW (current_matrix, i));
|
|
4371 old_line_syms[i] = sym;
|
|
4372 ++sym->old_uses;
|
|
4373 }
|
|
4374 else
|
|
4375 old_line_syms[i] = NULL;
|
|
4376 }
|
|
4377
|
|
4378 /* Add desired rows to the symbol table. */
|
|
4379 for (i = first_new; i < last_new; ++i)
|
|
4380 {
|
|
4381 xassert (MATRIX_ROW_ENABLED_P (desired_matrix, i));
|
|
4382 ADDSYM (MATRIX_ROW (desired_matrix, i));
|
|
4383 ++sym->new_uses;
|
|
4384 new_line_syms[i] = sym;
|
|
4385 sym->new_line_number = i;
|
|
4386 }
|
|
4387
|
|
4388 #undef ADDSYM
|
|
4389
|
|
4390 /* Record in runs which moves were found, ordered by pixel
|
|
4391 height of copied areas. */
|
|
4392 nruns = 0;
|
|
4393 runs = (struct run **) alloca (desired_matrix->nrows * sizeof *runs);
|
|
4394
|
|
4395 /* Identify moves based on lines that are unique and equal
|
|
4396 in both matrices. */
|
|
4397 for (i = first_old; i < last_old;)
|
|
4398 if (old_line_syms[i]
|
|
4399 && old_line_syms[i]->old_uses == 1
|
|
4400 && old_line_syms[i]->new_uses == 1)
|
|
4401 {
|
|
4402 int j, k;
|
|
4403 int new_line = old_line_syms[i]->new_line_number;
|
|
4404 struct run *run = (struct run *) alloca (sizeof *run);
|
|
4405
|
|
4406 /* Record move. */
|
|
4407 run->current_vpos = i;
|
|
4408 run->current_y = MATRIX_ROW (current_matrix, i)->y;
|
|
4409 run->desired_vpos = new_line;
|
|
4410 run->desired_y = MATRIX_ROW (desired_matrix, new_line)->y;
|
|
4411 run->nrows = 1;
|
|
4412 run->height = MATRIX_ROW (current_matrix, i)->height;
|
|
4413
|
|
4414 /* Extend backward. */
|
|
4415 j = i - 1;
|
|
4416 k = new_line - 1;
|
|
4417 while (j > first_old
|
|
4418 && k > first_new
|
|
4419 && old_line_syms[j] == new_line_syms[k])
|
|
4420 {
|
|
4421 int h = MATRIX_ROW (current_matrix, j)->height;
|
|
4422 --run->current_vpos;
|
|
4423 --run->desired_vpos;
|
|
4424 ++run->nrows;
|
|
4425 run->height += h;
|
|
4426 run->desired_y -= h;
|
|
4427 run->current_y -= h;
|
|
4428 --j, --k;
|
|
4429 }
|
|
4430
|
|
4431 /* Extend forward. */
|
|
4432 j = i + 1;
|
|
4433 k = new_line + 1;
|
|
4434 while (j < last_old
|
|
4435 && k < last_new
|
|
4436 && old_line_syms[j] == new_line_syms[k])
|
|
4437 {
|
|
4438 int h = MATRIX_ROW (current_matrix, j)->height;
|
|
4439 ++run->nrows;
|
|
4440 run->height += h;
|
|
4441 ++j, ++k;
|
|
4442 }
|
|
4443
|
|
4444 /* Insert run into list of all runs. Order runs by copied
|
|
4445 pixel lines. Note that we record runs that don't have to
|
|
4446 be copied because they are already in place. This is done
|
|
4447 because we can avoid calling update_window_line in this
|
|
4448 case. */
|
|
4449 for (j = 0; j < nruns && runs[j]->height > run->height; ++j)
|
|
4450 ;
|
|
4451 for (k = nruns; k >= j; --k)
|
|
4452 runs[k] = runs[k - 1];
|
|
4453 runs[j] = run;
|
|
4454 ++nruns;
|
|
4455
|
|
4456 i += run->nrows;
|
|
4457 }
|
|
4458 else
|
|
4459 ++i;
|
|
4460
|
|
4461 /* Do the moves. Do it in a way that we don't overwrite something
|
|
4462 we want to copy later on. This is not solvable in general
|
|
4463 because there is only one display and we don't have a way to
|
|
4464 exchange areas on this display. Example:
|
|
4465
|
|
4466 +-----------+ +-----------+
|
|
4467 | A | | B |
|
|
4468 +-----------+ --> +-----------+
|
|
4469 | B | | A |
|
|
4470 +-----------+ +-----------+
|
|
4471
|
|
4472 Instead, prefer bigger moves, and invalidate moves that would
|
|
4473 copy from where we copied to. */
|
|
4474
|
|
4475 for (i = 0; i < nruns; ++i)
|
|
4476 if (runs[i]->nrows > 0)
|
|
4477 {
|
|
4478 struct run *r = runs[i];
|
|
4479
|
|
4480 /* Copy on the display. */
|
|
4481 if (r->current_y != r->desired_y)
|
|
4482 {
|
|
4483 rif->scroll_run_hook (w, r);
|
|
4484
|
|
4485 /* Invalidate runs that copy from where we copied to. */
|
|
4486 for (j = i + 1; j < nruns; ++j)
|
|
4487 {
|
|
4488 struct run *p = runs[j];
|
|
4489
|
|
4490 if ((p->current_y >= r->desired_y
|
|
4491 && p->current_y < r->desired_y + r->height)
|
|
4492 || (p->current_y + p->height >= r->desired_y
|
|
4493 && (p->current_y + p->height
|
|
4494 < r->desired_y + r->height)))
|
|
4495 p->nrows = 0;
|
|
4496 }
|
|
4497 }
|
|
4498
|
|
4499 /* Assign matrix rows. */
|
|
4500 for (j = 0; j < r->nrows; ++j)
|
|
4501 {
|
|
4502 struct glyph_row *from, *to;
|
25186
|
4503 int to_overlapped_p;
|
|
4504
|
25012
|
4505 to = MATRIX_ROW (current_matrix, r->desired_vpos + j);
|
25186
|
4506 to_overlapped_p = to->overlapped_p;
|
25012
|
4507 from = MATRIX_ROW (desired_matrix, r->desired_vpos + j);
|
|
4508 assign_row (to, from);
|
|
4509 to->enabled_p = 1, from->enabled_p = 0;
|
25186
|
4510 to->overlapped_p = to_overlapped_p;
|
25012
|
4511 }
|
|
4512 }
|
|
4513
|
|
4514 /* Value is non-zero to indicate that we scrolled the display. */
|
|
4515 return 1;
|
|
4516 }
|
|
4517
|
|
4518
|
|
4519 /* Set WINDOW->must_be_updated_p TO ON_P for all windows WINDOW in the
|
|
4520 window tree rooted at W. */
|
|
4521
|
|
4522 void
|
|
4523 set_window_update_flags (w, on_p)
|
|
4524 struct window *w;
|
|
4525 int on_p;
|
|
4526 {
|
|
4527 while (w)
|
|
4528 {
|
|
4529 if (!NILP (w->hchild))
|
|
4530 set_window_update_flags (XWINDOW (w->hchild), on_p);
|
|
4531 else if (!NILP (w->vchild))
|
|
4532 set_window_update_flags (XWINDOW (w->vchild), on_p);
|
|
4533 else
|
|
4534 w->must_be_updated_p = on_p;
|
|
4535
|
|
4536 w = NILP (w->next) ? 0 : XWINDOW (w->next);
|
|
4537 }
|
|
4538 }
|
|
4539
|
|
4540
|
|
4541
|
|
4542 /************************************************************************
|
|
4543 Frame-Based Updates
|
|
4544 ************************************************************************/
|
|
4545
|
|
4546 /* Update the desired frame matrix of frame F.
|
|
4547
|
|
4548 FORCE_P non-zero means that the update should not be stopped by
|
|
4549 pending input. INHIBIT_HAIRY_ID_P non-zero means that scrolling
|
|
4550 should not be tried.
|
|
4551
|
|
4552 Value is non-zero if update was stopped due to pending input. */
|
|
4553
|
|
4554 static int
|
|
4555 update_frame_1 (f, force_p, inhibit_id_p)
|
|
4556 struct frame *f;
|
|
4557 int force_p;
|
|
4558 int inhibit_id_p;
|
|
4559 {
|
|
4560 /* Frame matrices to work on. */
|
|
4561 struct glyph_matrix *current_matrix = f->current_matrix;
|
|
4562 struct glyph_matrix *desired_matrix = f->desired_matrix;
|
|
4563 int i;
|
314
|
4564 int pause;
|
|
4565 int preempt_count = baud_rate / 2400 + 1;
|
21514
|
4566 extern int input_pending;
|
25012
|
4567
|
|
4568 xassert (current_matrix && desired_matrix);
|
314
|
4569
|
10122
|
4570 if (baud_rate != FRAME_COST_BAUD_RATE (f))
|
|
4571 calculate_costs (f);
|
|
4572
|
3357
|
4573 if (preempt_count <= 0)
|
|
4574 preempt_count = 1;
|
|
4575
|
314
|
4576 detect_input_pending ();
|
25012
|
4577 if (input_pending && !force_p)
|
314
|
4578 {
|
|
4579 pause = 1;
|
|
4580 goto do_pause;
|
|
4581 }
|
|
4582
|
764
|
4583 update_begin (f);
|
314
|
4584
|
25012
|
4585 /* If we cannot insert/delete lines, it's no use trying it. */
|
314
|
4586 if (!line_ins_del_ok)
|
25012
|
4587 inhibit_id_p = 1;
|
7188
|
4588
|
493
|
4589 /* See if any of the desired lines are enabled; don't compute for
|
25012
|
4590 i/d line if just want cursor motion. */
|
|
4591 for (i = 0; i < desired_matrix->nrows; i++)
|
|
4592 if (MATRIX_ROW_ENABLED_P (desired_matrix, i))
|
314
|
4593 break;
|
|
4594
|
|
4595 /* Try doing i/d line, if not yet inhibited. */
|
25012
|
4596 if (!inhibit_id_p && i < desired_matrix->nrows)
|
|
4597 force_p |= scrolling (f);
|
314
|
4598
|
|
4599 /* Update the individual lines as needed. Do bottom line first. */
|
25012
|
4600 if (MATRIX_ROW_ENABLED_P (desired_matrix, desired_matrix->nrows - 1))
|
|
4601 update_frame_line (f, desired_matrix->nrows - 1);
|
|
4602
|
|
4603 /* Now update the rest of the lines. */
|
|
4604 for (i = 0; i < desired_matrix->nrows - 1 && (force_p || !input_pending); i++)
|
314
|
4605 {
|
25012
|
4606 if (MATRIX_ROW_ENABLED_P (desired_matrix, i))
|
314
|
4607 {
|
960
|
4608 if (FRAME_TERMCAP_P (f))
|
314
|
4609 {
|
|
4610 /* Flush out every so many lines.
|
|
4611 Also flush out if likely to have more than 1k buffered
|
|
4612 otherwise. I'm told that some telnet connections get
|
|
4613 really screwed by more than 1k output at once. */
|
|
4614 int outq = PENDING_OUTPUT_COUNT (stdout);
|
|
4615 if (outq > 900
|
|
4616 || (outq > 20 && ((i - 1) % preempt_count == 0)))
|
|
4617 {
|
|
4618 fflush (stdout);
|
|
4619 if (preempt_count == 1)
|
|
4620 {
|
554
|
4621 #ifdef EMACS_OUTQSIZE
|
|
4622 if (EMACS_OUTQSIZE (0, &outq) < 0)
|
314
|
4623 /* Probably not a tty. Ignore the error and reset
|
25012
|
4624 * the outq count. */
|
314
|
4625 outq = PENDING_OUTPUT_COUNT (stdout);
|
|
4626 #endif
|
|
4627 outq *= 10;
|
7530
|
4628 if (baud_rate <= outq && baud_rate > 0)
|
3357
|
4629 sleep (outq / baud_rate);
|
314
|
4630 }
|
|
4631 }
|
|
4632 }
|
|
4633
|
16822
|
4634 if ((i - 1) % preempt_count == 0)
|
|
4635 detect_input_pending ();
|
|
4636
|
25012
|
4637 update_frame_line (f, i);
|
314
|
4638 }
|
|
4639 }
|
25012
|
4640
|
764
|
4641 pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0;
|
314
|
4642
|
|
4643 /* Now just clean up termcap drivers and set cursor, etc. */
|
|
4644 if (!pause)
|
|
4645 {
|
12409
|
4646 if ((cursor_in_echo_area
|
25012
|
4647 /* If we are showing a message instead of the mini-buffer,
|
12627
c7bc7a24b1ff
(update_frame): Check that the echo area is in the frame being displayed.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
4648 show the cursor for the message instead of for the
|
25012
|
4649 (now hidden) mini-buffer contents. */
|
12627
c7bc7a24b1ff
(update_frame): Check that the echo area is in the frame being displayed.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
4650 || (EQ (minibuf_window, selected_window)
|
c7bc7a24b1ff
(update_frame): Check that the echo area is in the frame being displayed.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
4651 && EQ (minibuf_window, echo_area_window)
|
25345
|
4652 && !NILP (echo_area_buffer[0])))
|
12627
c7bc7a24b1ff
(update_frame): Check that the echo area is in the frame being displayed.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
4653 /* These cases apply only to the frame that contains
|
25012
|
4654 the active mini-buffer window. */
|
12627
c7bc7a24b1ff
(update_frame): Check that the echo area is in the frame being displayed.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
4655 && FRAME_HAS_MINIBUF_P (f)
|
14459
|
4656 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
|
708
|
4657 {
|
1042
|
4658 int top = XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
|
|
4659 int row, col;
|
|
4660
|
|
4661 if (cursor_in_echo_area < 0)
|
|
4662 {
|
25012
|
4663 /* Negative value of cursor_in_echo_area means put
|
|
4664 cursor at beginning of line. */
|
1042
|
4665 row = top;
|
|
4666 col = 0;
|
|
4667 }
|
708
|
4668 else
|
1042
|
4669 {
|
25012
|
4670 /* Positive value of cursor_in_echo_area means put
|
|
4671 cursor at the end of the prompt. If the mini-buffer
|
|
4672 is several lines high, find the last line that has
|
|
4673 any text on it. */
|
1042
|
4674 row = FRAME_HEIGHT (f);
|
|
4675 do
|
|
4676 {
|
25012
|
4677 --row;
|
|
4678 col = 0;
|
|
4679
|
|
4680 if (MATRIX_ROW_ENABLED_P (current_matrix, row))
|
|
4681 {
|
|
4682 /* Frame rows are filled up with spaces that
|
|
4683 must be ignored here. */
|
|
4684 struct glyph_row *r = MATRIX_ROW (current_matrix,
|
|
4685 row);
|
|
4686 struct glyph *start = r->glyphs[TEXT_AREA];
|
|
4687 struct glyph *last = start + r->used[TEXT_AREA];
|
|
4688
|
|
4689 while (last > start
|
|
4690 && (last - 1)->charpos < 0)
|
|
4691 --last;
|
|
4692
|
|
4693 col = last - start;
|
|
4694 }
|
1042
|
4695 }
|
|
4696 while (row > top && col == 0);
|
|
4697
|
21757
|
4698 /* Make sure COL is not out of range. */
|
21763
|
4699 if (col >= FRAME_CURSOR_X_LIMIT (f))
|
1042
|
4700 {
|
21757
|
4701 /* If we have another row, advance cursor into it. */
|
1042
|
4702 if (row < FRAME_HEIGHT (f) - 1)
|
21757
|
4703 {
|
|
4704 col = FRAME_LEFT_SCROLL_BAR_WIDTH (f);
|
|
4705 row++;
|
|
4706 }
|
|
4707 /* Otherwise move it back in range. */
|
|
4708 else
|
21763
|
4709 col = FRAME_CURSOR_X_LIMIT (f) - 1;
|
1042
|
4710 }
|
|
4711 }
|
|
4712
|
|
4713 cursor_to (row, col);
|
708
|
4714 }
|
314
|
4715 else
|
25012
|
4716 {
|
|
4717 /* We have only one cursor on terminal frames. Use it to
|
|
4718 display the cursor of the selected window. */
|
|
4719 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
|
|
4720 if (w->cursor.vpos >= 0)
|
|
4721 {
|
|
4722 int x = WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos);
|
|
4723 int y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos);
|
|
4724
|
|
4725 if (INTEGERP (w->left_margin_width))
|
|
4726 x += XFASTINT (w->left_margin_width);
|
|
4727
|
|
4728 /* x = max (min (x, FRAME_WINDOW_WIDTH (f) - 1), 0); */
|
|
4729 cursor_to (y, x);
|
|
4730 }
|
|
4731 }
|
314
|
4732 }
|
|
4733
|
764
|
4734 update_end (f);
|
314
|
4735
|
|
4736 if (termscript)
|
|
4737 fflush (termscript);
|
|
4738 fflush (stdout);
|
|
4739
|
|
4740 do_pause:
|
|
4741
|
|
4742 display_completed = !pause;
|
25012
|
4743 clear_desired_matrices (f);
|
314
|
4744 return pause;
|
|
4745 }
|
|
4746
|
25012
|
4747
|
|
4748 /* Do line insertions/deletions on frame F for frame-based redisplay. */
|
314
|
4749
|
21514
|
4750 int
|
764
|
4751 scrolling (frame)
|
25012
|
4752 struct frame *frame;
|
314
|
4753 {
|
|
4754 int unchanged_at_top, unchanged_at_bottom;
|
|
4755 int window_size;
|
|
4756 int changed_lines;
|
764
|
4757 int *old_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
|
|
4758 int *new_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
|
|
4759 int *draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
|
10259
|
4760 int *old_draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
|
314
|
4761 register int i;
|
764
|
4762 int free_at_end_vpos = FRAME_HEIGHT (frame);
|
25012
|
4763 struct glyph_matrix *current_matrix = frame->current_matrix;
|
|
4764 struct glyph_matrix *desired_matrix = frame->desired_matrix;
|
|
4765
|
|
4766 if (!current_matrix)
|
|
4767 abort ();
|
|
4768
|
|
4769 /* Compute hash codes of all the lines. Also calculate number of
|
|
4770 changed lines, number of unchanged lines at the beginning, and
|
|
4771 number of unchanged lines at the end. */
|
314
|
4772 changed_lines = 0;
|
|
4773 unchanged_at_top = 0;
|
764
|
4774 unchanged_at_bottom = FRAME_HEIGHT (frame);
|
|
4775 for (i = 0; i < FRAME_HEIGHT (frame); i++)
|
314
|
4776 {
|
|
4777 /* Give up on this scrolling if some old lines are not enabled. */
|
25012
|
4778 if (!MATRIX_ROW_ENABLED_P (current_matrix, i))
|
314
|
4779 return 0;
|
25012
|
4780 old_hash[i] = line_hash_code (MATRIX_ROW (current_matrix, i));
|
|
4781 if (! MATRIX_ROW_ENABLED_P (desired_matrix, i))
|
18015
|
4782 {
|
|
4783 /* This line cannot be redrawn, so don't let scrolling mess it. */
|
|
4784 new_hash[i] = old_hash[i];
|
|
4785 #define INFINITY 1000000 /* Taken from scroll.c */
|
|
4786 draw_cost[i] = INFINITY;
|
|
4787 }
|
314
|
4788 else
|
18015
|
4789 {
|
25012
|
4790 new_hash[i] = line_hash_code (MATRIX_ROW (desired_matrix, i));
|
|
4791 draw_cost[i] = line_draw_cost (desired_matrix, i);
|
18015
|
4792 }
|
314
|
4793
|
|
4794 if (old_hash[i] != new_hash[i])
|
|
4795 {
|
|
4796 changed_lines++;
|
764
|
4797 unchanged_at_bottom = FRAME_HEIGHT (frame) - i - 1;
|
314
|
4798 }
|
|
4799 else if (i == unchanged_at_top)
|
|
4800 unchanged_at_top++;
|
25012
|
4801 old_draw_cost[i] = line_draw_cost (current_matrix, i);
|
314
|
4802 }
|
|
4803
|
|
4804 /* If changed lines are few, don't allow preemption, don't scroll. */
|
25012
|
4805 if ((!scroll_region_ok && changed_lines < baud_rate / 2400)
|
764
|
4806 || unchanged_at_bottom == FRAME_HEIGHT (frame))
|
314
|
4807 return 1;
|
|
4808
|
764
|
4809 window_size = (FRAME_HEIGHT (frame) - unchanged_at_top
|
314
|
4810 - unchanged_at_bottom);
|
|
4811
|
|
4812 if (scroll_region_ok)
|
|
4813 free_at_end_vpos -= unchanged_at_bottom;
|
764
|
4814 else if (memory_below_frame)
|
314
|
4815 free_at_end_vpos = -1;
|
|
4816
|
|
4817 /* If large window, fast terminal and few lines in common between
|
25012
|
4818 current frame and desired frame, don't bother with i/d calc. */
|
10259
|
4819 if (!scroll_region_ok && window_size >= 18 && baud_rate > 2400
|
314
|
4820 && (window_size >=
|
|
4821 10 * scrolling_max_lines_saved (unchanged_at_top,
|
764
|
4822 FRAME_HEIGHT (frame) - unchanged_at_bottom,
|
314
|
4823 old_hash, new_hash, draw_cost)))
|
|
4824 return 0;
|
|
4825
|
25012
|
4826 if (window_size < 2)
|
|
4827 return 0;
|
|
4828
|
764
|
4829 scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
|
314
|
4830 draw_cost + unchanged_at_top - 1,
|
10259
|
4831 old_draw_cost + unchanged_at_top - 1,
|
314
|
4832 old_hash + unchanged_at_top - 1,
|
|
4833 new_hash + unchanged_at_top - 1,
|
|
4834 free_at_end_vpos - unchanged_at_top);
|
|
4835
|
|
4836 return 0;
|
|
4837 }
|
25012
|
4838
|
|
4839
|
|
4840 /* Count the number of blanks at the start of the vector of glyphs R
|
|
4841 which is LEN glyphs long. */
|
|
4842
|
|
4843 static int
|
|
4844 count_blanks (r, len)
|
|
4845 struct glyph *r;
|
|
4846 int len;
|
314
|
4847 {
|
25012
|
4848 int i;
|
|
4849
|
|
4850 for (i = 0; i < len; ++i)
|
|
4851 if (!CHAR_GLYPH_SPACE_P (r[i]))
|
|
4852 break;
|
|
4853
|
|
4854 return i;
|
314
|
4855 }
|
25012
|
4856
|
|
4857
|
|
4858 /* Count the number of glyphs in common at the start of the glyph
|
|
4859 vectors STR1 and STR2. END1 is the end of STR1 and END2 is the end
|
|
4860 of STR2. Value is the number of equal glyphs equal at the start. */
|
314
|
4861
|
|
4862 static int
|
25012
|
4863 count_match (str1, end1, str2, end2)
|
|
4864 struct glyph *str1, *end1, *str2, *end2;
|
314
|
4865 {
|
25012
|
4866 struct glyph *p1 = str1;
|
|
4867 struct glyph *p2 = str2;
|
|
4868
|
|
4869 while (p1 < end1
|
|
4870 && p2 < end2
|
26998
|
4871 && GLYPH_CHAR_AND_FACE_EQUAL_P (p1, p2))
|
25012
|
4872 ++p1, ++p2;
|
|
4873
|
|
4874 return p1 - str1;
|
314
|
4875 }
|
|
4876
|
25012
|
4877
|
314
|
4878 /* Char insertion/deletion cost vector, from term.c */
|
25012
|
4879
|
314
|
4880 extern int *char_ins_del_vector;
|
16267
|
4881 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WINDOW_WIDTH((f))])
|
314
|
4882
|
25012
|
4883
|
|
4884 /* Perform a frame-based update on line VPOS in frame FRAME. */
|
|
4885
|
314
|
4886 static void
|
25012
|
4887 update_frame_line (frame, vpos)
|
|
4888 register struct frame *frame;
|
314
|
4889 int vpos;
|
|
4890 {
|
25012
|
4891 struct glyph *obody, *nbody, *op1, *op2, *np1, *nend;
|
314
|
4892 int tem;
|
|
4893 int osp, nsp, begmatch, endmatch, olen, nlen;
|
25012
|
4894 struct glyph_matrix *current_matrix = frame->current_matrix;
|
|
4895 struct glyph_matrix *desired_matrix = frame->desired_matrix;
|
|
4896 struct glyph_row *current_row = MATRIX_ROW (current_matrix, vpos);
|
|
4897 struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, vpos);
|
|
4898 int must_write_whole_line_p;
|
|
4899
|
|
4900 if (desired_row->inverse_p
|
|
4901 != (current_row->enabled_p && current_row->inverse_p))
|
314
|
4902 {
|
25012
|
4903 int n = current_row->enabled_p ? current_row->used[TEXT_AREA] : 0;
|
|
4904 change_line_highlight (desired_row->inverse_p, vpos, vpos, n);
|
|
4905 current_row->enabled_p = 0;
|
314
|
4906 }
|
|
4907 else
|
25012
|
4908 reassert_line_highlight (desired_row->inverse_p, vpos);
|
|
4909
|
25725
|
4910 /* Current row not enabled means it has unknown contents. We must
|
|
4911 write the whole desired line in that case. */
|
25012
|
4912 must_write_whole_line_p = !current_row->enabled_p;
|
|
4913 if (must_write_whole_line_p)
|
314
|
4914 {
|
25012
|
4915 obody = 0;
|
314
|
4916 olen = 0;
|
|
4917 }
|
|
4918 else
|
|
4919 {
|
25012
|
4920 obody = MATRIX_ROW_GLYPH_START (current_matrix, vpos);
|
|
4921 olen = current_row->used[TEXT_AREA];
|
|
4922
|
|
4923 if (! current_row->inverse_p)
|
314
|
4924 {
|
25725
|
4925 /* Ignore trailing spaces, if we can. */
|
314
|
4926 if (!must_write_spaces)
|
25012
|
4927 while (olen > 0 && CHAR_GLYPH_SPACE_P (obody[olen-1]))
|
314
|
4928 olen--;
|
|
4929 }
|
|
4930 else
|
|
4931 {
|
25725
|
4932 /* For an inverse-video line, make sure it's filled with
|
|
4933 spaces all the way to the frame edge so that the reverse
|
|
4934 video extends all the way across. */
|
25012
|
4935 while (olen < FRAME_WIDTH (frame) - 1)
|
|
4936 obody[olen++] = space_glyph;
|
314
|
4937 }
|
|
4938 }
|
|
4939
|
25012
|
4940 current_row->enabled_p = 1;
|
|
4941 current_row->used[TEXT_AREA] = desired_row->used[TEXT_AREA];
|
|
4942 current_row->inverse_p = desired_row->inverse_p;
|
|
4943
|
|
4944 /* If desired line is empty, just clear the line. */
|
|
4945 if (!desired_row->enabled_p)
|
314
|
4946 {
|
|
4947 nlen = 0;
|
|
4948 goto just_erase;
|
|
4949 }
|
|
4950
|
25012
|
4951 nbody = desired_row->glyphs[TEXT_AREA];
|
|
4952 nlen = desired_row->used[TEXT_AREA];
|
|
4953 nend = nbody + nlen;
|
|
4954
|
|
4955 /* If display line has unknown contents, write the whole line. */
|
|
4956 if (must_write_whole_line_p)
|
|
4957 {
|
25725
|
4958 /* Ignore spaces at the end, if we can. */
|
25313
|
4959 if (!must_write_spaces)
|
|
4960 while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
|
|
4961 --nlen;
|
|
4962
|
25725
|
4963 /* Write the contents of the desired line. */
|
25313
|
4964 if (nlen)
|
25725
|
4965 {
|
|
4966 cursor_to (vpos, 0);
|
|
4967 write_glyphs (nbody, nlen);
|
|
4968 }
|
25313
|
4969
|
25725
|
4970 /* Don't call clear_end_of_line if we already wrote the whole
|
|
4971 line. The cursor will not be at the right margin in that
|
|
4972 case but in the line below. */
|
|
4973 if (nlen < FRAME_WINDOW_WIDTH (frame))
|
|
4974 {
|
|
4975 cursor_to (vpos, nlen);
|
|
4976 clear_end_of_line (FRAME_WINDOW_WIDTH (frame));
|
|
4977 }
|
28682
|
4978 else
|
|
4979 /* Make sure we are in the right row, otherwise cursor movement
|
|
4980 with cmgoto might use `ch' in the wrong row. */
|
|
4981 cursor_to (vpos, 0);
|
|
4982
|
25012
|
4983 make_current (desired_matrix, current_matrix, vpos);
|
|
4984 return;
|
|
4985 }
|
314
|
4986
|
|
4987 /* Pretend trailing spaces are not there at all,
|
|
4988 unless for one reason or another we must write all spaces. */
|
25012
|
4989 if (!desired_row->inverse_p)
|
314
|
4990 {
|
|
4991 if (!must_write_spaces)
|
25012
|
4992 while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
|
314
|
4993 nlen--;
|
|
4994 }
|
|
4995 else
|
|
4996 {
|
25012
|
4997 /* For an inverse-video line, give it extra trailing spaces all
|
|
4998 the way to the frame edge so that the reverse video extends
|
|
4999 all the way across. */
|
|
5000 while (nlen < FRAME_WIDTH (frame) - 1)
|
|
5001 nbody[nlen++] = space_glyph;
|
314
|
5002 }
|
|
5003
|
|
5004 /* If there's no i/d char, quickly do the best we can without it. */
|
|
5005 if (!char_ins_del_ok)
|
|
5006 {
|
25012
|
5007 int i, j;
|
|
5008
|
|
5009 /* Find the first glyph in desired row that doesn't agree with
|
|
5010 a glyph in the current row, and write the rest from there on. */
|
314
|
5011 for (i = 0; i < nlen; i++)
|
|
5012 {
|
25012
|
5013 if (i >= olen || !GLYPH_EQUAL_P (nbody + i, obody + i))
|
314
|
5014 {
|
25012
|
5015 /* Find the end of the run of different glyphs. */
|
|
5016 j = i + 1;
|
|
5017 while (j < nlen
|
|
5018 && (j >= olen
|
|
5019 || !GLYPH_EQUAL_P (nbody + j, obody + j)
|
|
5020 || CHAR_GLYPH_PADDING_P (nbody[j])))
|
|
5021 ++j;
|
|
5022
|
|
5023 /* Output this run of non-matching chars. */
|
314
|
5024 cursor_to (vpos, i);
|
25012
|
5025 write_glyphs (nbody + i, j - i);
|
|
5026 i = j - 1;
|
314
|
5027
|
|
5028 /* Now find the next non-match. */
|
|
5029 }
|
|
5030 }
|
|
5031
|
|
5032 /* Clear the rest of the line, or the non-clear part of it. */
|
|
5033 if (olen > nlen)
|
|
5034 {
|
|
5035 cursor_to (vpos, nlen);
|
|
5036 clear_end_of_line (olen);
|
|
5037 }
|
|
5038
|
25012
|
5039 /* Make current row = desired row. */
|
|
5040 make_current (desired_matrix, current_matrix, vpos);
|
314
|
5041 return;
|
|
5042 }
|
|
5043
|
25012
|
5044 /* Here when CHAR_INS_DEL_OK != 0, i.e. we can insert or delete
|
|
5045 characters in a row. */
|
|
5046
|
314
|
5047 if (!olen)
|
|
5048 {
|
25012
|
5049 /* If current line is blank, skip over initial spaces, if
|
|
5050 possible, and write the rest. */
|
|
5051 if (must_write_spaces || desired_row->inverse_p)
|
|
5052 nsp = 0;
|
|
5053 else
|
|
5054 nsp = count_blanks (nbody, nlen);
|
|
5055
|
314
|
5056 if (nlen > nsp)
|
|
5057 {
|
|
5058 cursor_to (vpos, nsp);
|
|
5059 write_glyphs (nbody + nsp, nlen - nsp);
|
|
5060 }
|
|
5061
|
764
|
5062 /* Exchange contents between current_frame and new_frame. */
|
25012
|
5063 make_current (desired_matrix, current_matrix, vpos);
|
314
|
5064 return;
|
|
5065 }
|
|
5066
|
|
5067 /* Compute number of leading blanks in old and new contents. */
|
25012
|
5068 osp = count_blanks (obody, olen);
|
|
5069 nsp = desired_row->inverse_p ? 0 : count_blanks (nbody, nlen);
|
|
5070
|
|
5071 /* Compute number of matching chars starting with first non-blank. */
|
|
5072 begmatch = count_match (obody + osp, obody + olen,
|
|
5073 nbody + nsp, nbody + nlen);
|
314
|
5074
|
|
5075 /* Spaces in new match implicit space past the end of old. */
|
|
5076 /* A bug causing this to be a no-op was fixed in 18.29. */
|
|
5077 if (!must_write_spaces && osp + begmatch == olen)
|
|
5078 {
|
|
5079 np1 = nbody + nsp;
|
25012
|
5080 while (np1 + begmatch < nend && CHAR_GLYPH_SPACE_P (np1[begmatch]))
|
|
5081 ++begmatch;
|
314
|
5082 }
|
|
5083
|
|
5084 /* Avoid doing insert/delete char
|
|
5085 just cause number of leading spaces differs
|
25012
|
5086 when the following text does not match. */
|
314
|
5087 if (begmatch == 0 && osp != nsp)
|
|
5088 osp = nsp = min (osp, nsp);
|
|
5089
|
|
5090 /* Find matching characters at end of line */
|
|
5091 op1 = obody + olen;
|
|
5092 np1 = nbody + nlen;
|
|
5093 op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
|
25012
|
5094 while (op1 > op2
|
|
5095 && GLYPH_EQUAL_P (op1 - 1, np1 - 1))
|
314
|
5096 {
|
|
5097 op1--;
|
|
5098 np1--;
|
|
5099 }
|
|
5100 endmatch = obody + olen - op1;
|
|
5101
|
|
5102 /* tem gets the distance to insert or delete.
|
|
5103 endmatch is how many characters we save by doing so.
|
|
5104 Is it worth it? */
|
|
5105
|
|
5106 tem = (nlen - nsp) - (olen - osp);
|
|
5107 if (endmatch && tem
|
764
|
5108 && (!char_ins_del_ok || endmatch <= char_ins_del_cost (frame)[tem]))
|
314
|
5109 endmatch = 0;
|
|
5110
|
|
5111 /* nsp - osp is the distance to insert or delete.
|
|
5112 If that is nonzero, begmatch is known to be nonzero also.
|
|
5113 begmatch + endmatch is how much we save by doing the ins/del.
|
|
5114 Is it worth it? */
|
|
5115
|
|
5116 if (nsp != osp
|
|
5117 && (!char_ins_del_ok
|
764
|
5118 || begmatch + endmatch <= char_ins_del_cost (frame)[nsp - osp]))
|
314
|
5119 {
|
|
5120 begmatch = 0;
|
|
5121 endmatch = 0;
|
|
5122 osp = nsp = min (osp, nsp);
|
|
5123 }
|
|
5124
|
|
5125 /* Now go through the line, inserting, writing and
|
|
5126 deleting as appropriate. */
|
|
5127
|
|
5128 if (osp > nsp)
|
|
5129 {
|
|
5130 cursor_to (vpos, nsp);
|
|
5131 delete_glyphs (osp - nsp);
|
|
5132 }
|
|
5133 else if (nsp > osp)
|
|
5134 {
|
|
5135 /* If going to delete chars later in line
|
|
5136 and insert earlier in the line,
|
|
5137 must delete first to avoid losing data in the insert */
|
|
5138 if (endmatch && nlen < olen + nsp - osp)
|
|
5139 {
|
|
5140 cursor_to (vpos, nlen - endmatch + osp - nsp);
|
|
5141 delete_glyphs (olen + nsp - osp - nlen);
|
|
5142 olen = nlen - (nsp - osp);
|
|
5143 }
|
|
5144 cursor_to (vpos, osp);
|
25012
|
5145 insert_glyphs (0, nsp - osp);
|
314
|
5146 }
|
|
5147 olen += nsp - osp;
|
|
5148
|
|
5149 tem = nsp + begmatch + endmatch;
|
|
5150 if (nlen != tem || olen != tem)
|
|
5151 {
|
|
5152 cursor_to (vpos, nsp + begmatch);
|
|
5153 if (!endmatch || nlen == olen)
|
|
5154 {
|
|
5155 /* If new text being written reaches right margin,
|
|
5156 there is no need to do clear-to-eol at the end.
|
|
5157 (and it would not be safe, since cursor is not
|
|
5158 going to be "at the margin" after the text is done) */
|
16267
|
5159 if (nlen == FRAME_WINDOW_WIDTH (frame))
|
314
|
5160 olen = 0;
|
|
5161 write_glyphs (nbody + nsp + begmatch, nlen - tem);
|
|
5162 }
|
|
5163 else if (nlen > olen)
|
|
5164 {
|
17015
|
5165 /* Here, we used to have the following simple code:
|
|
5166 ----------------------------------------
|
|
5167 write_glyphs (nbody + nsp + begmatch, olen - tem);
|
|
5168 insert_glyphs (nbody + nsp + begmatch + olen - tem, nlen - olen);
|
|
5169 ----------------------------------------
|
|
5170 but it doesn't work if nbody[nsp + begmatch + olen - tem]
|
|
5171 is a padding glyph. */
|
|
5172 int out = olen - tem; /* Columns to be overwritten originally. */
|
|
5173 int del;
|
|
5174
|
|
5175 /* Calculate columns we can actually overwrite. */
|
25012
|
5176 while (CHAR_GLYPH_PADDING_P (nbody[nsp + begmatch + out])) out--;
|
17015
|
5177 write_glyphs (nbody + nsp + begmatch, out);
|
25012
|
5178 /* If we left columns to be overwritten, we must delete them. */
|
17015
|
5179 del = olen - tem - out;
|
|
5180 if (del > 0) delete_glyphs (del);
|
|
5181 /* At last, we insert columns not yet written out. */
|
|
5182 insert_glyphs (nbody + nsp + begmatch + out, nlen - olen + del);
|
314
|
5183 olen = nlen;
|
|
5184 }
|
|
5185 else if (olen > nlen)
|
|
5186 {
|
|
5187 write_glyphs (nbody + nsp + begmatch, nlen - tem);
|
|
5188 delete_glyphs (olen - nlen);
|
|
5189 olen = nlen;
|
|
5190 }
|
|
5191 }
|
|
5192
|
|
5193 just_erase:
|
|
5194 /* If any unerased characters remain after the new line, erase them. */
|
|
5195 if (olen > nlen)
|
|
5196 {
|
|
5197 cursor_to (vpos, nlen);
|
|
5198 clear_end_of_line (olen);
|
|
5199 }
|
|
5200
|
764
|
5201 /* Exchange contents between current_frame and new_frame. */
|
25012
|
5202 make_current (desired_matrix, current_matrix, vpos);
|
314
|
5203 }
|
25012
|
5204
|
|
5205
|
314
|
5206
|
25012
|
5207 /***********************************************************************
|
|
5208 X/Y Position -> Buffer Position
|
|
5209 ***********************************************************************/
|
|
5210
|
|
5211 /* Return the character position of the character at window relative
|
|
5212 pixel position (*X, *Y). *X and *Y are adjusted to character
|
|
5213 boundaries. */
|
|
5214
|
|
5215 int
|
|
5216 buffer_posn_from_coords (w, x, y)
|
|
5217 struct window *w;
|
|
5218 int *x, *y;
|
7810
|
5219 {
|
25012
|
5220 struct it it;
|
|
5221 struct buffer *old_current_buffer = current_buffer;
|
|
5222 struct text_pos startp;
|
|
5223 int left_area_width;
|
|
5224
|
|
5225 current_buffer = XBUFFER (w->buffer);
|
|
5226 SET_TEXT_POS_FROM_MARKER (startp, w->start);
|
|
5227 CHARPOS (startp) = min (ZV, max (BEGV, CHARPOS (startp)));
|
|
5228 BYTEPOS (startp) = min (ZV_BYTE, max (BEGV_BYTE, BYTEPOS (startp)));
|
|
5229 start_display (&it, w, startp);
|
|
5230
|
|
5231 left_area_width = WINDOW_DISPLAY_LEFT_AREA_PIXEL_WIDTH (w);
|
|
5232 move_it_to (&it, -1, *x + it.first_visible_x - left_area_width, *y, -1,
|
|
5233 MOVE_TO_X | MOVE_TO_Y);
|
|
5234
|
|
5235 *x = it.current_x - it.first_visible_x + left_area_width;
|
|
5236 *y = it.current_y;
|
|
5237 current_buffer = old_current_buffer;
|
|
5238 return IT_CHARPOS (it);
|
|
5239 }
|
|
5240
|
|
5241
|
|
5242 /* Value is the string under window-relative coordinates X/Y in the
|
|
5243 mode or top line of window W, or nil if none. MODE_LINE_P non-zero
|
|
5244 means look at the mode line. *CHARPOS is set to the position in
|
|
5245 the string returned. */
|
|
5246
|
|
5247 Lisp_Object
|
|
5248 mode_line_string (w, x, y, mode_line_p, charpos)
|
|
5249 struct window *w;
|
|
5250 int x, y;
|
|
5251 int *charpos;
|
|
5252 {
|
|
5253 struct glyph_row *row;
|
|
5254 struct glyph *glyph, *end;
|
|
5255 struct frame *f = XFRAME (w->frame);
|
|
5256 int x0;
|
|
5257 Lisp_Object string = Qnil;
|
|
5258
|
|
5259 if (mode_line_p)
|
|
5260 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
|
|
5261 else
|
25546
|
5262 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
|
25012
|
5263
|
|
5264 if (row->mode_line_p && row->enabled_p)
|
11919
|
5265 {
|
25012
|
5266 /* The mode lines are displayed over scroll bars and bitmap
|
|
5267 areas, and X is window-relative. Correct X by the scroll bar
|
|
5268 and bitmap area width. */
|
|
5269 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
|
|
5270 x += FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
|
25459
|
5271 x += FRAME_LEFT_FLAGS_AREA_WIDTH (f);
|
25012
|
5272
|
|
5273 /* Find the glyph under X. If we find one with a string object,
|
|
5274 it's the one we were looking for. */
|
|
5275 glyph = row->glyphs[TEXT_AREA];
|
|
5276 end = glyph + row->used[TEXT_AREA];
|
|
5277 for (x0 = 0; glyph < end; x0 += glyph->pixel_width, ++glyph)
|
|
5278 if (x >= x0 && x < x0 + glyph->pixel_width)
|
|
5279 {
|
|
5280 string = glyph->object;
|
|
5281 *charpos = glyph->charpos;
|
|
5282 break;
|
|
5283 }
|
7810
|
5284 }
|
25012
|
5285
|
|
5286 return string;
|
7810
|
5287 }
|
25012
|
5288
|
|
5289
|
|
5290 /***********************************************************************
|
|
5291 Changing Frame Sizes
|
|
5292 ***********************************************************************/
|
314
|
5293
|
|
5294 #ifdef SIGWINCH
|
25012
|
5295
|
493
|
5296 SIGTYPE
|
10745
|
5297 window_change_signal (signalnum) /* If we don't have an argument, */
|
25012
|
5298 int signalnum; /* some compilers complain in signal calls. */
|
314
|
5299 {
|
|
5300 int width, height;
|
|
5301 extern int errno;
|
|
5302 int old_errno = errno;
|
|
5303
|
764
|
5304 get_frame_size (&width, &height);
|
314
|
5305
|
764
|
5306 /* The frame size change obviously applies to a termcap-controlled
|
|
5307 frame. Find such a frame in the list, and assume it's the only
|
314
|
5308 one (since the redisplay code always writes to stdout, not a
|
764
|
5309 FILE * specified in the frame structure). Record the new size,
|
314
|
5310 but don't reallocate the data structures now. Let that be done
|
|
5311 later outside of the signal handler. */
|
|
5312
|
|
5313 {
|
2252
|
5314 Lisp_Object tail, frame;
|
314
|
5315
|
2252
|
5316 FOR_EACH_FRAME (tail, frame)
|
314
|
5317 {
|
2252
|
5318 if (FRAME_TERMCAP_P (XFRAME (frame)))
|
314
|
5319 {
|
25345
|
5320 change_frame_size (XFRAME (frame), height, width, 0, 1, 0);
|
314
|
5321 break;
|
|
5322 }
|
|
5323 }
|
|
5324 }
|
|
5325
|
|
5326 signal (SIGWINCH, window_change_signal);
|
|
5327 errno = old_errno;
|
|
5328 }
|
|
5329 #endif /* SIGWINCH */
|
|
5330
|
|
5331
|
25345
|
5332 /* Do any change in frame size that was requested by a signal. SAFE
|
|
5333 non-zero means this function is called from a place where it is
|
|
5334 safe to change frame sizes while a redisplay is in progress. */
|
314
|
5335
|
21514
|
5336 void
|
25345
|
5337 do_pending_window_change (safe)
|
|
5338 int safe;
|
314
|
5339 {
|
|
5340 /* If window_change_signal should have run before, run it now. */
|
25345
|
5341 if (redisplaying_p && !safe)
|
|
5342 return;
|
|
5343
|
314
|
5344 while (delayed_size_change)
|
|
5345 {
|
2252
|
5346 Lisp_Object tail, frame;
|
314
|
5347
|
|
5348 delayed_size_change = 0;
|
|
5349
|
2252
|
5350 FOR_EACH_FRAME (tail, frame)
|
314
|
5351 {
|
25012
|
5352 struct frame *f = XFRAME (frame);
|
2252
|
5353
|
764
|
5354 int height = FRAME_NEW_HEIGHT (f);
|
|
5355 int width = FRAME_NEW_WIDTH (f);
|
314
|
5356
|
3449
|
5357 if (height != 0 || width != 0)
|
25345
|
5358 change_frame_size (f, height, width, 0, 0, safe);
|
314
|
5359 }
|
|
5360 }
|
|
5361 }
|
|
5362
|
|
5363
|
764
|
5364 /* Change the frame height and/or width. Values may be given as zero to
|
960
|
5365 indicate no change is to take place.
|
314
|
5366
|
960
|
5367 If DELAY is non-zero, then assume we're being called from a signal
|
|
5368 handler, and queue the change for later - perhaps the next
|
|
5369 redisplay. Since this tries to resize windows, we can't call it
|
25345
|
5370 from a signal handler.
|
|
5371
|
|
5372 SAFE non-zero means this function is called from a place where it's
|
|
5373 safe to change frame sizes while a redisplay is in progress. */
|
960
|
5374
|
21514
|
5375 void
|
25345
|
5376 change_frame_size (f, newheight, newwidth, pretend, delay, safe)
|
25012
|
5377 register struct frame *f;
|
25345
|
5378 int newheight, newwidth, pretend, delay, safe;
|
10770
|
5379 {
|
|
5380 Lisp_Object tail, frame;
|
16881
245ba9f2781a
(change_frame_size_1): Reject new sizes if they cause overflow.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
5381
|
15395
|
5382 if (! FRAME_WINDOW_P (f))
|
10770
|
5383 {
|
15394
|
5384 /* When using termcap, or on MS-DOS, all frames use
|
|
5385 the same screen, so a change in size affects all frames. */
|
10770
|
5386 FOR_EACH_FRAME (tail, frame)
|
15395
|
5387 if (! FRAME_WINDOW_P (XFRAME (frame)))
|
10770
|
5388 change_frame_size_1 (XFRAME (frame), newheight, newwidth,
|
25345
|
5389 pretend, delay, safe);
|
10770
|
5390 }
|
|
5391 else
|
25345
|
5392 change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe);
|
10770
|
5393 }
|
|
5394
|
|
5395 static void
|
25345
|
5396 change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe)
|
25012
|
5397 register struct frame *f;
|
25345
|
5398 int newheight, newwidth, pretend, delay, safe;
|
314
|
5399 {
|
16256
|
5400 int new_frame_window_width;
|
19627
|
5401 int count = specpdl_ptr - specpdl;
|
16881
245ba9f2781a
(change_frame_size_1): Reject new sizes if they cause overflow.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
5402
|
314
|
5403 /* If we can't deal with the change now, queue it for later. */
|
25345
|
5404 if (delay || (redisplaying_p && !safe))
|
314
|
5405 {
|
25012
|
5406 FRAME_NEW_HEIGHT (f) = newheight;
|
|
5407 FRAME_NEW_WIDTH (f) = newwidth;
|
314
|
5408 delayed_size_change = 1;
|
|
5409 return;
|
|
5410 }
|
|
5411
|
764
|
5412 /* This size-change overrides any pending one for this frame. */
|
25012
|
5413 FRAME_NEW_HEIGHT (f) = 0;
|
|
5414 FRAME_NEW_WIDTH (f) = 0;
|
960
|
5415
|
3449
|
5416 /* If an argument is zero, set it to the current value. */
|
15896
|
5417 if (newheight == 0)
|
25012
|
5418 newheight = FRAME_HEIGHT (f);
|
15896
|
5419 if (newwidth == 0)
|
25012
|
5420 newwidth = FRAME_WIDTH (f);
|
|
5421
|
|
5422 /* Compute width of windows in F.
|
|
5423 This is the width of the frame without vertical scroll bars. */
|
|
5424 new_frame_window_width = FRAME_WINDOW_WIDTH_ARG (f, newwidth);
|
16881
245ba9f2781a
(change_frame_size_1): Reject new sizes if they cause overflow.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
5425
|
960
|
5426 /* Round up to the smallest acceptable size. */
|
25012
|
5427 check_frame_size (f, &newheight, &newwidth);
|
960
|
5428
|
|
5429 /* If we're not changing the frame size, quit now. */
|
25012
|
5430 if (newheight == FRAME_HEIGHT (f)
|
|
5431 && new_frame_window_width == FRAME_WINDOW_WIDTH (f))
|
314
|
5432 return;
|
|
5433
|
15078
|
5434 BLOCK_INPUT;
|
|
5435
|
14286
|
5436 #ifdef MSDOS
|
|
5437 /* We only can set screen dimensions to certain values supported
|
|
5438 by our video hardware. Try to find the smallest size greater
|
|
5439 or equal to the requested dimensions. */
|
|
5440 dos_set_window_size (&newheight, &newwidth);
|
|
5441 #endif
|
|
5442
|
25012
|
5443 if (newheight != FRAME_HEIGHT (f))
|
314
|
5444 {
|
25012
|
5445 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
|
314
|
5446 {
|
25012
|
5447 /* Frame has both root and mini-buffer. */
|
|
5448 XSETFASTINT (XWINDOW (FRAME_ROOT_WINDOW (f))->top,
|
|
5449 FRAME_TOP_MARGIN (f));
|
|
5450 set_window_height (FRAME_ROOT_WINDOW (f),
|
|
5451 (newheight
|
|
5452 - 1
|
|
5453 - FRAME_TOP_MARGIN (f)),
|
|
5454 0);
|
|
5455 XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top,
|
9303
3115ae493c30
(direct_output_for_insert, direct_output_forward_char, change_frame_size,
Karl Heuer <kwzh@gnu.org>
diff
changeset
|
5456 newheight - 1);
|
25012
|
5457 set_window_height (FRAME_MINIBUF_WINDOW (f), 1, 0);
|
314
|
5458 }
|
|
5459 else
|
764
|
5460 /* Frame has just one top-level window. */
|
25012
|
5461 set_window_height (FRAME_ROOT_WINDOW (f),
|
|
5462 newheight - FRAME_TOP_MARGIN (f), 0);
|
|
5463
|
|
5464 if (FRAME_TERMCAP_P (f) && !pretend)
|
960
|
5465 FrameRows = newheight;
|
314
|
5466 }
|
|
5467
|
25012
|
5468 if (new_frame_window_width != FRAME_WINDOW_WIDTH (f))
|
314
|
5469 {
|
25012
|
5470 set_window_width (FRAME_ROOT_WINDOW (f), new_frame_window_width, 0);
|
|
5471 if (FRAME_HAS_MINIBUF_P (f))
|
|
5472 set_window_width (FRAME_MINIBUF_WINDOW (f), new_frame_window_width, 0);
|
|
5473
|
|
5474 if (FRAME_TERMCAP_P (f) && !pretend)
|
764
|
5475 FrameCols = newwidth;
|
25012
|
5476
|
25544
|
5477 if (WINDOWP (f->tool_bar_window))
|
|
5478 XSETFASTINT (XWINDOW (f->tool_bar_window)->width, newwidth);
|
314
|
5479 }
|
|
5480
|
25012
|
5481 FRAME_HEIGHT (f) = newheight;
|
|
5482 SET_FRAME_WIDTH (f, newwidth);
|
|
5483
|
|
5484 {
|
|
5485 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
|
|
5486 int text_area_x, text_area_y, text_area_width, text_area_height;
|
|
5487
|
|
5488 window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width,
|
|
5489 &text_area_height);
|
|
5490 if (w->cursor.x >= text_area_x + text_area_width)
|
|
5491 w->cursor.hpos = w->cursor.x = 0;
|
|
5492 if (w->cursor.y >= text_area_y + text_area_height)
|
|
5493 w->cursor.vpos = w->cursor.y = 0;
|
|
5494 }
|
|
5495
|
|
5496 adjust_glyphs (f);
|
|
5497 SET_FRAME_GARBAGED (f);
|
|
5498 calculate_costs (f);
|
15065
|
5499
|
|
5500 UNBLOCK_INPUT;
|
17282
|
5501
|
19627
|
5502 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
|
|
5503
|
17282
|
5504 /* This isn't quite a no-op: it runs window-configuration-change-hook. */
|
25012
|
5505 Fset_window_buffer (FRAME_SELECTED_WINDOW (f),
|
|
5506 XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer);
|
19627
|
5507
|
|
5508 unbind_to (count, Qnil);
|
314
|
5509 }
|
25012
|
5510
|
|
5511
|
314
|
5512
|
25012
|
5513 /***********************************************************************
|
|
5514 Terminal Related Lisp Functions
|
|
5515 ***********************************************************************/
|
|
5516
|
|
5517 DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
|
|
5518 1, 1, "FOpen termscript file: ",
|
|
5519 "Start writing all terminal output to FILE as well as the terminal.\n\
|
|
5520 FILE = nil means just close any termscript file currently open.")
|
|
5521 (file)
|
|
5522 Lisp_Object file;
|
|
5523 {
|
|
5524 if (termscript != 0) fclose (termscript);
|
|
5525 termscript = 0;
|
|
5526
|
|
5527 if (! NILP (file))
|
|
5528 {
|
|
5529 file = Fexpand_file_name (file, Qnil);
|
|
5530 termscript = fopen (XSTRING (file)->data, "w");
|
|
5531 if (termscript == 0)
|
|
5532 report_file_error ("Opening termscript", Fcons (file, Qnil));
|
|
5533 }
|
|
5534 return Qnil;
|
|
5535 }
|
|
5536
|
|
5537
|
314
|
5538 DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
|
|
5539 Ssend_string_to_terminal, 1, 1, 0,
|
|
5540 "Send STRING to the terminal without alteration.\n\
|
|
5541 Control characters in STRING will have terminal-dependent effects.")
|
14068
|
5542 (string)
|
|
5543 Lisp_Object string;
|
314
|
5544 {
|
20618
|
5545 /* ??? Perhaps we should do something special for multibyte strings here. */
|
14068
|
5546 CHECK_STRING (string, 0);
|
21244
|
5547 fwrite (XSTRING (string)->data, 1, STRING_BYTES (XSTRING (string)), stdout);
|
314
|
5548 fflush (stdout);
|
|
5549 if (termscript)
|
|
5550 {
|
21244
|
5551 fwrite (XSTRING (string)->data, 1, STRING_BYTES (XSTRING (string)),
|
|
5552 termscript);
|
314
|
5553 fflush (termscript);
|
|
5554 }
|
|
5555 return Qnil;
|
|
5556 }
|
|
5557
|
25012
|
5558
|
314
|
5559 DEFUN ("ding", Fding, Sding, 0, 1, 0,
|
|
5560 "Beep, or flash the screen.\n\
|
|
5561 Also, unless an argument is given,\n\
|
|
5562 terminate any keyboard macro currently executing.")
|
|
5563 (arg)
|
|
5564 Lisp_Object arg;
|
|
5565 {
|
493
|
5566 if (!NILP (arg))
|
314
|
5567 {
|
649
|
5568 if (noninteractive)
|
|
5569 putchar (07);
|
|
5570 else
|
|
5571 ring_bell ();
|
314
|
5572 fflush (stdout);
|
|
5573 }
|
|
5574 else
|
|
5575 bitch_at_user ();
|
|
5576
|
|
5577 return Qnil;
|
|
5578 }
|
|
5579
|
21514
|
5580 void
|
314
|
5581 bitch_at_user ()
|
|
5582 {
|
|
5583 if (noninteractive)
|
|
5584 putchar (07);
|
25012
|
5585 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */
|
314
|
5586 error ("Keyboard macro terminated by a command ringing the bell");
|
|
5587 else
|
|
5588 ring_bell ();
|
|
5589 fflush (stdout);
|
|
5590 }
|
|
5591
|
25012
|
5592
|
|
5593
|
|
5594 /***********************************************************************
|
|
5595 Sleeping, Waiting
|
|
5596 ***********************************************************************/
|
|
5597
|
314
|
5598 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
|
2291
|
5599 "Pause, without updating display, for SECONDS seconds.\n\
|
2648
|
5600 SECONDS may be a floating-point value, meaning that you can wait for a\n\
|
|
5601 fraction of a second. Optional second arg MILLISECONDS specifies an\n\
|
|
5602 additional wait period, in milliseconds; this may be useful if your\n\
|
|
5603 Emacs was built without floating point support.\n\
|
|
5604 \(Not all operating systems support waiting for a fraction of a second.)")
|
2291
|
5605 (seconds, milliseconds)
|
|
5606 Lisp_Object seconds, milliseconds;
|
314
|
5607 {
|
2291
|
5608 int sec, usec;
|
|
5609
|
|
5610 if (NILP (milliseconds))
|
9264
9338a124ea84
(redraw_frame, Fsleep_for, sit_for, Fsit_for): Use new accessor macros instead
Karl Heuer <kwzh@gnu.org>
diff
changeset
|
5611 XSETINT (milliseconds, 0);
|
2291
|
5612 else
|
|
5613 CHECK_NUMBER (milliseconds, 1);
|
2648
|
5614 usec = XINT (milliseconds) * 1000;
|
|
5615
|
|
5616 {
|
|
5617 double duration = extract_float (seconds);
|
|
5618 sec = (int) duration;
|
|
5619 usec += (duration - sec) * 1000000;
|
|
5620 }
|
314
|
5621
|
2291
|
5622 #ifndef EMACS_HAS_USECS
|
|
5623 if (sec == 0 && usec != 0)
|
|
5624 error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
|
|
5625 #endif
|
|
5626
|
|
5627 /* Assure that 0 <= usec < 1000000. */
|
|
5628 if (usec < 0)
|
|
5629 {
|
|
5630 /* We can't rely on the rounding being correct if user is negative. */
|
|
5631 if (-1000000 < usec)
|
|
5632 sec--, usec += 1000000;
|
|
5633 else
|
|
5634 sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
|
|
5635 }
|
|
5636 else
|
|
5637 sec += usec / 1000000, usec %= 1000000;
|
|
5638
|
14646
|
5639 if (sec < 0 || (sec == 0 && usec == 0))
|
314
|
5640 return Qnil;
|
|
5641
|
650
|
5642 {
|
|
5643 Lisp_Object zero;
|
|
5644
|
9303
3115ae493c30
(direct_output_for_insert, direct_output_forward_char, change_frame_size,
Karl Heuer <kwzh@gnu.org>
diff
changeset
|
5645 XSETFASTINT (zero, 0);
|
650
|
5646 wait_reading_process_input (sec, usec, zero, 0);
|
|
5647 }
|
587
|
5648
|
2291
|
5649 /* We should always have wait_reading_process_input; we have a dummy
|
|
5650 implementation for systems which don't support subprocesses. */
|
|
5651 #if 0
|
|
5652 /* No wait_reading_process_input */
|
314
|
5653 immediate_quit = 1;
|
|
5654 QUIT;
|
|
5655
|
|
5656 #ifdef VMS
|
|
5657 sys_sleep (sec);
|
|
5658 #else /* not VMS */
|
|
5659 /* The reason this is done this way
|
|
5660 (rather than defined (H_S) && defined (H_T))
|
|
5661 is because the VMS preprocessor doesn't grok `defined' */
|
|
5662 #ifdef HAVE_SELECT
|
554
|
5663 EMACS_GET_TIME (end_time);
|
|
5664 EMACS_SET_SECS_USECS (timeout, sec, usec);
|
587
|
5665 EMACS_ADD_TIME (end_time, end_time, timeout);
|
554
|
5666
|
314
|
5667 while (1)
|
|
5668 {
|
554
|
5669 EMACS_GET_TIME (timeout);
|
|
5670 EMACS_SUB_TIME (timeout, end_time, timeout);
|
|
5671 if (EMACS_TIME_NEG_P (timeout)
|
|
5672 || !select (1, 0, 0, 0, &timeout))
|
314
|
5673 break;
|
|
5674 }
|
|
5675 #else /* not HAVE_SELECT */
|
|
5676 sleep (sec);
|
|
5677 #endif /* HAVE_SELECT */
|
|
5678 #endif /* not VMS */
|
|
5679
|
|
5680 immediate_quit = 0;
|
|
5681 #endif /* no subprocesses */
|
|
5682
|
|
5683 return Qnil;
|
|
5684 }
|
|
5685
|
25012
|
5686
|
650
|
5687 /* This is just like wait_reading_process_input, except that
|
|
5688 it does the redisplay.
|
|
5689
|
5223
|
5690 It's also much like Fsit_for, except that it can be used for
|
11411
91bcce2fd486
(Fframe_or_buffer_changed_p): Ignore buffers whose names start with space.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
5691 waiting for input as well. */
|
650
|
5692
|
|
5693 Lisp_Object
|
17961
|
5694 sit_for (sec, usec, reading, display, initial_display)
|
|
5695 int sec, usec, reading, display, initial_display;
|
314
|
5696 {
|
650
|
5697 Lisp_Object read_kbd;
|
314
|
5698
|
14964
|
5699 swallow_events (display);
|
|
5700
|
14757
|
5701 if (detect_input_pending_run_timers (display))
|
314
|
5702 return Qnil;
|
650
|
5703
|
17961
|
5704 if (initial_display)
|
314
|
5705 redisplay_preserve_echo_area ();
|
|
5706
|
673
|
5707 if (sec == 0 && usec == 0)
|
|
5708 return Qt;
|
|
5709
|
314
|
5710 #ifdef SIGIO
|
1915
|
5711 gobble_input (0);
|
650
|
5712 #endif
|
|
5713
|
9264
9338a124ea84
(redraw_frame, Fsleep_for, sit_for, Fsit_for): Use new accessor macros instead
Karl Heuer <kwzh@gnu.org>
diff
changeset
|
5714 XSETINT (read_kbd, reading ? -1 : 1);
|
650
|
5715 wait_reading_process_input (sec, usec, read_kbd, display);
|
|
5716
|
314
|
5717 return detect_input_pending () ? Qnil : Qt;
|
|
5718 }
|
|
5719
|
25012
|
5720
|
650
|
5721 DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
|
2291
|
5722 "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
|
2648
|
5723 SECONDS may be a floating-point value, meaning that you can wait for a\n\
|
|
5724 fraction of a second. Optional second arg MILLISECONDS specifies an\n\
|
|
5725 additional wait period, in milliseconds; this may be useful if your\n\
|
|
5726 Emacs was built without floating point support.\n\
|
|
5727 \(Not all operating systems support waiting for a fraction of a second.)\n\
|
14068
|
5728 Optional third arg NODISP non-nil means don't redisplay, just wait for input.\n\
|
650
|
5729 Redisplay is preempted as always if input arrives, and does not happen\n\
|
|
5730 if input is available before it starts.\n\
|
|
5731 Value is t if waited the full time with no input arriving.")
|
2291
|
5732 (seconds, milliseconds, nodisp)
|
|
5733 Lisp_Object seconds, milliseconds, nodisp;
|
650
|
5734 {
|
2291
|
5735 int sec, usec;
|
650
|
5736
|
2291
|
5737 if (NILP (milliseconds))
|
9264
9338a124ea84
(redraw_frame, Fsleep_for, sit_for, Fsit_for): Use new accessor macros instead
Karl Heuer <kwzh@gnu.org>
diff
changeset
|
5738 XSETINT (milliseconds, 0);
|
2291
|
5739 else
|
|
5740 CHECK_NUMBER (milliseconds, 1);
|
2648
|
5741 usec = XINT (milliseconds) * 1000;
|
|
5742
|
|
5743 {
|
|
5744 double duration = extract_float (seconds);
|
|
5745 sec = (int) duration;
|
|
5746 usec += (duration - sec) * 1000000;
|
|
5747 }
|
2291
|
5748
|
650
|
5749 #ifndef EMACS_HAS_USECS
|
2291
|
5750 if (usec != 0 && sec == 0)
|
|
5751 error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
|
650
|
5752 #endif
|
|
5753
|
17961
|
5754 return sit_for (sec, usec, 0, NILP (nodisp), NILP (nodisp));
|
650
|
5755 }
|
25012
|
5756
|
|
5757
|
314
|
5758
|
25012
|
5759 /***********************************************************************
|
|
5760 Other Lisp Functions
|
|
5761 ***********************************************************************/
|
|
5762
|
|
5763 /* A vector of size >= 2 * NFRAMES + 3 * NBUFFERS + 1, containing the
|
|
5764 session's frames, frame names, buffers, buffer-read-only flags, and
|
|
5765 buffer-modified-flags, and a trailing sentinel (so we don't need to
|
|
5766 add length checks). */
|
|
5767
|
|
5768 static Lisp_Object frame_and_buffer_state;
|
|
5769
|
|
5770
|
|
5771 DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
|
|
5772 Sframe_or_buffer_changed_p, 0, 0, 0,
|
|
5773 "Return non-nil if the frame and buffer state appears to have changed.\n\
|
|
5774 The state variable is an internal vector containing all frames and buffers,\n\
|
|
5775 aside from buffers whose names start with space,\n\
|
|
5776 along with the buffers' read-only and modified flags, which allows a fast\n\
|
|
5777 check to see whether the menu bars might need to be recomputed.\n\
|
|
5778 If this function returns non-nil, it updates the internal vector to reflect\n\
|
|
5779 the current state.\n")
|
|
5780 ()
|
|
5781 {
|
|
5782 Lisp_Object tail, frame, buf;
|
|
5783 Lisp_Object *vecp;
|
|
5784 int n;
|
|
5785
|
|
5786 vecp = XVECTOR (frame_and_buffer_state)->contents;
|
|
5787 FOR_EACH_FRAME (tail, frame)
|
|
5788 {
|
|
5789 if (!EQ (*vecp++, frame))
|
|
5790 goto changed;
|
|
5791 if (!EQ (*vecp++, XFRAME (frame)->name))
|
|
5792 goto changed;
|
|
5793 }
|
|
5794 /* Check that the buffer info matches.
|
|
5795 No need to test for the end of the vector
|
|
5796 because the last element of the vector is lambda
|
|
5797 and that will always cause a mismatch. */
|
26164
|
5798 for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
|
25012
|
5799 {
|
26164
|
5800 buf = XCDR (XCAR (tail));
|
25012
|
5801 /* Ignore buffers that aren't included in buffer lists. */
|
|
5802 if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
|
|
5803 continue;
|
|
5804 if (!EQ (*vecp++, buf))
|
|
5805 goto changed;
|
|
5806 if (!EQ (*vecp++, XBUFFER (buf)->read_only))
|
|
5807 goto changed;
|
|
5808 if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
|
|
5809 goto changed;
|
|
5810 }
|
|
5811 /* Detect deletion of a buffer at the end of the list. */
|
|
5812 if (EQ (*vecp, Qlambda))
|
|
5813 return Qnil;
|
|
5814 changed:
|
|
5815 /* Start with 1 so there is room for at least one lambda at the end. */
|
|
5816 n = 1;
|
|
5817 FOR_EACH_FRAME (tail, frame)
|
|
5818 n += 2;
|
26164
|
5819 for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
|
25012
|
5820 n += 3;
|
|
5821 /* Reallocate the vector if it's grown, or if it's shrunk a lot. */
|
|
5822 if (n > XVECTOR (frame_and_buffer_state)->size
|
|
5823 || n + 20 < XVECTOR (frame_and_buffer_state)->size / 2)
|
|
5824 /* Add 20 extra so we grow it less often. */
|
|
5825 frame_and_buffer_state = Fmake_vector (make_number (n + 20), Qlambda);
|
|
5826 vecp = XVECTOR (frame_and_buffer_state)->contents;
|
|
5827 FOR_EACH_FRAME (tail, frame)
|
|
5828 {
|
|
5829 *vecp++ = frame;
|
|
5830 *vecp++ = XFRAME (frame)->name;
|
|
5831 }
|
26164
|
5832 for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
|
25012
|
5833 {
|
26164
|
5834 buf = XCDR (XCAR (tail));
|
25012
|
5835 /* Ignore buffers that aren't included in buffer lists. */
|
|
5836 if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
|
|
5837 continue;
|
|
5838 *vecp++ = buf;
|
|
5839 *vecp++ = XBUFFER (buf)->read_only;
|
|
5840 *vecp++ = Fbuffer_modified_p (buf);
|
|
5841 }
|
|
5842 /* Fill up the vector with lambdas (always at least one). */
|
|
5843 *vecp++ = Qlambda;
|
|
5844 while (vecp - XVECTOR (frame_and_buffer_state)->contents
|
|
5845 < XVECTOR (frame_and_buffer_state)->size)
|
|
5846 *vecp++ = Qlambda;
|
|
5847 /* Make sure we didn't overflow the vector. */
|
|
5848 if (vecp - XVECTOR (frame_and_buffer_state)->contents
|
|
5849 > XVECTOR (frame_and_buffer_state)->size)
|
|
5850 abort ();
|
|
5851 return Qt;
|
|
5852 }
|
|
5853
|
|
5854
|
|
5855
|
|
5856 /***********************************************************************
|
|
5857 Initialization
|
|
5858 ***********************************************************************/
|
|
5859
|
314
|
5860 char *terminal_type;
|
|
5861
|
25012
|
5862 /* Initialization done when Emacs fork is started, before doing stty.
|
|
5863 Determine terminal type and set terminal_driver. Then invoke its
|
|
5864 decoding routine to set up variables in the terminal package. */
|
314
|
5865
|
21514
|
5866 void
|
314
|
5867 init_display ()
|
|
5868 {
|
|
5869 #ifdef HAVE_X_WINDOWS
|
|
5870 extern int display_arg;
|
|
5871 #endif
|
|
5872
|
25012
|
5873 /* Construct the space glyph. */
|
|
5874 space_glyph.type = CHAR_GLYPH;
|
|
5875 SET_CHAR_GLYPH_FROM_GLYPH (space_glyph, ' ');
|
|
5876 space_glyph.charpos = -1;
|
|
5877
|
314
|
5878 meta_key = 0;
|
|
5879 inverse_video = 0;
|
|
5880 cursor_in_echo_area = 0;
|
|
5881 terminal_type = (char *) 0;
|
|
5882
|
2339
|
5883 /* Now is the time to initialize this; it's used by init_sys_modes
|
|
5884 during startup. */
|
|
5885 Vwindow_system = Qnil;
|
314
|
5886
|
2339
|
5887 /* If the user wants to use a window system, we shouldn't bother
|
|
5888 initializing the terminal. This is especially important when the
|
|
5889 terminal is so dumb that emacs gives up before and doesn't bother
|
|
5890 using the window system.
|
|
5891
|
14125
|
5892 If the DISPLAY environment variable is set and nonempty,
|
|
5893 try to use X, and die with an error message if that doesn't work. */
|
314
|
5894
|
|
5895 #ifdef HAVE_X_WINDOWS
|
2359
|
5896 if (! display_arg)
|
|
5897 {
|
14125
|
5898 char *display;
|
2359
|
5899 #ifdef VMS
|
14125
|
5900 display = getenv ("DECW$DISPLAY");
|
2359
|
5901 #else
|
14125
|
5902 display = getenv ("DISPLAY");
|
2359
|
5903 #endif
|
14125
|
5904
|
|
5905 display_arg = (display != 0 && *display != 0);
|
2364
|
5906 }
|
2359
|
5907
|
18774
|
5908 if (!inhibit_window_system && display_arg
|
|
5909 #ifndef CANNOT_DUMP
|
|
5910 && initialized
|
|
5911 #endif
|
|
5912 )
|
314
|
5913 {
|
|
5914 Vwindow_system = intern ("x");
|
|
5915 #ifdef HAVE_X11
|
|
5916 Vwindow_system_version = make_number (11);
|
|
5917 #else
|
|
5918 Vwindow_system_version = make_number (10);
|
|
5919 #endif
|
15273
|
5920 #if defined (LINUX) && defined (HAVE_LIBNCURSES)
|
|
5921 /* In some versions of ncurses,
|
15282
|
5922 tputs crashes if we have not called tgetent.
|
15273
|
5923 So call tgetent. */
|
|
5924 { char b[2044]; tgetent (b, "xterm");}
|
|
5925 #endif
|
25012
|
5926 adjust_frame_glyphs_initially ();
|
314
|
5927 return;
|
|
5928 }
|
|
5929 #endif /* HAVE_X_WINDOWS */
|
|
5930
|
13408
|
5931 #ifdef HAVE_NTGUI
|
|
5932 if (!inhibit_window_system)
|
|
5933 {
|
16589
ec300a10e407
(init_display) [HAVE_NTGUI]: Use w32 for window-system.
Geoff Voelker <voelker@cs.washington.edu>
diff
changeset
|
5934 Vwindow_system = intern ("w32");
|
13408
|
5935 Vwindow_system_version = make_number (1);
|
25012
|
5936 adjust_frame_glyphs_initially ();
|
13408
|
5937 return;
|
|
5938 }
|
|
5939 #endif /* HAVE_NTGUI */
|
|
5940
|
314
|
5941 /* If no window system has been specified, try to use the terminal. */
|
|
5942 if (! isatty (0))
|
|
5943 {
|
16896
|
5944 fatal ("standard input is not a tty");
|
314
|
5945 exit (1);
|
|
5946 }
|
|
5947
|
|
5948 /* Look at the TERM variable */
|
|
5949 terminal_type = (char *) getenv ("TERM");
|
|
5950 if (!terminal_type)
|
|
5951 {
|
|
5952 #ifdef VMS
|
|
5953 fprintf (stderr, "Please specify your terminal type.\n\
|
|
5954 For types defined in VMS, use set term /device=TYPE.\n\
|
|
5955 For types not defined in VMS, use define emacs_term \"TYPE\".\n\
|
|
5956 \(The quotation marks are necessary since terminal types are lower case.)\n");
|
|
5957 #else
|
|
5958 fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
|
|
5959 #endif
|
|
5960 exit (1);
|
|
5961 }
|
|
5962
|
|
5963 #ifdef VMS
|
25012
|
5964 /* VMS DCL tends to up-case things, so down-case term type.
|
314
|
5965 Hardly any uppercase letters in terminal types; should be none. */
|
|
5966 {
|
|
5967 char *new = (char *) xmalloc (strlen (terminal_type) + 1);
|
|
5968 char *p;
|
|
5969
|
|
5970 strcpy (new, terminal_type);
|
|
5971
|
|
5972 for (p = new; *p; p++)
|
|
5973 if (isupper (*p))
|
|
5974 *p = tolower (*p);
|
|
5975
|
|
5976 terminal_type = new;
|
|
5977 }
|
25012
|
5978 #endif /* VMS */
|
314
|
5979
|
|
5980 term_init (terminal_type);
|
25012
|
5981
|
16891
|
5982 {
|
25666
|
5983 struct frame *sf = SELECTED_FRAME ();
|
|
5984 int width = FRAME_WINDOW_WIDTH (sf);
|
|
5985 int height = FRAME_HEIGHT (sf);
|
16891
|
5986
|
25012
|
5987 unsigned int total_glyphs = height * (width + 2) * sizeof (struct glyph);
|
|
5988
|
|
5989 /* If these sizes are so big they cause overflow, just ignore the
|
|
5990 change. It's not clear what better we could do. */
|
|
5991 if (total_glyphs / sizeof (struct glyph) / height != width + 2)
|
16896
|
5992 fatal ("screen size %dx%d too big", width, height);
|
16891
|
5993 }
|
|
5994
|
25012
|
5995 adjust_frame_glyphs_initially ();
|
25666
|
5996 calculate_costs (XFRAME (selected_frame));
|
314
|
5997
|
|
5998 #ifdef SIGWINCH
|
|
5999 #ifndef CANNOT_DUMP
|
|
6000 if (initialized)
|
|
6001 #endif /* CANNOT_DUMP */
|
|
6002 signal (SIGWINCH, window_change_signal);
|
|
6003 #endif /* SIGWINCH */
|
25012
|
6004
|
|
6005 /* Set up faces of the initial terminal frame of a dumped Emacs. */
|
|
6006 if (initialized
|
|
6007 && !noninteractive
|
25118
|
6008 #ifdef MSDOS
|
|
6009 /* The MSDOS terminal turns on its ``window system'' relatively
|
|
6010 late into the startup, so we cannot do the frame faces'
|
|
6011 initialization just yet. It will be done later by pc-win.el
|
|
6012 and internal_terminal_init. */
|
|
6013 && (strcmp (terminal_type, "internal") != 0 || inhibit_window_system)
|
|
6014 #endif
|
25012
|
6015 && NILP (Vwindow_system))
|
26729
|
6016 {
|
|
6017 /* For the initial frame, we don't have any way of knowing what
|
|
6018 are the foreground and background colors of the terminal. */
|
|
6019 struct frame *sf = SELECTED_FRAME();
|
|
6020
|
26902
|
6021 FRAME_FOREGROUND_PIXEL (sf) = FACE_TTY_DEFAULT_FG_COLOR;
|
|
6022 FRAME_BACKGROUND_PIXEL (sf) = FACE_TTY_DEFAULT_BG_COLOR;
|
26729
|
6023 call0 (intern ("tty-set-up-initial-frame-faces"));
|
|
6024 }
|
314
|
6025 }
|
25012
|
6026
|
|
6027
|
314
|
6028
|
25012
|
6029 /***********************************************************************
|
|
6030 Blinking cursor
|
|
6031 ***********************************************************************/
|
|
6032
|
26280
|
6033 DEFUN ("internal-show-cursor", Finternal_show_cursor,
|
26334
|
6034 Sinternal_show_cursor, 2, 2, 0,
|
|
6035 "Set the cursor-visibility flag of WINDOW to SHOW.\n\
|
|
6036 WINDOW nil means use the selected window. SHOW non-nil means\n\
|
|
6037 show a cursor in WINDOW in the next redisplay. SHOW nil means\n\
|
|
6038 don't show a cursor.")
|
|
6039 (window, show)
|
|
6040 Lisp_Object window, show;
|
25012
|
6041 {
|
|
6042 /* Don't change cursor state while redisplaying. This could confuse
|
|
6043 output routines. */
|
|
6044 if (!redisplaying_p)
|
|
6045 {
|
|
6046 if (NILP (window))
|
|
6047 window = selected_window;
|
|
6048 else
|
|
6049 CHECK_WINDOW (window, 2);
|
|
6050
|
26334
|
6051 XWINDOW (window)->cursor_off_p = NILP (show);
|
25012
|
6052 }
|
|
6053
|
|
6054 return Qnil;
|
|
6055 }
|
|
6056
|
|
6057
|
26334
|
6058 DEFUN ("internal-show-cursor-p", Finternal_show_cursor_p,
|
|
6059 Sinternal_show_cursor_p, 0, 1, 0,
|
26499
|
6060 "Value is non-nil if next redisplay will display a cursor in WINDOW.\n\
|
26334
|
6061 WINDOW nil or omitted means report on the selected window.")
|
|
6062 (window)
|
|
6063 Lisp_Object window;
|
|
6064 {
|
|
6065 struct window *w;
|
|
6066
|
|
6067 if (NILP (window))
|
|
6068 window = selected_window;
|
|
6069 else
|
|
6070 CHECK_WINDOW (window, 2);
|
|
6071
|
|
6072 w = XWINDOW (window);
|
|
6073 return w->cursor_off_p ? Qnil : Qt;
|
|
6074 }
|
|
6075
|
25012
|
6076
|
|
6077 /***********************************************************************
|
|
6078 Initialization
|
|
6079 ***********************************************************************/
|
|
6080
|
21514
|
6081 void
|
314
|
6082 syms_of_display ()
|
|
6083 {
|
764
|
6084 defsubr (&Sredraw_frame);
|
314
|
6085 defsubr (&Sredraw_display);
|
7810
|
6086 defsubr (&Sframe_or_buffer_changed_p);
|
314
|
6087 defsubr (&Sopen_termscript);
|
|
6088 defsubr (&Sding);
|
|
6089 defsubr (&Ssit_for);
|
|
6090 defsubr (&Ssleep_for);
|
|
6091 defsubr (&Ssend_string_to_terminal);
|
26280
|
6092 defsubr (&Sinternal_show_cursor);
|
26334
|
6093 defsubr (&Sinternal_show_cursor_p);
|
314
|
6094
|
12186
|
6095 frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
|
7810
|
6096 staticpro (&frame_and_buffer_state);
|
|
6097
|
13220
|
6098 Qdisplay_table = intern ("display-table");
|
|
6099 staticpro (&Qdisplay_table);
|
|
6100
|
314
|
6101 DEFVAR_INT ("baud-rate", &baud_rate,
|
7926
|
6102 "*The output baud rate of the terminal.\n\
|
314
|
6103 On most systems, changing this value will affect the amount of padding\n\
|
|
6104 and the other strategic decisions made during redisplay.");
|
25012
|
6105
|
314
|
6106 DEFVAR_BOOL ("inverse-video", &inverse_video,
|
764
|
6107 "*Non-nil means invert the entire frame display.\n\
|
314
|
6108 This means everything is in inverse video which otherwise would not be.");
|
25012
|
6109
|
314
|
6110 DEFVAR_BOOL ("visible-bell", &visible_bell,
|
764
|
6111 "*Non-nil means try to flash the frame to represent a bell.");
|
25012
|
6112
|
314
|
6113 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
|
764
|
6114 "*Non-nil means no need to redraw entire frame after suspending.\n\
|
314
|
6115 A non-nil value is useful if the terminal can automatically preserve\n\
|
764
|
6116 Emacs's frame display when you reenter Emacs.\n\
|
314
|
6117 It is up to you to set this variable if your terminal can do that.");
|
25012
|
6118
|
314
|
6119 DEFVAR_LISP ("window-system", &Vwindow_system,
|
|
6120 "A symbol naming the window-system under which Emacs is running\n\
|
|
6121 \(such as `x'), or nil if emacs is running on an ordinary terminal.");
|
25012
|
6122
|
314
|
6123 DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
|
|
6124 "The version number of the window system in use.\n\
|
|
6125 For X windows, this is 10 or 11.");
|
25012
|
6126
|
314
|
6127 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
|
|
6128 "Non-nil means put cursor in minibuffer, at end of any message there.");
|
25012
|
6129
|
314
|
6130 DEFVAR_LISP ("glyph-table", &Vglyph_table,
|
764
|
6131 "Table defining how to output a glyph code to the frame.\n\
|
314
|
6132 If not nil, this is a vector indexed by glyph code to define the glyph.\n\
|
|
6133 Each element can be:\n\
|
|
6134 integer: a glyph code which this glyph is an alias for.\n\
|
|
6135 string: output this glyph using that string (not impl. in X windows).\n\
|
|
6136 nil: this glyph mod 256 is char code to output,\n\
|
6857
|
6137 and this glyph / 256 is face code for X windows (see `face-id').");
|
314
|
6138 Vglyph_table = Qnil;
|
|
6139
|
|
6140 DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
|
|
6141 "Display table to use for buffers that specify none.\n\
|
|
6142 See `buffer-display-table' for more information.");
|
|
6143 Vstandard_display_table = Qnil;
|
|
6144
|
25012
|
6145 DEFVAR_BOOL ("redisplay-dont-pause", &redisplay_dont_pause,
|
|
6146 "*Non-nil means update isn't paused when input is detected.");
|
|
6147 redisplay_dont_pause = 0;
|
|
6148
|
314
|
6149 /* Initialize `window-system', unless init_display already decided it. */
|
|
6150 #ifdef CANNOT_DUMP
|
|
6151 if (noninteractive)
|
|
6152 #endif
|
|
6153 {
|
|
6154 Vwindow_system = Qnil;
|
|
6155 Vwindow_system_version = Qnil;
|
|
6156 }
|
|
6157 }
|