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