1 /* Gutter implementation.
2 Copyright (C) 1999, 2000 Andy Piper.
4 This file is part of XEmacs.
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
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
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. */
21 /* Synched up with: Not in FSF. */
23 /* written by Andy Piper <andy@xemacs.org> with specifiers partially
24 ripped-off from toolbar.c */
34 #include "redisplay.h"
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];
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;
47 Lisp_Object Vdefault_gutter_position;
49 Lisp_Object Qgutter_size;
50 Lisp_Object Qgutter_visible;
51 Lisp_Object Qdefault_gutter_position_changed_hook;
54 update_gutter_geometry (struct frame *f, enum gutter_pos pos);
56 #define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag) \
61 (frame)->top_gutter_was_visible = flag; \
64 (frame)->bottom_gutter_was_visible = flag; \
67 (frame)->left_gutter_was_visible = flag; \
70 (frame)->right_gutter_was_visible = flag; \
77 static int gutter_was_visible (struct frame* frame, enum gutter_pos pos)
82 return frame->top_gutter_was_visible;
84 return frame->bottom_gutter_was_visible;
86 return frame->left_gutter_was_visible;
88 return frame->right_gutter_was_visible;
91 return 0; /* To keep the compiler happy */
97 frame_topmost_window (struct frame *f)
99 Lisp_Object w = FRAME_ROOT_WINDOW (f);
102 while (!NILP (XWINDOW (w)->vchild))
104 w = XWINDOW (w)->vchild;
106 } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild));
113 frame_bottommost_window (struct frame *f)
115 Lisp_Object w = FRAME_ROOT_WINDOW (f);
118 while (!NILP (XWINDOW (w)->vchild))
120 w = XWINDOW (w)->vchild;
121 while (!NILP (XWINDOW (w)->next))
123 w = XWINDOW (w)->next;
126 } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild));
133 frame_leftmost_window (struct frame *f)
135 Lisp_Object w = FRAME_ROOT_WINDOW (f);
138 while (!NILP (XWINDOW (w)->hchild))
140 w = XWINDOW (w)->hchild;
142 } while (!NILP (XWINDOW (w)->vchild) && !NILP (w = XWINDOW (w)->vchild));
148 frame_rightmost_window (struct frame *f)
150 Lisp_Object w = FRAME_ROOT_WINDOW (f);
153 while (!NILP (XWINDOW (w)->hchild))
155 w = XWINDOW (w)->hchild;
156 while (!NILP (XWINDOW (w)->next))
158 w = XWINDOW (w)->next;
161 } while (!NILP (XWINDOW (w)->vchild) && !NILP (w = XWINDOW (w)->vchild));
166 /* calculate the coordinates of a gutter for the current frame and
167 selected window. we have to be careful in calculating this as we
168 need to use *two* windows, the currently selected window will give
169 us the actual height, width and contents of the gutter, but if we
170 use this for calculating the gutter positions we run into trouble
171 if it is not the window nearest the gutter. Instead we predetermine
172 the nearest window and then use that.*/
174 get_gutter_coords (struct frame *f, enum gutter_pos pos, int *x, int *y,
175 int *width, int *height)
178 * bot = XWINDOW (frame_bottommost_window (f));
179 /* The top and bottom gutters take precedence over the left and
184 *x = FRAME_LEFT_BORDER_END (f);
185 *y = FRAME_TOP_BORDER_END (f);
186 *width = FRAME_RIGHT_BORDER_START (f)
187 - FRAME_LEFT_BORDER_END (f);
188 *height = FRAME_TOP_GUTTER_BOUNDS (f);
192 *x = FRAME_LEFT_BORDER_END (f);
193 *y = WINDOW_BOTTOM (bot);
194 *width = FRAME_RIGHT_BORDER_START (f)
195 - FRAME_LEFT_BORDER_END (f);
196 *height = FRAME_BOTTOM_GUTTER_BOUNDS (f);
200 *x = FRAME_LEFT_BORDER_END (f);
201 *y = FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f);
202 *width = FRAME_LEFT_GUTTER_BOUNDS (f);
203 *height = WINDOW_BOTTOM (bot)
204 - (FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f));
208 *x = FRAME_RIGHT_BORDER_START (f)
209 - FRAME_RIGHT_GUTTER_BOUNDS (f);
210 *y = FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f);
211 *width = FRAME_RIGHT_GUTTER_BOUNDS (f);
212 *height = WINDOW_BOTTOM (bot)
213 - (FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f));
221 /* Convert the gutter specifier into something we can actually
223 static Lisp_Object construct_window_gutter_spec (struct window* w,
226 Lisp_Object rest, *args;
228 Lisp_Object gutter = RAW_WINDOW_GUTTER (w, pos);
230 if (STRINGP (gutter) || NILP (gutter))
233 GET_LIST_LENGTH (gutter, nargs);
234 args = alloca_array (Lisp_Object, nargs >> 1);
237 for (rest = gutter; !NILP (rest); rest = XCDR (XCDR (rest)))
239 /* We only put things in the real gutter that are declared to be
241 if (!CONSP (WINDOW_GUTTER_VISIBLE (w, pos))
243 !NILP (Fmemq (XCAR (rest), WINDOW_GUTTER_VISIBLE (w, pos))))
245 args [nargs++] = XCAR (XCDR (rest));
249 return Fconcat (nargs, args);
253 output_gutter (struct frame *f, enum gutter_pos pos, int force)
256 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
257 struct device *d = XDEVICE (f->device);
258 struct window* w = XWINDOW (window);
259 int x, y, width, height, ypos;
260 int line, border_width;
262 display_line_dynarr* ddla, *cdla;
263 struct display_line *dl = 0;
266 if (!WINDOW_LIVE_P (w))
269 border_width = FRAME_GUTTER_BORDER_WIDTH (f, pos);
270 findex = get_builtin_face_cache_index (w, Vwidget_face);
272 if (!f->current_display_lines[pos])
273 f->current_display_lines[pos] = Dynarr_new (display_line);
274 if (!f->desired_display_lines[pos])
275 f->desired_display_lines[pos] = Dynarr_new (display_line);
277 ddla = f->desired_display_lines[pos];
278 cdla = f->current_display_lines[pos];
279 cdla_len = Dynarr_length (cdla);
281 XSETFRAME (frame, f);
283 get_gutter_coords (f, pos, &x, &y, &width, &height);
284 /* generate some display lines */
285 generate_displayable_area (w, WINDOW_GUTTER (w, pos),
286 x + border_width, y + border_width,
287 width - 2 * border_width,
288 height - 2 * border_width, ddla, 0, findex);
290 /* We only output the gutter if we think something of significance
291 has changed. This is, for example, because redisplay can cause
292 new face cache elements to get added causing compare_runes to
293 fail because the findex for a particular face has changed. */
294 if (force || f->faces_changed || f->frame_changed ||
295 f->gutter_changed || f->glyphs_changed ||
296 f->size_changed || f->subwindows_changed ||
297 w->windows_changed || f->windows_structure_changed ||
298 cdla_len != Dynarr_length (ddla) ||
299 (f->extents_changed && w->gutter_extent_modiff[pos]))
302 printf ("gutter redisplay triggered by %s\n", force ? "force" :
303 f->faces_changed ? "f->faces_changed" :
304 f->frame_changed ? "f->frame_changed" :
305 f->gutter_changed ? "f->gutter_changed" :
306 f->glyphs_changed ? "f->glyphs_changed" :
307 f->size_changed ? "f->size_changed" :
308 f->subwindows_changed ? "f->subwindows_changed" :
309 w->windows_changed ? "w->windows_changed" :
310 f->windows_structure_changed ? "f->windows_structure_changed" :
311 cdla_len != Dynarr_length (ddla) ? "different display structures" :
312 f->extents_changed && w->gutter_extent_modiff[pos] ?
313 "f->extents_changed && w->gutter_extent_modiff[pos]" : "<null>");
315 /* Output each line. */
316 for (line = 0; line < Dynarr_length (ddla); line++)
318 output_display_line (w, cdla, ddla, line, -1, -1);
321 /* If the number of display lines has shrunk, adjust. */
322 if (cdla_len > Dynarr_length (ddla))
324 Dynarr_length (cdla) = Dynarr_length (ddla);
327 /* grab coordinates of last line and blank after it. */
328 if (Dynarr_length (ddla) > 0)
330 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1);
331 ypos = dl->ypos + dl->descent - dl->clip;
336 redisplay_clear_region (window, findex, x + border_width , ypos,
337 width - 2 * border_width, height - (ypos - y) - border_width);
338 /* If, for some reason, we have more to display than we have
339 room for, and we are allowed to resize the gutter, then make
340 sure this happens before the next time we try and
341 output. This can happen when face font sizes change. */
342 if (dl && dl->clip > 0 && EQ (w->gutter_size[pos], Qautodetect))
344 /* #### Ideally we would just mark the specifier as dirty
345 and everything else would "just work". Unfortunately we have
346 two problems with this. One is that the specifier cache
347 won't be recalculated unless the specifier code thinks the
348 cached value has actually changed, even though we have
349 marked the specifier as dirty. Additionally, although doing
350 this results in a gutter size change, we never seem to get
351 back into redisplay so that the frame size can be updated. I
352 think this is because we are already in redisplay and later
353 on the frame will be marked as clean. Thus we also have to
354 force a pending recalculation of the frame size. */
355 w->gutter_size[pos] = Qnil;
356 Fset_specifier_dirty_flag (Vgutter_size[pos]);
357 update_gutter_geometry (f, pos);
360 /* bevel the gutter area if so desired */
361 if (border_width != 0)
363 MAYBE_DEVMETH (d, bevel_area,
364 (w, findex, x, y, width, height, border_width,
365 EDGE_ALL, EDGE_BEVEL_OUT));
370 /* Nothing of significance happened so sync the display line
372 for (line = 0; line < Dynarr_length (ddla); line++)
374 sync_display_line_structs (w, line, 1, cdla, ddla);
378 w->gutter_extent_modiff [pos] = 0;
381 /* Sizing gutters is a pain so we try and help the user by detemining
382 what height will accommodate all lines. This is useless on left and
383 right gutters as we always have a maximal number of lines. */
385 calculate_gutter_size (struct window *w, enum gutter_pos pos)
387 struct frame* f = XFRAME (WINDOW_FRAME (w));
389 display_line_dynarr* ddla;
390 struct display_line *dl;
392 /* we cannot autodetect gutter sizes for the left and right as there
393 is no reasonable metric to use */
394 assert (pos == TOP_GUTTER || pos == BOTTOM_GUTTER);
395 /* degenerate case */
396 if (NILP (RAW_WINDOW_GUTTER (w, pos))
403 /* Redisplay code that we use relies on GC not happening. Make it
405 count = specpdl_depth ();
406 record_unwind_protect (restore_gc_inhibit,
407 make_int (gc_currently_forbidden));
408 gc_currently_forbidden = 1;
410 ddla = Dynarr_new (display_line);
411 /* generate some display lines */
412 generate_displayable_area (w, WINDOW_GUTTER (w, pos),
413 FRAME_LEFT_BORDER_END (f),
415 FRAME_RIGHT_BORDER_START (f)
416 - FRAME_LEFT_BORDER_END (f),
420 /* Let GC happen again. */
421 unbind_to (count, Qnil);
423 /* grab coordinates of last line */
424 if (Dynarr_length (ddla))
426 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1);
427 ypos = dl->ypos + dl->descent - dl->clip;
428 free_display_lines (ddla);
429 return make_int (ypos);
433 free_display_lines (ddla);
439 clear_gutter (struct frame *f, enum gutter_pos pos)
441 int x, y, width, height;
442 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
443 face_index findex = get_builtin_face_cache_index (XWINDOW (window),
445 get_gutter_coords (f, pos, &x, &y, &width, &height);
447 SET_GUTTER_WAS_VISIBLE_FLAG (f, pos, 0);
449 redisplay_clear_region (window, findex, x, y, width, height);
452 /* #### I don't currently believe that redisplay needs to mark the
453 glyphs in its structures since these will always be referenced from
454 somewhere else. However, I'm not sure enough to stake my life on it
455 at this point, so we do the safe thing. */
457 /* See the comment in image_instantiate_cache_result as to why marking
458 the glyph will also mark the image_instance. */
460 mark_gutters (struct frame* f)
463 GUTTER_POS_LOOP (pos)
465 if (f->current_display_lines[pos])
466 mark_redisplay_structs (f->current_display_lines[pos]);
467 /* #### Do we really need to mark the desired lines? */
468 if (f->desired_display_lines[pos])
469 mark_redisplay_structs (f->desired_display_lines[pos]);
473 /* This is called by extent_changed_for_redisplay, so that redisplay
474 knows exactly what extents have changed. */
476 gutter_extent_signal_changed_region_maybe (Lisp_Object obj,
477 Bufpos start, Bufpos end)
479 /* #### Start and end are currently ignored but could be used by a
480 more optimal gutter redisplay. We currently loop over all frames
481 here, this could be optimized. */
482 Lisp_Object frmcons, devcons, concons;
484 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
486 struct frame *f = XFRAME (XCAR (frmcons));
488 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
489 struct window* w = XWINDOW (window);
491 GUTTER_POS_LOOP (pos)
493 if (EQ (WINDOW_GUTTER (w, pos), obj))
495 w->gutter_extent_modiff[pos]++;
501 /* We have to change the gutter geometry separately to the gutter
502 update since it needs to occur outside of redisplay proper. */
504 update_gutter_geometry (struct frame *f, enum gutter_pos pos)
506 /* If the gutter geometry has changed then re-layout the
507 frame. If we are in display there is almost no point in doing
508 anything else since the frame size changes will be delayed
509 until we are out of redisplay proper. */
510 if (FRAME_GUTTER_BOUNDS (f, pos) != f->current_gutter_bounds[pos])
513 pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f),
515 change_frame_size (f, height, width, 0);
518 /* Mark sizes as up-to-date. */
519 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos);
523 update_frame_gutter_geometry (struct frame *f)
525 if (f->gutter_changed || f->windows_structure_changed)
529 /* If the gutter geometry has changed then re-layout the
530 frame. If we are in display there is almost no point in doing
531 anything else since the frame size changes will be delayed
532 until we are out of redisplay proper. */
533 GUTTER_POS_LOOP (pos)
535 update_gutter_geometry (f, pos);
541 update_frame_gutters (struct frame *f)
543 if (f->faces_changed || f->frame_changed ||
544 f->gutter_changed || f->glyphs_changed ||
545 f->size_changed || f->subwindows_changed ||
546 f->windows_changed || f->windows_structure_changed ||
551 /* We don't actually care about these when outputting the gutter
552 so locally disable them. */
553 int local_clip_changed = f->clip_changed;
554 int local_buffers_changed = f->buffers_changed;
556 f->buffers_changed = 0;
559 GUTTER_POS_LOOP (pos)
561 if (FRAME_GUTTER_VISIBLE (f, pos))
562 output_gutter (f, pos, 0);
564 else if (gutter_was_visible (f, pos))
565 clear_gutter (f, pos);
568 f->clip_changed = local_clip_changed;
569 f->buffers_changed = local_buffers_changed;
570 f->gutter_changed = 0;
575 reset_gutter_display_lines (struct frame* f)
578 GUTTER_POS_LOOP (pos)
580 if (f->current_display_lines[pos])
581 Dynarr_reset (f->current_display_lines[pos]);
586 redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y,
587 int width, int height)
589 int g_x, g_y, g_width, g_height;
591 get_gutter_coords (f, pos, &g_x, &g_y, &g_width, &g_height);
593 if (((y + height) < g_y) || (y > (g_y + g_height)) || !height || !width || !g_height || !g_width)
595 if (((x + width) < g_x) || (x > (g_x + g_width)))
599 printf ("redrawing gutter after expose %d+%d, %dx%d\n",
600 x, y, width, height);
602 /* #### optimize this - redrawing the whole gutter for every expose
603 is very expensive. We reset the current display lines because if
604 they're being exposed they are no longer current. */
605 reset_gutter_display_lines (f);
607 /* Even if none of the gutter is in the area, the blank region at
608 the very least must be because the first thing we did is verify
609 that some portion of the gutter is in the exposed region. */
610 output_gutter (f, pos, 1);
614 redraw_exposed_gutters (struct frame *f, int x, int y, int width,
619 /* We have to be "in display" when we output the gutter - make it
621 hold_frame_size_changes ();
622 GUTTER_POS_LOOP (pos)
624 if (FRAME_GUTTER_VISIBLE (f, pos))
625 redraw_exposed_gutter (f, pos, x, y, width, height);
627 unhold_one_frame_size_changes (f);
631 free_frame_gutters (struct frame *f)
634 GUTTER_POS_LOOP (pos)
636 if (f->current_display_lines[pos])
638 free_display_lines (f->current_display_lines[pos]);
639 f->current_display_lines[pos] = 0;
641 if (f->desired_display_lines[pos])
643 free_display_lines (f->desired_display_lines[pos]);
644 f->desired_display_lines[pos] = 0;
649 static enum gutter_pos
650 decode_gutter_position (Lisp_Object position)
652 if (EQ (position, Qtop)) return TOP_GUTTER;
653 if (EQ (position, Qbottom)) return BOTTOM_GUTTER;
654 if (EQ (position, Qleft)) return LEFT_GUTTER;
655 if (EQ (position, Qright)) return RIGHT_GUTTER;
656 signal_simple_error ("Invalid gutter position", position);
658 return TOP_GUTTER; /* not reached */
661 DEFUN ("set-default-gutter-position", Fset_default_gutter_position, 1, 1, 0, /*
662 Set the position that the `default-gutter' will be displayed at.
663 Valid positions are 'top, 'bottom, 'left and 'right.
664 See `default-gutter-position'.
668 enum gutter_pos cur = decode_gutter_position (Vdefault_gutter_position);
669 enum gutter_pos new = decode_gutter_position (position);
673 /* The following calls will automatically cause the dirty
674 flags to be set; we delay frame size changes to avoid
675 lots of frame flickering. */
676 /* #### I think this should be GC protected. -sb */
677 hold_frame_size_changes ();
678 set_specifier_fallback (Vgutter[cur], list1 (Fcons (Qnil, Qnil)));
679 set_specifier_fallback (Vgutter[new], Vdefault_gutter);
680 set_specifier_fallback (Vgutter_size[cur], list1 (Fcons (Qnil, Qzero)));
681 set_specifier_fallback (Vgutter_size[new],
682 new == TOP_GUTTER || new == BOTTOM_GUTTER
683 ? Vdefault_gutter_height
684 : Vdefault_gutter_width);
685 set_specifier_fallback (Vgutter_border_width[cur],
686 list1 (Fcons (Qnil, Qzero)));
687 set_specifier_fallback (Vgutter_border_width[new],
688 Vdefault_gutter_border_width);
689 /* We don't realy want the left and right gutters to default to
691 set_specifier_fallback (Vgutter_visible_p[cur],
692 cur == TOP_GUTTER || cur == BOTTOM_GUTTER ?
693 list1 (Fcons (Qnil, Qt))
694 : list1 (Fcons (Qnil, Qnil)));
695 set_specifier_fallback (Vgutter_visible_p[new],
696 Vdefault_gutter_visible_p);
698 Vdefault_gutter_position = position;
699 unhold_frame_size_changes ();
702 run_hook (Qdefault_gutter_position_changed_hook);
707 DEFUN ("default-gutter-position", Fdefault_gutter_position, 0, 0, 0, /*
708 Return the position that the `default-gutter' will be displayed at.
709 The `default-gutter' will only be displayed here if the corresponding
710 position-specific gutter specifier does not provide a value.
714 return Vdefault_gutter_position;
717 DEFUN ("gutter-pixel-width", Fgutter_pixel_width, 0, 2, 0, /*
718 Return the pixel width of the gutter at POS in LOCALE.
719 POS defaults to the default gutter position. LOCALE defaults to
724 int x, y, width, height;
725 enum gutter_pos p = TOP_GUTTER;
726 struct frame *f = decode_frame (FW_FRAME (locale));
729 pos = Vdefault_gutter_position;
730 p = decode_gutter_position (pos);
732 get_gutter_coords (f, p, &x, &y, &width, &height);
733 width -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2);
735 return make_int (width);
738 DEFUN ("gutter-pixel-height", Fgutter_pixel_height, 0, 2, 0, /*
739 Return the pixel height of the gutter at POS in LOCALE.
740 POS defaults to the default gutter position. LOCALE defaults to
745 int x, y, width, height;
746 enum gutter_pos p = TOP_GUTTER;
747 struct frame *f = decode_frame (FW_FRAME (locale));
750 pos = Vdefault_gutter_position;
751 p = decode_gutter_position (pos);
753 get_gutter_coords (f, p, &x, &y, &width, &height);
754 height -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2);
756 return make_int (height);
759 DEFINE_SPECIFIER_TYPE (gutter);
762 gutter_after_change (Lisp_Object specifier, Lisp_Object locale)
768 gutter_validate (Lisp_Object instantiator)
770 if (NILP (instantiator))
773 /* Must be a string or a plist. */
774 if (!STRINGP (instantiator) && NILP (Fvalid_plist_p (instantiator)))
775 signal_simple_error ("Gutter spec must be string, plist or nil", instantiator);
777 if (!STRINGP (instantiator))
781 for (rest = instantiator; !NILP (rest); rest = XCDR (XCDR (rest)))
783 if (!SYMBOLP (XCAR (rest))
784 || !STRINGP (XCAR (XCDR (rest))))
785 signal_simple_error ("Gutter plist spec must contain strings", instantiator);
790 DEFUN ("gutter-specifier-p", Fgutter_specifier_p, 1, 1, 0, /*
791 Return non-nil if OBJECT is a gutter specifier.
792 Gutter specifiers are used to specify the format of a gutter.
793 The values of the variables `default-gutter', `top-gutter',
794 `left-gutter', `right-gutter', and `bottom-gutter' are always
797 Valid gutter instantiators are called "gutter descriptors" and are
798 either strings or property-lists of strings. See `default-gutter' for
799 a description of the exact format.
803 return GUTTER_SPECIFIERP (object) ? Qt : Qnil;
808 Helper for invalidating the real specifier when default
809 specifier caching changes
812 recompute_overlaying_specifier (Lisp_Object real_one[4])
814 enum gutter_pos pos = decode_gutter_position (Vdefault_gutter_position);
815 Fset_specifier_dirty_flag (real_one[pos]);
819 gutter_specs_changed (Lisp_Object specifier, struct window *w,
820 Lisp_Object oldval, enum gutter_pos pos)
822 w->real_gutter[pos] = construct_window_gutter_spec (w, pos);
823 w->real_gutter_size[pos] = w->gutter_size[pos];
825 if (EQ (w->real_gutter_size[pos], Qautodetect)
826 && !NILP (w->gutter_visible_p[pos]))
828 w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
831 MARK_MODELINE_CHANGED;
832 MARK_WINDOWS_CHANGED (w);
835 /* We define all of these so we can access which actual gutter changed. */
837 top_gutter_specs_changed (Lisp_Object specifier, struct window *w,
840 gutter_specs_changed (specifier, w, oldval, TOP_GUTTER);
844 bottom_gutter_specs_changed (Lisp_Object specifier, struct window *w,
847 gutter_specs_changed (specifier, w, oldval, BOTTOM_GUTTER);
851 left_gutter_specs_changed (Lisp_Object specifier, struct window *w,
854 gutter_specs_changed (specifier, w, oldval, LEFT_GUTTER);
858 right_gutter_specs_changed (Lisp_Object specifier, struct window *w,
861 gutter_specs_changed (specifier, w, oldval, RIGHT_GUTTER);
865 default_gutter_specs_changed (Lisp_Object specifier, struct window *w,
868 recompute_overlaying_specifier (Vgutter);
872 gutter_geometry_changed_in_window (Lisp_Object specifier, struct window *w,
876 GUTTER_POS_LOOP (pos)
878 w->real_gutter_size[pos] = w->gutter_size[pos];
879 if (EQ (w->real_gutter_size[pos], Qautodetect)
880 && !NILP (w->gutter_visible_p[pos]))
882 w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
887 MARK_MODELINE_CHANGED;
888 MARK_WINDOWS_CHANGED (w);
892 default_gutter_size_changed_in_window (Lisp_Object specifier, struct window *w,
895 recompute_overlaying_specifier (Vgutter_size);
899 default_gutter_border_width_changed_in_window (Lisp_Object specifier,
903 recompute_overlaying_specifier (Vgutter_border_width);
907 default_gutter_visible_p_changed_in_window (Lisp_Object specifier,
911 recompute_overlaying_specifier (Vgutter_visible_p);
912 /* Need to reconstruct the gutter specifier as it is affected by the
914 recompute_overlaying_specifier (Vgutter);
918 DECLARE_SPECIFIER_TYPE (gutter_size);
919 #define GUTTER_SIZE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_size)
920 DEFINE_SPECIFIER_TYPE (gutter_size);
923 gutter_size_validate (Lisp_Object instantiator)
925 if (NILP (instantiator))
928 if (!INTP (instantiator) && !EQ (instantiator, Qautodetect))
929 signal_simple_error ("Gutter size must be an integer or 'autodetect", instantiator);
932 DEFUN ("gutter-size-specifier-p", Fgutter_size_specifier_p, 1, 1, 0, /*
933 Return non-nil if OBJECT is a gutter-size specifier.
935 Gutter-size specifiers are used to specify the size of a gutter. The
936 values of the variables `default-gutter-size', `top-gutter-size',
937 `left-gutter-size', `right-gutter-size', and `bottom-gutter-size' are
938 always gutter-size specifiers.
940 Valid gutter-size instantiators are either integers or the special
941 symbol 'autodetect. If a gutter-size is set to 'autodetect them the
942 size of the gutter will be adjusted to just accomodate the gutters
943 contents. 'autodetect only works for top and bottom gutters.
947 return GUTTER_SIZE_SPECIFIERP (object) ? Qt : Qnil;
950 DECLARE_SPECIFIER_TYPE (gutter_visible);
951 #define GUTTER_VISIBLE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_visible)
952 DEFINE_SPECIFIER_TYPE (gutter_visible);
955 gutter_visible_validate (Lisp_Object instantiator)
957 if (NILP (instantiator))
960 if (!NILP (instantiator) && !EQ (instantiator, Qt) && !CONSP (instantiator))
961 signal_simple_error ("Gutter visibility must be a boolean or list of symbols",
964 if (CONSP (instantiator))
968 EXTERNAL_LIST_LOOP (rest, instantiator)
970 if (!SYMBOLP (XCAR (rest)))
971 signal_simple_error ("Gutter visibility must be a boolean or list of symbols",
977 DEFUN ("gutter-visible-specifier-p", Fgutter_visible_specifier_p, 1, 1, 0, /*
978 Return non-nil if OBJECT is a gutter-visible specifier.
980 Gutter-visible specifiers are used to specify the visibility of a
981 gutter. The values of the variables `default-gutter-visible-p',
982 `top-gutter-visible-p', `left-gutter-visible-p',
983 `right-gutter-visible-p', and `bottom-gutter-visible-p' are always
984 gutter-visible specifiers.
986 Valid gutter-visible instantiators are t, nil or a list of symbols.
987 If a gutter-visible instantiator is set to a list of symbols, and the
988 correspondong gutter specification is a property-list strings, then
989 elements of the gutter specification will only be visible if the
990 corresponding symbol occurs in the gutter-visible instantiator.
994 return GUTTER_VISIBLE_SPECIFIERP (object) ? Qt : Qnil;
997 DEFUN ("redisplay-gutter-area", Fredisplay_gutter_area, 0, 0, 0, /*
998 Ensure that all gutters are correctly showing their gutter specifier.
1002 Lisp_Object devcons, concons;
1004 DEVICE_LOOP_NO_BREAK (devcons, concons)
1006 struct device *d = XDEVICE (XCAR (devcons));
1007 Lisp_Object frmcons;
1009 DEVICE_FRAME_LOOP (frmcons, d)
1011 struct frame *f = XFRAME (XCAR (frmcons));
1013 /* Sequence is quite important here. We not only want to
1014 redisplay the gutter area but we also want to flush any
1015 frame size changes out so that the gutter redisplay happens
1016 in a kosha environment.
1018 This is not only so that things look right but so that
1019 glyph redisplay optimization kicks in, by default display
1020 lines will be completely re-output if
1021 f->windows_structure_changed is 1, and this is true if
1022 frame size changes haven't been flushed out. Once frame
1023 size changes have been flushed out we then need to
1024 redisplay the frame in order to flush out pending window
1026 update_frame_gutter_geometry (f);
1028 if (f->windows_structure_changed)
1029 redisplay_frame (f, 1);
1030 else if (FRAME_REPAINT_P (f))
1032 /* We have to be "in display" when we output the gutter
1034 hold_frame_size_changes ();
1035 update_frame_gutters (f);
1036 unhold_one_frame_size_changes (f);
1039 /* We now call the output_end routine for tty frames. We delay
1040 doing so in order to avoid cursor flicker. So much for 100%
1042 if (DEVICE_TTY_P (d))
1043 DEVMETH (d, output_end, (d));
1045 d->gutter_changed = 0;
1048 /* This is so that further changes to the gutters will trigger redisplay. */
1049 gutter_changed_set = 0;
1056 init_frame_gutters (struct frame *f)
1058 enum gutter_pos pos;
1059 struct window* w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f));
1060 /* We are here as far in frame creation so cached specifiers are
1061 already recomputed, and possibly modified by resource
1062 initialization. We need to recalculate autodetected gutters. */
1063 GUTTER_POS_LOOP (pos)
1065 w->real_gutter[pos] = construct_window_gutter_spec (w, pos);
1066 w->real_gutter_size[pos] = w->gutter_size[pos];
1067 if (EQ (w->gutter_size[pos], Qautodetect)
1068 && !NILP (w->gutter_visible_p[pos]))
1070 w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
1071 MARK_GUTTER_CHANGED;
1072 MARK_WINDOWS_CHANGED (w);
1076 /* Keep a record of the current sizes of things. */
1077 GUTTER_POS_LOOP (pos)
1079 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos);
1084 syms_of_gutter (void)
1086 DEFSUBR (Fgutter_specifier_p);
1087 DEFSUBR (Fgutter_size_specifier_p);
1088 DEFSUBR (Fgutter_visible_specifier_p);
1089 DEFSUBR (Fset_default_gutter_position);
1090 DEFSUBR (Fdefault_gutter_position);
1091 DEFSUBR (Fgutter_pixel_height);
1092 DEFSUBR (Fgutter_pixel_width);
1093 DEFSUBR (Fredisplay_gutter_area);
1095 defsymbol (&Qgutter_size, "gutter-size");
1096 defsymbol (&Qgutter_visible, "gutter-visible");
1097 defsymbol (&Qdefault_gutter_position_changed_hook,
1098 "default-gutter-position-changed-hook");
1102 vars_of_gutter (void)
1104 staticpro (&Vdefault_gutter_position);
1105 Vdefault_gutter_position = Qtop;
1111 specifier_type_create_gutter (void)
1113 INITIALIZE_SPECIFIER_TYPE (gutter, "gutter", "gutter-specifier-p");
1114 SPECIFIER_HAS_METHOD (gutter, validate);
1115 SPECIFIER_HAS_METHOD (gutter, after_change);
1117 INITIALIZE_SPECIFIER_TYPE (gutter_size, "gutter-size", "gutter-size-specifier-p");
1118 SPECIFIER_HAS_METHOD (gutter_size, validate);
1120 INITIALIZE_SPECIFIER_TYPE (gutter_visible, "gutter-visible", "gutter-visible-specifier-p");
1121 SPECIFIER_HAS_METHOD (gutter_visible, validate);
1125 reinit_specifier_type_create_gutter (void)
1127 REINITIALIZE_SPECIFIER_TYPE (gutter);
1128 REINITIALIZE_SPECIFIER_TYPE (gutter_size);
1129 REINITIALIZE_SPECIFIER_TYPE (gutter_visible);
1133 specifier_vars_of_gutter (void)
1137 DEFVAR_SPECIFIER ("default-gutter", &Vdefault_gutter /*
1138 Specifier for a fallback gutter.
1139 Use `set-specifier' to change this.
1141 The position of this gutter is specified in the function
1142 `default-gutter-position'. If the corresponding position-specific
1143 gutter (e.g. `top-gutter' if `default-gutter-position' is 'top)
1144 does not specify a gutter in a particular domain (usually a window),
1145 then the value of `default-gutter' in that domain, if any, will be
1148 Note that the gutter at any particular position will not be
1149 displayed unless its visibility flag is true and its thickness
1150 \(width or height, depending on orientation) is non-zero. The
1151 visibility is controlled by the specifiers `top-gutter-visible-p',
1152 `bottom-gutter-visible-p', `left-gutter-visible-p', and
1153 `right-gutter-visible-p', and the thickness is controlled by the
1154 specifiers `top-gutter-height', `bottom-gutter-height',
1155 `left-gutter-width', and `right-gutter-width'.
1157 Note that one of the four visibility specifiers inherits from
1158 `default-gutter-visibility' and one of the four thickness
1159 specifiers inherits from either `default-gutter-width' or
1160 `default-gutter-height' (depending on orientation), just
1161 like for the gutter description specifiers (e.g. `top-gutter')
1164 Therefore, if you are setting `default-gutter', you should control
1165 the visibility and thickness using `default-gutter-visible-p',
1166 `default-gutter-width', and `default-gutter-height', rather than
1167 using position-specific specifiers. That way, you will get sane
1168 behavior if the user changes the default gutter position.
1170 The gutter value should be a string, a property list of strings or
1171 nil. You can attach extents and glyphs to the string and hence display
1172 glyphs and text in other fonts in the gutter area. If the gutter value
1173 is a property list then the strings will be concatenated together
1174 before being displayed. */ );
1176 Vdefault_gutter = Fmake_specifier (Qgutter);
1177 /* #### It would be even nicer if the specifier caching
1178 automatically knew about specifier fallbacks, so we didn't
1179 have to do it ourselves. */
1180 set_specifier_caching (Vdefault_gutter,
1181 offsetof (struct window, default_gutter),
1182 default_gutter_specs_changed,
1185 DEFVAR_SPECIFIER ("top-gutter",
1186 &Vgutter[TOP_GUTTER] /*
1187 Specifier for the gutter at the top of the frame.
1188 Use `set-specifier' to change this.
1189 See `default-gutter' for a description of a valid gutter instantiator.
1191 Vgutter[TOP_GUTTER] = Fmake_specifier (Qgutter);
1192 set_specifier_caching (Vgutter[TOP_GUTTER],
1193 offsetof (struct window, gutter[TOP_GUTTER]),
1194 top_gutter_specs_changed,
1197 DEFVAR_SPECIFIER ("bottom-gutter",
1198 &Vgutter[BOTTOM_GUTTER] /*
1199 Specifier for the gutter at the bottom of the frame.
1200 Use `set-specifier' to change this.
1201 See `default-gutter' for a description of a valid gutter instantiator.
1203 Note that, unless the `default-gutter-position' is `bottom', by
1204 default the height of the bottom gutter (controlled by
1205 `bottom-gutter-height') is 0; thus, a bottom gutter will not be
1206 displayed even if you provide a value for `bottom-gutter'.
1208 Vgutter[BOTTOM_GUTTER] = Fmake_specifier (Qgutter);
1209 set_specifier_caching (Vgutter[BOTTOM_GUTTER],
1210 offsetof (struct window, gutter[BOTTOM_GUTTER]),
1211 bottom_gutter_specs_changed,
1214 DEFVAR_SPECIFIER ("left-gutter",
1215 &Vgutter[LEFT_GUTTER] /*
1216 Specifier for the gutter at the left edge of the frame.
1217 Use `set-specifier' to change this.
1218 See `default-gutter' for a description of a valid gutter instantiator.
1220 Note that, unless the `default-gutter-position' is `left', by
1221 default the height of the left gutter (controlled by
1222 `left-gutter-width') is 0; thus, a left gutter will not be
1223 displayed even if you provide a value for `left-gutter'.
1225 Vgutter[LEFT_GUTTER] = Fmake_specifier (Qgutter);
1226 set_specifier_caching (Vgutter[LEFT_GUTTER],
1227 offsetof (struct window, gutter[LEFT_GUTTER]),
1228 left_gutter_specs_changed,
1231 DEFVAR_SPECIFIER ("right-gutter",
1232 &Vgutter[RIGHT_GUTTER] /*
1233 Specifier for the gutter at the right edge of the frame.
1234 Use `set-specifier' to change this.
1235 See `default-gutter' for a description of a valid gutter instantiator.
1237 Note that, unless the `default-gutter-position' is `right', by
1238 default the height of the right gutter (controlled by
1239 `right-gutter-width') is 0; thus, a right gutter will not be
1240 displayed even if you provide a value for `right-gutter'.
1242 Vgutter[RIGHT_GUTTER] = Fmake_specifier (Qgutter);
1243 set_specifier_caching (Vgutter[RIGHT_GUTTER],
1244 offsetof (struct window, gutter[RIGHT_GUTTER]),
1245 right_gutter_specs_changed,
1248 /* initially, top inherits from default; this can be
1249 changed with `set-default-gutter-position'. */
1250 fb = list1 (Fcons (Qnil, Qnil));
1251 set_specifier_fallback (Vdefault_gutter, fb);
1252 set_specifier_fallback (Vgutter[TOP_GUTTER], Vdefault_gutter);
1253 set_specifier_fallback (Vgutter[BOTTOM_GUTTER], fb);
1254 set_specifier_fallback (Vgutter[LEFT_GUTTER], fb);
1255 set_specifier_fallback (Vgutter[RIGHT_GUTTER], fb);
1257 DEFVAR_SPECIFIER ("default-gutter-height", &Vdefault_gutter_height /*
1258 *Height of the default gutter, if it's oriented horizontally.
1259 This is a specifier; use `set-specifier' to change it.
1261 The position of the default gutter is specified by the function
1262 `set-default-gutter-position'. If the corresponding position-specific
1263 gutter thickness specifier (e.g. `top-gutter-height' if
1264 `default-gutter-position' is 'top) does not specify a thickness in a
1265 particular domain (a window or a frame), then the value of
1266 `default-gutter-height' or `default-gutter-width' (depending on the
1267 gutter orientation) in that domain, if any, will be used instead.
1269 Note that `default-gutter-height' is only used when
1270 `default-gutter-position' is 'top or 'bottom, and `default-gutter-width'
1271 is only used when `default-gutter-position' is 'left or 'right.
1273 Note that all of the position-specific gutter thickness specifiers
1274 have a fallback value of zero when they do not correspond to the
1275 default gutter. Therefore, you will have to set a non-zero thickness
1276 value if you want a position-specific gutter to be displayed.
1278 If you set the height to 'autodetect the size of the gutter will be
1279 calculated to be large enough to hold the contents of the gutter. This
1282 Vdefault_gutter_height = Fmake_specifier (Qgutter_size);
1283 set_specifier_caching (Vdefault_gutter_height,
1284 offsetof (struct window, default_gutter_height),
1285 default_gutter_size_changed_in_window,
1288 DEFVAR_SPECIFIER ("default-gutter-width", &Vdefault_gutter_width /*
1289 *Width of the default gutter, if it's oriented vertically.
1290 This is a specifier; use `set-specifier' to change it.
1292 See `default-gutter-height' for more information.
1294 Vdefault_gutter_width = Fmake_specifier (Qnatnum);
1295 set_specifier_caching (Vdefault_gutter_width,
1296 offsetof (struct window, default_gutter_width),
1297 default_gutter_size_changed_in_window,
1300 DEFVAR_SPECIFIER ("top-gutter-height",
1301 &Vgutter_size[TOP_GUTTER] /*
1302 *Height of the top gutter.
1303 This is a specifier; use `set-specifier' to change it.
1305 See `default-gutter-height' for more information.
1307 Vgutter_size[TOP_GUTTER] = Fmake_specifier (Qgutter_size);
1308 set_specifier_caching (Vgutter_size[TOP_GUTTER],
1309 offsetof (struct window, gutter_size[TOP_GUTTER]),
1310 gutter_geometry_changed_in_window, 0, 0);
1312 DEFVAR_SPECIFIER ("bottom-gutter-height",
1313 &Vgutter_size[BOTTOM_GUTTER] /*
1314 *Height of the bottom gutter.
1315 This is a specifier; use `set-specifier' to change it.
1317 See `default-gutter-height' for more information.
1319 Vgutter_size[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_size);
1320 set_specifier_caching (Vgutter_size[BOTTOM_GUTTER],
1321 offsetof (struct window, gutter_size[BOTTOM_GUTTER]),
1322 gutter_geometry_changed_in_window, 0, 0);
1324 DEFVAR_SPECIFIER ("left-gutter-width",
1325 &Vgutter_size[LEFT_GUTTER] /*
1326 *Width of left gutter.
1327 This is a specifier; use `set-specifier' to change it.
1329 See `default-gutter-height' for more information.
1331 Vgutter_size[LEFT_GUTTER] = Fmake_specifier (Qnatnum);
1332 set_specifier_caching (Vgutter_size[LEFT_GUTTER],
1333 offsetof (struct window, gutter_size[LEFT_GUTTER]),
1334 gutter_geometry_changed_in_window, 0, 0);
1336 DEFVAR_SPECIFIER ("right-gutter-width",
1337 &Vgutter_size[RIGHT_GUTTER] /*
1338 *Width of right gutter.
1339 This is a specifier; use `set-specifier' to change it.
1341 See `default-gutter-height' for more information.
1343 Vgutter_size[RIGHT_GUTTER] = Fmake_specifier (Qnatnum);
1344 set_specifier_caching (Vgutter_size[RIGHT_GUTTER],
1345 offsetof (struct window, gutter_size[RIGHT_GUTTER]),
1346 gutter_geometry_changed_in_window, 0, 0);
1350 fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb);
1352 #ifdef HAVE_X_WINDOWS
1353 fb = Fcons (Fcons (list1 (Qx), Qautodetect), fb);
1355 #ifdef HAVE_MS_WINDOWS
1356 fb = Fcons (Fcons (list1 (Qmsprinter), Qautodetect), fb);
1357 fb = Fcons (Fcons (list1 (Qmswindows), Qautodetect), fb);
1360 set_specifier_fallback (Vdefault_gutter_height, fb);
1364 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
1366 #ifdef HAVE_X_WINDOWS
1367 fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_GUTTER_WIDTH)), fb);
1369 #ifdef HAVE_MS_WINDOWS
1370 fb = Fcons (Fcons (list1 (Qmsprinter), Qzero), fb);
1371 fb = Fcons (Fcons (list1 (Qmswindows),
1372 make_int (DEFAULT_GUTTER_WIDTH)), fb);
1375 set_specifier_fallback (Vdefault_gutter_width, fb);
1377 set_specifier_fallback (Vgutter_size[TOP_GUTTER], Vdefault_gutter_height);
1378 fb = list1 (Fcons (Qnil, Qzero));
1379 set_specifier_fallback (Vgutter_size[BOTTOM_GUTTER], fb);
1380 set_specifier_fallback (Vgutter_size[LEFT_GUTTER], fb);
1381 set_specifier_fallback (Vgutter_size[RIGHT_GUTTER], fb);
1383 DEFVAR_SPECIFIER ("default-gutter-border-width",
1384 &Vdefault_gutter_border_width /*
1385 *Width of the border around the default gutter.
1386 This is a specifier; use `set-specifier' to change it.
1388 The position of the default gutter is specified by the function
1389 `set-default-gutter-position'. If the corresponding position-specific
1390 gutter border width specifier (e.g. `top-gutter-border-width' if
1391 `default-gutter-position' is 'top) does not specify a border width in a
1392 particular domain (a window or a frame), then the value of
1393 `default-gutter-border-width' in that domain, if any, will be used
1397 Vdefault_gutter_border_width = Fmake_specifier (Qnatnum);
1398 set_specifier_caching (Vdefault_gutter_border_width,
1399 offsetof (struct window, default_gutter_border_width),
1400 default_gutter_border_width_changed_in_window,
1403 DEFVAR_SPECIFIER ("top-gutter-border-width",
1404 &Vgutter_border_width[TOP_GUTTER] /*
1405 *Border width of the top gutter.
1406 This is a specifier; use `set-specifier' to change it.
1408 See `default-gutter-height' for more information.
1410 Vgutter_border_width[TOP_GUTTER] = Fmake_specifier (Qnatnum);
1411 set_specifier_caching (Vgutter_border_width[TOP_GUTTER],
1412 offsetof (struct window,
1413 gutter_border_width[TOP_GUTTER]),
1414 gutter_geometry_changed_in_window, 0, 0);
1416 DEFVAR_SPECIFIER ("bottom-gutter-border-width",
1417 &Vgutter_border_width[BOTTOM_GUTTER] /*
1418 *Border width of the bottom gutter.
1419 This is a specifier; use `set-specifier' to change it.
1421 See `default-gutter-height' for more information.
1423 Vgutter_border_width[BOTTOM_GUTTER] = Fmake_specifier (Qnatnum);
1424 set_specifier_caching (Vgutter_border_width[BOTTOM_GUTTER],
1425 offsetof (struct window,
1426 gutter_border_width[BOTTOM_GUTTER]),
1427 gutter_geometry_changed_in_window, 0, 0);
1429 DEFVAR_SPECIFIER ("left-gutter-border-width",
1430 &Vgutter_border_width[LEFT_GUTTER] /*
1431 *Border width of left gutter.
1432 This is a specifier; use `set-specifier' to change it.
1434 See `default-gutter-height' for more information.
1436 Vgutter_border_width[LEFT_GUTTER] = Fmake_specifier (Qnatnum);
1437 set_specifier_caching (Vgutter_border_width[LEFT_GUTTER],
1438 offsetof (struct window,
1439 gutter_border_width[LEFT_GUTTER]),
1440 gutter_geometry_changed_in_window, 0, 0);
1442 DEFVAR_SPECIFIER ("right-gutter-border-width",
1443 &Vgutter_border_width[RIGHT_GUTTER] /*
1444 *Border width of right gutter.
1445 This is a specifier; use `set-specifier' to change it.
1447 See `default-gutter-height' for more information.
1449 Vgutter_border_width[RIGHT_GUTTER] = Fmake_specifier (Qnatnum);
1450 set_specifier_caching (Vgutter_border_width[RIGHT_GUTTER],
1451 offsetof (struct window,
1452 gutter_border_width[RIGHT_GUTTER]),
1453 gutter_geometry_changed_in_window, 0, 0);
1457 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
1459 #ifdef HAVE_X_WINDOWS
1460 fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_GUTTER_BORDER_WIDTH)), fb);
1462 #ifdef HAVE_MS_WINDOWS
1463 fb = Fcons (Fcons (list1 (Qmsprinter), Qzero), fb);
1464 fb = Fcons (Fcons (list1 (Qmswindows), make_int (DEFAULT_GUTTER_BORDER_WIDTH)), fb);
1467 set_specifier_fallback (Vdefault_gutter_border_width, fb);
1469 set_specifier_fallback (Vgutter_border_width[TOP_GUTTER], Vdefault_gutter_border_width);
1470 fb = list1 (Fcons (Qnil, Qzero));
1471 set_specifier_fallback (Vgutter_border_width[BOTTOM_GUTTER], fb);
1472 set_specifier_fallback (Vgutter_border_width[LEFT_GUTTER], fb);
1473 set_specifier_fallback (Vgutter_border_width[RIGHT_GUTTER], fb);
1475 DEFVAR_SPECIFIER ("default-gutter-visible-p", &Vdefault_gutter_visible_p /*
1476 *Whether the default gutter is visible.
1477 This is a specifier; use `set-specifier' to change it.
1479 The position of the default gutter is specified by the function
1480 `set-default-gutter-position'. If the corresponding position-specific
1481 gutter visibility specifier (e.g. `top-gutter-visible-p' if
1482 `default-gutter-position' is 'top) does not specify a visible-p value
1483 in a particular domain (a window or a frame), then the value of
1484 `default-gutter-visible-p' in that domain, if any, will be used
1487 `default-gutter-visible-p' and all of the position-specific gutter
1488 visibility specifiers have a fallback value of true.
1490 Vdefault_gutter_visible_p = Fmake_specifier (Qgutter_visible);
1491 set_specifier_caching (Vdefault_gutter_visible_p,
1492 offsetof (struct window,
1493 default_gutter_visible_p),
1494 default_gutter_visible_p_changed_in_window,
1497 DEFVAR_SPECIFIER ("top-gutter-visible-p",
1498 &Vgutter_visible_p[TOP_GUTTER] /*
1499 *Whether the top gutter is visible.
1500 This is a specifier; use `set-specifier' to change it.
1502 See `default-gutter-visible-p' for more information.
1504 Vgutter_visible_p[TOP_GUTTER] = Fmake_specifier (Qgutter_visible);
1505 set_specifier_caching (Vgutter_visible_p[TOP_GUTTER],
1506 offsetof (struct window,
1507 gutter_visible_p[TOP_GUTTER]),
1508 top_gutter_specs_changed, 0, 0);
1510 DEFVAR_SPECIFIER ("bottom-gutter-visible-p",
1511 &Vgutter_visible_p[BOTTOM_GUTTER] /*
1512 *Whether the bottom gutter is visible.
1513 This is a specifier; use `set-specifier' to change it.
1515 See `default-gutter-visible-p' for more information.
1517 Vgutter_visible_p[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_visible);
1518 set_specifier_caching (Vgutter_visible_p[BOTTOM_GUTTER],
1519 offsetof (struct window,
1520 gutter_visible_p[BOTTOM_GUTTER]),
1521 bottom_gutter_specs_changed, 0, 0);
1523 DEFVAR_SPECIFIER ("left-gutter-visible-p",
1524 &Vgutter_visible_p[LEFT_GUTTER] /*
1525 *Whether the left gutter is visible.
1526 This is a specifier; use `set-specifier' to change it.
1528 See `default-gutter-visible-p' for more information.
1530 Vgutter_visible_p[LEFT_GUTTER] = Fmake_specifier (Qgutter_visible);
1531 set_specifier_caching (Vgutter_visible_p[LEFT_GUTTER],
1532 offsetof (struct window,
1533 gutter_visible_p[LEFT_GUTTER]),
1534 left_gutter_specs_changed, 0, 0);
1536 DEFVAR_SPECIFIER ("right-gutter-visible-p",
1537 &Vgutter_visible_p[RIGHT_GUTTER] /*
1538 *Whether the right gutter is visible.
1539 This is a specifier; use `set-specifier' to change it.
1541 See `default-gutter-visible-p' for more information.
1543 Vgutter_visible_p[RIGHT_GUTTER] = Fmake_specifier (Qgutter_visible);
1544 set_specifier_caching (Vgutter_visible_p[RIGHT_GUTTER],
1545 offsetof (struct window,
1546 gutter_visible_p[RIGHT_GUTTER]),
1547 right_gutter_specs_changed, 0, 0);
1549 /* initially, top inherits from default; this can be
1550 changed with `set-default-gutter-position'. */
1551 fb = list1 (Fcons (Qnil, Qt));
1552 set_specifier_fallback (Vdefault_gutter_visible_p, fb);
1553 set_specifier_fallback (Vgutter_visible_p[TOP_GUTTER],
1554 Vdefault_gutter_visible_p);
1555 set_specifier_fallback (Vgutter_visible_p[BOTTOM_GUTTER], fb);
1556 set_specifier_fallback (Vgutter_visible_p[LEFT_GUTTER], fb);
1557 set_specifier_fallback (Vgutter_visible_p[RIGHT_GUTTER], fb);