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);
252 /* Sizing gutters is a pain so we try and help the user by determining
253 what height will accommodate all lines. This is useless on left and
254 right gutters as we always have a maximal number of lines. */
256 calculate_gutter_size_from_display_lines (enum gutter_pos pos,
257 display_line_dynarr* ddla)
260 struct display_line *dl;
262 /* For top and bottom the calculation is easy. */
263 if (pos == TOP_GUTTER || pos == BOTTOM_GUTTER)
265 /* grab coordinates of last line */
266 if (Dynarr_length (ddla))
268 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1);
269 size = (dl->ypos + dl->descent - dl->clip)
270 - (Dynarr_atp (ddla, 0)->ypos - Dynarr_atp (ddla, 0)->ascent);
273 /* For left and right we have to do some maths. */
276 int start_pos = 0, end_pos = 0, line;
277 for (line = 0; line < Dynarr_length (ddla); line++)
280 dl = Dynarr_atp (ddla, line);
282 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
284 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
286 if (db->type == TEXT)
288 start_pos = min (db->start_pos, start_pos);
289 end_pos = max (db->end_pos, end_pos);
293 size = end_pos - start_pos;
300 calculate_gutter_size (struct window *w, enum gutter_pos pos)
302 struct frame* f = XFRAME (WINDOW_FRAME (w));
304 display_line_dynarr* ddla;
305 Lisp_Object ret = Qnil;
307 /* degenerate case */
308 if (NILP (RAW_WINDOW_GUTTER (w, pos))
315 /* Redisplay code that we use relies on GC not happening. Make it
317 count = specpdl_depth ();
318 record_unwind_protect (restore_gc_inhibit,
319 make_int (gc_currently_forbidden));
320 gc_currently_forbidden = 1;
322 ddla = Dynarr_new (display_line);
323 /* generate some display lines */
324 generate_displayable_area (w, WINDOW_GUTTER (w, pos),
325 FRAME_LEFT_BORDER_END (f),
326 FRAME_TOP_BORDER_END (f),
327 FRAME_RIGHT_BORDER_START (f)
328 - FRAME_LEFT_BORDER_END (f),
329 FRAME_BOTTOM_BORDER_START (f)
330 - FRAME_TOP_BORDER_END (f),
333 /* Let GC happen again. */
334 unbind_to (count, Qnil);
336 ret = make_int (calculate_gutter_size_from_display_lines (pos, ddla));
337 free_display_lines (ddla);
343 output_gutter (struct frame *f, enum gutter_pos pos, int force)
346 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
347 struct device *d = XDEVICE (f->device);
348 struct window* w = XWINDOW (window);
349 int x, y, width, height, ypos;
350 int line, border_width;
352 display_line_dynarr* ddla, *cdla;
353 struct display_line *dl = 0;
356 if (!WINDOW_LIVE_P (w))
359 border_width = FRAME_GUTTER_BORDER_WIDTH (f, pos);
360 findex = get_builtin_face_cache_index (w, Vwidget_face);
362 if (!f->current_display_lines[pos])
363 f->current_display_lines[pos] = Dynarr_new (display_line);
364 if (!f->desired_display_lines[pos])
365 f->desired_display_lines[pos] = Dynarr_new (display_line);
367 ddla = f->desired_display_lines[pos];
368 cdla = f->current_display_lines[pos];
369 cdla_len = Dynarr_length (cdla);
371 XSETFRAME (frame, f);
373 get_gutter_coords (f, pos, &x, &y, &width, &height);
374 /* generate some display lines */
375 generate_displayable_area (w, WINDOW_GUTTER (w, pos),
376 x + border_width, y + border_width,
377 width - 2 * border_width,
378 height - 2 * border_width, ddla, 0, findex);
380 /* We only output the gutter if we think something of significance
381 has changed. This is, for example, because redisplay can cause
382 new face cache elements to get added causing compare_runes to
383 fail because the findex for a particular face has changed. */
384 if (force || f->faces_changed || f->frame_changed ||
385 f->gutter_changed || f->glyphs_changed ||
386 f->size_changed || f->subwindows_changed ||
387 w->windows_changed || f->windows_structure_changed ||
388 cdla_len != Dynarr_length (ddla) ||
389 (f->extents_changed && w->gutter_extent_modiff[pos]))
392 printf ("gutter redisplay triggered by %s\n", force ? "force" :
393 f->faces_changed ? "f->faces_changed" :
394 f->frame_changed ? "f->frame_changed" :
395 f->gutter_changed ? "f->gutter_changed" :
396 f->glyphs_changed ? "f->glyphs_changed" :
397 f->size_changed ? "f->size_changed" :
398 f->subwindows_changed ? "f->subwindows_changed" :
399 w->windows_changed ? "w->windows_changed" :
400 f->windows_structure_changed ? "f->windows_structure_changed" :
401 cdla_len != Dynarr_length (ddla) ? "different display structures" :
402 f->extents_changed && w->gutter_extent_modiff[pos] ?
403 "f->extents_changed && w->gutter_extent_modiff[pos]" : "<null>");
405 /* Output each line. */
406 for (line = 0; line < Dynarr_length (ddla); line++)
408 output_display_line (w, cdla, ddla, line, -1, -1);
411 /* If the number of display lines has shrunk, adjust. */
412 if (cdla_len > Dynarr_length (ddla))
414 Dynarr_length (cdla) = Dynarr_length (ddla);
417 /* grab coordinates of last line and blank after it. */
418 if (Dynarr_length (ddla) > 0)
420 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1);
421 ypos = dl->ypos + dl->descent - dl->clip;
426 redisplay_clear_region (window, findex, x + border_width , ypos,
427 width - 2 * border_width, height - (ypos - y) - border_width);
428 /* If, for some reason, we have more to display than we have
429 room for, and we are allowed to resize the gutter, then make
430 sure this happens before the next time we try and
431 output. This can happen when face font sizes change. */
432 if (dl && EQ (w->gutter_size[pos], Qautodetect)
434 calculate_gutter_size_from_display_lines (pos, ddla) >
435 WINDOW_GUTTER_SIZE_INTERNAL (w, pos)))
437 /* #### Ideally we would just mark the specifier as dirty
438 and everything else would "just work". Unfortunately we have
439 two problems with this. One is that the specifier cache
440 won't be recalculated unless the specifier code thinks the
441 cached value has actually changed, even though we have
442 marked the specifier as dirty. Additionally, although doing
443 this results in a gutter size change, we never seem to get
444 back into redisplay so that the frame size can be updated. I
445 think this is because we are already in redisplay and later
446 on the frame will be marked as clean. Thus we also have to
447 force a pending recalculation of the frame size. */
448 w->gutter_size[pos] = Qnil;
449 Fset_specifier_dirty_flag (Vgutter_size[pos]);
450 update_gutter_geometry (f, pos);
453 /* bevel the gutter area if so desired */
454 if (border_width != 0)
456 MAYBE_DEVMETH (d, bevel_area,
457 (w, findex, x, y, width, height, border_width,
458 EDGE_ALL, EDGE_BEVEL_OUT));
463 /* Nothing of significance happened so sync the display line
465 for (line = 0; line < Dynarr_length (ddla); line++)
467 sync_display_line_structs (w, line, 1, cdla, ddla);
471 w->gutter_extent_modiff [pos] = 0;
475 clear_gutter (struct frame *f, enum gutter_pos pos)
477 int x, y, width, height;
478 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
479 face_index findex = get_builtin_face_cache_index (XWINDOW (window),
481 get_gutter_coords (f, pos, &x, &y, &width, &height);
483 SET_GUTTER_WAS_VISIBLE_FLAG (f, pos, 0);
485 redisplay_clear_region (window, findex, x, y, width, height);
488 /* #### I don't currently believe that redisplay needs to mark the
489 glyphs in its structures since these will always be referenced from
490 somewhere else. However, I'm not sure enough to stake my life on it
491 at this point, so we do the safe thing. */
493 /* See the comment in image_instantiate_cache_result as to why marking
494 the glyph will also mark the image_instance. */
496 mark_gutters (struct frame* f)
499 GUTTER_POS_LOOP (pos)
501 if (f->current_display_lines[pos])
502 mark_redisplay_structs (f->current_display_lines[pos]);
503 /* #### Do we really need to mark the desired lines? */
504 if (f->desired_display_lines[pos])
505 mark_redisplay_structs (f->desired_display_lines[pos]);
509 /* This is called by extent_changed_for_redisplay, so that redisplay
510 knows exactly what extents have changed. */
512 gutter_extent_signal_changed_region_maybe (Lisp_Object obj,
513 Bufpos start, Bufpos end)
515 /* #### Start and end are currently ignored but could be used by a
516 more optimal gutter redisplay. We currently loop over all frames
517 here, this could be optimized. */
518 Lisp_Object frmcons, devcons, concons;
520 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
522 struct frame *f = XFRAME (XCAR (frmcons));
524 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
525 struct window* w = XWINDOW (window);
527 GUTTER_POS_LOOP (pos)
529 if (EQ (WINDOW_GUTTER (w, pos), obj))
531 w->gutter_extent_modiff[pos]++;
537 /* We have to change the gutter geometry separately to the gutter
538 update since it needs to occur outside of redisplay proper. */
540 update_gutter_geometry (struct frame *f, enum gutter_pos pos)
542 /* If the gutter geometry has changed then re-layout the
543 frame. If we are in display there is almost no point in doing
544 anything else since the frame size changes will be delayed
545 until we are out of redisplay proper. */
546 if (FRAME_GUTTER_BOUNDS (f, pos) != f->current_gutter_bounds[pos])
549 pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f),
551 change_frame_size (f, height, width, 0);
554 /* Mark sizes as up-to-date. */
555 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos);
559 update_frame_gutter_geometry (struct frame *f)
561 if (f->gutter_changed || f->windows_structure_changed)
565 /* If the gutter geometry has changed then re-layout the
566 frame. If we are in display there is almost no point in doing
567 anything else since the frame size changes will be delayed
568 until we are out of redisplay proper. */
569 GUTTER_POS_LOOP (pos)
571 update_gutter_geometry (f, pos);
577 update_frame_gutters (struct frame *f)
579 if (f->faces_changed || f->frame_changed ||
580 f->gutter_changed || f->glyphs_changed ||
581 f->size_changed || f->subwindows_changed ||
582 f->windows_changed || f->windows_structure_changed ||
587 /* We don't actually care about these when outputting the gutter
588 so locally disable them. */
589 int local_clip_changed = f->clip_changed;
590 int local_buffers_changed = f->buffers_changed;
592 f->buffers_changed = 0;
595 GUTTER_POS_LOOP (pos)
597 if (FRAME_GUTTER_VISIBLE (f, pos))
598 output_gutter (f, pos, 0);
600 else if (gutter_was_visible (f, pos))
601 clear_gutter (f, pos);
604 f->clip_changed = local_clip_changed;
605 f->buffers_changed = local_buffers_changed;
606 f->gutter_changed = 0;
611 reset_gutter_display_lines (struct frame* f)
614 GUTTER_POS_LOOP (pos)
616 if (f->current_display_lines[pos])
617 Dynarr_reset (f->current_display_lines[pos]);
622 redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y,
623 int width, int height)
625 int g_x, g_y, g_width, g_height;
627 get_gutter_coords (f, pos, &g_x, &g_y, &g_width, &g_height);
629 if (((y + height) < g_y) || (y > (g_y + g_height)) || !height || !width || !g_height || !g_width)
631 if (((x + width) < g_x) || (x > (g_x + g_width)))
635 printf ("redrawing gutter after expose %d+%d, %dx%d\n",
636 x, y, width, height);
638 /* #### optimize this - redrawing the whole gutter for every expose
639 is very expensive. We reset the current display lines because if
640 they're being exposed they are no longer current. */
641 reset_gutter_display_lines (f);
643 /* Even if none of the gutter is in the area, the blank region at
644 the very least must be because the first thing we did is verify
645 that some portion of the gutter is in the exposed region. */
646 output_gutter (f, pos, 1);
650 redraw_exposed_gutters (struct frame *f, int x, int y, int width,
655 /* We have to be "in display" when we output the gutter - make it
657 hold_frame_size_changes ();
658 GUTTER_POS_LOOP (pos)
660 if (FRAME_GUTTER_VISIBLE (f, pos))
661 redraw_exposed_gutter (f, pos, x, y, width, height);
663 unhold_one_frame_size_changes (f);
667 free_frame_gutters (struct frame *f)
670 GUTTER_POS_LOOP (pos)
672 if (f->current_display_lines[pos])
674 free_display_lines (f->current_display_lines[pos]);
675 f->current_display_lines[pos] = 0;
677 if (f->desired_display_lines[pos])
679 free_display_lines (f->desired_display_lines[pos]);
680 f->desired_display_lines[pos] = 0;
685 static enum gutter_pos
686 decode_gutter_position (Lisp_Object position)
688 if (EQ (position, Qtop)) return TOP_GUTTER;
689 if (EQ (position, Qbottom)) return BOTTOM_GUTTER;
690 if (EQ (position, Qleft)) return LEFT_GUTTER;
691 if (EQ (position, Qright)) return RIGHT_GUTTER;
692 signal_simple_error ("Invalid gutter position", position);
694 return TOP_GUTTER; /* not reached */
697 DEFUN ("set-default-gutter-position", Fset_default_gutter_position, 1, 1, 0, /*
698 Set the position that the `default-gutter' will be displayed at.
699 Valid positions are 'top, 'bottom, 'left and 'right.
700 See `default-gutter-position'.
704 enum gutter_pos cur = decode_gutter_position (Vdefault_gutter_position);
705 enum gutter_pos new = decode_gutter_position (position);
709 /* The following calls will automatically cause the dirty
710 flags to be set; we delay frame size changes to avoid
711 lots of frame flickering. */
712 /* #### I think this should be GC protected. -sb */
713 hold_frame_size_changes ();
714 set_specifier_fallback (Vgutter[cur], list1 (Fcons (Qnil, Qnil)));
715 set_specifier_fallback (Vgutter[new], Vdefault_gutter);
716 set_specifier_fallback (Vgutter_size[cur], list1 (Fcons (Qnil, Qzero)));
717 set_specifier_fallback (Vgutter_size[new],
718 new == TOP_GUTTER || new == BOTTOM_GUTTER
719 ? Vdefault_gutter_height
720 : Vdefault_gutter_width);
721 set_specifier_fallback (Vgutter_border_width[cur],
722 list1 (Fcons (Qnil, Qzero)));
723 set_specifier_fallback (Vgutter_border_width[new],
724 Vdefault_gutter_border_width);
725 set_specifier_fallback (Vgutter_visible_p[cur], list1 (Fcons (Qnil, Qt)));
726 set_specifier_fallback (Vgutter_visible_p[new], Vdefault_gutter_visible_p);
728 Vdefault_gutter_position = position;
729 unhold_frame_size_changes ();
732 run_hook (Qdefault_gutter_position_changed_hook);
737 DEFUN ("default-gutter-position", Fdefault_gutter_position, 0, 0, 0, /*
738 Return the position that the `default-gutter' will be displayed at.
739 The `default-gutter' will only be displayed here if the corresponding
740 position-specific gutter specifier does not provide a value.
744 return Vdefault_gutter_position;
747 DEFUN ("gutter-pixel-width", Fgutter_pixel_width, 0, 2, 0, /*
748 Return the pixel width of the gutter at POS in LOCALE.
749 POS defaults to the default gutter position. LOCALE defaults to
754 int x, y, width, height;
755 enum gutter_pos p = TOP_GUTTER;
756 struct frame *f = decode_frame (FW_FRAME (locale));
759 pos = Vdefault_gutter_position;
760 p = decode_gutter_position (pos);
762 get_gutter_coords (f, p, &x, &y, &width, &height);
763 width -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2);
765 return make_int (width);
768 DEFUN ("gutter-pixel-height", Fgutter_pixel_height, 0, 2, 0, /*
769 Return the pixel height of the gutter at POS in LOCALE.
770 POS defaults to the default gutter position. LOCALE defaults to
775 int x, y, width, height;
776 enum gutter_pos p = TOP_GUTTER;
777 struct frame *f = decode_frame (FW_FRAME (locale));
780 pos = Vdefault_gutter_position;
781 p = decode_gutter_position (pos);
783 get_gutter_coords (f, p, &x, &y, &width, &height);
784 height -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2);
786 return make_int (height);
789 DEFINE_SPECIFIER_TYPE (gutter);
792 gutter_after_change (Lisp_Object specifier, Lisp_Object locale)
798 gutter_validate (Lisp_Object instantiator)
800 if (NILP (instantiator))
803 /* Must be a string or a plist. */
804 if (!STRINGP (instantiator) && NILP (Fvalid_plist_p (instantiator)))
805 signal_simple_error ("Gutter spec must be string, plist or nil", instantiator);
807 if (!STRINGP (instantiator))
811 for (rest = instantiator; !NILP (rest); rest = XCDR (XCDR (rest)))
813 if (!SYMBOLP (XCAR (rest))
814 || !STRINGP (XCAR (XCDR (rest))))
815 signal_simple_error ("Gutter plist spec must contain strings", instantiator);
820 DEFUN ("gutter-specifier-p", Fgutter_specifier_p, 1, 1, 0, /*
821 Return non-nil if OBJECT is a gutter specifier.
823 See `make-gutter-specifier' for a description of possible gutter
828 return GUTTER_SPECIFIERP (object) ? Qt : Qnil;
833 Helper for invalidating the real specifier when default
834 specifier caching changes
837 recompute_overlaying_specifier (Lisp_Object real_one[4])
839 enum gutter_pos pos = decode_gutter_position (Vdefault_gutter_position);
840 Fset_specifier_dirty_flag (real_one[pos]);
844 gutter_specs_changed (Lisp_Object specifier, struct window *w,
845 Lisp_Object oldval, enum gutter_pos pos)
847 w->real_gutter[pos] = construct_window_gutter_spec (w, pos);
848 w->real_gutter_size[pos] = w->gutter_size[pos];
850 if (EQ (w->real_gutter_size[pos], Qautodetect)
851 && !NILP (w->gutter_visible_p[pos]))
853 w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
856 MARK_MODELINE_CHANGED;
857 MARK_WINDOWS_CHANGED (w);
860 /* We define all of these so we can access which actual gutter changed. */
862 top_gutter_specs_changed (Lisp_Object specifier, struct window *w,
865 gutter_specs_changed (specifier, w, oldval, TOP_GUTTER);
869 bottom_gutter_specs_changed (Lisp_Object specifier, struct window *w,
872 gutter_specs_changed (specifier, w, oldval, BOTTOM_GUTTER);
876 left_gutter_specs_changed (Lisp_Object specifier, struct window *w,
879 gutter_specs_changed (specifier, w, oldval, LEFT_GUTTER);
883 right_gutter_specs_changed (Lisp_Object specifier, struct window *w,
886 gutter_specs_changed (specifier, w, oldval, RIGHT_GUTTER);
890 default_gutter_specs_changed (Lisp_Object specifier, struct window *w,
893 recompute_overlaying_specifier (Vgutter);
897 gutter_geometry_changed_in_window (Lisp_Object specifier, struct window *w,
901 GUTTER_POS_LOOP (pos)
903 w->real_gutter_size[pos] = w->gutter_size[pos];
904 if (EQ (w->real_gutter_size[pos], Qautodetect)
905 && !NILP (w->gutter_visible_p[pos]))
907 w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
912 MARK_MODELINE_CHANGED;
913 MARK_WINDOWS_CHANGED (w);
917 default_gutter_size_changed_in_window (Lisp_Object specifier, struct window *w,
920 recompute_overlaying_specifier (Vgutter_size);
924 default_gutter_border_width_changed_in_window (Lisp_Object specifier,
928 recompute_overlaying_specifier (Vgutter_border_width);
932 default_gutter_visible_p_changed_in_window (Lisp_Object specifier,
936 recompute_overlaying_specifier (Vgutter_visible_p);
937 /* Need to reconstruct the gutter specifier as it is affected by the
939 recompute_overlaying_specifier (Vgutter);
943 DECLARE_SPECIFIER_TYPE (gutter_size);
944 #define GUTTER_SIZE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_size)
945 DEFINE_SPECIFIER_TYPE (gutter_size);
948 gutter_size_validate (Lisp_Object instantiator)
950 if (NILP (instantiator))
953 if (!INTP (instantiator) && !EQ (instantiator, Qautodetect))
954 signal_simple_error ("Gutter size must be an integer or 'autodetect", instantiator);
957 DEFUN ("gutter-size-specifier-p", Fgutter_size_specifier_p, 1, 1, 0, /*
958 Return non-nil if OBJECT is a gutter-size specifier.
960 See `make-gutter-size-specifier' for a description of possible gutter-size
965 return GUTTER_SIZE_SPECIFIERP (object) ? Qt : Qnil;
968 DECLARE_SPECIFIER_TYPE (gutter_visible);
969 #define GUTTER_VISIBLE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_visible)
970 DEFINE_SPECIFIER_TYPE (gutter_visible);
973 gutter_visible_validate (Lisp_Object instantiator)
975 if (NILP (instantiator))
978 if (!NILP (instantiator) && !EQ (instantiator, Qt) && !CONSP (instantiator))
979 signal_simple_error ("Gutter visibility must be a boolean or list of symbols",
982 if (CONSP (instantiator))
986 EXTERNAL_LIST_LOOP (rest, instantiator)
988 if (!SYMBOLP (XCAR (rest)))
989 signal_simple_error ("Gutter visibility must be a boolean or list of symbols",
995 DEFUN ("gutter-visible-specifier-p", Fgutter_visible_specifier_p, 1, 1, 0, /*
996 Return non-nil if OBJECT is a gutter-visible specifier.
998 See `make-gutter-visible-specifier' for a description of possible
999 gutter-visible instantiators.
1003 return GUTTER_VISIBLE_SPECIFIERP (object) ? Qt : Qnil;
1006 DEFUN ("redisplay-gutter-area", Fredisplay_gutter_area, 0, 0, 0, /*
1007 Ensure that all gutters are correctly showing their gutter specifier.
1011 Lisp_Object devcons, concons;
1013 DEVICE_LOOP_NO_BREAK (devcons, concons)
1015 struct device *d = XDEVICE (XCAR (devcons));
1016 Lisp_Object frmcons;
1018 DEVICE_FRAME_LOOP (frmcons, d)
1020 struct frame *f = XFRAME (XCAR (frmcons));
1022 MAYBE_DEVMETH (d, frame_output_begin, (f));
1024 /* Sequence is quite important here. We not only want to
1025 redisplay the gutter area but we also want to flush any
1026 frame size changes out so that the gutter redisplay happens
1027 in a kosha environment.
1029 This is not only so that things look right but so that
1030 glyph redisplay optimization kicks in, by default display
1031 lines will be completely re-output if
1032 f->windows_structure_changed is 1, and this is true if
1033 frame size changes haven't been flushed out. Once frame
1034 size changes have been flushed out we then need to
1035 redisplay the frame in order to flush out pending window
1037 update_frame_gutter_geometry (f);
1039 if (f->windows_structure_changed)
1040 redisplay_frame (f, 1);
1041 else if (FRAME_REPAINT_P (f))
1043 /* We have to be "in display" when we output the gutter
1045 hold_frame_size_changes ();
1046 update_frame_gutters (f);
1047 unhold_one_frame_size_changes (f);
1050 MAYBE_DEVMETH (d, frame_output_end, (f));
1053 d->gutter_changed = 0;
1056 /* This is so that further changes to the gutters will trigger redisplay. */
1057 gutter_changed_set = 0;
1064 init_frame_gutters (struct frame *f)
1066 enum gutter_pos pos;
1067 struct window* w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f));
1068 /* We are here as far in frame creation so cached specifiers are
1069 already recomputed, and possibly modified by resource
1070 initialization. We need to recalculate autodetected gutters. */
1071 GUTTER_POS_LOOP (pos)
1073 w->real_gutter[pos] = construct_window_gutter_spec (w, pos);
1074 w->real_gutter_size[pos] = w->gutter_size[pos];
1075 if (EQ (w->gutter_size[pos], Qautodetect)
1076 && !NILP (w->gutter_visible_p[pos]))
1078 w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
1079 MARK_GUTTER_CHANGED;
1080 MARK_WINDOWS_CHANGED (w);
1084 /* Keep a record of the current sizes of things. */
1085 GUTTER_POS_LOOP (pos)
1087 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos);
1092 syms_of_gutter (void)
1094 DEFSUBR (Fgutter_specifier_p);
1095 DEFSUBR (Fgutter_size_specifier_p);
1096 DEFSUBR (Fgutter_visible_specifier_p);
1097 DEFSUBR (Fset_default_gutter_position);
1098 DEFSUBR (Fdefault_gutter_position);
1099 DEFSUBR (Fgutter_pixel_height);
1100 DEFSUBR (Fgutter_pixel_width);
1101 DEFSUBR (Fredisplay_gutter_area);
1103 defsymbol (&Qgutter_size, "gutter-size");
1104 defsymbol (&Qgutter_visible, "gutter-visible");
1105 defsymbol (&Qdefault_gutter_position_changed_hook,
1106 "default-gutter-position-changed-hook");
1110 vars_of_gutter (void)
1112 staticpro (&Vdefault_gutter_position);
1113 Vdefault_gutter_position = Qtop;
1119 specifier_type_create_gutter (void)
1121 INITIALIZE_SPECIFIER_TYPE (gutter, "gutter", "gutter-specifier-p");
1122 SPECIFIER_HAS_METHOD (gutter, validate);
1123 SPECIFIER_HAS_METHOD (gutter, after_change);
1125 INITIALIZE_SPECIFIER_TYPE (gutter_size, "gutter-size", "gutter-size-specifier-p");
1126 SPECIFIER_HAS_METHOD (gutter_size, validate);
1128 INITIALIZE_SPECIFIER_TYPE (gutter_visible, "gutter-visible", "gutter-visible-specifier-p");
1129 SPECIFIER_HAS_METHOD (gutter_visible, validate);
1133 reinit_specifier_type_create_gutter (void)
1135 REINITIALIZE_SPECIFIER_TYPE (gutter);
1136 REINITIALIZE_SPECIFIER_TYPE (gutter_size);
1137 REINITIALIZE_SPECIFIER_TYPE (gutter_visible);
1141 specifier_vars_of_gutter (void)
1145 DEFVAR_SPECIFIER ("default-gutter", &Vdefault_gutter /*
1146 Specifier for a fallback gutter.
1147 Use `set-specifier' to change this.
1149 The position of this gutter is specified in the function
1150 `default-gutter-position'. If the corresponding position-specific
1151 gutter (e.g. `top-gutter' if `default-gutter-position' is 'top)
1152 does not specify a gutter in a particular domain (usually a window),
1153 then the value of `default-gutter' in that domain, if any, will be
1156 Note that the gutter at any particular position will not be
1157 displayed unless its visibility flag is true and its thickness
1158 \(width or height, depending on orientation) is non-zero. The
1159 visibility is controlled by the specifiers `top-gutter-visible-p',
1160 `bottom-gutter-visible-p', `left-gutter-visible-p', and
1161 `right-gutter-visible-p', and the thickness is controlled by the
1162 specifiers `top-gutter-height', `bottom-gutter-height',
1163 `left-gutter-width', and `right-gutter-width'.
1165 Note that one of the four visibility specifiers inherits from
1166 `default-gutter-visibility' and one of the four thickness
1167 specifiers inherits from either `default-gutter-width' or
1168 `default-gutter-height' (depending on orientation), just
1169 like for the gutter description specifiers (e.g. `top-gutter')
1172 Therefore, if you are setting `default-gutter', you should control
1173 the visibility and thickness using `default-gutter-visible-p',
1174 `default-gutter-width', and `default-gutter-height', rather than
1175 using position-specific specifiers. That way, you will get sane
1176 behavior if the user changes the default gutter position.
1178 The gutter value should be a string, a property list of strings or
1179 nil. You can attach extents and glyphs to the string and hence display
1180 glyphs and text in other fonts in the gutter area. If the gutter value
1181 is a property list then the strings will be concatenated together
1182 before being displayed. */ );
1184 Vdefault_gutter = Fmake_specifier (Qgutter);
1185 /* #### It would be even nicer if the specifier caching
1186 automatically knew about specifier fallbacks, so we didn't
1187 have to do it ourselves. */
1188 set_specifier_caching (Vdefault_gutter,
1189 offsetof (struct window, default_gutter),
1190 default_gutter_specs_changed,
1193 DEFVAR_SPECIFIER ("top-gutter",
1194 &Vgutter[TOP_GUTTER] /*
1195 Specifier for the gutter at the top of the frame.
1196 Use `set-specifier' to change this.
1197 See `default-gutter' for a description of a valid gutter instantiator.
1199 Vgutter[TOP_GUTTER] = Fmake_specifier (Qgutter);
1200 set_specifier_caching (Vgutter[TOP_GUTTER],
1201 offsetof (struct window, gutter[TOP_GUTTER]),
1202 top_gutter_specs_changed,
1205 DEFVAR_SPECIFIER ("bottom-gutter",
1206 &Vgutter[BOTTOM_GUTTER] /*
1207 Specifier for the gutter at the bottom of the frame.
1208 Use `set-specifier' to change this.
1209 See `default-gutter' for a description of a valid gutter instantiator.
1211 Note that, unless the `default-gutter-position' is `bottom', by
1212 default the height of the bottom gutter (controlled by
1213 `bottom-gutter-height') is 0; thus, a bottom gutter will not be
1214 displayed even if you provide a value for `bottom-gutter'.
1216 Vgutter[BOTTOM_GUTTER] = Fmake_specifier (Qgutter);
1217 set_specifier_caching (Vgutter[BOTTOM_GUTTER],
1218 offsetof (struct window, gutter[BOTTOM_GUTTER]),
1219 bottom_gutter_specs_changed,
1222 DEFVAR_SPECIFIER ("left-gutter",
1223 &Vgutter[LEFT_GUTTER] /*
1224 Specifier for the gutter at the left edge of the frame.
1225 Use `set-specifier' to change this.
1226 See `default-gutter' for a description of a valid gutter instantiator.
1228 Note that, unless the `default-gutter-position' is `left', by
1229 default the height of the left gutter (controlled by
1230 `left-gutter-width') is 0; thus, a left gutter will not be
1231 displayed even if you provide a value for `left-gutter'.
1233 Vgutter[LEFT_GUTTER] = Fmake_specifier (Qgutter);
1234 set_specifier_caching (Vgutter[LEFT_GUTTER],
1235 offsetof (struct window, gutter[LEFT_GUTTER]),
1236 left_gutter_specs_changed,
1239 DEFVAR_SPECIFIER ("right-gutter",
1240 &Vgutter[RIGHT_GUTTER] /*
1241 Specifier for the gutter at the right edge of the frame.
1242 Use `set-specifier' to change this.
1243 See `default-gutter' for a description of a valid gutter instantiator.
1245 Note that, unless the `default-gutter-position' is `right', by
1246 default the height of the right gutter (controlled by
1247 `right-gutter-width') is 0; thus, a right gutter will not be
1248 displayed even if you provide a value for `right-gutter'.
1250 Vgutter[RIGHT_GUTTER] = Fmake_specifier (Qgutter);
1251 set_specifier_caching (Vgutter[RIGHT_GUTTER],
1252 offsetof (struct window, gutter[RIGHT_GUTTER]),
1253 right_gutter_specs_changed,
1256 /* initially, top inherits from default; this can be
1257 changed with `set-default-gutter-position'. */
1258 fb = list1 (Fcons (Qnil, Qnil));
1259 set_specifier_fallback (Vdefault_gutter, fb);
1260 set_specifier_fallback (Vgutter[TOP_GUTTER], Vdefault_gutter);
1261 set_specifier_fallback (Vgutter[BOTTOM_GUTTER], fb);
1262 set_specifier_fallback (Vgutter[LEFT_GUTTER], fb);
1263 set_specifier_fallback (Vgutter[RIGHT_GUTTER], fb);
1265 DEFVAR_SPECIFIER ("default-gutter-height", &Vdefault_gutter_height /*
1266 *Height of the default gutter, if it's oriented horizontally.
1267 This is a specifier; use `set-specifier' to change it.
1269 The position of the default gutter is specified by the function
1270 `set-default-gutter-position'. If the corresponding position-specific
1271 gutter thickness specifier (e.g. `top-gutter-height' if
1272 `default-gutter-position' is 'top) does not specify a thickness in a
1273 particular domain (a window or a frame), then the value of
1274 `default-gutter-height' or `default-gutter-width' (depending on the
1275 gutter orientation) in that domain, if any, will be used instead.
1277 Note that `default-gutter-height' is only used when
1278 `default-gutter-position' is 'top or 'bottom, and `default-gutter-width'
1279 is only used when `default-gutter-position' is 'left or 'right.
1281 Note that all of the position-specific gutter thickness specifiers
1282 have a fallback value of zero when they do not correspond to the
1283 default gutter. Therefore, you will have to set a non-zero thickness
1284 value if you want a position-specific gutter to be displayed.
1286 If you set the height to 'autodetect the size of the gutter will be
1287 calculated to be large enough to hold the contents of the gutter. This
1290 Vdefault_gutter_height = Fmake_specifier (Qgutter_size);
1291 set_specifier_caching (Vdefault_gutter_height,
1292 offsetof (struct window, default_gutter_height),
1293 default_gutter_size_changed_in_window,
1296 DEFVAR_SPECIFIER ("default-gutter-width", &Vdefault_gutter_width /*
1297 *Width of the default gutter, if it's oriented vertically.
1298 This is a specifier; use `set-specifier' to change it.
1300 See `default-gutter-height' for more information.
1302 Vdefault_gutter_width = Fmake_specifier (Qgutter_size);
1303 set_specifier_caching (Vdefault_gutter_width,
1304 offsetof (struct window, default_gutter_width),
1305 default_gutter_size_changed_in_window,
1308 DEFVAR_SPECIFIER ("top-gutter-height",
1309 &Vgutter_size[TOP_GUTTER] /*
1310 *Height of the top gutter.
1311 This is a specifier; use `set-specifier' to change it.
1313 See `default-gutter-height' for more information.
1315 Vgutter_size[TOP_GUTTER] = Fmake_specifier (Qgutter_size);
1316 set_specifier_caching (Vgutter_size[TOP_GUTTER],
1317 offsetof (struct window, gutter_size[TOP_GUTTER]),
1318 gutter_geometry_changed_in_window, 0, 0, 1);
1320 DEFVAR_SPECIFIER ("bottom-gutter-height",
1321 &Vgutter_size[BOTTOM_GUTTER] /*
1322 *Height of the bottom gutter.
1323 This is a specifier; use `set-specifier' to change it.
1325 See `default-gutter-height' for more information.
1327 Vgutter_size[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_size);
1328 set_specifier_caching (Vgutter_size[BOTTOM_GUTTER],
1329 offsetof (struct window, gutter_size[BOTTOM_GUTTER]),
1330 gutter_geometry_changed_in_window, 0, 0, 1);
1332 DEFVAR_SPECIFIER ("left-gutter-width",
1333 &Vgutter_size[LEFT_GUTTER] /*
1334 *Width of left gutter.
1335 This is a specifier; use `set-specifier' to change it.
1337 See `default-gutter-height' for more information.
1339 Vgutter_size[LEFT_GUTTER] = Fmake_specifier (Qgutter_size);
1340 set_specifier_caching (Vgutter_size[LEFT_GUTTER],
1341 offsetof (struct window, gutter_size[LEFT_GUTTER]),
1342 gutter_geometry_changed_in_window, 0, 0, 1);
1344 DEFVAR_SPECIFIER ("right-gutter-width",
1345 &Vgutter_size[RIGHT_GUTTER] /*
1346 *Width of right gutter.
1347 This is a specifier; use `set-specifier' to change it.
1349 See `default-gutter-height' for more information.
1351 Vgutter_size[RIGHT_GUTTER] = Fmake_specifier (Qgutter_size);
1352 set_specifier_caching (Vgutter_size[RIGHT_GUTTER],
1353 offsetof (struct window, gutter_size[RIGHT_GUTTER]),
1354 gutter_geometry_changed_in_window, 0, 0, 1);
1358 fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb);
1360 #ifdef HAVE_X_WINDOWS
1361 fb = Fcons (Fcons (list1 (Qx), Qautodetect), fb);
1363 #ifdef HAVE_MS_WINDOWS
1364 fb = Fcons (Fcons (list1 (Qmsprinter), Qautodetect), fb);
1365 fb = Fcons (Fcons (list1 (Qmswindows), Qautodetect), fb);
1368 set_specifier_fallback (Vdefault_gutter_height, fb);
1372 fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb);
1374 #ifdef HAVE_X_WINDOWS
1375 fb = Fcons (Fcons (list1 (Qx), Qautodetect), fb);
1377 #ifdef HAVE_MS_WINDOWS
1378 fb = Fcons (Fcons (list1 (Qmsprinter), Qautodetect), fb);
1379 fb = Fcons (Fcons (list1 (Qmswindows), Qautodetect), fb);
1382 set_specifier_fallback (Vdefault_gutter_width, fb);
1384 set_specifier_fallback (Vgutter_size[TOP_GUTTER], Vdefault_gutter_height);
1385 fb = list1 (Fcons (Qnil, Qzero));
1386 set_specifier_fallback (Vgutter_size[BOTTOM_GUTTER], fb);
1387 set_specifier_fallback (Vgutter_size[LEFT_GUTTER], fb);
1388 set_specifier_fallback (Vgutter_size[RIGHT_GUTTER], fb);
1390 DEFVAR_SPECIFIER ("default-gutter-border-width",
1391 &Vdefault_gutter_border_width /*
1392 *Width of the border around the default gutter.
1393 This is a specifier; use `set-specifier' to change it.
1395 The position of the default gutter is specified by the function
1396 `set-default-gutter-position'. If the corresponding position-specific
1397 gutter border width specifier (e.g. `top-gutter-border-width' if
1398 `default-gutter-position' is 'top) does not specify a border width in a
1399 particular domain (a window or a frame), then the value of
1400 `default-gutter-border-width' in that domain, if any, will be used
1404 Vdefault_gutter_border_width = Fmake_specifier (Qnatnum);
1405 set_specifier_caching (Vdefault_gutter_border_width,
1406 offsetof (struct window, default_gutter_border_width),
1407 default_gutter_border_width_changed_in_window,
1410 DEFVAR_SPECIFIER ("top-gutter-border-width",
1411 &Vgutter_border_width[TOP_GUTTER] /*
1412 *Border width of the top gutter.
1413 This is a specifier; use `set-specifier' to change it.
1415 See `default-gutter-height' for more information.
1417 Vgutter_border_width[TOP_GUTTER] = Fmake_specifier (Qnatnum);
1418 set_specifier_caching (Vgutter_border_width[TOP_GUTTER],
1419 offsetof (struct window,
1420 gutter_border_width[TOP_GUTTER]),
1421 gutter_geometry_changed_in_window, 0, 0, 0);
1423 DEFVAR_SPECIFIER ("bottom-gutter-border-width",
1424 &Vgutter_border_width[BOTTOM_GUTTER] /*
1425 *Border width of the bottom gutter.
1426 This is a specifier; use `set-specifier' to change it.
1428 See `default-gutter-height' for more information.
1430 Vgutter_border_width[BOTTOM_GUTTER] = Fmake_specifier (Qnatnum);
1431 set_specifier_caching (Vgutter_border_width[BOTTOM_GUTTER],
1432 offsetof (struct window,
1433 gutter_border_width[BOTTOM_GUTTER]),
1434 gutter_geometry_changed_in_window, 0, 0, 0);
1436 DEFVAR_SPECIFIER ("left-gutter-border-width",
1437 &Vgutter_border_width[LEFT_GUTTER] /*
1438 *Border width of left gutter.
1439 This is a specifier; use `set-specifier' to change it.
1441 See `default-gutter-height' for more information.
1443 Vgutter_border_width[LEFT_GUTTER] = Fmake_specifier (Qnatnum);
1444 set_specifier_caching (Vgutter_border_width[LEFT_GUTTER],
1445 offsetof (struct window,
1446 gutter_border_width[LEFT_GUTTER]),
1447 gutter_geometry_changed_in_window, 0, 0, 0);
1449 DEFVAR_SPECIFIER ("right-gutter-border-width",
1450 &Vgutter_border_width[RIGHT_GUTTER] /*
1451 *Border width of right gutter.
1452 This is a specifier; use `set-specifier' to change it.
1454 See `default-gutter-height' for more information.
1456 Vgutter_border_width[RIGHT_GUTTER] = Fmake_specifier (Qnatnum);
1457 set_specifier_caching (Vgutter_border_width[RIGHT_GUTTER],
1458 offsetof (struct window,
1459 gutter_border_width[RIGHT_GUTTER]),
1460 gutter_geometry_changed_in_window, 0, 0, 0);
1464 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
1466 #ifdef HAVE_X_WINDOWS
1467 fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_GUTTER_BORDER_WIDTH)), fb);
1469 #ifdef HAVE_MS_WINDOWS
1470 fb = Fcons (Fcons (list1 (Qmsprinter), Qzero), fb);
1471 fb = Fcons (Fcons (list1 (Qmswindows), make_int (DEFAULT_GUTTER_BORDER_WIDTH)), fb);
1474 set_specifier_fallback (Vdefault_gutter_border_width, fb);
1476 set_specifier_fallback (Vgutter_border_width[TOP_GUTTER], Vdefault_gutter_border_width);
1477 fb = list1 (Fcons (Qnil, Qzero));
1478 set_specifier_fallback (Vgutter_border_width[BOTTOM_GUTTER], fb);
1479 set_specifier_fallback (Vgutter_border_width[LEFT_GUTTER], fb);
1480 set_specifier_fallback (Vgutter_border_width[RIGHT_GUTTER], fb);
1482 DEFVAR_SPECIFIER ("default-gutter-visible-p", &Vdefault_gutter_visible_p /*
1483 *Whether the default gutter is visible.
1484 This is a specifier; use `set-specifier' to change it.
1486 The position of the default gutter is specified by the function
1487 `set-default-gutter-position'. If the corresponding position-specific
1488 gutter visibility specifier (e.g. `top-gutter-visible-p' if
1489 `default-gutter-position' is 'top) does not specify a visible-p value
1490 in a particular domain (a window or a frame), then the value of
1491 `default-gutter-visible-p' in that domain, if any, will be used
1494 `default-gutter-visible-p' and all of the position-specific gutter
1495 visibility specifiers have a fallback value of true.
1497 Vdefault_gutter_visible_p = Fmake_specifier (Qgutter_visible);
1498 set_specifier_caching (Vdefault_gutter_visible_p,
1499 offsetof (struct window,
1500 default_gutter_visible_p),
1501 default_gutter_visible_p_changed_in_window,
1504 DEFVAR_SPECIFIER ("top-gutter-visible-p",
1505 &Vgutter_visible_p[TOP_GUTTER] /*
1506 *Whether the top gutter is visible.
1507 This is a specifier; use `set-specifier' to change it.
1509 See `default-gutter-visible-p' for more information.
1511 Vgutter_visible_p[TOP_GUTTER] = Fmake_specifier (Qgutter_visible);
1512 set_specifier_caching (Vgutter_visible_p[TOP_GUTTER],
1513 offsetof (struct window,
1514 gutter_visible_p[TOP_GUTTER]),
1515 top_gutter_specs_changed, 0, 0, 0);
1517 DEFVAR_SPECIFIER ("bottom-gutter-visible-p",
1518 &Vgutter_visible_p[BOTTOM_GUTTER] /*
1519 *Whether the bottom gutter is visible.
1520 This is a specifier; use `set-specifier' to change it.
1522 See `default-gutter-visible-p' for more information.
1524 Vgutter_visible_p[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_visible);
1525 set_specifier_caching (Vgutter_visible_p[BOTTOM_GUTTER],
1526 offsetof (struct window,
1527 gutter_visible_p[BOTTOM_GUTTER]),
1528 bottom_gutter_specs_changed, 0, 0, 0);
1530 DEFVAR_SPECIFIER ("left-gutter-visible-p",
1531 &Vgutter_visible_p[LEFT_GUTTER] /*
1532 *Whether the left gutter is visible.
1533 This is a specifier; use `set-specifier' to change it.
1535 See `default-gutter-visible-p' for more information.
1537 Vgutter_visible_p[LEFT_GUTTER] = Fmake_specifier (Qgutter_visible);
1538 set_specifier_caching (Vgutter_visible_p[LEFT_GUTTER],
1539 offsetof (struct window,
1540 gutter_visible_p[LEFT_GUTTER]),
1541 left_gutter_specs_changed, 0, 0, 0);
1543 DEFVAR_SPECIFIER ("right-gutter-visible-p",
1544 &Vgutter_visible_p[RIGHT_GUTTER] /*
1545 *Whether the right gutter is visible.
1546 This is a specifier; use `set-specifier' to change it.
1548 See `default-gutter-visible-p' for more information.
1550 Vgutter_visible_p[RIGHT_GUTTER] = Fmake_specifier (Qgutter_visible);
1551 set_specifier_caching (Vgutter_visible_p[RIGHT_GUTTER],
1552 offsetof (struct window,
1553 gutter_visible_p[RIGHT_GUTTER]),
1554 right_gutter_specs_changed, 0, 0, 0);
1556 /* initially, top inherits from default; this can be
1557 changed with `set-default-gutter-position'. */
1558 fb = list1 (Fcons (Qnil, Qt));
1559 set_specifier_fallback (Vdefault_gutter_visible_p, fb);
1560 set_specifier_fallback (Vgutter_visible_p[TOP_GUTTER],
1561 Vdefault_gutter_visible_p);
1562 set_specifier_fallback (Vgutter_visible_p[BOTTOM_GUTTER], fb);
1563 set_specifier_fallback (Vgutter_visible_p[LEFT_GUTTER], fb);
1564 set_specifier_fallback (Vgutter_visible_p[RIGHT_GUTTER], fb);