Mercurial > hg > xemacs-beta
comparison src/gutter.c @ 428:3ecd8885ac67 r21-2-22
Import from CVS: tag r21-2-22
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:28:15 +0200 |
parents | |
children | 84b14dcb0985 |
comparison
equal
deleted
inserted
replaced
427:0a0253eac470 | 428:3ecd8885ac67 |
---|---|
1 /* Gutter implementation. | |
2 Copyright (C) 1999 Andy Piper. | |
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" | |
30 #include "frame.h" | |
31 #include "device.h" | |
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; | |
50 | |
51 #define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag) \ | |
52 do { \ | |
53 switch (pos) \ | |
54 { \ | |
55 case TOP_GUTTER: \ | |
56 (frame)->top_gutter_was_visible = flag; \ | |
57 break; \ | |
58 case BOTTOM_GUTTER: \ | |
59 (frame)->bottom_gutter_was_visible = flag; \ | |
60 break; \ | |
61 case LEFT_GUTTER: \ | |
62 (frame)->left_gutter_was_visible = flag; \ | |
63 break; \ | |
64 case RIGHT_GUTTER: \ | |
65 (frame)->right_gutter_was_visible = flag; \ | |
66 break; \ | |
67 default: \ | |
68 abort (); \ | |
69 } \ | |
70 } while (0) | |
71 | |
72 static int gutter_was_visible (struct frame* frame, enum gutter_pos pos) | |
73 { | |
74 switch (pos) | |
75 { | |
76 case TOP_GUTTER: | |
77 return frame->top_gutter_was_visible; | |
78 case BOTTOM_GUTTER: | |
79 return frame->bottom_gutter_was_visible; | |
80 case LEFT_GUTTER: | |
81 return frame->left_gutter_was_visible; | |
82 case RIGHT_GUTTER: | |
83 return frame->right_gutter_was_visible; | |
84 default: | |
85 abort (); | |
86 } | |
87 } | |
88 | |
89 static Lisp_Object | |
90 frame_topmost_window (struct frame *f) | |
91 { | |
92 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
93 | |
94 do { | |
95 while (!NILP (XWINDOW (w)->vchild)) | |
96 { | |
97 w = XWINDOW (w)->vchild; | |
98 } | |
99 } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild)); | |
100 | |
101 return w; | |
102 } | |
103 | |
104 static Lisp_Object | |
105 frame_bottommost_window (struct frame *f) | |
106 { | |
107 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
108 | |
109 do { | |
110 while (!NILP (XWINDOW (w)->vchild)) | |
111 { | |
112 w = XWINDOW (w)->vchild; | |
113 while (!NILP (XWINDOW (w)->next)) | |
114 { | |
115 w = XWINDOW (w)->next; | |
116 } | |
117 } | |
118 } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild)); | |
119 | |
120 return w; | |
121 } | |
122 | |
123 #if 0 | |
124 static Lisp_Object | |
125 frame_leftmost_window (struct frame *f) | |
126 { | |
127 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
128 | |
129 do { | |
130 while (!NILP (XWINDOW (w)->hchild)) | |
131 { | |
132 w = XWINDOW (w)->hchild; | |
133 } | |
134 } while (!NILP (XWINDOW (w)->vchild) && !NILP (w = XWINDOW (w)->vchild)); | |
135 | |
136 return w; | |
137 } | |
138 | |
139 static Lisp_Object | |
140 frame_rightmost_window (struct frame *f) | |
141 { | |
142 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
143 | |
144 do { | |
145 while (!NILP (XWINDOW (w)->hchild)) | |
146 { | |
147 w = XWINDOW (w)->hchild; | |
148 while (!NILP (XWINDOW (w)->next)) | |
149 { | |
150 w = XWINDOW (w)->next; | |
151 } | |
152 } | |
153 } while (!NILP (XWINDOW (w)->vchild) && !NILP (w = XWINDOW (w)->vchild)); | |
154 return w; | |
155 } | |
156 #endif | |
157 | |
158 /* calculate the coordinates of a gutter for the current frame and | |
159 selected window. we have to be careful in calculating this as we | |
160 need to use *two* windows, the currently selected window will give | |
161 us the actual height, width and contents of the gutter, but if we | |
162 use this for calculating the gutter positions we run into trouble | |
163 if it is not the window nearest the gutter. Instead we predetermine | |
164 the nearest window and then use that.*/ | |
165 static void | |
166 get_gutter_coords (struct frame *f, enum gutter_pos pos, int *x, int *y, | |
167 int *width, int *height) | |
168 { | |
169 struct window | |
170 * top = XWINDOW (frame_topmost_window (f)), | |
171 * bot = XWINDOW (frame_bottommost_window (f)); | |
172 /* The top and bottom gutters take precedence over the left and | |
173 right. */ | |
174 switch (pos) | |
175 { | |
176 case TOP_GUTTER: | |
177 *x = FRAME_LEFT_BORDER_END (f); | |
178 *y = FRAME_TOP_BORDER_END (f); | |
179 *width = FRAME_RIGHT_BORDER_START (f) | |
180 - FRAME_LEFT_BORDER_END (f); | |
181 *height = FRAME_TOP_GUTTER_BOUNDS (f); | |
182 break; | |
183 | |
184 case BOTTOM_GUTTER: | |
185 *x = FRAME_LEFT_BORDER_END (f); | |
186 *y = WINDOW_BOTTOM (bot) | |
187 - FRAME_BOTTOM_GUTTER_BOUNDS (f); | |
188 *width = FRAME_RIGHT_BORDER_START (f) | |
189 - FRAME_LEFT_BORDER_END (f); | |
190 *height = FRAME_BOTTOM_GUTTER_BOUNDS (f); | |
191 break; | |
192 | |
193 case LEFT_GUTTER: | |
194 *x = FRAME_LEFT_BORDER_END (f); | |
195 *y = WINDOW_TEXT_TOP (top); | |
196 *width = FRAME_LEFT_GUTTER_BOUNDS (f); | |
197 *height = WINDOW_BOTTOM (bot) | |
198 - (WINDOW_TEXT_TOP (top) | |
199 + FRAME_BOTTOM_GUTTER_BOUNDS (f)); | |
200 break; | |
201 | |
202 case RIGHT_GUTTER: | |
203 *x = FRAME_RIGHT_BORDER_START (f) | |
204 - FRAME_RIGHT_GUTTER_BOUNDS (f); | |
205 *y = WINDOW_TEXT_TOP (top); | |
206 *width = FRAME_RIGHT_GUTTER_BOUNDS (f); | |
207 *height = WINDOW_BOTTOM (bot) | |
208 - (WINDOW_TEXT_TOP (top) | |
209 + FRAME_BOTTOM_GUTTER_BOUNDS (f)); | |
210 break; | |
211 | |
212 default: | |
213 abort (); | |
214 } | |
215 } | |
216 | |
217 static void | |
218 output_gutter (struct frame *f, enum gutter_pos pos) | |
219 { | |
220 Lisp_Object frame; | |
221 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
222 struct device *d = XDEVICE (f->device); | |
223 struct window* w = XWINDOW (window); | |
224 int x, y, width, height, ypos; | |
225 int line; | |
226 int border_width = FRAME_GUTTER_BORDER_WIDTH (f, pos); | |
227 face_index findex = get_builtin_face_cache_index (w, Vgui_element_face); | |
228 display_line_dynarr* ddla, *cdla; | |
229 struct display_line *dl; | |
230 int cdla_len; | |
231 | |
232 if (!f->current_display_lines) | |
233 f->current_display_lines = Dynarr_new (display_line); | |
234 if (!f->desired_display_lines) | |
235 f->desired_display_lines = Dynarr_new (display_line); | |
236 | |
237 ddla = f->desired_display_lines; | |
238 cdla = f->current_display_lines; | |
239 cdla_len = Dynarr_length (cdla); | |
240 | |
241 XSETFRAME (frame, f); | |
242 | |
243 get_gutter_coords (f, pos, &x, &y, &width, &height); | |
244 /* generate some display lines */ | |
245 generate_displayable_area (w, WINDOW_GUTTER (w, pos), | |
246 x + border_width, y + border_width, | |
247 width - 2 * border_width, | |
248 height - 2 * border_width, ddla, 0, findex); | |
249 /* Output each line. */ | |
250 for (line = 0; line < Dynarr_length (ddla); line++) | |
251 { | |
252 output_display_line (w, cdla, ddla, line, -1, -1); | |
253 } | |
254 | |
255 /* If the number of display lines has shrunk, adjust. */ | |
256 if (cdla_len > Dynarr_length (ddla)) | |
257 { | |
258 Dynarr_length (cdla) = Dynarr_length (ddla); | |
259 } | |
260 | |
261 /* grab coordinates of last line and blank after it. */ | |
262 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); | |
263 ypos = dl->ypos + dl->descent - dl->clip; | |
264 redisplay_clear_region (window, findex, x + border_width , ypos, | |
265 width - 2 * border_width, height - (ypos - y) - border_width); | |
266 /* bevel the gutter area if so desired */ | |
267 if (border_width != 0) | |
268 { | |
269 MAYBE_DEVMETH (d, bevel_area, | |
270 (w, findex, x, y, width, height, border_width, | |
271 EDGE_ALL, EDGE_BEVEL_OUT)); | |
272 } | |
273 } | |
274 | |
275 /* sizing gutters is a pain so we try and help the user by detemining | |
276 what height will accommodate all lines. This is useless on left and | |
277 right gutters as we always have a maximal number of lines. */ | |
278 static Lisp_Object | |
279 calculate_gutter_size (struct window *w, enum gutter_pos pos) | |
280 { | |
281 struct frame* f = XFRAME (WINDOW_FRAME (w)); | |
282 int ypos; | |
283 display_line_dynarr* ddla; | |
284 struct display_line *dl; | |
285 | |
286 /* we cannot autodetect gutter sizes for the left and right as there | |
287 is no reasonable metric to use */ | |
288 assert (pos == TOP_GUTTER || pos == BOTTOM_GUTTER); | |
289 /* degenerate case */ | |
290 if (NILP (WINDOW_GUTTER (w, pos)) | |
291 || | |
292 !FRAME_VISIBLE_P (f) | |
293 || | |
294 NILP (w->buffer)) | |
295 return Qnil; | |
296 | |
297 ddla = Dynarr_new (display_line); | |
298 /* generate some display lines */ | |
299 generate_displayable_area (w, WINDOW_GUTTER (w, pos), | |
300 FRAME_LEFT_BORDER_END (f), | |
301 0, | |
302 FRAME_RIGHT_BORDER_START (f) | |
303 - FRAME_LEFT_BORDER_END (f), | |
304 200, | |
305 ddla, 0, 0); | |
306 /* grab coordinates of last line */ | |
307 if (Dynarr_length (ddla)) | |
308 { | |
309 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); | |
310 ypos = dl->ypos + dl->descent - dl->clip; | |
311 free_display_lines (ddla); | |
312 return make_int (ypos); | |
313 } | |
314 else | |
315 { | |
316 free_display_lines (ddla); | |
317 return Qnil; | |
318 } | |
319 } | |
320 | |
321 static void | |
322 clear_gutter (struct frame *f, enum gutter_pos pos) | |
323 { | |
324 int x, y, width, height; | |
325 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
326 face_index findex = get_builtin_face_cache_index (XWINDOW (window), | |
327 Vgui_element_face); | |
328 get_gutter_coords (f, pos, &x, &y, &width, &height); | |
329 | |
330 SET_GUTTER_WAS_VISIBLE_FLAG (f, pos, 0); | |
331 | |
332 redisplay_clear_region (window, findex, x, y, width, height); | |
333 } | |
334 | |
335 void | |
336 update_frame_gutters (struct frame *f) | |
337 { | |
338 if (f->gutter_changed || f->clear || | |
339 f->glyphs_changed || f->subwindows_changed || | |
340 f->windows_changed || f->windows_structure_changed || | |
341 f->extents_changed || f->faces_changed) | |
342 { | |
343 enum gutter_pos pos; | |
344 | |
345 /* We don't actually care about these when outputting the gutter | |
346 so locally disable them. */ | |
347 int local_clip_changed = f->clip_changed; | |
348 int local_buffers_changed = f->buffers_changed; | |
349 f->clip_changed = 0; | |
350 f->buffers_changed = 0; | |
351 | |
352 /* and output */ | |
353 GUTTER_POS_LOOP (pos) | |
354 { | |
355 if (FRAME_GUTTER_VISIBLE (f, pos)) | |
356 output_gutter (f, pos); | |
357 else if (gutter_was_visible (f, pos)) | |
358 clear_gutter (f, pos); | |
359 } | |
360 f->clip_changed = local_clip_changed; | |
361 f->buffers_changed = local_buffers_changed; | |
362 f->gutter_changed = 0; | |
363 } | |
364 } | |
365 | |
366 void | |
367 reset_gutter_display_lines (struct frame* f) | |
368 { | |
369 if (f->current_display_lines) | |
370 Dynarr_reset (f->current_display_lines); | |
371 } | |
372 | |
373 static void | |
374 redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y, | |
375 int width, int height) | |
376 { | |
377 int g_x, g_y, g_width, g_height; | |
378 | |
379 get_gutter_coords (f, pos, &g_x, &g_y, &g_width, &g_height); | |
380 | |
381 if (((y + height) < g_y) || (y > (g_y + g_height)) || !height || !width || !g_height || !g_width) | |
382 return; | |
383 if (((x + width) < g_x) || (x > (g_x + g_width))) | |
384 return; | |
385 | |
386 /* #### optimize this - redrawing the whole gutter for every expose | |
387 is very expensive. We reset the current display lines because if | |
388 they're being exposed they are no longer current. */ | |
389 reset_gutter_display_lines (f); | |
390 | |
391 /* Even if none of the gutter is in the area, the blank region at | |
392 the very least must be because the first thing we did is verify | |
393 that some portion of the gutter is in the exposed region. */ | |
394 output_gutter (f, pos); | |
395 } | |
396 | |
397 void | |
398 redraw_exposed_gutters (struct frame *f, int x, int y, int width, | |
399 int height) | |
400 { | |
401 enum gutter_pos pos; | |
402 GUTTER_POS_LOOP (pos) | |
403 { | |
404 if (FRAME_GUTTER_VISIBLE (f, pos)) | |
405 redraw_exposed_gutter (f, pos, x, y, width, height); | |
406 } | |
407 } | |
408 | |
409 void | |
410 free_frame_gutters (struct frame *f) | |
411 { | |
412 if (f->current_display_lines) | |
413 { | |
414 free_display_lines (f->current_display_lines); | |
415 f->current_display_lines = 0; | |
416 } | |
417 if (f->desired_display_lines) | |
418 { | |
419 free_display_lines (f->desired_display_lines); | |
420 f->desired_display_lines = 0; | |
421 } | |
422 } | |
423 | |
424 static enum gutter_pos | |
425 decode_gutter_position (Lisp_Object position) | |
426 { | |
427 if (EQ (position, Qtop)) return TOP_GUTTER; | |
428 if (EQ (position, Qbottom)) return BOTTOM_GUTTER; | |
429 if (EQ (position, Qleft)) return LEFT_GUTTER; | |
430 if (EQ (position, Qright)) return RIGHT_GUTTER; | |
431 signal_simple_error ("Invalid gutter position", position); | |
432 | |
433 return TOP_GUTTER; /* not reached */ | |
434 } | |
435 | |
436 DEFUN ("set-default-gutter-position", Fset_default_gutter_position, 1, 1, 0, /* | |
437 Set the position that the `default-gutter' will be displayed at. | |
438 Valid positions are 'top, 'bottom, 'left and 'right. | |
439 See `default-gutter-position'. | |
440 */ | |
441 (position)) | |
442 { | |
443 enum gutter_pos cur = decode_gutter_position (Vdefault_gutter_position); | |
444 enum gutter_pos new = decode_gutter_position (position); | |
445 | |
446 if (cur != new) | |
447 { | |
448 /* The following calls will automatically cause the dirty | |
449 flags to be set; we delay frame size changes to avoid | |
450 lots of frame flickering. */ | |
451 /* #### I think this should be GC protected. -sb */ | |
452 hold_frame_size_changes (); | |
453 set_specifier_fallback (Vgutter[cur], list1 (Fcons (Qnil, Qnil))); | |
454 set_specifier_fallback (Vgutter[new], Vdefault_gutter); | |
455 set_specifier_fallback (Vgutter_size[cur], list1 (Fcons (Qnil, Qzero))); | |
456 set_specifier_fallback (Vgutter_size[new], | |
457 new == TOP_GUTTER || new == BOTTOM_GUTTER | |
458 ? Vdefault_gutter_height | |
459 : Vdefault_gutter_width); | |
460 set_specifier_fallback (Vgutter_border_width[cur], | |
461 list1 (Fcons (Qnil, Qzero))); | |
462 set_specifier_fallback (Vgutter_border_width[new], | |
463 Vdefault_gutter_border_width); | |
464 set_specifier_fallback (Vgutter_visible_p[cur], | |
465 list1 (Fcons (Qnil, Qt))); | |
466 set_specifier_fallback (Vgutter_visible_p[new], | |
467 Vdefault_gutter_visible_p); | |
468 Vdefault_gutter_position = position; | |
469 unhold_frame_size_changes (); | |
470 } | |
471 | |
472 return position; | |
473 } | |
474 | |
475 DEFUN ("default-gutter-position", Fdefault_gutter_position, 0, 0, 0, /* | |
476 Return the position that the `default-gutter' will be displayed at. | |
477 The `default-gutter' will only be displayed here if the corresponding | |
478 position-specific gutter specifier does not provide a value. | |
479 */ | |
480 ()) | |
481 { | |
482 return Vdefault_gutter_position; | |
483 } | |
484 | |
485 DEFUN ("gutter-pixel-width", Fgutter_pixel_width, 0, 2, 0, /* | |
486 Return the pixel width of the gutter at POS in LOCALE. | |
487 POS defaults to the default gutter position. LOCALE defaults to | |
488 the current window. | |
489 */ | |
490 (pos, locale)) | |
491 { | |
492 int x, y, width, height; | |
493 enum gutter_pos p = TOP_GUTTER; | |
494 struct frame *f = decode_frame (FW_FRAME (locale)); | |
495 | |
496 if (NILP (pos)) | |
497 pos = Vdefault_gutter_position; | |
498 p = decode_gutter_position (pos); | |
499 | |
500 get_gutter_coords (f, p, &x, &y, &width, &height); | |
501 width -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2); | |
502 | |
503 return make_int (width); | |
504 } | |
505 | |
506 DEFUN ("gutter-pixel-height", Fgutter_pixel_height, 0, 2, 0, /* | |
507 Return the pixel height of the gutter at POS in LOCALE. | |
508 POS defaults to the default gutter position. LOCALE defaults to | |
509 the current window. | |
510 */ | |
511 (pos, locale)) | |
512 { | |
513 int x, y, width, height; | |
514 enum gutter_pos p = TOP_GUTTER; | |
515 struct frame *f = decode_frame (FW_FRAME (locale)); | |
516 | |
517 if (NILP (pos)) | |
518 pos = Vdefault_gutter_position; | |
519 p = decode_gutter_position (pos); | |
520 | |
521 get_gutter_coords (f, p, &x, &y, &width, &height); | |
522 height -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2); | |
523 | |
524 return make_int (height); | |
525 } | |
526 | |
527 DEFINE_SPECIFIER_TYPE (gutter); | |
528 | |
529 static void | |
530 gutter_after_change (Lisp_Object specifier, Lisp_Object locale) | |
531 { | |
532 MARK_GUTTER_CHANGED; | |
533 } | |
534 | |
535 static void | |
536 gutter_validate (Lisp_Object instantiator) | |
537 { | |
538 if (NILP (instantiator)) | |
539 return; | |
540 | |
541 if (!STRINGP (instantiator)) | |
542 signal_simple_error ("Gutter spec must be string or nil", instantiator); | |
543 } | |
544 | |
545 DEFUN ("gutter-specifier-p", Fgutter_specifier_p, 1, 1, 0, /* | |
546 Return non-nil if OBJECT is a gutter specifier. | |
547 Gutter specifiers are used to specify the format of a gutter. | |
548 The values of the variables `default-gutter', `top-gutter', | |
549 `left-gutter', `right-gutter', and `bottom-gutter' are always | |
550 gutter specifiers. | |
551 | |
552 Valid gutter instantiators are called "gutter descriptors" | |
553 and are lists of vectors. See `default-gutter' for a description | |
554 of the exact format. | |
555 */ | |
556 (object)) | |
557 { | |
558 return GUTTER_SPECIFIERP (object) ? Qt : Qnil; | |
559 } | |
560 | |
561 | |
562 /* | |
563 Helper for invalidating the real specifier when default | |
564 specifier caching changes | |
565 */ | |
566 static void | |
567 recompute_overlaying_specifier (Lisp_Object real_one[4]) | |
568 { | |
569 enum gutter_pos pos = decode_gutter_position (Vdefault_gutter_position); | |
570 Fset_specifier_dirty_flag (real_one[pos]); | |
571 } | |
572 | |
573 static void | |
574 gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
575 Lisp_Object oldval) | |
576 { | |
577 enum gutter_pos pos; | |
578 GUTTER_POS_LOOP (pos) | |
579 { | |
580 w->real_gutter_size[pos] = w->gutter_size[pos]; | |
581 if (EQ (w->real_gutter_size[pos], Qautodetect) | |
582 && !NILP (w->gutter_visible_p[pos])) | |
583 { | |
584 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); | |
585 } | |
586 } | |
587 MARK_GUTTER_CHANGED; | |
588 MARK_WINDOWS_CHANGED (w); | |
589 } | |
590 | |
591 static void | |
592 default_gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
593 Lisp_Object oldval) | |
594 { | |
595 recompute_overlaying_specifier (Vgutter); | |
596 } | |
597 | |
598 static void | |
599 gutter_geometry_changed_in_window (Lisp_Object specifier, struct window *w, | |
600 Lisp_Object oldval) | |
601 { | |
602 enum gutter_pos pos; | |
603 GUTTER_POS_LOOP (pos) | |
604 { | |
605 w->real_gutter_size[pos] = w->gutter_size[pos]; | |
606 if (EQ (w->real_gutter_size[pos], Qautodetect) | |
607 && !NILP (w->gutter_visible_p[pos])) | |
608 { | |
609 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); | |
610 } | |
611 } | |
612 | |
613 MARK_GUTTER_CHANGED; | |
614 MARK_WINDOWS_CHANGED (w); | |
615 } | |
616 | |
617 static void | |
618 default_gutter_size_changed_in_window (Lisp_Object specifier, struct window *w, | |
619 Lisp_Object oldval) | |
620 { | |
621 recompute_overlaying_specifier (Vgutter_size); | |
622 } | |
623 | |
624 static void | |
625 default_gutter_border_width_changed_in_window (Lisp_Object specifier, | |
626 struct window *w, | |
627 Lisp_Object oldval) | |
628 { | |
629 recompute_overlaying_specifier (Vgutter_border_width); | |
630 } | |
631 | |
632 static void | |
633 default_gutter_visible_p_changed_in_window (Lisp_Object specifier, | |
634 struct window *w, | |
635 Lisp_Object oldval) | |
636 { | |
637 recompute_overlaying_specifier (Vgutter_visible_p); | |
638 } | |
639 | |
640 | |
641 DECLARE_SPECIFIER_TYPE (gutter_size); | |
642 #define GUTTER_SIZE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_size) | |
643 DEFINE_SPECIFIER_TYPE (gutter_size); | |
644 | |
645 static void | |
646 gutter_size_validate (Lisp_Object instantiator) | |
647 { | |
648 if (NILP (instantiator)) | |
649 return; | |
650 | |
651 if (!INTP (instantiator) && !EQ (instantiator, Qautodetect)) | |
652 signal_simple_error ("Gutter size must be an integer or 'autodetect", instantiator); | |
653 } | |
654 | |
655 DEFUN ("gutter-size-specifier-p", Fgutter_size_specifier_p, 1, 1, 0, /* | |
656 Return non-nil if OBJECT is a gutter-size specifier. | |
657 */ | |
658 (object)) | |
659 { | |
660 return GUTTER_SIZE_SPECIFIERP (object) ? Qt : Qnil; | |
661 } | |
662 | |
663 DEFUN ("redisplay-gutter-area", Fredisplay_gutter_area, 0, 0, 0, /* | |
664 Ensure that all gutters are correctly showing their gutter specifier. | |
665 */ | |
666 ()) | |
667 { | |
668 Lisp_Object devcons, concons; | |
669 | |
670 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
671 { | |
672 struct device *d = XDEVICE (XCAR (devcons)); | |
673 Lisp_Object frmcons; | |
674 | |
675 DEVICE_FRAME_LOOP (frmcons, d) | |
676 { | |
677 struct frame *f = XFRAME (XCAR (frmcons)); | |
678 | |
679 if (FRAME_REPAINT_P (f)) | |
680 { | |
681 update_frame_gutters (f); | |
682 } | |
683 } | |
684 | |
685 /* We now call the output_end routine for tty frames. We delay | |
686 doing so in order to avoid cursor flicker. So much for 100% | |
687 encapsulation. */ | |
688 if (DEVICE_TTY_P (d)) | |
689 DEVMETH (d, output_end, (d)); | |
690 } | |
691 | |
692 return Qnil; | |
693 } | |
694 | |
695 void | |
696 init_frame_gutters (struct frame *f) | |
697 { | |
698 enum gutter_pos pos; | |
699 struct window* w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)); | |
700 /* We are here as far in frame creation so cached specifiers are | |
701 already recomputed, and possibly modified by resource | |
702 initialization. We need to recalculate autodetected gutters. */ | |
703 GUTTER_POS_LOOP (pos) | |
704 { | |
705 w->real_gutter_size[pos] = w->gutter_size[pos]; | |
706 if (EQ (w->gutter_size[pos], Qautodetect) | |
707 && !NILP (w->gutter_visible_p[pos])) | |
708 { | |
709 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); | |
710 MARK_GUTTER_CHANGED; | |
711 MARK_WINDOWS_CHANGED (w); | |
712 } | |
713 } | |
714 } | |
715 | |
716 void | |
717 syms_of_gutter (void) | |
718 { | |
719 DEFSUBR (Fgutter_specifier_p); | |
720 DEFSUBR (Fgutter_size_specifier_p); | |
721 DEFSUBR (Fset_default_gutter_position); | |
722 DEFSUBR (Fdefault_gutter_position); | |
723 DEFSUBR (Fgutter_pixel_height); | |
724 DEFSUBR (Fgutter_pixel_width); | |
725 DEFSUBR (Fredisplay_gutter_area); | |
726 | |
727 defsymbol (&Qgutter_size, "gutter-size"); | |
728 } | |
729 | |
730 void | |
731 vars_of_gutter (void) | |
732 { | |
733 staticpro (&Vdefault_gutter_position); | |
734 Vdefault_gutter_position = Qtop; | |
735 | |
736 Fprovide (Qgutter); | |
737 } | |
738 | |
739 void | |
740 specifier_type_create_gutter (void) | |
741 { | |
742 INITIALIZE_SPECIFIER_TYPE (gutter, "gutter", "gutter-specifier-p"); | |
743 | |
744 SPECIFIER_HAS_METHOD (gutter, validate); | |
745 SPECIFIER_HAS_METHOD (gutter, after_change); | |
746 | |
747 INITIALIZE_SPECIFIER_TYPE (gutter_size, "gutter-size", "gutter-size-specifier-p"); | |
748 | |
749 SPECIFIER_HAS_METHOD (gutter_size, validate); | |
750 } | |
751 | |
752 void | |
753 reinit_specifier_type_create_gutter (void) | |
754 { | |
755 REINITIALIZE_SPECIFIER_TYPE (gutter); | |
756 REINITIALIZE_SPECIFIER_TYPE (gutter_size); | |
757 } | |
758 | |
759 void | |
760 specifier_vars_of_gutter (void) | |
761 { | |
762 Lisp_Object fb; | |
763 | |
764 DEFVAR_SPECIFIER ("default-gutter", &Vdefault_gutter /* | |
765 Specifier for a fallback gutter. | |
766 Use `set-specifier' to change this. | |
767 | |
768 The position of this gutter is specified in the function | |
769 `default-gutter-position'. If the corresponding position-specific | |
770 gutter (e.g. `top-gutter' if `default-gutter-position' is 'top) | |
771 does not specify a gutter in a particular domain (usually a window), | |
772 then the value of `default-gutter' in that domain, if any, will be | |
773 used instead. | |
774 | |
775 Note that the gutter at any particular position will not be | |
776 displayed unless its visibility flag is true and its thickness | |
777 \(width or height, depending on orientation) is non-zero. The | |
778 visibility is controlled by the specifiers `top-gutter-visible-p', | |
779 `bottom-gutter-visible-p', `left-gutter-visible-p', and | |
780 `right-gutter-visible-p', and the thickness is controlled by the | |
781 specifiers `top-gutter-height', `bottom-gutter-height', | |
782 `left-gutter-width', and `right-gutter-width'. | |
783 | |
784 Note that one of the four visibility specifiers inherits from | |
785 `default-gutter-visibility' and one of the four thickness | |
786 specifiers inherits from either `default-gutter-width' or | |
787 `default-gutter-height' (depending on orientation), just | |
788 like for the gutter description specifiers (e.g. `top-gutter') | |
789 mentioned above. | |
790 | |
791 Therefore, if you are setting `default-gutter', you should control | |
792 the visibility and thickness using `default-gutter-visible-p', | |
793 `default-gutter-width', and `default-gutter-height', rather than | |
794 using position-specific specifiers. That way, you will get sane | |
795 behavior if the user changes the default gutter position. | |
796 | |
797 The gutter value should be a string or nil. You can attach extents and | |
798 glyphs to the string and hence display glyphs and text in other fonts | |
799 in the gutter area. | |
800 | |
801 */ ); | |
802 | |
803 Vdefault_gutter = Fmake_specifier (Qgutter); | |
804 /* #### It would be even nicer if the specifier caching | |
805 automatically knew about specifier fallbacks, so we didn't | |
806 have to do it ourselves. */ | |
807 set_specifier_caching (Vdefault_gutter, | |
808 slot_offset (struct window, | |
809 default_gutter), | |
810 default_gutter_specs_changed, | |
811 0, 0); | |
812 | |
813 DEFVAR_SPECIFIER ("top-gutter", | |
814 &Vgutter[TOP_GUTTER] /* | |
815 Specifier for the gutter at the top of the frame. | |
816 Use `set-specifier' to change this. | |
817 See `default-gutter' for a description of a valid gutter instantiator. | |
818 */ ); | |
819 Vgutter[TOP_GUTTER] = Fmake_specifier (Qgutter); | |
820 set_specifier_caching (Vgutter[TOP_GUTTER], | |
821 slot_offset (struct window, | |
822 gutter[TOP_GUTTER]), | |
823 gutter_specs_changed, | |
824 0, 0); | |
825 | |
826 DEFVAR_SPECIFIER ("bottom-gutter", | |
827 &Vgutter[BOTTOM_GUTTER] /* | |
828 Specifier for the gutter at the bottom of the frame. | |
829 Use `set-specifier' to change this. | |
830 See `default-gutter' for a description of a valid gutter instantiator. | |
831 | |
832 Note that, unless the `default-gutter-position' is `bottom', by | |
833 default the height of the bottom gutter (controlled by | |
834 `bottom-gutter-height') is 0; thus, a bottom gutter will not be | |
835 displayed even if you provide a value for `bottom-gutter'. | |
836 */ ); | |
837 Vgutter[BOTTOM_GUTTER] = Fmake_specifier (Qgutter); | |
838 set_specifier_caching (Vgutter[BOTTOM_GUTTER], | |
839 slot_offset (struct window, | |
840 gutter[BOTTOM_GUTTER]), | |
841 gutter_specs_changed, | |
842 0, 0); | |
843 | |
844 DEFVAR_SPECIFIER ("left-gutter", | |
845 &Vgutter[LEFT_GUTTER] /* | |
846 Specifier for the gutter at the left edge of the frame. | |
847 Use `set-specifier' to change this. | |
848 See `default-gutter' for a description of a valid gutter instantiator. | |
849 | |
850 Note that, unless the `default-gutter-position' is `left', by | |
851 default the height of the left gutter (controlled by | |
852 `left-gutter-width') is 0; thus, a left gutter will not be | |
853 displayed even if you provide a value for `left-gutter'. | |
854 */ ); | |
855 Vgutter[LEFT_GUTTER] = Fmake_specifier (Qgutter); | |
856 set_specifier_caching (Vgutter[LEFT_GUTTER], | |
857 slot_offset (struct window, | |
858 gutter[LEFT_GUTTER]), | |
859 gutter_specs_changed, | |
860 0, 0); | |
861 | |
862 DEFVAR_SPECIFIER ("right-gutter", | |
863 &Vgutter[RIGHT_GUTTER] /* | |
864 Specifier for the gutter at the right edge of the frame. | |
865 Use `set-specifier' to change this. | |
866 See `default-gutter' for a description of a valid gutter instantiator. | |
867 | |
868 Note that, unless the `default-gutter-position' is `right', by | |
869 default the height of the right gutter (controlled by | |
870 `right-gutter-width') is 0; thus, a right gutter will not be | |
871 displayed even if you provide a value for `right-gutter'. | |
872 */ ); | |
873 Vgutter[RIGHT_GUTTER] = Fmake_specifier (Qgutter); | |
874 set_specifier_caching (Vgutter[RIGHT_GUTTER], | |
875 slot_offset (struct window, | |
876 gutter[RIGHT_GUTTER]), | |
877 gutter_specs_changed, | |
878 0, 0); | |
879 | |
880 /* initially, top inherits from default; this can be | |
881 changed with `set-default-gutter-position'. */ | |
882 fb = list1 (Fcons (Qnil, Qnil)); | |
883 set_specifier_fallback (Vdefault_gutter, fb); | |
884 set_specifier_fallback (Vgutter[TOP_GUTTER], Vdefault_gutter); | |
885 set_specifier_fallback (Vgutter[BOTTOM_GUTTER], fb); | |
886 set_specifier_fallback (Vgutter[LEFT_GUTTER], fb); | |
887 set_specifier_fallback (Vgutter[RIGHT_GUTTER], fb); | |
888 | |
889 DEFVAR_SPECIFIER ("default-gutter-height", &Vdefault_gutter_height /* | |
890 *Height of the default gutter, if it's oriented horizontally. | |
891 This is a specifier; use `set-specifier' to change it. | |
892 | |
893 The position of the default gutter is specified by the function | |
894 `set-default-gutter-position'. If the corresponding position-specific | |
895 gutter thickness specifier (e.g. `top-gutter-height' if | |
896 `default-gutter-position' is 'top) does not specify a thickness in a | |
897 particular domain (a window or a frame), then the value of | |
898 `default-gutter-height' or `default-gutter-width' (depending on the | |
899 gutter orientation) in that domain, if any, will be used instead. | |
900 | |
901 Note that `default-gutter-height' is only used when | |
902 `default-gutter-position' is 'top or 'bottom, and `default-gutter-width' | |
903 is only used when `default-gutter-position' is 'left or 'right. | |
904 | |
905 Note that all of the position-specific gutter thickness specifiers | |
906 have a fallback value of zero when they do not correspond to the | |
907 default gutter. Therefore, you will have to set a non-zero thickness | |
908 value if you want a position-specific gutter to be displayed. | |
909 | |
910 If you set the height to 'autodetect the size of the gutter will be | |
911 calculated to be large enough to hold the contents of the gutter. This | |
912 is the default. | |
913 */ ); | |
914 Vdefault_gutter_height = Fmake_specifier (Qgutter_size); | |
915 set_specifier_caching (Vdefault_gutter_height, | |
916 slot_offset (struct window, | |
917 default_gutter_height), | |
918 default_gutter_size_changed_in_window, | |
919 0, 0); | |
920 | |
921 DEFVAR_SPECIFIER ("default-gutter-width", &Vdefault_gutter_width /* | |
922 *Width of the default gutter, if it's oriented vertically. | |
923 This is a specifier; use `set-specifier' to change it. | |
924 | |
925 See `default-gutter-height' for more information. | |
926 */ ); | |
927 Vdefault_gutter_width = Fmake_specifier (Qnatnum); | |
928 set_specifier_caching (Vdefault_gutter_width, | |
929 slot_offset (struct window, | |
930 default_gutter_width), | |
931 default_gutter_size_changed_in_window, | |
932 0, 0); | |
933 | |
934 DEFVAR_SPECIFIER ("top-gutter-height", | |
935 &Vgutter_size[TOP_GUTTER] /* | |
936 *Height of the top gutter. | |
937 This is a specifier; use `set-specifier' to change it. | |
938 | |
939 See `default-gutter-height' for more information. | |
940 */ ); | |
941 Vgutter_size[TOP_GUTTER] = Fmake_specifier (Qgutter_size); | |
942 set_specifier_caching (Vgutter_size[TOP_GUTTER], | |
943 slot_offset (struct window, | |
944 gutter_size[TOP_GUTTER]), | |
945 gutter_geometry_changed_in_window, | |
946 0, 0); | |
947 | |
948 DEFVAR_SPECIFIER ("bottom-gutter-height", | |
949 &Vgutter_size[BOTTOM_GUTTER] /* | |
950 *Height of the bottom gutter. | |
951 This is a specifier; use `set-specifier' to change it. | |
952 | |
953 See `default-gutter-height' for more information. | |
954 */ ); | |
955 Vgutter_size[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_size); | |
956 set_specifier_caching (Vgutter_size[BOTTOM_GUTTER], | |
957 slot_offset (struct window, | |
958 gutter_size[BOTTOM_GUTTER]), | |
959 gutter_geometry_changed_in_window, | |
960 0, 0); | |
961 | |
962 DEFVAR_SPECIFIER ("left-gutter-width", | |
963 &Vgutter_size[LEFT_GUTTER] /* | |
964 *Width of left gutter. | |
965 This is a specifier; use `set-specifier' to change it. | |
966 | |
967 See `default-gutter-height' for more information. | |
968 */ ); | |
969 Vgutter_size[LEFT_GUTTER] = Fmake_specifier (Qnatnum); | |
970 set_specifier_caching (Vgutter_size[LEFT_GUTTER], | |
971 slot_offset (struct window, | |
972 gutter_size[LEFT_GUTTER]), | |
973 gutter_geometry_changed_in_window, | |
974 0, 0); | |
975 | |
976 DEFVAR_SPECIFIER ("right-gutter-width", | |
977 &Vgutter_size[RIGHT_GUTTER] /* | |
978 *Width of right gutter. | |
979 This is a specifier; use `set-specifier' to change it. | |
980 | |
981 See `default-gutter-height' for more information. | |
982 */ ); | |
983 Vgutter_size[RIGHT_GUTTER] = Fmake_specifier (Qnatnum); | |
984 set_specifier_caching (Vgutter_size[RIGHT_GUTTER], | |
985 slot_offset (struct window, | |
986 gutter_size[RIGHT_GUTTER]), | |
987 gutter_geometry_changed_in_window, | |
988 0, 0); | |
989 | |
990 fb = Qnil; | |
991 #ifdef HAVE_TTY | |
992 fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb); | |
993 #endif | |
994 #ifdef HAVE_X_WINDOWS | |
995 fb = Fcons (Fcons (list1 (Qx), Qautodetect), fb); | |
996 #endif | |
997 #ifdef HAVE_MS_WINDOWS | |
998 fb = Fcons (Fcons (list1 (Qmswindows), Qautodetect), fb); | |
999 #endif | |
1000 if (!NILP (fb)) | |
1001 set_specifier_fallback (Vdefault_gutter_height, fb); | |
1002 | |
1003 fb = Qnil; | |
1004 #ifdef HAVE_TTY | |
1005 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb); | |
1006 #endif | |
1007 #ifdef HAVE_X_WINDOWS | |
1008 fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_GUTTER_WIDTH)), fb); | |
1009 #endif | |
1010 #ifdef HAVE_MS_WINDOWS | |
1011 fb = Fcons (Fcons (list1 (Qmswindows), | |
1012 make_int (DEFAULT_GUTTER_WIDTH)), fb); | |
1013 #endif | |
1014 if (!NILP (fb)) | |
1015 set_specifier_fallback (Vdefault_gutter_width, fb); | |
1016 | |
1017 set_specifier_fallback (Vgutter_size[TOP_GUTTER], Vdefault_gutter_height); | |
1018 fb = list1 (Fcons (Qnil, Qzero)); | |
1019 set_specifier_fallback (Vgutter_size[BOTTOM_GUTTER], fb); | |
1020 set_specifier_fallback (Vgutter_size[LEFT_GUTTER], fb); | |
1021 set_specifier_fallback (Vgutter_size[RIGHT_GUTTER], fb); | |
1022 | |
1023 DEFVAR_SPECIFIER ("default-gutter-border-width", | |
1024 &Vdefault_gutter_border_width /* | |
1025 *Width of the border around the default gutter. | |
1026 This is a specifier; use `set-specifier' to change it. | |
1027 | |
1028 The position of the default gutter is specified by the function | |
1029 `set-default-gutter-position'. If the corresponding position-specific | |
1030 gutter border width specifier (e.g. `top-gutter-border-width' if | |
1031 `default-gutter-position' is 'top) does not specify a border width in a | |
1032 particular domain (a window or a frame), then the value of | |
1033 `default-gutter-border-width' in that domain, if any, will be used | |
1034 instead. | |
1035 | |
1036 */ ); | |
1037 Vdefault_gutter_border_width = Fmake_specifier (Qnatnum); | |
1038 set_specifier_caching (Vdefault_gutter_border_width, | |
1039 slot_offset (struct window, | |
1040 default_gutter_border_width), | |
1041 default_gutter_border_width_changed_in_window, | |
1042 0, 0); | |
1043 | |
1044 DEFVAR_SPECIFIER ("top-gutter-border-width", | |
1045 &Vgutter_border_width[TOP_GUTTER] /* | |
1046 *Border width of the top gutter. | |
1047 This is a specifier; use `set-specifier' to change it. | |
1048 | |
1049 See `default-gutter-height' for more information. | |
1050 */ ); | |
1051 Vgutter_border_width[TOP_GUTTER] = Fmake_specifier (Qnatnum); | |
1052 set_specifier_caching (Vgutter_border_width[TOP_GUTTER], | |
1053 slot_offset (struct window, | |
1054 gutter_border_width[TOP_GUTTER]), | |
1055 gutter_geometry_changed_in_window, | |
1056 0, 0); | |
1057 | |
1058 DEFVAR_SPECIFIER ("bottom-gutter-border-width", | |
1059 &Vgutter_border_width[BOTTOM_GUTTER] /* | |
1060 *Border width of the bottom gutter. | |
1061 This is a specifier; use `set-specifier' to change it. | |
1062 | |
1063 See `default-gutter-height' for more information. | |
1064 */ ); | |
1065 Vgutter_border_width[BOTTOM_GUTTER] = Fmake_specifier (Qnatnum); | |
1066 set_specifier_caching (Vgutter_border_width[BOTTOM_GUTTER], | |
1067 slot_offset (struct window, | |
1068 gutter_border_width[BOTTOM_GUTTER]), | |
1069 gutter_geometry_changed_in_window, | |
1070 0, 0); | |
1071 | |
1072 DEFVAR_SPECIFIER ("left-gutter-border-width", | |
1073 &Vgutter_border_width[LEFT_GUTTER] /* | |
1074 *Border width of left gutter. | |
1075 This is a specifier; use `set-specifier' to change it. | |
1076 | |
1077 See `default-gutter-height' for more information. | |
1078 */ ); | |
1079 Vgutter_border_width[LEFT_GUTTER] = Fmake_specifier (Qnatnum); | |
1080 set_specifier_caching (Vgutter_border_width[LEFT_GUTTER], | |
1081 slot_offset (struct window, | |
1082 gutter_border_width[LEFT_GUTTER]), | |
1083 gutter_geometry_changed_in_window, | |
1084 0, 0); | |
1085 | |
1086 DEFVAR_SPECIFIER ("right-gutter-border-width", | |
1087 &Vgutter_border_width[RIGHT_GUTTER] /* | |
1088 *Border width of right gutter. | |
1089 This is a specifier; use `set-specifier' to change it. | |
1090 | |
1091 See `default-gutter-height' for more information. | |
1092 */ ); | |
1093 Vgutter_border_width[RIGHT_GUTTER] = Fmake_specifier (Qnatnum); | |
1094 set_specifier_caching (Vgutter_border_width[RIGHT_GUTTER], | |
1095 slot_offset (struct window, | |
1096 gutter_border_width[RIGHT_GUTTER]), | |
1097 gutter_geometry_changed_in_window, | |
1098 0, 0); | |
1099 | |
1100 fb = Qnil; | |
1101 #ifdef HAVE_TTY | |
1102 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb); | |
1103 #endif | |
1104 #ifdef HAVE_X_WINDOWS | |
1105 fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_GUTTER_BORDER_WIDTH)), fb); | |
1106 #endif | |
1107 #ifdef HAVE_MS_WINDOWS | |
1108 fb = Fcons (Fcons (list1 (Qmswindows), make_int (DEFAULT_GUTTER_BORDER_WIDTH)), fb); | |
1109 #endif | |
1110 if (!NILP (fb)) | |
1111 set_specifier_fallback (Vdefault_gutter_border_width, fb); | |
1112 | |
1113 set_specifier_fallback (Vgutter_border_width[TOP_GUTTER], Vdefault_gutter_border_width); | |
1114 fb = list1 (Fcons (Qnil, Qzero)); | |
1115 set_specifier_fallback (Vgutter_border_width[BOTTOM_GUTTER], fb); | |
1116 set_specifier_fallback (Vgutter_border_width[LEFT_GUTTER], fb); | |
1117 set_specifier_fallback (Vgutter_border_width[RIGHT_GUTTER], fb); | |
1118 | |
1119 DEFVAR_SPECIFIER ("default-gutter-visible-p", &Vdefault_gutter_visible_p /* | |
1120 *Whether the default gutter is visible. | |
1121 This is a specifier; use `set-specifier' to change it. | |
1122 | |
1123 The position of the default gutter is specified by the function | |
1124 `set-default-gutter-position'. If the corresponding position-specific | |
1125 gutter visibility specifier (e.g. `top-gutter-visible-p' if | |
1126 `default-gutter-position' is 'top) does not specify a visible-p value | |
1127 in a particular domain (a window or a frame), then the value of | |
1128 `default-gutter-visible-p' in that domain, if any, will be used | |
1129 instead. | |
1130 | |
1131 `default-gutter-visible-p' and all of the position-specific gutter | |
1132 visibility specifiers have a fallback value of true. | |
1133 */ ); | |
1134 Vdefault_gutter_visible_p = Fmake_specifier (Qboolean); | |
1135 set_specifier_caching (Vdefault_gutter_visible_p, | |
1136 slot_offset (struct window, | |
1137 default_gutter_visible_p), | |
1138 default_gutter_visible_p_changed_in_window, | |
1139 0, 0); | |
1140 | |
1141 DEFVAR_SPECIFIER ("top-gutter-visible-p", | |
1142 &Vgutter_visible_p[TOP_GUTTER] /* | |
1143 *Whether the top gutter is visible. | |
1144 This is a specifier; use `set-specifier' to change it. | |
1145 | |
1146 See `default-gutter-visible-p' for more information. | |
1147 */ ); | |
1148 Vgutter_visible_p[TOP_GUTTER] = Fmake_specifier (Qboolean); | |
1149 set_specifier_caching (Vgutter_visible_p[TOP_GUTTER], | |
1150 slot_offset (struct window, | |
1151 gutter_visible_p[TOP_GUTTER]), | |
1152 gutter_geometry_changed_in_window, | |
1153 0, 0); | |
1154 | |
1155 DEFVAR_SPECIFIER ("bottom-gutter-visible-p", | |
1156 &Vgutter_visible_p[BOTTOM_GUTTER] /* | |
1157 *Whether the bottom gutter is visible. | |
1158 This is a specifier; use `set-specifier' to change it. | |
1159 | |
1160 See `default-gutter-visible-p' for more information. | |
1161 */ ); | |
1162 Vgutter_visible_p[BOTTOM_GUTTER] = Fmake_specifier (Qboolean); | |
1163 set_specifier_caching (Vgutter_visible_p[BOTTOM_GUTTER], | |
1164 slot_offset (struct window, | |
1165 gutter_visible_p[BOTTOM_GUTTER]), | |
1166 gutter_geometry_changed_in_window, | |
1167 0, 0); | |
1168 | |
1169 DEFVAR_SPECIFIER ("left-gutter-visible-p", | |
1170 &Vgutter_visible_p[LEFT_GUTTER] /* | |
1171 *Whether the left gutter is visible. | |
1172 This is a specifier; use `set-specifier' to change it. | |
1173 | |
1174 See `default-gutter-visible-p' for more information. | |
1175 */ ); | |
1176 Vgutter_visible_p[LEFT_GUTTER] = Fmake_specifier (Qboolean); | |
1177 set_specifier_caching (Vgutter_visible_p[LEFT_GUTTER], | |
1178 slot_offset (struct window, | |
1179 gutter_visible_p[LEFT_GUTTER]), | |
1180 gutter_geometry_changed_in_window, | |
1181 0, 0); | |
1182 | |
1183 DEFVAR_SPECIFIER ("right-gutter-visible-p", | |
1184 &Vgutter_visible_p[RIGHT_GUTTER] /* | |
1185 *Whether the right gutter is visible. | |
1186 This is a specifier; use `set-specifier' to change it. | |
1187 | |
1188 See `default-gutter-visible-p' for more information. | |
1189 */ ); | |
1190 Vgutter_visible_p[RIGHT_GUTTER] = Fmake_specifier (Qboolean); | |
1191 set_specifier_caching (Vgutter_visible_p[RIGHT_GUTTER], | |
1192 slot_offset (struct window, | |
1193 gutter_visible_p[RIGHT_GUTTER]), | |
1194 gutter_geometry_changed_in_window, | |
1195 0, 0); | |
1196 | |
1197 /* initially, top inherits from default; this can be | |
1198 changed with `set-default-gutter-position'. */ | |
1199 fb = list1 (Fcons (Qnil, Qt)); | |
1200 set_specifier_fallback (Vdefault_gutter_visible_p, fb); | |
1201 set_specifier_fallback (Vgutter_visible_p[TOP_GUTTER], | |
1202 Vdefault_gutter_visible_p); | |
1203 set_specifier_fallback (Vgutter_visible_p[BOTTOM_GUTTER], fb); | |
1204 set_specifier_fallback (Vgutter_visible_p[LEFT_GUTTER], fb); | |
1205 set_specifier_fallback (Vgutter_visible_p[RIGHT_GUTTER], fb); | |
1206 | |
1207 } |