Mercurial > hg > xemacs-beta
annotate src/gutter.c @ 4967:0d4c9d0f6a8d
rewrite dynarr code
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-02-03 Ben Wing <ben@xemacs.org>
* device-x.c (x_get_resource_prefix):
* device-x.c (Fx_get_resource):
* device-x.c (Fx_get_resource_prefix):
* device-x.c (Fx_put_resource):
* dialog-msw.c:
* dialog-msw.c (handle_question_dialog_box):
* dired-msw.c (mswindows_sort_files):
* dired-msw.c (mswindows_get_files):
* extents.c (extent_fragment_sort_by_priority):
* extents.c (Fset_extent_parent):
* file-coding.c (coding_reader):
* file-coding.c (coding_writer):
* file-coding.c (gzip_convert):
* frame.c (generate_title_string):
* gutter.c (calculate_gutter_size_from_display_lines):
* indent.c (vmotion_1):
* lread.c (read_bit_vector):
* mule-coding.c (iso2022_decode):
* rangetab.c:
* rangetab.c (Fcopy_range_table):
* rangetab.c (Fget_range_table):
* rangetab.c (unified_range_table_copy_data):
* redisplay-msw.c (mswindows_output_string):
* redisplay-output.c (output_display_line):
* redisplay-output.c (redisplay_move_cursor):
* redisplay-output.c (redisplay_clear_bottom_of_window):
* redisplay-tty.c (tty_output_ichar_dynarr):
* redisplay-tty.c (set_foreground_to):
* redisplay-tty.c (set_background_to):
* redisplay-xlike-inc.c (XLIKE_output_string):
* redisplay.c (redisplay_window_text_width_string):
* redisplay.c (redisplay_text_width_string):
* redisplay.c (create_text_block):
* redisplay.c (SET_CURRENT_MODE_CHARS_PIXSIZE):
* redisplay.c (generate_fstring_runes):
* redisplay.c (regenerate_modeline):
* redisplay.c (ensure_modeline_generated):
* redisplay.c (real_current_modeline_height):
* redisplay.c (create_string_text_block):
* redisplay.c (regenerate_window):
* redisplay.c (REGEN_INC_FIND_START_END):
* redisplay.c (point_visible):
* redisplay.c (redisplay_window):
* redisplay.c (mark_glyph_block_dynarr):
* redisplay.c (line_start_cache_start):
* redisplay.c (start_with_line_at_pixpos):
* redisplay.c (update_line_start_cache):
* redisplay.c (glyph_to_pixel_translation):
* redisplay.c (pixel_to_glyph_translation):
* sysdep.c (qxe_readdir):
* text.c (dfc_convert_to_external_format):
* text.c (dfc_convert_to_internal_format):
* toolbar-common.c (common_output_toolbar_button):
* window.c (window_modeline_height):
* window.c (Fwindow_last_line_visible_height):
* window.c (window_displayed_height):
* window.c (window_scroll):
* window.c (get_current_pixel_pos):
Use Dynarr_begin() in place of Dynarr_atp (foo, 0).
* dynarr.c (Dynarr_realloc):
* dynarr.c (Dynarr_lisp_realloc):
* dynarr.c (Dynarr_resize):
* dynarr.c (Dynarr_insert_many):
* dynarr.c (Dynarr_delete_many):
* dynarr.c (Dynarr_memory_usage):
* dynarr.c (stack_like_malloc):
* dynarr.c (stack_like_free):
* lisp.h:
* lisp.h (DECLARE_DYNARR_LISP_IMP):
* lisp.h (XD_DYNARR_DESC):
* lisp.h (Dynarr_pop):
* gutter.c (output_gutter):
* redisplay-output.c (sync_rune_structs):
* redisplay-output.c (redisplay_output_window):
Redo the dynarr code, add greater checks.
Rename the `len', `largest' and `max' members to `len_',
`largest_' and `max_' to try and catch existing places that might
directly modify these values. Make new accessors Dynarr_largest()
and Dynarr_max() and make them and existing Dynarr_length() be
non-lvalues by adding '+ 0' to them; fix a couple of places in the
redisplay code that tried to modify the length directly by setting
Dynarr_length(). Use the accessors whenever possible even in the
dynarr code itself. The accessors also verify that 0 <= len <=
largest <= max. Rename settor function Dynarr_set_size() to
Dynarr_set_length() and use it more consistently; also create
lower-level Dynarr_set_length_1(). This latter function should be
the only function that directly modifies the `len_' member of a
Dynarr, and in the process makes sure that the `largest' value is
kept correct.
Consistently use ERROR_CHECK_STRUCTURES instead of
ERROR_CHECK_TYPES for error-checking code. Reintroduce the
temporarily disabled verification code on the positions of
Dynarr_at(), Dynarr_atp() and Dynarr_atp_past_end().
Also create Dynarr_resize_if() in place of a repeated
code fragment. Clean up all the functions that modify Dynarrs to
use the new macros and functions and verify the correctness of the
Dynarr both before and after the change.
Note that there are two kinds of verification -- one for accessing
and one for modifying. The difference is that the modify
verification additionally checks to make sure that the Dynarr
isn't locked. (This is used in redisplay to check for problems
with reentrancy.)
* lrecord.h: Move XD_DYNARR_DESC to lisp.h, grouping with the dynarr code.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Wed, 03 Feb 2010 20:51:18 -0600 |
parents | 91b3d00e717f |
children | 9410323e4b0d d0c14ea98592 |
rev | line source |
---|---|
428 | 1 /* Gutter implementation. |
442 | 2 Copyright (C) 1999, 2000 Andy Piper. |
428 | 3 |
4 This file is part of XEmacs. | |
5 | |
6 XEmacs is free software; you can redistribute it and/or modify it | |
7 under the terms of the GNU General Public License as published by the | |
8 Free Software Foundation; either version 2, or (at your option) any | |
9 later version. | |
10 | |
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with XEmacs; see the file COPYING. If not, write to | |
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
19 Boston, MA 02111-1307, USA. */ | |
20 | |
21 /* Synched up with: Not in FSF. */ | |
22 | |
23 /* written by Andy Piper <andy@xemacs.org> with specifiers partially | |
24 ripped-off from toolbar.c */ | |
25 | |
26 #include <config.h> | |
27 #include "lisp.h" | |
28 | |
29 #include "buffer.h" | |
872 | 30 #include "frame-impl.h" |
31 #include "device-impl.h" | |
428 | 32 #include "faces.h" |
33 #include "glyphs.h" | |
34 #include "redisplay.h" | |
35 #include "window.h" | |
36 #include "gutter.h" | |
37 | |
38 Lisp_Object Vgutter[4]; | |
39 Lisp_Object Vgutter_size[4]; | |
40 Lisp_Object Vgutter_visible_p[4]; | |
41 Lisp_Object Vgutter_border_width[4]; | |
42 | |
43 Lisp_Object Vdefault_gutter, Vdefault_gutter_visible_p; | |
44 Lisp_Object Vdefault_gutter_width, Vdefault_gutter_height; | |
45 Lisp_Object Vdefault_gutter_border_width; | |
46 | |
47 Lisp_Object Vdefault_gutter_position; | |
48 | |
49 Lisp_Object Qgutter_size; | |
442 | 50 Lisp_Object Qgutter_visible; |
51 Lisp_Object Qdefault_gutter_position_changed_hook; | |
52 | |
53 static void | |
54 update_gutter_geometry (struct frame *f, enum gutter_pos pos); | |
428 | 55 |
56 #define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag) \ | |
57 do { \ | |
58 switch (pos) \ | |
59 { \ | |
60 case TOP_GUTTER: \ | |
61 (frame)->top_gutter_was_visible = flag; \ | |
62 break; \ | |
63 case BOTTOM_GUTTER: \ | |
64 (frame)->bottom_gutter_was_visible = flag; \ | |
65 break; \ | |
66 case LEFT_GUTTER: \ | |
67 (frame)->left_gutter_was_visible = flag; \ | |
68 break; \ | |
69 case RIGHT_GUTTER: \ | |
70 (frame)->right_gutter_was_visible = flag; \ | |
71 break; \ | |
72 default: \ | |
2500 | 73 ABORT (); \ |
428 | 74 } \ |
75 } while (0) | |
76 | |
77 static int gutter_was_visible (struct frame* frame, enum gutter_pos pos) | |
78 { | |
79 switch (pos) | |
80 { | |
81 case TOP_GUTTER: | |
82 return frame->top_gutter_was_visible; | |
83 case BOTTOM_GUTTER: | |
84 return frame->bottom_gutter_was_visible; | |
85 case LEFT_GUTTER: | |
86 return frame->left_gutter_was_visible; | |
87 case RIGHT_GUTTER: | |
88 return frame->right_gutter_was_visible; | |
89 default: | |
2500 | 90 ABORT (); |
442 | 91 return 0; /* To keep the compiler happy */ |
428 | 92 } |
93 } | |
94 | |
442 | 95 #if 0 |
428 | 96 static Lisp_Object |
97 frame_topmost_window (struct frame *f) | |
98 { | |
99 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
100 | |
101 do { | |
102 while (!NILP (XWINDOW (w)->vchild)) | |
103 { | |
104 w = XWINDOW (w)->vchild; | |
105 } | |
106 } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild)); | |
107 | |
108 return w; | |
109 } | |
442 | 110 #endif |
428 | 111 |
112 static Lisp_Object | |
113 frame_bottommost_window (struct frame *f) | |
114 { | |
115 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
116 | |
117 do { | |
118 while (!NILP (XWINDOW (w)->vchild)) | |
119 { | |
120 w = XWINDOW (w)->vchild; | |
121 while (!NILP (XWINDOW (w)->next)) | |
122 { | |
123 w = XWINDOW (w)->next; | |
124 } | |
125 } | |
126 } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild)); | |
127 | |
128 return w; | |
129 } | |
130 | |
131 #if 0 | |
132 static Lisp_Object | |
133 frame_leftmost_window (struct frame *f) | |
134 { | |
135 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
136 | |
137 do { | |
138 while (!NILP (XWINDOW (w)->hchild)) | |
139 { | |
140 w = XWINDOW (w)->hchild; | |
141 } | |
142 } while (!NILP (XWINDOW (w)->vchild) && !NILP (w = XWINDOW (w)->vchild)); | |
143 | |
144 return w; | |
145 } | |
146 | |
147 static Lisp_Object | |
148 frame_rightmost_window (struct frame *f) | |
149 { | |
150 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
151 | |
152 do { | |
153 while (!NILP (XWINDOW (w)->hchild)) | |
154 { | |
155 w = XWINDOW (w)->hchild; | |
156 while (!NILP (XWINDOW (w)->next)) | |
157 { | |
158 w = XWINDOW (w)->next; | |
159 } | |
160 } | |
161 } while (!NILP (XWINDOW (w)->vchild) && !NILP (w = XWINDOW (w)->vchild)); | |
162 return w; | |
163 } | |
164 #endif | |
165 | |
166 /* calculate the coordinates of a gutter for the current frame and | |
167 selected window. we have to be careful in calculating this as we | |
168 need to use *two* windows, the currently selected window will give | |
169 us the actual height, width and contents of the gutter, but if we | |
170 use this for calculating the gutter positions we run into trouble | |
171 if it is not the window nearest the gutter. Instead we predetermine | |
172 the nearest window and then use that.*/ | |
173 static void | |
174 get_gutter_coords (struct frame *f, enum gutter_pos pos, int *x, int *y, | |
175 int *width, int *height) | |
176 { | |
177 struct window | |
178 * bot = XWINDOW (frame_bottommost_window (f)); | |
179 /* The top and bottom gutters take precedence over the left and | |
180 right. */ | |
181 switch (pos) | |
182 { | |
183 case TOP_GUTTER: | |
184 *x = FRAME_LEFT_BORDER_END (f); | |
185 *y = FRAME_TOP_BORDER_END (f); | |
442 | 186 *width = FRAME_RIGHT_BORDER_START (f) |
428 | 187 - FRAME_LEFT_BORDER_END (f); |
188 *height = FRAME_TOP_GUTTER_BOUNDS (f); | |
189 break; | |
190 | |
191 case BOTTOM_GUTTER: | |
192 *x = FRAME_LEFT_BORDER_END (f); | |
442 | 193 *y = WINDOW_BOTTOM (bot); |
194 *width = FRAME_RIGHT_BORDER_START (f) | |
428 | 195 - FRAME_LEFT_BORDER_END (f); |
196 *height = FRAME_BOTTOM_GUTTER_BOUNDS (f); | |
197 break; | |
198 | |
199 case LEFT_GUTTER: | |
200 *x = FRAME_LEFT_BORDER_END (f); | |
442 | 201 *y = FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f); |
428 | 202 *width = FRAME_LEFT_GUTTER_BOUNDS (f); |
203 *height = WINDOW_BOTTOM (bot) | |
442 | 204 - (FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f)); |
428 | 205 break; |
442 | 206 |
428 | 207 case RIGHT_GUTTER: |
208 *x = FRAME_RIGHT_BORDER_START (f) | |
209 - FRAME_RIGHT_GUTTER_BOUNDS (f); | |
442 | 210 *y = FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f); |
428 | 211 *width = FRAME_RIGHT_GUTTER_BOUNDS (f); |
212 *height = WINDOW_BOTTOM (bot) | |
442 | 213 - (FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f)); |
428 | 214 break; |
215 | |
216 default: | |
2500 | 217 ABORT (); |
428 | 218 } |
219 } | |
220 | |
446 | 221 /* |
222 display_boxes_in_gutter_p | |
223 | |
224 Determine whether the required display_glyph_area is completely | |
225 inside the gutter. -1 means the display_box is not in the gutter. 1 | |
226 means the display_box and the display_glyph_area are in the | |
227 window. 0 means the display_box is in the gutter but the | |
228 display_glyph_area is not. */ | |
229 int display_boxes_in_gutter_p (struct frame *f, struct display_box* db, | |
230 struct display_glyph_area* dga) | |
231 { | |
232 enum gutter_pos pos; | |
233 GUTTER_POS_LOOP (pos) | |
234 { | |
235 if (FRAME_GUTTER_VISIBLE (f, pos)) | |
236 { | |
237 int x, y, width, height; | |
238 get_gutter_coords (f, pos, &x, &y, &width, &height); | |
239 if (db->xpos + dga->xoffset >= x | |
240 && | |
241 db->ypos + dga->yoffset >= y | |
242 && | |
243 db->xpos + dga->xoffset + dga->width <= x + width | |
244 && | |
245 db->ypos + dga->yoffset + dga->height <= y + height) | |
246 return 1; | |
247 else if (db->xpos >= x && db->ypos >= y | |
248 && db->xpos + db->width <= x + width | |
249 && db->ypos + db->height <= y + height) | |
250 return 0; | |
251 } | |
252 } | |
253 return -1; | |
254 } | |
255 | |
442 | 256 /* Convert the gutter specifier into something we can actually |
257 display. */ | |
258 static Lisp_Object construct_window_gutter_spec (struct window* w, | |
259 enum gutter_pos pos) | |
260 { | |
261 Lisp_Object rest, *args; | |
262 int nargs = 0; | |
263 Lisp_Object gutter = RAW_WINDOW_GUTTER (w, pos); | |
264 | |
265 if (STRINGP (gutter) || NILP (gutter)) | |
266 return gutter; | |
267 | |
268 GET_LIST_LENGTH (gutter, nargs); | |
269 args = alloca_array (Lisp_Object, nargs >> 1); | |
270 nargs = 0; | |
271 | |
272 for (rest = gutter; !NILP (rest); rest = XCDR (XCDR (rest))) | |
273 { | |
274 /* We only put things in the real gutter that are declared to be | |
4186 | 275 visible. */ |
442 | 276 if (!CONSP (WINDOW_GUTTER_VISIBLE (w, pos)) |
277 || | |
278 !NILP (Fmemq (XCAR (rest), WINDOW_GUTTER_VISIBLE (w, pos)))) | |
279 { | |
280 args [nargs++] = XCAR (XCDR (rest)); | |
281 } | |
282 } | |
283 | |
284 return Fconcat (nargs, args); | |
285 } | |
286 | |
444 | 287 /* Sizing gutters is a pain so we try and help the user by determining |
288 what height will accommodate all lines. This is useless on left and | |
289 right gutters as we always have a maximal number of lines. */ | |
290 static int | |
291 calculate_gutter_size_from_display_lines (enum gutter_pos pos, | |
292 display_line_dynarr* ddla) | |
293 { | |
294 int size = 0; | |
295 struct display_line *dl; | |
296 | |
297 /* For top and bottom the calculation is easy. */ | |
298 if (pos == TOP_GUTTER || pos == BOTTOM_GUTTER) | |
299 { | |
300 /* grab coordinates of last line */ | |
301 if (Dynarr_length (ddla)) | |
302 { | |
303 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); | |
4186 | 304 size = (dl->ypos + dl->descent - dl->clip) |
4967 | 305 - (Dynarr_begin (ddla)->ypos - Dynarr_begin (ddla)->ascent); |
444 | 306 } |
307 } | |
308 /* For left and right we have to do some maths. */ | |
309 else | |
310 { | |
311 int start_pos = 0, end_pos = 0, line; | |
312 for (line = 0; line < Dynarr_length (ddla); line++) | |
313 { | |
314 int block; | |
315 dl = Dynarr_atp (ddla, line); | |
316 | |
317 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++) | |
318 { | |
319 struct display_block *db = Dynarr_atp (dl->display_blocks, block); | |
320 | |
321 if (db->type == TEXT) | |
322 { | |
323 start_pos = min (db->start_pos, start_pos); | |
324 end_pos = max (db->end_pos, end_pos); | |
325 } | |
326 } | |
327 } | |
328 size = end_pos - start_pos; | |
329 } | |
330 | |
331 return size; | |
332 } | |
333 | |
334 static Lisp_Object | |
335 calculate_gutter_size (struct window *w, enum gutter_pos pos) | |
336 { | |
337 struct frame* f = XFRAME (WINDOW_FRAME (w)); | |
1318 | 338 display_line_dynarr *ddla; |
444 | 339 Lisp_Object ret = Qnil; |
340 | |
1318 | 341 /* Callers need to handle this. */ |
342 assert (!in_display); | |
444 | 343 /* degenerate case */ |
344 if (NILP (RAW_WINDOW_GUTTER (w, pos)) | |
345 || | |
346 !FRAME_VISIBLE_P (f) | |
347 || | |
348 NILP (w->buffer)) | |
349 return Qnil; | |
350 | |
1318 | 351 if (!in_display) |
352 { | |
353 int count; | |
354 | |
355 /* We are calling directly into redisplay from the outside, so turn on | |
356 critical section protection. */ | |
357 count = enter_redisplay_critical_section (); | |
444 | 358 |
1318 | 359 ddla = Dynarr_new (display_line); |
360 /* generate some display lines */ | |
361 generate_displayable_area (w, WINDOW_GUTTER (w, pos), | |
362 FRAME_LEFT_BORDER_END (f), | |
363 FRAME_TOP_BORDER_END (f), | |
364 FRAME_RIGHT_BORDER_START (f) | |
365 - FRAME_LEFT_BORDER_END (f), | |
366 FRAME_BOTTOM_BORDER_START (f) | |
367 - FRAME_TOP_BORDER_END (f), | |
4186 | 368 ddla, 0, DEFAULT_INDEX); |
444 | 369 |
1318 | 370 /* Let GC happen again. */ |
371 exit_redisplay_critical_section (count); | |
444 | 372 |
1318 | 373 ret = make_int (calculate_gutter_size_from_display_lines (pos, ddla)); |
374 free_display_lines (ddla); | |
375 } | |
444 | 376 |
377 return ret; | |
378 } | |
379 | |
428 | 380 static void |
442 | 381 output_gutter (struct frame *f, enum gutter_pos pos, int force) |
428 | 382 { |
383 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
384 struct device *d = XDEVICE (f->device); | |
385 struct window* w = XWINDOW (window); | |
386 int x, y, width, height, ypos; | |
440 | 387 int line, border_width; |
388 face_index findex; | |
428 | 389 display_line_dynarr* ddla, *cdla; |
442 | 390 struct display_line *dl = 0; |
428 | 391 int cdla_len; |
392 | |
440 | 393 if (!WINDOW_LIVE_P (w)) |
394 return; | |
395 | |
396 border_width = FRAME_GUTTER_BORDER_WIDTH (f, pos); | |
442 | 397 findex = get_builtin_face_cache_index (w, Vwidget_face); |
440 | 398 |
442 | 399 if (!f->current_display_lines[pos]) |
400 f->current_display_lines[pos] = Dynarr_new (display_line); | |
401 if (!f->desired_display_lines[pos]) | |
402 f->desired_display_lines[pos] = Dynarr_new (display_line); | |
428 | 403 |
442 | 404 ddla = f->desired_display_lines[pos]; |
405 cdla = f->current_display_lines[pos]; | |
428 | 406 cdla_len = Dynarr_length (cdla); |
407 | |
408 get_gutter_coords (f, pos, &x, &y, &width, &height); | |
409 /* generate some display lines */ | |
410 generate_displayable_area (w, WINDOW_GUTTER (w, pos), | |
411 x + border_width, y + border_width, | |
442 | 412 width - 2 * border_width, |
428 | 413 height - 2 * border_width, ddla, 0, findex); |
442 | 414 |
415 /* We only output the gutter if we think something of significance | |
416 has changed. This is, for example, because redisplay can cause | |
417 new face cache elements to get added causing compare_runes to | |
418 fail because the findex for a particular face has changed. */ | |
419 if (force || f->faces_changed || f->frame_changed || | |
420 f->gutter_changed || f->glyphs_changed || | |
421 f->size_changed || f->subwindows_changed || | |
422 w->windows_changed || f->windows_structure_changed || | |
423 cdla_len != Dynarr_length (ddla) || | |
424 (f->extents_changed && w->gutter_extent_modiff[pos])) | |
428 | 425 { |
442 | 426 #ifdef DEBUG_GUTTERS |
4186 | 427 stderr_out ("gutter redisplay [%s %dx%d@%d+%d] triggered by %s,\n", |
639 | 428 pos == TOP_GUTTER ? "TOP" : |
429 pos == BOTTOM_GUTTER ? "BOTTOM" : | |
430 pos == LEFT_GUTTER ? "LEFT" : "RIGHT", | |
446 | 431 width, height, x, y, force ? "force" : |
442 | 432 f->faces_changed ? "f->faces_changed" : |
433 f->frame_changed ? "f->frame_changed" : | |
434 f->gutter_changed ? "f->gutter_changed" : | |
435 f->glyphs_changed ? "f->glyphs_changed" : | |
436 f->size_changed ? "f->size_changed" : | |
437 f->subwindows_changed ? "f->subwindows_changed" : | |
438 w->windows_changed ? "w->windows_changed" : | |
439 f->windows_structure_changed ? "f->windows_structure_changed" : | |
440 cdla_len != Dynarr_length (ddla) ? "different display structures" : | |
441 f->extents_changed && w->gutter_extent_modiff[pos] ? | |
442 "f->extents_changed && w->gutter_extent_modiff[pos]" : "<null>"); | |
443 #endif | |
444 /* Output each line. */ | |
445 for (line = 0; line < Dynarr_length (ddla); line++) | |
446 { | |
447 output_display_line (w, cdla, ddla, line, -1, -1); | |
448 } | |
449 | |
450 /* If the number of display lines has shrunk, adjust. */ | |
451 if (cdla_len > Dynarr_length (ddla)) | |
452 { | |
4967 | 453 Dynarr_set_length (cdla, Dynarr_length (ddla)); |
442 | 454 } |
455 | |
456 /* grab coordinates of last line and blank after it. */ | |
457 if (Dynarr_length (ddla) > 0) | |
458 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4186
diff
changeset
|
459 dl = Dynarr_lastp (ddla); |
442 | 460 ypos = dl->ypos + dl->descent - dl->clip; |
461 } | |
462 else | |
463 ypos = y; | |
428 | 464 |
442 | 465 redisplay_clear_region (window, findex, x + border_width , ypos, |
466 width - 2 * border_width, height - (ypos - y) - border_width); | |
467 /* If, for some reason, we have more to display than we have | |
4186 | 468 room for, and we are allowed to resize the gutter, then make |
469 sure this happens before the next time we try and | |
470 output. This can happen when face font sizes change. */ | |
471 if (dl && EQ (w->gutter_size[pos], Qautodetect) | |
444 | 472 && (dl->clip > 0 || |
4186 | 473 calculate_gutter_size_from_display_lines (pos, ddla) > |
444 | 474 WINDOW_GUTTER_SIZE_INTERNAL (w, pos))) |
442 | 475 { |
476 /* #### Ideally we would just mark the specifier as dirty | |
477 and everything else would "just work". Unfortunately we have | |
478 two problems with this. One is that the specifier cache | |
479 won't be recalculated unless the specifier code thinks the | |
480 cached value has actually changed, even though we have | |
481 marked the specifier as dirty. Additionally, although doing | |
482 this results in a gutter size change, we never seem to get | |
483 back into redisplay so that the frame size can be updated. I | |
484 think this is because we are already in redisplay and later | |
485 on the frame will be marked as clean. Thus we also have to | |
486 force a pending recalculation of the frame size. */ | |
487 w->gutter_size[pos] = Qnil; | |
488 Fset_specifier_dirty_flag (Vgutter_size[pos]); | |
489 update_gutter_geometry (f, pos); | |
490 } | |
491 | |
492 /* bevel the gutter area if so desired */ | |
493 if (border_width != 0) | |
494 { | |
495 MAYBE_DEVMETH (d, bevel_area, | |
496 (w, findex, x, y, width, height, border_width, | |
497 EDGE_ALL, EDGE_BEVEL_OUT)); | |
498 } | |
499 } | |
500 else | |
428 | 501 { |
442 | 502 /* Nothing of significance happened so sync the display line |
4186 | 503 structs. */ |
442 | 504 for (line = 0; line < Dynarr_length (ddla); line++) |
505 { | |
506 sync_display_line_structs (w, line, 1, cdla, ddla); | |
507 } | |
428 | 508 } |
509 | |
442 | 510 w->gutter_extent_modiff [pos] = 0; |
428 | 511 } |
512 | |
513 static void | |
514 clear_gutter (struct frame *f, enum gutter_pos pos) | |
515 { | |
516 int x, y, width, height; | |
517 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
518 face_index findex = get_builtin_face_cache_index (XWINDOW (window), | |
442 | 519 Vwidget_face); |
428 | 520 get_gutter_coords (f, pos, &x, &y, &width, &height); |
521 | |
522 SET_GUTTER_WAS_VISIBLE_FLAG (f, pos, 0); | |
523 | |
524 redisplay_clear_region (window, findex, x, y, width, height); | |
525 } | |
526 | |
617 | 527 /* [[#### I don't currently believe that redisplay needs to mark the |
442 | 528 glyphs in its structures since these will always be referenced from |
529 somewhere else. However, I'm not sure enough to stake my life on it | |
617 | 530 at this point, so we do the safe thing.]] |
531 | |
532 ALWAYS mark everything. --ben */ | |
442 | 533 |
534 /* See the comment in image_instantiate_cache_result as to why marking | |
535 the glyph will also mark the image_instance. */ | |
536 void | |
617 | 537 mark_gutters (struct frame *f) |
442 | 538 { |
539 enum gutter_pos pos; | |
540 GUTTER_POS_LOOP (pos) | |
541 { | |
542 if (f->current_display_lines[pos]) | |
543 mark_redisplay_structs (f->current_display_lines[pos]); | |
617 | 544 /* [[#### Do we really need to mark the desired lines?]] |
4186 | 545 ALWAYS mark everything. --ben */ |
442 | 546 if (f->desired_display_lines[pos]) |
547 mark_redisplay_structs (f->desired_display_lines[pos]); | |
548 } | |
549 } | |
550 | |
551 /* This is called by extent_changed_for_redisplay, so that redisplay | |
552 knows exactly what extents have changed. */ | |
553 void | |
554 gutter_extent_signal_changed_region_maybe (Lisp_Object obj, | |
2286 | 555 Charbpos UNUSED (start), |
556 Charbpos UNUSED (end)) | |
442 | 557 { |
558 /* #### Start and end are currently ignored but could be used by a | |
559 more optimal gutter redisplay. We currently loop over all frames | |
560 here, this could be optimized. */ | |
561 Lisp_Object frmcons, devcons, concons; | |
562 | |
563 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
564 { | |
565 struct frame *f = XFRAME (XCAR (frmcons)); | |
566 enum gutter_pos pos; | |
567 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
568 struct window* w = XWINDOW (window); | |
569 | |
570 GUTTER_POS_LOOP (pos) | |
571 { | |
572 if (EQ (WINDOW_GUTTER (w, pos), obj)) | |
573 { | |
574 w->gutter_extent_modiff[pos]++; | |
575 } | |
576 } | |
577 } | |
578 } | |
579 | |
580 /* We have to change the gutter geometry separately to the gutter | |
581 update since it needs to occur outside of redisplay proper. */ | |
582 static void | |
583 update_gutter_geometry (struct frame *f, enum gutter_pos pos) | |
584 { | |
585 /* If the gutter geometry has changed then re-layout the | |
586 frame. If we are in display there is almost no point in doing | |
587 anything else since the frame size changes will be delayed | |
588 until we are out of redisplay proper. */ | |
589 if (FRAME_GUTTER_BOUNDS (f, pos) != f->current_gutter_bounds[pos]) | |
590 { | |
591 int width, height; | |
592 pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f), | |
593 &width, &height); | |
594 change_frame_size (f, height, width, 0); | |
905 | 595 MARK_FRAME_LAYOUT_CHANGED (f); |
442 | 596 } |
597 | |
598 /* Mark sizes as up-to-date. */ | |
599 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos); | |
600 } | |
601 | |
602 void | |
603 update_frame_gutter_geometry (struct frame *f) | |
604 { | |
4186 | 605 if (f->gutter_changed |
606 || f->frame_layout_changed | |
905 | 607 || f->windows_structure_changed) |
442 | 608 { |
609 enum gutter_pos pos; | |
610 | |
611 /* If the gutter geometry has changed then re-layout the | |
4186 | 612 frame. If we are in display there is almost no point in doing |
613 anything else since the frame size changes will be delayed | |
614 until we are out of redisplay proper. */ | |
442 | 615 GUTTER_POS_LOOP (pos) |
616 { | |
617 update_gutter_geometry (f, pos); | |
618 } | |
619 } | |
620 } | |
621 | |
428 | 622 void |
623 update_frame_gutters (struct frame *f) | |
624 { | |
442 | 625 if (f->faces_changed || f->frame_changed || |
626 f->gutter_changed || f->glyphs_changed || | |
627 f->size_changed || f->subwindows_changed || | |
628 f->windows_changed || f->windows_structure_changed || | |
905 | 629 f->extents_changed || f->frame_layout_changed) |
428 | 630 { |
631 enum gutter_pos pos; | |
442 | 632 |
428 | 633 /* We don't actually care about these when outputting the gutter |
4186 | 634 so locally disable them. */ |
428 | 635 int local_clip_changed = f->clip_changed; |
636 int local_buffers_changed = f->buffers_changed; | |
637 f->clip_changed = 0; | |
638 f->buffers_changed = 0; | |
639 | |
640 /* and output */ | |
641 GUTTER_POS_LOOP (pos) | |
642 { | |
643 if (FRAME_GUTTER_VISIBLE (f, pos)) | |
442 | 644 output_gutter (f, pos, 0); |
645 | |
428 | 646 else if (gutter_was_visible (f, pos)) |
442 | 647 clear_gutter (f, pos); |
428 | 648 } |
442 | 649 |
428 | 650 f->clip_changed = local_clip_changed; |
651 f->buffers_changed = local_buffers_changed; | |
652 f->gutter_changed = 0; | |
653 } | |
654 } | |
655 | |
656 void | |
657 reset_gutter_display_lines (struct frame* f) | |
658 { | |
442 | 659 enum gutter_pos pos; |
660 GUTTER_POS_LOOP (pos) | |
661 { | |
662 if (f->current_display_lines[pos]) | |
663 Dynarr_reset (f->current_display_lines[pos]); | |
664 } | |
428 | 665 } |
666 | |
667 static void | |
668 redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y, | |
669 int width, int height) | |
670 { | |
671 int g_x, g_y, g_width, g_height; | |
672 | |
673 get_gutter_coords (f, pos, &g_x, &g_y, &g_width, &g_height); | |
674 | |
675 if (((y + height) < g_y) || (y > (g_y + g_height)) || !height || !width || !g_height || !g_width) | |
676 return; | |
677 if (((x + width) < g_x) || (x > (g_x + g_width))) | |
678 return; | |
679 | |
442 | 680 #ifdef DEBUG_WIDGETS |
639 | 681 stderr_out ("redrawing gutter after expose %d+%d, %dx%d\n", |
442 | 682 x, y, width, height); |
683 #endif | |
428 | 684 /* #### optimize this - redrawing the whole gutter for every expose |
685 is very expensive. We reset the current display lines because if | |
686 they're being exposed they are no longer current. */ | |
687 reset_gutter_display_lines (f); | |
688 | |
689 /* Even if none of the gutter is in the area, the blank region at | |
690 the very least must be because the first thing we did is verify | |
691 that some portion of the gutter is in the exposed region. */ | |
442 | 692 output_gutter (f, pos, 1); |
428 | 693 } |
694 | |
695 void | |
696 redraw_exposed_gutters (struct frame *f, int x, int y, int width, | |
697 int height) | |
698 { | |
699 enum gutter_pos pos; | |
442 | 700 |
1318 | 701 /* We are already inside the critical section -- our caller did that. */ |
428 | 702 GUTTER_POS_LOOP (pos) |
703 { | |
704 if (FRAME_GUTTER_VISIBLE (f, pos)) | |
705 redraw_exposed_gutter (f, pos, x, y, width, height); | |
706 } | |
707 } | |
708 | |
709 void | |
710 free_frame_gutters (struct frame *f) | |
711 { | |
442 | 712 enum gutter_pos pos; |
713 GUTTER_POS_LOOP (pos) | |
428 | 714 { |
442 | 715 if (f->current_display_lines[pos]) |
716 { | |
717 free_display_lines (f->current_display_lines[pos]); | |
718 f->current_display_lines[pos] = 0; | |
719 } | |
720 if (f->desired_display_lines[pos]) | |
721 { | |
722 free_display_lines (f->desired_display_lines[pos]); | |
723 f->desired_display_lines[pos] = 0; | |
724 } | |
428 | 725 } |
726 } | |
727 | |
728 static enum gutter_pos | |
729 decode_gutter_position (Lisp_Object position) | |
730 { | |
731 if (EQ (position, Qtop)) return TOP_GUTTER; | |
732 if (EQ (position, Qbottom)) return BOTTOM_GUTTER; | |
733 if (EQ (position, Qleft)) return LEFT_GUTTER; | |
734 if (EQ (position, Qright)) return RIGHT_GUTTER; | |
563 | 735 invalid_constant ("Invalid gutter position", position); |
428 | 736 |
1204 | 737 RETURN_NOT_REACHED (TOP_GUTTER); |
428 | 738 } |
739 | |
740 DEFUN ("set-default-gutter-position", Fset_default_gutter_position, 1, 1, 0, /* | |
741 Set the position that the `default-gutter' will be displayed at. | |
3025 | 742 Valid positions are `top', `bottom', `left' and `right'. |
428 | 743 See `default-gutter-position'. |
744 */ | |
745 (position)) | |
746 { | |
747 enum gutter_pos cur = decode_gutter_position (Vdefault_gutter_position); | |
3025 | 748 enum gutter_pos new_ = decode_gutter_position (position); |
428 | 749 |
3025 | 750 if (cur != new_) |
428 | 751 { |
752 /* The following calls will automatically cause the dirty | |
753 flags to be set; we delay frame size changes to avoid | |
754 lots of frame flickering. */ | |
755 /* #### I think this should be GC protected. -sb */ | |
1318 | 756 int depth = begin_hold_frame_size_changes (); |
757 | |
428 | 758 set_specifier_fallback (Vgutter[cur], list1 (Fcons (Qnil, Qnil))); |
3025 | 759 set_specifier_fallback (Vgutter[new_], Vdefault_gutter); |
428 | 760 set_specifier_fallback (Vgutter_size[cur], list1 (Fcons (Qnil, Qzero))); |
3025 | 761 set_specifier_fallback (Vgutter_size[new_], |
762 new_ == TOP_GUTTER || new_ == BOTTOM_GUTTER | |
428 | 763 ? Vdefault_gutter_height |
764 : Vdefault_gutter_width); | |
765 set_specifier_fallback (Vgutter_border_width[cur], | |
766 list1 (Fcons (Qnil, Qzero))); | |
3025 | 767 set_specifier_fallback (Vgutter_border_width[new_], |
428 | 768 Vdefault_gutter_border_width); |
444 | 769 set_specifier_fallback (Vgutter_visible_p[cur], list1 (Fcons (Qnil, Qt))); |
3025 | 770 set_specifier_fallback (Vgutter_visible_p[new_], Vdefault_gutter_visible_p); |
1318 | 771 Vdefault_gutter_position = position; |
442 | 772 |
1318 | 773 unbind_to (depth); |
428 | 774 } |
775 | |
442 | 776 run_hook (Qdefault_gutter_position_changed_hook); |
777 | |
428 | 778 return position; |
779 } | |
780 | |
781 DEFUN ("default-gutter-position", Fdefault_gutter_position, 0, 0, 0, /* | |
782 Return the position that the `default-gutter' will be displayed at. | |
783 The `default-gutter' will only be displayed here if the corresponding | |
784 position-specific gutter specifier does not provide a value. | |
785 */ | |
786 ()) | |
787 { | |
788 return Vdefault_gutter_position; | |
789 } | |
790 | |
791 DEFUN ("gutter-pixel-width", Fgutter_pixel_width, 0, 2, 0, /* | |
792 Return the pixel width of the gutter at POS in LOCALE. | |
793 POS defaults to the default gutter position. LOCALE defaults to | |
794 the current window. | |
795 */ | |
796 (pos, locale)) | |
797 { | |
798 int x, y, width, height; | |
799 enum gutter_pos p = TOP_GUTTER; | |
800 struct frame *f = decode_frame (FW_FRAME (locale)); | |
801 | |
802 if (NILP (pos)) | |
803 pos = Vdefault_gutter_position; | |
804 p = decode_gutter_position (pos); | |
805 | |
806 get_gutter_coords (f, p, &x, &y, &width, &height); | |
807 width -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2); | |
808 | |
809 return make_int (width); | |
810 } | |
811 | |
812 DEFUN ("gutter-pixel-height", Fgutter_pixel_height, 0, 2, 0, /* | |
813 Return the pixel height of the gutter at POS in LOCALE. | |
814 POS defaults to the default gutter position. LOCALE defaults to | |
815 the current window. | |
816 */ | |
817 (pos, locale)) | |
818 { | |
819 int x, y, width, height; | |
820 enum gutter_pos p = TOP_GUTTER; | |
821 struct frame *f = decode_frame (FW_FRAME (locale)); | |
822 | |
823 if (NILP (pos)) | |
824 pos = Vdefault_gutter_position; | |
825 p = decode_gutter_position (pos); | |
826 | |
827 get_gutter_coords (f, p, &x, &y, &width, &height); | |
828 height -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2); | |
829 | |
830 return make_int (height); | |
831 } | |
832 | |
833 DEFINE_SPECIFIER_TYPE (gutter); | |
834 | |
835 static void | |
2286 | 836 gutter_after_change (Lisp_Object UNUSED (specifier), |
837 Lisp_Object UNUSED (locale)) | |
428 | 838 { |
839 MARK_GUTTER_CHANGED; | |
840 } | |
841 | |
842 static void | |
843 gutter_validate (Lisp_Object instantiator) | |
844 { | |
845 if (NILP (instantiator)) | |
846 return; | |
847 | |
442 | 848 /* Must be a string or a plist. */ |
849 if (!STRINGP (instantiator) && NILP (Fvalid_plist_p (instantiator))) | |
563 | 850 sferror ("Gutter spec must be string, plist or nil", instantiator); |
442 | 851 |
428 | 852 if (!STRINGP (instantiator)) |
442 | 853 { |
854 Lisp_Object rest; | |
855 | |
856 for (rest = instantiator; !NILP (rest); rest = XCDR (XCDR (rest))) | |
857 { | |
858 if (!SYMBOLP (XCAR (rest)) | |
859 || !STRINGP (XCAR (XCDR (rest)))) | |
563 | 860 sferror ("Gutter plist spec must contain strings", instantiator); |
442 | 861 } |
862 } | |
428 | 863 } |
864 | |
865 DEFUN ("gutter-specifier-p", Fgutter_specifier_p, 1, 1, 0, /* | |
866 Return non-nil if OBJECT is a gutter specifier. | |
867 | |
442 | 868 See `make-gutter-specifier' for a description of possible gutter |
869 instantiators. | |
428 | 870 */ |
871 (object)) | |
872 { | |
873 return GUTTER_SPECIFIERP (object) ? Qt : Qnil; | |
874 } | |
875 | |
876 | |
877 /* | |
878 Helper for invalidating the real specifier when default | |
879 specifier caching changes | |
880 */ | |
881 static void | |
882 recompute_overlaying_specifier (Lisp_Object real_one[4]) | |
883 { | |
884 enum gutter_pos pos = decode_gutter_position (Vdefault_gutter_position); | |
885 Fset_specifier_dirty_flag (real_one[pos]); | |
886 } | |
887 | |
1318 | 888 static void gutter_specs_changed (Lisp_Object specifier, struct window *w, |
889 Lisp_Object oldval, enum gutter_pos pos); | |
890 | |
891 static void | |
892 gutter_specs_changed_1 (Lisp_Object arg) | |
893 { | |
894 gutter_specs_changed (X1ST (arg), XWINDOW (X2ND (arg)), | |
895 X3RD (arg), (enum gutter_pos) XINT (X4TH (arg))); | |
896 free_list (arg); | |
897 } | |
898 | |
428 | 899 static void |
900 gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
1318 | 901 Lisp_Object oldval, enum gutter_pos pos) |
428 | 902 { |
1318 | 903 if (in_display) |
904 register_post_redisplay_action (gutter_specs_changed_1, | |
905 list4 (specifier, wrap_window (w), | |
906 oldval, make_int (pos))); | |
907 else | |
908 { | |
909 w->real_gutter[pos] = construct_window_gutter_spec (w, pos); | |
910 w->real_gutter_size[pos] = w->gutter_size[pos]; | |
442 | 911 |
1318 | 912 if (EQ (w->real_gutter_size[pos], Qautodetect) |
913 && !NILP (w->gutter_visible_p[pos])) | |
914 { | |
915 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); | |
916 } | |
917 MARK_GUTTER_CHANGED; | |
918 MARK_MODELINE_CHANGED; | |
919 MARK_WINDOWS_CHANGED (w); | |
428 | 920 } |
921 } | |
922 | |
442 | 923 /* We define all of these so we can access which actual gutter changed. */ |
924 static void | |
925 top_gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
926 Lisp_Object oldval) | |
927 { | |
928 gutter_specs_changed (specifier, w, oldval, TOP_GUTTER); | |
929 } | |
930 | |
931 static void | |
932 bottom_gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
933 Lisp_Object oldval) | |
934 { | |
935 gutter_specs_changed (specifier, w, oldval, BOTTOM_GUTTER); | |
936 } | |
937 | |
938 static void | |
939 left_gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
940 Lisp_Object oldval) | |
941 { | |
942 gutter_specs_changed (specifier, w, oldval, LEFT_GUTTER); | |
943 } | |
944 | |
945 static void | |
946 right_gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
947 Lisp_Object oldval) | |
948 { | |
949 gutter_specs_changed (specifier, w, oldval, RIGHT_GUTTER); | |
950 } | |
951 | |
428 | 952 static void |
2286 | 953 default_gutter_specs_changed (Lisp_Object UNUSED (specifier), |
954 struct window *UNUSED (w), | |
955 Lisp_Object UNUSED (oldval)) | |
428 | 956 { |
957 recompute_overlaying_specifier (Vgutter); | |
958 } | |
959 | |
1318 | 960 static void gutter_geometry_changed_in_window (Lisp_Object specifier, |
961 struct window *w, | |
962 Lisp_Object oldval); | |
963 | |
964 static void | |
965 gutter_geometry_changed_in_window_1 (Lisp_Object arg) | |
966 { | |
967 gutter_geometry_changed_in_window (X1ST (arg), XWINDOW (X2ND (arg)), | |
968 X3RD (arg)); | |
969 free_list (arg); | |
970 } | |
971 | |
428 | 972 static void |
973 gutter_geometry_changed_in_window (Lisp_Object specifier, struct window *w, | |
974 Lisp_Object oldval) | |
975 { | |
1318 | 976 if (in_display) |
977 register_post_redisplay_action (gutter_geometry_changed_in_window_1, | |
978 list3 (specifier, wrap_window (w), | |
979 oldval)); | |
980 else | |
428 | 981 { |
1318 | 982 enum gutter_pos pos; |
983 GUTTER_POS_LOOP (pos) | |
428 | 984 { |
1318 | 985 w->real_gutter_size[pos] = w->gutter_size[pos]; |
986 if (EQ (w->real_gutter_size[pos], Qautodetect) | |
987 && !NILP (w->gutter_visible_p[pos])) | |
988 { | |
989 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); | |
990 } | |
428 | 991 } |
442 | 992 |
1318 | 993 MARK_GUTTER_CHANGED; |
994 MARK_MODELINE_CHANGED; | |
995 MARK_WINDOWS_CHANGED (w); | |
996 } | |
428 | 997 } |
998 | |
999 static void | |
2286 | 1000 default_gutter_size_changed_in_window (Lisp_Object UNUSED (specifier), |
1001 struct window *UNUSED (w), | |
1002 Lisp_Object UNUSED (oldval)) | |
428 | 1003 { |
1004 recompute_overlaying_specifier (Vgutter_size); | |
1005 } | |
1006 | |
1007 static void | |
2286 | 1008 default_gutter_border_width_changed_in_window (Lisp_Object UNUSED (specifier), |
1009 struct window *UNUSED (w), | |
1010 Lisp_Object UNUSED (oldval)) | |
428 | 1011 { |
1012 recompute_overlaying_specifier (Vgutter_border_width); | |
1013 } | |
1014 | |
1015 static void | |
2286 | 1016 default_gutter_visible_p_changed_in_window (Lisp_Object UNUSED (specifier), |
1017 struct window *UNUSED (w), | |
1018 Lisp_Object UNUSED (oldval)) | |
428 | 1019 { |
1020 recompute_overlaying_specifier (Vgutter_visible_p); | |
442 | 1021 /* Need to reconstruct the gutter specifier as it is affected by the |
1022 visibility. */ | |
1023 recompute_overlaying_specifier (Vgutter); | |
428 | 1024 } |
1025 | |
1026 | |
1027 DECLARE_SPECIFIER_TYPE (gutter_size); | |
1028 #define GUTTER_SIZE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_size) | |
1029 DEFINE_SPECIFIER_TYPE (gutter_size); | |
1030 | |
1031 static void | |
1032 gutter_size_validate (Lisp_Object instantiator) | |
1033 { | |
1034 if (NILP (instantiator)) | |
1035 return; | |
1036 | |
1037 if (!INTP (instantiator) && !EQ (instantiator, Qautodetect)) | |
3025 | 1038 invalid_argument ("Gutter size must be an integer or `autodetect'", instantiator); |
428 | 1039 } |
1040 | |
1041 DEFUN ("gutter-size-specifier-p", Fgutter_size_specifier_p, 1, 1, 0, /* | |
1042 Return non-nil if OBJECT is a gutter-size specifier. | |
442 | 1043 |
1044 See `make-gutter-size-specifier' for a description of possible gutter-size | |
1045 instantiators. | |
428 | 1046 */ |
1047 (object)) | |
1048 { | |
1049 return GUTTER_SIZE_SPECIFIERP (object) ? Qt : Qnil; | |
1050 } | |
1051 | |
442 | 1052 DECLARE_SPECIFIER_TYPE (gutter_visible); |
1053 #define GUTTER_VISIBLE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_visible) | |
1054 DEFINE_SPECIFIER_TYPE (gutter_visible); | |
1055 | |
1056 static void | |
1057 gutter_visible_validate (Lisp_Object instantiator) | |
1058 { | |
1059 if (NILP (instantiator)) | |
1060 return; | |
1061 | |
1062 if (!NILP (instantiator) && !EQ (instantiator, Qt) && !CONSP (instantiator)) | |
563 | 1063 invalid_argument ("Gutter visibility must be a boolean or list of symbols", |
442 | 1064 instantiator); |
1065 | |
1066 if (CONSP (instantiator)) | |
1067 { | |
2367 | 1068 EXTERNAL_LIST_LOOP_2 (elt, instantiator) |
442 | 1069 { |
2367 | 1070 if (!SYMBOLP (elt)) |
563 | 1071 invalid_argument ("Gutter visibility must be a boolean or list of symbols", |
442 | 1072 instantiator); |
1073 } | |
1074 } | |
1075 } | |
1076 | |
1077 DEFUN ("gutter-visible-specifier-p", Fgutter_visible_specifier_p, 1, 1, 0, /* | |
1078 Return non-nil if OBJECT is a gutter-visible specifier. | |
1079 | |
1080 See `make-gutter-visible-specifier' for a description of possible | |
1081 gutter-visible instantiators. | |
1082 */ | |
1083 (object)) | |
1084 { | |
1085 return GUTTER_VISIBLE_SPECIFIERP (object) ? Qt : Qnil; | |
1086 } | |
1087 | |
428 | 1088 DEFUN ("redisplay-gutter-area", Fredisplay_gutter_area, 0, 0, 0, /* |
1089 Ensure that all gutters are correctly showing their gutter specifier. | |
1090 */ | |
1091 ()) | |
1092 { | |
1093 Lisp_Object devcons, concons; | |
1094 | |
1318 | 1095 /* Can't reentrantly enter redisplay */ |
1096 if (in_display) | |
1097 return Qnil; | |
1098 | |
428 | 1099 DEVICE_LOOP_NO_BREAK (devcons, concons) |
1100 { | |
1101 struct device *d = XDEVICE (XCAR (devcons)); | |
1102 Lisp_Object frmcons; | |
1103 | |
1104 DEVICE_FRAME_LOOP (frmcons, d) | |
1105 { | |
1106 struct frame *f = XFRAME (XCAR (frmcons)); | |
1107 | |
442 | 1108 MAYBE_DEVMETH (d, frame_output_begin, (f)); |
1109 | |
1110 /* Sequence is quite important here. We not only want to | |
1111 redisplay the gutter area but we also want to flush any | |
1112 frame size changes out so that the gutter redisplay happens | |
1113 in a kosha environment. | |
1114 | |
1115 This is not only so that things look right but so that | |
1116 glyph redisplay optimization kicks in, by default display | |
1117 lines will be completely re-output if | |
1118 f->windows_structure_changed is 1, and this is true if | |
1119 frame size changes haven't been flushed out. Once frame | |
1120 size changes have been flushed out we then need to | |
1121 redisplay the frame in order to flush out pending window | |
1122 size changes. */ | |
1123 update_frame_gutter_geometry (f); | |
428 | 1124 |
442 | 1125 if (f->windows_structure_changed) |
1126 redisplay_frame (f, 1); | |
1127 else if (FRAME_REPAINT_P (f)) | |
1128 { | |
853 | 1129 int depth; |
1130 | |
442 | 1131 /* We have to be "in display" when we output the gutter |
4186 | 1132 - make it so. */ |
853 | 1133 depth = enter_redisplay_critical_section (); |
442 | 1134 update_frame_gutters (f); |
853 | 1135 exit_redisplay_critical_section (depth); |
442 | 1136 } |
1137 | |
1138 MAYBE_DEVMETH (d, frame_output_end, (f)); | |
1139 } | |
1140 | |
1141 d->gutter_changed = 0; | |
428 | 1142 } |
1143 | |
442 | 1144 /* This is so that further changes to the gutters will trigger redisplay. */ |
1145 gutter_changed_set = 0; | |
1146 gutter_changed = 0; | |
1147 | |
428 | 1148 return Qnil; |
1149 } | |
1150 | |
1151 void | |
1152 init_frame_gutters (struct frame *f) | |
1153 { | |
1154 enum gutter_pos pos; | |
1155 struct window* w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)); | |
1156 /* We are here as far in frame creation so cached specifiers are | |
1157 already recomputed, and possibly modified by resource | |
1158 initialization. We need to recalculate autodetected gutters. */ | |
1159 GUTTER_POS_LOOP (pos) | |
1160 { | |
442 | 1161 w->real_gutter[pos] = construct_window_gutter_spec (w, pos); |
428 | 1162 w->real_gutter_size[pos] = w->gutter_size[pos]; |
1163 if (EQ (w->gutter_size[pos], Qautodetect) | |
1164 && !NILP (w->gutter_visible_p[pos])) | |
1165 { | |
1166 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); | |
1167 MARK_GUTTER_CHANGED; | |
1168 MARK_WINDOWS_CHANGED (w); | |
1169 } | |
1170 } | |
442 | 1171 |
1172 /* Keep a record of the current sizes of things. */ | |
1173 GUTTER_POS_LOOP (pos) | |
1174 { | |
1175 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos); | |
1176 } | |
428 | 1177 } |
1178 | |
1179 void | |
1180 syms_of_gutter (void) | |
1181 { | |
1182 DEFSUBR (Fgutter_specifier_p); | |
1183 DEFSUBR (Fgutter_size_specifier_p); | |
442 | 1184 DEFSUBR (Fgutter_visible_specifier_p); |
428 | 1185 DEFSUBR (Fset_default_gutter_position); |
1186 DEFSUBR (Fdefault_gutter_position); | |
1187 DEFSUBR (Fgutter_pixel_height); | |
1188 DEFSUBR (Fgutter_pixel_width); | |
1189 DEFSUBR (Fredisplay_gutter_area); | |
1190 | |
563 | 1191 DEFSYMBOL (Qgutter_size); |
1192 DEFSYMBOL (Qgutter_visible); | |
1193 DEFSYMBOL (Qdefault_gutter_position_changed_hook); | |
428 | 1194 } |
1195 | |
1196 void | |
1197 vars_of_gutter (void) | |
1198 { | |
1199 staticpro (&Vdefault_gutter_position); | |
1200 Vdefault_gutter_position = Qtop; | |
1201 | |
1202 Fprovide (Qgutter); | |
1203 } | |
1204 | |
1205 void | |
1206 specifier_type_create_gutter (void) | |
1207 { | |
1208 INITIALIZE_SPECIFIER_TYPE (gutter, "gutter", "gutter-specifier-p"); | |
1209 SPECIFIER_HAS_METHOD (gutter, validate); | |
1210 SPECIFIER_HAS_METHOD (gutter, after_change); | |
1211 | |
1212 INITIALIZE_SPECIFIER_TYPE (gutter_size, "gutter-size", "gutter-size-specifier-p"); | |
442 | 1213 SPECIFIER_HAS_METHOD (gutter_size, validate); |
428 | 1214 |
442 | 1215 INITIALIZE_SPECIFIER_TYPE (gutter_visible, "gutter-visible", "gutter-visible-specifier-p"); |
1216 SPECIFIER_HAS_METHOD (gutter_visible, validate); | |
428 | 1217 } |
1218 | |
1219 void | |
1220 reinit_specifier_type_create_gutter (void) | |
1221 { | |
1222 REINITIALIZE_SPECIFIER_TYPE (gutter); | |
1223 REINITIALIZE_SPECIFIER_TYPE (gutter_size); | |
442 | 1224 REINITIALIZE_SPECIFIER_TYPE (gutter_visible); |
428 | 1225 } |
1226 | |
1227 void | |
1228 specifier_vars_of_gutter (void) | |
1229 { | |
1230 Lisp_Object fb; | |
1231 | |
1232 DEFVAR_SPECIFIER ("default-gutter", &Vdefault_gutter /* | |
1233 Specifier for a fallback gutter. | |
1234 Use `set-specifier' to change this. | |
1235 | |
1236 The position of this gutter is specified in the function | |
1237 `default-gutter-position'. If the corresponding position-specific | |
3025 | 1238 gutter (e.g. `top-gutter' if `default-gutter-position' is `top') |
428 | 1239 does not specify a gutter in a particular domain (usually a window), |
1240 then the value of `default-gutter' in that domain, if any, will be | |
1241 used instead. | |
1242 | |
1243 Note that the gutter at any particular position will not be | |
1244 displayed unless its visibility flag is true and its thickness | |
1245 \(width or height, depending on orientation) is non-zero. The | |
1246 visibility is controlled by the specifiers `top-gutter-visible-p', | |
1247 `bottom-gutter-visible-p', `left-gutter-visible-p', and | |
1248 `right-gutter-visible-p', and the thickness is controlled by the | |
1249 specifiers `top-gutter-height', `bottom-gutter-height', | |
1250 `left-gutter-width', and `right-gutter-width'. | |
1251 | |
1252 Note that one of the four visibility specifiers inherits from | |
1253 `default-gutter-visibility' and one of the four thickness | |
1254 specifiers inherits from either `default-gutter-width' or | |
1255 `default-gutter-height' (depending on orientation), just | |
1256 like for the gutter description specifiers (e.g. `top-gutter') | |
1257 mentioned above. | |
1258 | |
1259 Therefore, if you are setting `default-gutter', you should control | |
1260 the visibility and thickness using `default-gutter-visible-p', | |
1261 `default-gutter-width', and `default-gutter-height', rather than | |
1262 using position-specific specifiers. That way, you will get sane | |
1263 behavior if the user changes the default gutter position. | |
1264 | |
442 | 1265 The gutter value should be a string, a property list of strings or |
1266 nil. You can attach extents and glyphs to the string and hence display | |
1267 glyphs and text in other fonts in the gutter area. If the gutter value | |
1268 is a property list then the strings will be concatenated together | |
1269 before being displayed. */ ); | |
428 | 1270 |
1271 Vdefault_gutter = Fmake_specifier (Qgutter); | |
1272 /* #### It would be even nicer if the specifier caching | |
1273 automatically knew about specifier fallbacks, so we didn't | |
1274 have to do it ourselves. */ | |
1275 set_specifier_caching (Vdefault_gutter, | |
438 | 1276 offsetof (struct window, default_gutter), |
428 | 1277 default_gutter_specs_changed, |
444 | 1278 0, 0, 1); |
428 | 1279 |
1280 DEFVAR_SPECIFIER ("top-gutter", | |
1281 &Vgutter[TOP_GUTTER] /* | |
1282 Specifier for the gutter at the top of the frame. | |
1283 Use `set-specifier' to change this. | |
1284 See `default-gutter' for a description of a valid gutter instantiator. | |
1285 */ ); | |
1286 Vgutter[TOP_GUTTER] = Fmake_specifier (Qgutter); | |
1287 set_specifier_caching (Vgutter[TOP_GUTTER], | |
438 | 1288 offsetof (struct window, gutter[TOP_GUTTER]), |
442 | 1289 top_gutter_specs_changed, |
444 | 1290 0, 0, 1); |
428 | 1291 |
1292 DEFVAR_SPECIFIER ("bottom-gutter", | |
1293 &Vgutter[BOTTOM_GUTTER] /* | |
1294 Specifier for the gutter at the bottom of the frame. | |
1295 Use `set-specifier' to change this. | |
1296 See `default-gutter' for a description of a valid gutter instantiator. | |
1297 | |
1298 Note that, unless the `default-gutter-position' is `bottom', by | |
1299 default the height of the bottom gutter (controlled by | |
1300 `bottom-gutter-height') is 0; thus, a bottom gutter will not be | |
1301 displayed even if you provide a value for `bottom-gutter'. | |
1302 */ ); | |
1303 Vgutter[BOTTOM_GUTTER] = Fmake_specifier (Qgutter); | |
1304 set_specifier_caching (Vgutter[BOTTOM_GUTTER], | |
438 | 1305 offsetof (struct window, gutter[BOTTOM_GUTTER]), |
442 | 1306 bottom_gutter_specs_changed, |
444 | 1307 0, 0, 1); |
428 | 1308 |
1309 DEFVAR_SPECIFIER ("left-gutter", | |
1310 &Vgutter[LEFT_GUTTER] /* | |
1311 Specifier for the gutter at the left edge of the frame. | |
1312 Use `set-specifier' to change this. | |
1313 See `default-gutter' for a description of a valid gutter instantiator. | |
1314 | |
1315 Note that, unless the `default-gutter-position' is `left', by | |
1316 default the height of the left gutter (controlled by | |
1317 `left-gutter-width') is 0; thus, a left gutter will not be | |
1318 displayed even if you provide a value for `left-gutter'. | |
1319 */ ); | |
1320 Vgutter[LEFT_GUTTER] = Fmake_specifier (Qgutter); | |
1321 set_specifier_caching (Vgutter[LEFT_GUTTER], | |
438 | 1322 offsetof (struct window, gutter[LEFT_GUTTER]), |
442 | 1323 left_gutter_specs_changed, |
444 | 1324 0, 0, 1); |
428 | 1325 |
1326 DEFVAR_SPECIFIER ("right-gutter", | |
1327 &Vgutter[RIGHT_GUTTER] /* | |
1328 Specifier for the gutter at the right edge of the frame. | |
1329 Use `set-specifier' to change this. | |
1330 See `default-gutter' for a description of a valid gutter instantiator. | |
1331 | |
1332 Note that, unless the `default-gutter-position' is `right', by | |
1333 default the height of the right gutter (controlled by | |
1334 `right-gutter-width') is 0; thus, a right gutter will not be | |
1335 displayed even if you provide a value for `right-gutter'. | |
1336 */ ); | |
1337 Vgutter[RIGHT_GUTTER] = Fmake_specifier (Qgutter); | |
1338 set_specifier_caching (Vgutter[RIGHT_GUTTER], | |
438 | 1339 offsetof (struct window, gutter[RIGHT_GUTTER]), |
442 | 1340 right_gutter_specs_changed, |
444 | 1341 0, 0, 1); |
428 | 1342 |
1343 /* initially, top inherits from default; this can be | |
1344 changed with `set-default-gutter-position'. */ | |
1345 fb = list1 (Fcons (Qnil, Qnil)); | |
1346 set_specifier_fallback (Vdefault_gutter, fb); | |
1347 set_specifier_fallback (Vgutter[TOP_GUTTER], Vdefault_gutter); | |
1348 set_specifier_fallback (Vgutter[BOTTOM_GUTTER], fb); | |
1349 set_specifier_fallback (Vgutter[LEFT_GUTTER], fb); | |
1350 set_specifier_fallback (Vgutter[RIGHT_GUTTER], fb); | |
1351 | |
1352 DEFVAR_SPECIFIER ("default-gutter-height", &Vdefault_gutter_height /* | |
1353 *Height of the default gutter, if it's oriented horizontally. | |
1354 This is a specifier; use `set-specifier' to change it. | |
1355 | |
1356 The position of the default gutter is specified by the function | |
1357 `set-default-gutter-position'. If the corresponding position-specific | |
1358 gutter thickness specifier (e.g. `top-gutter-height' if | |
3025 | 1359 `default-gutter-position' is `top') does not specify a thickness in a |
428 | 1360 particular domain (a window or a frame), then the value of |
1361 `default-gutter-height' or `default-gutter-width' (depending on the | |
1362 gutter orientation) in that domain, if any, will be used instead. | |
1363 | |
1364 Note that `default-gutter-height' is only used when | |
3025 | 1365 `default-gutter-position' is `top' or `bottom', and `default-gutter-width' |
1366 is only used when `default-gutter-position' is `left' or `right'. | |
428 | 1367 |
1368 Note that all of the position-specific gutter thickness specifiers | |
1369 have a fallback value of zero when they do not correspond to the | |
1370 default gutter. Therefore, you will have to set a non-zero thickness | |
1371 value if you want a position-specific gutter to be displayed. | |
1372 | |
3025 | 1373 If you set the height to `autodetect' the size of the gutter will be |
428 | 1374 calculated to be large enough to hold the contents of the gutter. This |
1375 is the default. | |
1376 */ ); | |
1377 Vdefault_gutter_height = Fmake_specifier (Qgutter_size); | |
1378 set_specifier_caching (Vdefault_gutter_height, | |
438 | 1379 offsetof (struct window, default_gutter_height), |
428 | 1380 default_gutter_size_changed_in_window, |
444 | 1381 0, 0, 1); |
428 | 1382 |
1383 DEFVAR_SPECIFIER ("default-gutter-width", &Vdefault_gutter_width /* | |
1384 *Width of the default gutter, if it's oriented vertically. | |
1385 This is a specifier; use `set-specifier' to change it. | |
1386 | |
1387 See `default-gutter-height' for more information. | |
1388 */ ); | |
444 | 1389 Vdefault_gutter_width = Fmake_specifier (Qgutter_size); |
428 | 1390 set_specifier_caching (Vdefault_gutter_width, |
438 | 1391 offsetof (struct window, default_gutter_width), |
428 | 1392 default_gutter_size_changed_in_window, |
444 | 1393 0, 0, 1); |
428 | 1394 |
1395 DEFVAR_SPECIFIER ("top-gutter-height", | |
1396 &Vgutter_size[TOP_GUTTER] /* | |
1397 *Height of the top gutter. | |
1398 This is a specifier; use `set-specifier' to change it. | |
1399 | |
1400 See `default-gutter-height' for more information. | |
1401 */ ); | |
1402 Vgutter_size[TOP_GUTTER] = Fmake_specifier (Qgutter_size); | |
1403 set_specifier_caching (Vgutter_size[TOP_GUTTER], | |
438 | 1404 offsetof (struct window, gutter_size[TOP_GUTTER]), |
444 | 1405 gutter_geometry_changed_in_window, 0, 0, 1); |
428 | 1406 |
1407 DEFVAR_SPECIFIER ("bottom-gutter-height", | |
1408 &Vgutter_size[BOTTOM_GUTTER] /* | |
1409 *Height of the bottom gutter. | |
1410 This is a specifier; use `set-specifier' to change it. | |
1411 | |
1412 See `default-gutter-height' for more information. | |
1413 */ ); | |
1414 Vgutter_size[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_size); | |
1415 set_specifier_caching (Vgutter_size[BOTTOM_GUTTER], | |
438 | 1416 offsetof (struct window, gutter_size[BOTTOM_GUTTER]), |
444 | 1417 gutter_geometry_changed_in_window, 0, 0, 1); |
428 | 1418 |
1419 DEFVAR_SPECIFIER ("left-gutter-width", | |
1420 &Vgutter_size[LEFT_GUTTER] /* | |
1421 *Width of left gutter. | |
1422 This is a specifier; use `set-specifier' to change it. | |
1423 | |
1424 See `default-gutter-height' for more information. | |
1425 */ ); | |
444 | 1426 Vgutter_size[LEFT_GUTTER] = Fmake_specifier (Qgutter_size); |
428 | 1427 set_specifier_caching (Vgutter_size[LEFT_GUTTER], |
438 | 1428 offsetof (struct window, gutter_size[LEFT_GUTTER]), |
444 | 1429 gutter_geometry_changed_in_window, 0, 0, 1); |
428 | 1430 |
1431 DEFVAR_SPECIFIER ("right-gutter-width", | |
1432 &Vgutter_size[RIGHT_GUTTER] /* | |
1433 *Width of right gutter. | |
1434 This is a specifier; use `set-specifier' to change it. | |
1435 | |
1436 See `default-gutter-height' for more information. | |
1437 */ ); | |
444 | 1438 Vgutter_size[RIGHT_GUTTER] = Fmake_specifier (Qgutter_size); |
428 | 1439 set_specifier_caching (Vgutter_size[RIGHT_GUTTER], |
438 | 1440 offsetof (struct window, gutter_size[RIGHT_GUTTER]), |
444 | 1441 gutter_geometry_changed_in_window, 0, 0, 1); |
428 | 1442 |
1443 fb = Qnil; | |
1444 #ifdef HAVE_TTY | |
1445 fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb); | |
1446 #endif | |
462 | 1447 #ifdef HAVE_GTK |
1448 fb = Fcons (Fcons (list1 (Qgtk), Qautodetect), fb); | |
1449 #endif | |
428 | 1450 #ifdef HAVE_X_WINDOWS |
1451 fb = Fcons (Fcons (list1 (Qx), Qautodetect), fb); | |
1452 #endif | |
1453 #ifdef HAVE_MS_WINDOWS | |
440 | 1454 fb = Fcons (Fcons (list1 (Qmsprinter), Qautodetect), fb); |
428 | 1455 fb = Fcons (Fcons (list1 (Qmswindows), Qautodetect), fb); |
1456 #endif | |
1457 if (!NILP (fb)) | |
1458 set_specifier_fallback (Vdefault_gutter_height, fb); | |
1459 | |
1460 fb = Qnil; | |
1461 #ifdef HAVE_TTY | |
444 | 1462 fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb); |
428 | 1463 #endif |
1464 #ifdef HAVE_X_WINDOWS | |
444 | 1465 fb = Fcons (Fcons (list1 (Qx), Qautodetect), fb); |
428 | 1466 #endif |
462 | 1467 #ifdef HAVE_GTK |
1468 fb = Fcons (Fcons (list1 (Qgtk), Qautodetect), fb); | |
1469 #endif | |
428 | 1470 #ifdef HAVE_MS_WINDOWS |
444 | 1471 fb = Fcons (Fcons (list1 (Qmsprinter), Qautodetect), fb); |
1472 fb = Fcons (Fcons (list1 (Qmswindows), Qautodetect), fb); | |
428 | 1473 #endif |
1474 if (!NILP (fb)) | |
1475 set_specifier_fallback (Vdefault_gutter_width, fb); | |
1476 | |
1477 set_specifier_fallback (Vgutter_size[TOP_GUTTER], Vdefault_gutter_height); | |
1478 fb = list1 (Fcons (Qnil, Qzero)); | |
1479 set_specifier_fallback (Vgutter_size[BOTTOM_GUTTER], fb); | |
1480 set_specifier_fallback (Vgutter_size[LEFT_GUTTER], fb); | |
1481 set_specifier_fallback (Vgutter_size[RIGHT_GUTTER], fb); | |
1482 | |
1483 DEFVAR_SPECIFIER ("default-gutter-border-width", | |
1484 &Vdefault_gutter_border_width /* | |
1485 *Width of the border around the default gutter. | |
1486 This is a specifier; use `set-specifier' to change it. | |
1487 | |
1488 The position of the default gutter is specified by the function | |
1489 `set-default-gutter-position'. If the corresponding position-specific | |
1490 gutter border width specifier (e.g. `top-gutter-border-width' if | |
3025 | 1491 `default-gutter-position' is `top') does not specify a border width in a |
428 | 1492 particular domain (a window or a frame), then the value of |
1493 `default-gutter-border-width' in that domain, if any, will be used | |
1494 instead. | |
1495 | |
1496 */ ); | |
1497 Vdefault_gutter_border_width = Fmake_specifier (Qnatnum); | |
1498 set_specifier_caching (Vdefault_gutter_border_width, | |
438 | 1499 offsetof (struct window, default_gutter_border_width), |
428 | 1500 default_gutter_border_width_changed_in_window, |
444 | 1501 0, 0, 0); |
428 | 1502 |
1503 DEFVAR_SPECIFIER ("top-gutter-border-width", | |
1504 &Vgutter_border_width[TOP_GUTTER] /* | |
1505 *Border width of the top gutter. | |
1506 This is a specifier; use `set-specifier' to change it. | |
1507 | |
1508 See `default-gutter-height' for more information. | |
1509 */ ); | |
1510 Vgutter_border_width[TOP_GUTTER] = Fmake_specifier (Qnatnum); | |
1511 set_specifier_caching (Vgutter_border_width[TOP_GUTTER], | |
438 | 1512 offsetof (struct window, |
1513 gutter_border_width[TOP_GUTTER]), | |
444 | 1514 gutter_geometry_changed_in_window, 0, 0, 0); |
428 | 1515 |
1516 DEFVAR_SPECIFIER ("bottom-gutter-border-width", | |
1517 &Vgutter_border_width[BOTTOM_GUTTER] /* | |
1518 *Border width of the bottom gutter. | |
1519 This is a specifier; use `set-specifier' to change it. | |
1520 | |
1521 See `default-gutter-height' for more information. | |
1522 */ ); | |
1523 Vgutter_border_width[BOTTOM_GUTTER] = Fmake_specifier (Qnatnum); | |
1524 set_specifier_caching (Vgutter_border_width[BOTTOM_GUTTER], | |
438 | 1525 offsetof (struct window, |
1526 gutter_border_width[BOTTOM_GUTTER]), | |
444 | 1527 gutter_geometry_changed_in_window, 0, 0, 0); |
428 | 1528 |
1529 DEFVAR_SPECIFIER ("left-gutter-border-width", | |
1530 &Vgutter_border_width[LEFT_GUTTER] /* | |
1531 *Border width of left gutter. | |
1532 This is a specifier; use `set-specifier' to change it. | |
1533 | |
1534 See `default-gutter-height' for more information. | |
1535 */ ); | |
1536 Vgutter_border_width[LEFT_GUTTER] = Fmake_specifier (Qnatnum); | |
1537 set_specifier_caching (Vgutter_border_width[LEFT_GUTTER], | |
438 | 1538 offsetof (struct window, |
1539 gutter_border_width[LEFT_GUTTER]), | |
444 | 1540 gutter_geometry_changed_in_window, 0, 0, 0); |
428 | 1541 |
1542 DEFVAR_SPECIFIER ("right-gutter-border-width", | |
1543 &Vgutter_border_width[RIGHT_GUTTER] /* | |
1544 *Border width of right gutter. | |
1545 This is a specifier; use `set-specifier' to change it. | |
1546 | |
1547 See `default-gutter-height' for more information. | |
1548 */ ); | |
1549 Vgutter_border_width[RIGHT_GUTTER] = Fmake_specifier (Qnatnum); | |
1550 set_specifier_caching (Vgutter_border_width[RIGHT_GUTTER], | |
438 | 1551 offsetof (struct window, |
1552 gutter_border_width[RIGHT_GUTTER]), | |
444 | 1553 gutter_geometry_changed_in_window, 0, 0, 0); |
428 | 1554 |
1555 fb = Qnil; | |
1556 #ifdef HAVE_TTY | |
1557 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb); | |
1558 #endif | |
1559 #ifdef HAVE_X_WINDOWS | |
1560 fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_GUTTER_BORDER_WIDTH)), fb); | |
1561 #endif | |
1562 #ifdef HAVE_MS_WINDOWS | |
440 | 1563 fb = Fcons (Fcons (list1 (Qmsprinter), Qzero), fb); |
428 | 1564 fb = Fcons (Fcons (list1 (Qmswindows), make_int (DEFAULT_GUTTER_BORDER_WIDTH)), fb); |
1565 #endif | |
1566 if (!NILP (fb)) | |
1567 set_specifier_fallback (Vdefault_gutter_border_width, fb); | |
1568 | |
1569 set_specifier_fallback (Vgutter_border_width[TOP_GUTTER], Vdefault_gutter_border_width); | |
1570 fb = list1 (Fcons (Qnil, Qzero)); | |
1571 set_specifier_fallback (Vgutter_border_width[BOTTOM_GUTTER], fb); | |
1572 set_specifier_fallback (Vgutter_border_width[LEFT_GUTTER], fb); | |
1573 set_specifier_fallback (Vgutter_border_width[RIGHT_GUTTER], fb); | |
1574 | |
1575 DEFVAR_SPECIFIER ("default-gutter-visible-p", &Vdefault_gutter_visible_p /* | |
1576 *Whether the default gutter is visible. | |
1577 This is a specifier; use `set-specifier' to change it. | |
1578 | |
1579 The position of the default gutter is specified by the function | |
1580 `set-default-gutter-position'. If the corresponding position-specific | |
1581 gutter visibility specifier (e.g. `top-gutter-visible-p' if | |
3025 | 1582 `default-gutter-position' is `top') does not specify a visible-p value |
428 | 1583 in a particular domain (a window or a frame), then the value of |
1584 `default-gutter-visible-p' in that domain, if any, will be used | |
1585 instead. | |
1586 | |
1587 `default-gutter-visible-p' and all of the position-specific gutter | |
1588 visibility specifiers have a fallback value of true. | |
1589 */ ); | |
442 | 1590 Vdefault_gutter_visible_p = Fmake_specifier (Qgutter_visible); |
428 | 1591 set_specifier_caching (Vdefault_gutter_visible_p, |
438 | 1592 offsetof (struct window, |
1593 default_gutter_visible_p), | |
428 | 1594 default_gutter_visible_p_changed_in_window, |
444 | 1595 0, 0, 0); |
428 | 1596 |
1597 DEFVAR_SPECIFIER ("top-gutter-visible-p", | |
1598 &Vgutter_visible_p[TOP_GUTTER] /* | |
1599 *Whether the top gutter is visible. | |
1600 This is a specifier; use `set-specifier' to change it. | |
1601 | |
1602 See `default-gutter-visible-p' for more information. | |
1603 */ ); | |
442 | 1604 Vgutter_visible_p[TOP_GUTTER] = Fmake_specifier (Qgutter_visible); |
428 | 1605 set_specifier_caching (Vgutter_visible_p[TOP_GUTTER], |
438 | 1606 offsetof (struct window, |
1607 gutter_visible_p[TOP_GUTTER]), | |
444 | 1608 top_gutter_specs_changed, 0, 0, 0); |
428 | 1609 |
1610 DEFVAR_SPECIFIER ("bottom-gutter-visible-p", | |
1611 &Vgutter_visible_p[BOTTOM_GUTTER] /* | |
1612 *Whether the bottom gutter is visible. | |
1613 This is a specifier; use `set-specifier' to change it. | |
1614 | |
1615 See `default-gutter-visible-p' for more information. | |
1616 */ ); | |
442 | 1617 Vgutter_visible_p[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_visible); |
428 | 1618 set_specifier_caching (Vgutter_visible_p[BOTTOM_GUTTER], |
438 | 1619 offsetof (struct window, |
1620 gutter_visible_p[BOTTOM_GUTTER]), | |
444 | 1621 bottom_gutter_specs_changed, 0, 0, 0); |
428 | 1622 |
1623 DEFVAR_SPECIFIER ("left-gutter-visible-p", | |
1624 &Vgutter_visible_p[LEFT_GUTTER] /* | |
1625 *Whether the left gutter is visible. | |
1626 This is a specifier; use `set-specifier' to change it. | |
1627 | |
1628 See `default-gutter-visible-p' for more information. | |
1629 */ ); | |
442 | 1630 Vgutter_visible_p[LEFT_GUTTER] = Fmake_specifier (Qgutter_visible); |
428 | 1631 set_specifier_caching (Vgutter_visible_p[LEFT_GUTTER], |
438 | 1632 offsetof (struct window, |
1633 gutter_visible_p[LEFT_GUTTER]), | |
444 | 1634 left_gutter_specs_changed, 0, 0, 0); |
428 | 1635 |
1636 DEFVAR_SPECIFIER ("right-gutter-visible-p", | |
1637 &Vgutter_visible_p[RIGHT_GUTTER] /* | |
1638 *Whether the right gutter is visible. | |
1639 This is a specifier; use `set-specifier' to change it. | |
1640 | |
1641 See `default-gutter-visible-p' for more information. | |
1642 */ ); | |
442 | 1643 Vgutter_visible_p[RIGHT_GUTTER] = Fmake_specifier (Qgutter_visible); |
428 | 1644 set_specifier_caching (Vgutter_visible_p[RIGHT_GUTTER], |
438 | 1645 offsetof (struct window, |
1646 gutter_visible_p[RIGHT_GUTTER]), | |
444 | 1647 right_gutter_specs_changed, 0, 0, 0); |
428 | 1648 |
1649 /* initially, top inherits from default; this can be | |
1650 changed with `set-default-gutter-position'. */ | |
1651 fb = list1 (Fcons (Qnil, Qt)); | |
1652 set_specifier_fallback (Vdefault_gutter_visible_p, fb); | |
1653 set_specifier_fallback (Vgutter_visible_p[TOP_GUTTER], | |
1654 Vdefault_gutter_visible_p); | |
1655 set_specifier_fallback (Vgutter_visible_p[BOTTOM_GUTTER], fb); | |
1656 set_specifier_fallback (Vgutter_visible_p[LEFT_GUTTER], fb); | |
1657 set_specifier_fallback (Vgutter_visible_p[RIGHT_GUTTER], fb); | |
1658 } |