comparison src/gutter.c @ 422:95016f13131a r21-2-19

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