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));
222 display_boxes_in_gutter_p
224 Determine whether the required display_glyph_area is completely
225 inside the gutter. -1 means the display_box is not in the gutter. 1
226 means the display_box and the display_glyph_area are in the
227 window. 0 means the display_box is in the gutter but the
228 display_glyph_area is not. */
229 int display_boxes_in_gutter_p (struct frame *f, struct display_box* db,
230 struct display_glyph_area* dga)
233 GUTTER_POS_LOOP (pos)
235 if (FRAME_GUTTER_VISIBLE (f, pos))
237 int x, y, width, height;
238 get_gutter_coords (f, pos, &x, &y, &width, &height);
239 if (db->xpos + dga->xoffset >= x
241 db->ypos + dga->yoffset >= y
243 db->xpos + dga->xoffset + dga->width <= x + width
245 db->ypos + dga->yoffset + dga->height <= y + height)
247 else if (db->xpos >= x && db->ypos >= y
248 && db->xpos + db->width <= x + width
249 && db->ypos + db->height <= y + height)
256 /* Convert the gutter specifier into something we can actually
258 static Lisp_Object construct_window_gutter_spec (struct window* w,
261 Lisp_Object rest, *args;
263 Lisp_Object gutter = RAW_WINDOW_GUTTER (w, pos);
265 if (STRINGP (gutter) || NILP (gutter))
268 GET_LIST_LENGTH (gutter, nargs);
269 args = alloca_array (Lisp_Object, nargs >> 1);
272 for (rest = gutter; !NILP (rest); rest = XCDR (XCDR (rest)))
274 /* We only put things in the real gutter that are declared to be
276 if (!CONSP (WINDOW_GUTTER_VISIBLE (w, pos))
278 !NILP (Fmemq (XCAR (rest), WINDOW_GUTTER_VISIBLE (w, pos))))
280 args [nargs++] = XCAR (XCDR (rest));
284 return Fconcat (nargs, args);
287 /* Sizing gutters is a pain so we try and help the user by determining
288 what height will accommodate all lines. This is useless on left and
289 right gutters as we always have a maximal number of lines. */
291 calculate_gutter_size_from_display_lines (enum gutter_pos pos,
292 display_line_dynarr* ddla)
295 struct display_line *dl;
297 /* For top and bottom the calculation is easy. */
298 if (pos == TOP_GUTTER || pos == BOTTOM_GUTTER)
300 /* grab coordinates of last line */
301 if (Dynarr_length (ddla))
303 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1);
304 size = (dl->ypos + dl->descent - dl->clip)
305 - (Dynarr_atp (ddla, 0)->ypos - Dynarr_atp (ddla, 0)->ascent);
308 /* For left and right we have to do some maths. */
311 int start_pos = 0, end_pos = 0, line;
312 for (line = 0; line < Dynarr_length (ddla); line++)
315 dl = Dynarr_atp (ddla, line);
317 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
319 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
321 if (db->type == TEXT)
323 start_pos = min (db->start_pos, start_pos);
324 end_pos = max (db->end_pos, end_pos);
328 size = end_pos - start_pos;
335 calculate_gutter_size (struct window *w, enum gutter_pos pos)
337 struct frame* f = XFRAME (WINDOW_FRAME (w));
339 display_line_dynarr* ddla;
340 Lisp_Object ret = Qnil;
342 /* degenerate case */
343 if (NILP (RAW_WINDOW_GUTTER (w, pos))
350 /* Redisplay code that we use relies on GC not happening. Make it
352 count = specpdl_depth ();
353 record_unwind_protect (restore_gc_inhibit,
354 make_int (gc_currently_forbidden));
355 gc_currently_forbidden = 1;
357 ddla = Dynarr_new (display_line);
358 /* generate some display lines */
359 generate_displayable_area (w, WINDOW_GUTTER (w, pos),
360 FRAME_LEFT_BORDER_END (f),
361 FRAME_TOP_BORDER_END (f),
362 FRAME_RIGHT_BORDER_START (f)
363 - FRAME_LEFT_BORDER_END (f),
364 FRAME_BOTTOM_BORDER_START (f)
365 - FRAME_TOP_BORDER_END (f),
368 /* Let GC happen again. */
369 unbind_to (count, Qnil);
371 ret = make_int (calculate_gutter_size_from_display_lines (pos, ddla));
372 free_display_lines (ddla);
378 output_gutter (struct frame *f, enum gutter_pos pos, int force)
381 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
382 struct device *d = XDEVICE (f->device);
383 struct window* w = XWINDOW (window);
384 int x, y, width, height, ypos;
385 int line, border_width;
387 display_line_dynarr* ddla, *cdla;
388 struct display_line *dl = 0;
391 if (!WINDOW_LIVE_P (w))
394 border_width = FRAME_GUTTER_BORDER_WIDTH (f, pos);
395 findex = get_builtin_face_cache_index (w, Vwidget_face);
397 if (!f->current_display_lines[pos])
398 f->current_display_lines[pos] = Dynarr_new (display_line);
399 if (!f->desired_display_lines[pos])
400 f->desired_display_lines[pos] = Dynarr_new (display_line);
402 ddla = f->desired_display_lines[pos];
403 cdla = f->current_display_lines[pos];
404 cdla_len = Dynarr_length (cdla);
406 XSETFRAME (frame, f);
408 get_gutter_coords (f, pos, &x, &y, &width, &height);
409 /* generate some display lines */
410 generate_displayable_area (w, WINDOW_GUTTER (w, pos),
411 x + border_width, y + border_width,
412 width - 2 * border_width,
413 height - 2 * border_width, ddla, 0, findex);
415 /* We only output the gutter if we think something of significance
416 has changed. This is, for example, because redisplay can cause
417 new face cache elements to get added causing compare_runes to
418 fail because the findex for a particular face has changed. */
419 if (force || f->faces_changed || f->frame_changed ||
420 f->gutter_changed || f->glyphs_changed ||
421 f->size_changed || f->subwindows_changed ||
422 w->windows_changed || f->windows_structure_changed ||
423 cdla_len != Dynarr_length (ddla) ||
424 (f->extents_changed && w->gutter_extent_modiff[pos]))
427 printf ("gutter redisplay [%dx%d@%d+%d] triggered by %s,\n",
428 width, height, x, y, force ? "force" :
429 f->faces_changed ? "f->faces_changed" :
430 f->frame_changed ? "f->frame_changed" :
431 f->gutter_changed ? "f->gutter_changed" :
432 f->glyphs_changed ? "f->glyphs_changed" :
433 f->size_changed ? "f->size_changed" :
434 f->subwindows_changed ? "f->subwindows_changed" :
435 w->windows_changed ? "w->windows_changed" :
436 f->windows_structure_changed ? "f->windows_structure_changed" :
437 cdla_len != Dynarr_length (ddla) ? "different display structures" :
438 f->extents_changed && w->gutter_extent_modiff[pos] ?
439 "f->extents_changed && w->gutter_extent_modiff[pos]" : "<null>");
441 /* Output each line. */
442 for (line = 0; line < Dynarr_length (ddla); line++)
444 output_display_line (w, cdla, ddla, line, -1, -1);
447 /* If the number of display lines has shrunk, adjust. */
448 if (cdla_len > Dynarr_length (ddla))
450 Dynarr_length (cdla) = Dynarr_length (ddla);
453 /* grab coordinates of last line and blank after it. */
454 if (Dynarr_length (ddla) > 0)
456 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1);
457 ypos = dl->ypos + dl->descent - dl->clip;
462 redisplay_clear_region (window, findex, x + border_width , ypos,
463 width - 2 * border_width, height - (ypos - y) - border_width);
464 /* If, for some reason, we have more to display than we have
465 room for, and we are allowed to resize the gutter, then make
466 sure this happens before the next time we try and
467 output. This can happen when face font sizes change. */
468 if (dl && EQ (w->gutter_size[pos], Qautodetect)
470 calculate_gutter_size_from_display_lines (pos, ddla) >
471 WINDOW_GUTTER_SIZE_INTERNAL (w, pos)))
473 /* #### Ideally we would just mark the specifier as dirty
474 and everything else would "just work". Unfortunately we have
475 two problems with this. One is that the specifier cache
476 won't be recalculated unless the specifier code thinks the
477 cached value has actually changed, even though we have
478 marked the specifier as dirty. Additionally, although doing
479 this results in a gutter size change, we never seem to get
480 back into redisplay so that the frame size can be updated. I
481 think this is because we are already in redisplay and later
482 on the frame will be marked as clean. Thus we also have to
483 force a pending recalculation of the frame size. */
484 w->gutter_size[pos] = Qnil;
485 Fset_specifier_dirty_flag (Vgutter_size[pos]);
486 update_gutter_geometry (f, pos);
489 /* bevel the gutter area if so desired */
490 if (border_width != 0)
492 MAYBE_DEVMETH (d, bevel_area,
493 (w, findex, x, y, width, height, border_width,
494 EDGE_ALL, EDGE_BEVEL_OUT));
499 /* Nothing of significance happened so sync the display line
501 for (line = 0; line < Dynarr_length (ddla); line++)
503 sync_display_line_structs (w, line, 1, cdla, ddla);
507 w->gutter_extent_modiff [pos] = 0;
511 clear_gutter (struct frame *f, enum gutter_pos pos)
513 int x, y, width, height;
514 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
515 face_index findex = get_builtin_face_cache_index (XWINDOW (window),
517 get_gutter_coords (f, pos, &x, &y, &width, &height);
519 SET_GUTTER_WAS_VISIBLE_FLAG (f, pos, 0);
521 redisplay_clear_region (window, findex, x, y, width, height);
524 /* #### I don't currently believe that redisplay needs to mark the
525 glyphs in its structures since these will always be referenced from
526 somewhere else. However, I'm not sure enough to stake my life on it
527 at this point, so we do the safe thing. */
529 /* See the comment in image_instantiate_cache_result as to why marking
530 the glyph will also mark the image_instance. */
532 mark_gutters (struct frame* f)
535 GUTTER_POS_LOOP (pos)
537 if (f->current_display_lines[pos])
538 mark_redisplay_structs (f->current_display_lines[pos]);
539 /* #### Do we really need to mark the desired lines? */
540 if (f->desired_display_lines[pos])
541 mark_redisplay_structs (f->desired_display_lines[pos]);
545 /* This is called by extent_changed_for_redisplay, so that redisplay
546 knows exactly what extents have changed. */
548 gutter_extent_signal_changed_region_maybe (Lisp_Object obj,
549 Bufpos start, Bufpos end)
551 /* #### Start and end are currently ignored but could be used by a
552 more optimal gutter redisplay. We currently loop over all frames
553 here, this could be optimized. */
554 Lisp_Object frmcons, devcons, concons;
556 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
558 struct frame *f = XFRAME (XCAR (frmcons));
560 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
561 struct window* w = XWINDOW (window);
563 GUTTER_POS_LOOP (pos)
565 if (EQ (WINDOW_GUTTER (w, pos), obj))
567 w->gutter_extent_modiff[pos]++;
573 /* We have to change the gutter geometry separately to the gutter
574 update since it needs to occur outside of redisplay proper. */
576 update_gutter_geometry (struct frame *f, enum gutter_pos pos)
578 /* If the gutter geometry has changed then re-layout the
579 frame. If we are in display there is almost no point in doing
580 anything else since the frame size changes will be delayed
581 until we are out of redisplay proper. */
582 if (FRAME_GUTTER_BOUNDS (f, pos) != f->current_gutter_bounds[pos])
585 pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f),
587 change_frame_size (f, height, width, 0);
590 /* Mark sizes as up-to-date. */
591 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos);
595 update_frame_gutter_geometry (struct frame *f)
597 if (f->gutter_changed || f->windows_structure_changed)
601 /* If the gutter geometry has changed then re-layout the
602 frame. If we are in display there is almost no point in doing
603 anything else since the frame size changes will be delayed
604 until we are out of redisplay proper. */
605 GUTTER_POS_LOOP (pos)
607 update_gutter_geometry (f, pos);
613 update_frame_gutters (struct frame *f)
615 if (f->faces_changed || f->frame_changed ||
616 f->gutter_changed || f->glyphs_changed ||
617 f->size_changed || f->subwindows_changed ||
618 f->windows_changed || f->windows_structure_changed ||
623 /* We don't actually care about these when outputting the gutter
624 so locally disable them. */
625 int local_clip_changed = f->clip_changed;
626 int local_buffers_changed = f->buffers_changed;
628 f->buffers_changed = 0;
631 GUTTER_POS_LOOP (pos)
633 if (FRAME_GUTTER_VISIBLE (f, pos))
634 output_gutter (f, pos, 0);
636 else if (gutter_was_visible (f, pos))
637 clear_gutter (f, pos);
640 f->clip_changed = local_clip_changed;
641 f->buffers_changed = local_buffers_changed;
642 f->gutter_changed = 0;
647 reset_gutter_display_lines (struct frame* f)
650 GUTTER_POS_LOOP (pos)
652 if (f->current_display_lines[pos])
653 Dynarr_reset (f->current_display_lines[pos]);
658 redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y,
659 int width, int height)
661 int g_x, g_y, g_width, g_height;
663 get_gutter_coords (f, pos, &g_x, &g_y, &g_width, &g_height);
665 if (((y + height) < g_y) || (y > (g_y + g_height)) || !height || !width || !g_height || !g_width)
667 if (((x + width) < g_x) || (x > (g_x + g_width)))
671 printf ("redrawing gutter after expose %d+%d, %dx%d\n",
672 x, y, width, height);
674 /* #### optimize this - redrawing the whole gutter for every expose
675 is very expensive. We reset the current display lines because if
676 they're being exposed they are no longer current. */
677 reset_gutter_display_lines (f);
679 /* Even if none of the gutter is in the area, the blank region at
680 the very least must be because the first thing we did is verify
681 that some portion of the gutter is in the exposed region. */
682 output_gutter (f, pos, 1);
686 redraw_exposed_gutters (struct frame *f, int x, int y, int width,
691 /* We have to be "in display" when we output the gutter - make it
693 hold_frame_size_changes ();
694 GUTTER_POS_LOOP (pos)
696 if (FRAME_GUTTER_VISIBLE (f, pos))
697 redraw_exposed_gutter (f, pos, x, y, width, height);
699 unhold_one_frame_size_changes (f);
703 free_frame_gutters (struct frame *f)
706 GUTTER_POS_LOOP (pos)
708 if (f->current_display_lines[pos])
710 free_display_lines (f->current_display_lines[pos]);
711 f->current_display_lines[pos] = 0;
713 if (f->desired_display_lines[pos])
715 free_display_lines (f->desired_display_lines[pos]);
716 f->desired_display_lines[pos] = 0;
721 static enum gutter_pos
722 decode_gutter_position (Lisp_Object position)
724 if (EQ (position, Qtop)) return TOP_GUTTER;
725 if (EQ (position, Qbottom)) return BOTTOM_GUTTER;
726 if (EQ (position, Qleft)) return LEFT_GUTTER;
727 if (EQ (position, Qright)) return RIGHT_GUTTER;
728 signal_simple_error ("Invalid gutter position", position);
730 return TOP_GUTTER; /* not reached */
733 DEFUN ("set-default-gutter-position", Fset_default_gutter_position, 1, 1, 0, /*
734 Set the position that the `default-gutter' will be displayed at.
735 Valid positions are 'top, 'bottom, 'left and 'right.
736 See `default-gutter-position'.
740 enum gutter_pos cur = decode_gutter_position (Vdefault_gutter_position);
741 enum gutter_pos new = decode_gutter_position (position);
745 /* The following calls will automatically cause the dirty
746 flags to be set; we delay frame size changes to avoid
747 lots of frame flickering. */
748 /* #### I think this should be GC protected. -sb */
749 hold_frame_size_changes ();
750 set_specifier_fallback (Vgutter[cur], list1 (Fcons (Qnil, Qnil)));
751 set_specifier_fallback (Vgutter[new], Vdefault_gutter);
752 set_specifier_fallback (Vgutter_size[cur], list1 (Fcons (Qnil, Qzero)));
753 set_specifier_fallback (Vgutter_size[new],
754 new == TOP_GUTTER || new == BOTTOM_GUTTER
755 ? Vdefault_gutter_height
756 : Vdefault_gutter_width);
757 set_specifier_fallback (Vgutter_border_width[cur],
758 list1 (Fcons (Qnil, Qzero)));
759 set_specifier_fallback (Vgutter_border_width[new],
760 Vdefault_gutter_border_width);
761 set_specifier_fallback (Vgutter_visible_p[cur], list1 (Fcons (Qnil, Qt)));
762 set_specifier_fallback (Vgutter_visible_p[new], Vdefault_gutter_visible_p);
764 Vdefault_gutter_position = position;
765 unhold_frame_size_changes ();
768 run_hook (Qdefault_gutter_position_changed_hook);
773 DEFUN ("default-gutter-position", Fdefault_gutter_position, 0, 0, 0, /*
774 Return the position that the `default-gutter' will be displayed at.
775 The `default-gutter' will only be displayed here if the corresponding
776 position-specific gutter specifier does not provide a value.
780 return Vdefault_gutter_position;
783 DEFUN ("gutter-pixel-width", Fgutter_pixel_width, 0, 2, 0, /*
784 Return the pixel width of the gutter at POS in LOCALE.
785 POS defaults to the default gutter position. LOCALE defaults to
790 int x, y, width, height;
791 enum gutter_pos p = TOP_GUTTER;
792 struct frame *f = decode_frame (FW_FRAME (locale));
795 pos = Vdefault_gutter_position;
796 p = decode_gutter_position (pos);
798 get_gutter_coords (f, p, &x, &y, &width, &height);
799 width -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2);
801 return make_int (width);
804 DEFUN ("gutter-pixel-height", Fgutter_pixel_height, 0, 2, 0, /*
805 Return the pixel height of the gutter at POS in LOCALE.
806 POS defaults to the default gutter position. LOCALE defaults to
811 int x, y, width, height;
812 enum gutter_pos p = TOP_GUTTER;
813 struct frame *f = decode_frame (FW_FRAME (locale));
816 pos = Vdefault_gutter_position;
817 p = decode_gutter_position (pos);
819 get_gutter_coords (f, p, &x, &y, &width, &height);
820 height -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2);
822 return make_int (height);
825 DEFINE_SPECIFIER_TYPE (gutter);
828 gutter_after_change (Lisp_Object specifier, Lisp_Object locale)
834 gutter_validate (Lisp_Object instantiator)
836 if (NILP (instantiator))
839 /* Must be a string or a plist. */
840 if (!STRINGP (instantiator) && NILP (Fvalid_plist_p (instantiator)))
841 signal_simple_error ("Gutter spec must be string, plist or nil", instantiator);
843 if (!STRINGP (instantiator))
847 for (rest = instantiator; !NILP (rest); rest = XCDR (XCDR (rest)))
849 if (!SYMBOLP (XCAR (rest))
850 || !STRINGP (XCAR (XCDR (rest))))
851 signal_simple_error ("Gutter plist spec must contain strings", instantiator);
856 DEFUN ("gutter-specifier-p", Fgutter_specifier_p, 1, 1, 0, /*
857 Return non-nil if OBJECT is a gutter specifier.
859 See `make-gutter-specifier' for a description of possible gutter
864 return GUTTER_SPECIFIERP (object) ? Qt : Qnil;
869 Helper for invalidating the real specifier when default
870 specifier caching changes
873 recompute_overlaying_specifier (Lisp_Object real_one[4])
875 enum gutter_pos pos = decode_gutter_position (Vdefault_gutter_position);
876 Fset_specifier_dirty_flag (real_one[pos]);
880 gutter_specs_changed (Lisp_Object specifier, struct window *w,
881 Lisp_Object oldval, enum gutter_pos pos)
883 w->real_gutter[pos] = construct_window_gutter_spec (w, pos);
884 w->real_gutter_size[pos] = w->gutter_size[pos];
886 if (EQ (w->real_gutter_size[pos], Qautodetect)
887 && !NILP (w->gutter_visible_p[pos]))
889 w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
892 MARK_MODELINE_CHANGED;
893 MARK_WINDOWS_CHANGED (w);
896 /* We define all of these so we can access which actual gutter changed. */
898 top_gutter_specs_changed (Lisp_Object specifier, struct window *w,
901 gutter_specs_changed (specifier, w, oldval, TOP_GUTTER);
905 bottom_gutter_specs_changed (Lisp_Object specifier, struct window *w,
908 gutter_specs_changed (specifier, w, oldval, BOTTOM_GUTTER);
912 left_gutter_specs_changed (Lisp_Object specifier, struct window *w,
915 gutter_specs_changed (specifier, w, oldval, LEFT_GUTTER);
919 right_gutter_specs_changed (Lisp_Object specifier, struct window *w,
922 gutter_specs_changed (specifier, w, oldval, RIGHT_GUTTER);
926 default_gutter_specs_changed (Lisp_Object specifier, struct window *w,
929 recompute_overlaying_specifier (Vgutter);
933 gutter_geometry_changed_in_window (Lisp_Object specifier, struct window *w,
937 GUTTER_POS_LOOP (pos)
939 w->real_gutter_size[pos] = w->gutter_size[pos];
940 if (EQ (w->real_gutter_size[pos], Qautodetect)
941 && !NILP (w->gutter_visible_p[pos]))
943 w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
948 MARK_MODELINE_CHANGED;
949 MARK_WINDOWS_CHANGED (w);
953 default_gutter_size_changed_in_window (Lisp_Object specifier, struct window *w,
956 recompute_overlaying_specifier (Vgutter_size);
960 default_gutter_border_width_changed_in_window (Lisp_Object specifier,
964 recompute_overlaying_specifier (Vgutter_border_width);
968 default_gutter_visible_p_changed_in_window (Lisp_Object specifier,
972 recompute_overlaying_specifier (Vgutter_visible_p);
973 /* Need to reconstruct the gutter specifier as it is affected by the
975 recompute_overlaying_specifier (Vgutter);
979 DECLARE_SPECIFIER_TYPE (gutter_size);
980 #define GUTTER_SIZE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_size)
981 DEFINE_SPECIFIER_TYPE (gutter_size);
984 gutter_size_validate (Lisp_Object instantiator)
986 if (NILP (instantiator))
989 if (!INTP (instantiator) && !EQ (instantiator, Qautodetect))
990 signal_simple_error ("Gutter size must be an integer or 'autodetect", instantiator);
993 DEFUN ("gutter-size-specifier-p", Fgutter_size_specifier_p, 1, 1, 0, /*
994 Return non-nil if OBJECT is a gutter-size specifier.
996 See `make-gutter-size-specifier' for a description of possible gutter-size
1001 return GUTTER_SIZE_SPECIFIERP (object) ? Qt : Qnil;
1004 DECLARE_SPECIFIER_TYPE (gutter_visible);
1005 #define GUTTER_VISIBLE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_visible)
1006 DEFINE_SPECIFIER_TYPE (gutter_visible);
1009 gutter_visible_validate (Lisp_Object instantiator)
1011 if (NILP (instantiator))
1014 if (!NILP (instantiator) && !EQ (instantiator, Qt) && !CONSP (instantiator))
1015 signal_simple_error ("Gutter visibility must be a boolean or list of symbols",
1018 if (CONSP (instantiator))
1022 EXTERNAL_LIST_LOOP (rest, instantiator)
1024 if (!SYMBOLP (XCAR (rest)))
1025 signal_simple_error ("Gutter visibility must be a boolean or list of symbols",
1031 DEFUN ("gutter-visible-specifier-p", Fgutter_visible_specifier_p, 1, 1, 0, /*
1032 Return non-nil if OBJECT is a gutter-visible specifier.
1034 See `make-gutter-visible-specifier' for a description of possible
1035 gutter-visible instantiators.
1039 return GUTTER_VISIBLE_SPECIFIERP (object) ? Qt : Qnil;
1042 DEFUN ("redisplay-gutter-area", Fredisplay_gutter_area, 0, 0, 0, /*
1043 Ensure that all gutters are correctly showing their gutter specifier.
1047 Lisp_Object devcons, concons;
1049 DEVICE_LOOP_NO_BREAK (devcons, concons)
1051 struct device *d = XDEVICE (XCAR (devcons));
1052 Lisp_Object frmcons;
1054 DEVICE_FRAME_LOOP (frmcons, d)
1056 struct frame *f = XFRAME (XCAR (frmcons));
1058 MAYBE_DEVMETH (d, frame_output_begin, (f));
1060 /* Sequence is quite important here. We not only want to
1061 redisplay the gutter area but we also want to flush any
1062 frame size changes out so that the gutter redisplay happens
1063 in a kosha environment.
1065 This is not only so that things look right but so that
1066 glyph redisplay optimization kicks in, by default display
1067 lines will be completely re-output if
1068 f->windows_structure_changed is 1, and this is true if
1069 frame size changes haven't been flushed out. Once frame
1070 size changes have been flushed out we then need to
1071 redisplay the frame in order to flush out pending window
1073 update_frame_gutter_geometry (f);
1075 if (f->windows_structure_changed)
1076 redisplay_frame (f, 1);
1077 else if (FRAME_REPAINT_P (f))
1079 /* We have to be "in display" when we output the gutter
1081 hold_frame_size_changes ();
1082 update_frame_gutters (f);
1083 unhold_one_frame_size_changes (f);
1086 MAYBE_DEVMETH (d, frame_output_end, (f));
1089 d->gutter_changed = 0;
1092 /* This is so that further changes to the gutters will trigger redisplay. */
1093 gutter_changed_set = 0;
1100 init_frame_gutters (struct frame *f)
1102 enum gutter_pos pos;
1103 struct window* w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f));
1104 /* We are here as far in frame creation so cached specifiers are
1105 already recomputed, and possibly modified by resource
1106 initialization. We need to recalculate autodetected gutters. */
1107 GUTTER_POS_LOOP (pos)
1109 w->real_gutter[pos] = construct_window_gutter_spec (w, pos);
1110 w->real_gutter_size[pos] = w->gutter_size[pos];
1111 if (EQ (w->gutter_size[pos], Qautodetect)
1112 && !NILP (w->gutter_visible_p[pos]))
1114 w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
1115 MARK_GUTTER_CHANGED;
1116 MARK_WINDOWS_CHANGED (w);
1120 /* Keep a record of the current sizes of things. */
1121 GUTTER_POS_LOOP (pos)
1123 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos);
1128 syms_of_gutter (void)
1130 DEFSUBR (Fgutter_specifier_p);
1131 DEFSUBR (Fgutter_size_specifier_p);
1132 DEFSUBR (Fgutter_visible_specifier_p);
1133 DEFSUBR (Fset_default_gutter_position);
1134 DEFSUBR (Fdefault_gutter_position);
1135 DEFSUBR (Fgutter_pixel_height);
1136 DEFSUBR (Fgutter_pixel_width);
1137 DEFSUBR (Fredisplay_gutter_area);
1139 defsymbol (&Qgutter_size, "gutter-size");
1140 defsymbol (&Qgutter_visible, "gutter-visible");
1141 defsymbol (&Qdefault_gutter_position_changed_hook,
1142 "default-gutter-position-changed-hook");
1146 vars_of_gutter (void)
1148 staticpro (&Vdefault_gutter_position);
1149 Vdefault_gutter_position = Qtop;
1155 specifier_type_create_gutter (void)
1157 INITIALIZE_SPECIFIER_TYPE (gutter, "gutter", "gutter-specifier-p");
1158 SPECIFIER_HAS_METHOD (gutter, validate);
1159 SPECIFIER_HAS_METHOD (gutter, after_change);
1161 INITIALIZE_SPECIFIER_TYPE (gutter_size, "gutter-size", "gutter-size-specifier-p");
1162 SPECIFIER_HAS_METHOD (gutter_size, validate);
1164 INITIALIZE_SPECIFIER_TYPE (gutter_visible, "gutter-visible", "gutter-visible-specifier-p");
1165 SPECIFIER_HAS_METHOD (gutter_visible, validate);
1169 reinit_specifier_type_create_gutter (void)
1171 REINITIALIZE_SPECIFIER_TYPE (gutter);
1172 REINITIALIZE_SPECIFIER_TYPE (gutter_size);
1173 REINITIALIZE_SPECIFIER_TYPE (gutter_visible);
1177 specifier_vars_of_gutter (void)
1181 DEFVAR_SPECIFIER ("default-gutter", &Vdefault_gutter /*
1182 Specifier for a fallback gutter.
1183 Use `set-specifier' to change this.
1185 The position of this gutter is specified in the function
1186 `default-gutter-position'. If the corresponding position-specific
1187 gutter (e.g. `top-gutter' if `default-gutter-position' is 'top)
1188 does not specify a gutter in a particular domain (usually a window),
1189 then the value of `default-gutter' in that domain, if any, will be
1192 Note that the gutter at any particular position will not be
1193 displayed unless its visibility flag is true and its thickness
1194 \(width or height, depending on orientation) is non-zero. The
1195 visibility is controlled by the specifiers `top-gutter-visible-p',
1196 `bottom-gutter-visible-p', `left-gutter-visible-p', and
1197 `right-gutter-visible-p', and the thickness is controlled by the
1198 specifiers `top-gutter-height', `bottom-gutter-height',
1199 `left-gutter-width', and `right-gutter-width'.
1201 Note that one of the four visibility specifiers inherits from
1202 `default-gutter-visibility' and one of the four thickness
1203 specifiers inherits from either `default-gutter-width' or
1204 `default-gutter-height' (depending on orientation), just
1205 like for the gutter description specifiers (e.g. `top-gutter')
1208 Therefore, if you are setting `default-gutter', you should control
1209 the visibility and thickness using `default-gutter-visible-p',
1210 `default-gutter-width', and `default-gutter-height', rather than
1211 using position-specific specifiers. That way, you will get sane
1212 behavior if the user changes the default gutter position.
1214 The gutter value should be a string, a property list of strings or
1215 nil. You can attach extents and glyphs to the string and hence display
1216 glyphs and text in other fonts in the gutter area. If the gutter value
1217 is a property list then the strings will be concatenated together
1218 before being displayed. */ );
1220 Vdefault_gutter = Fmake_specifier (Qgutter);
1221 /* #### It would be even nicer if the specifier caching
1222 automatically knew about specifier fallbacks, so we didn't
1223 have to do it ourselves. */
1224 set_specifier_caching (Vdefault_gutter,
1225 offsetof (struct window, default_gutter),
1226 default_gutter_specs_changed,
1229 DEFVAR_SPECIFIER ("top-gutter",
1230 &Vgutter[TOP_GUTTER] /*
1231 Specifier for the gutter at the top of the frame.
1232 Use `set-specifier' to change this.
1233 See `default-gutter' for a description of a valid gutter instantiator.
1235 Vgutter[TOP_GUTTER] = Fmake_specifier (Qgutter);
1236 set_specifier_caching (Vgutter[TOP_GUTTER],
1237 offsetof (struct window, gutter[TOP_GUTTER]),
1238 top_gutter_specs_changed,
1241 DEFVAR_SPECIFIER ("bottom-gutter",
1242 &Vgutter[BOTTOM_GUTTER] /*
1243 Specifier for the gutter at the bottom of the frame.
1244 Use `set-specifier' to change this.
1245 See `default-gutter' for a description of a valid gutter instantiator.
1247 Note that, unless the `default-gutter-position' is `bottom', by
1248 default the height of the bottom gutter (controlled by
1249 `bottom-gutter-height') is 0; thus, a bottom gutter will not be
1250 displayed even if you provide a value for `bottom-gutter'.
1252 Vgutter[BOTTOM_GUTTER] = Fmake_specifier (Qgutter);
1253 set_specifier_caching (Vgutter[BOTTOM_GUTTER],
1254 offsetof (struct window, gutter[BOTTOM_GUTTER]),
1255 bottom_gutter_specs_changed,
1258 DEFVAR_SPECIFIER ("left-gutter",
1259 &Vgutter[LEFT_GUTTER] /*
1260 Specifier for the gutter at the left edge of the frame.
1261 Use `set-specifier' to change this.
1262 See `default-gutter' for a description of a valid gutter instantiator.
1264 Note that, unless the `default-gutter-position' is `left', by
1265 default the height of the left gutter (controlled by
1266 `left-gutter-width') is 0; thus, a left gutter will not be
1267 displayed even if you provide a value for `left-gutter'.
1269 Vgutter[LEFT_GUTTER] = Fmake_specifier (Qgutter);
1270 set_specifier_caching (Vgutter[LEFT_GUTTER],
1271 offsetof (struct window, gutter[LEFT_GUTTER]),
1272 left_gutter_specs_changed,
1275 DEFVAR_SPECIFIER ("right-gutter",
1276 &Vgutter[RIGHT_GUTTER] /*
1277 Specifier for the gutter at the right edge of the frame.
1278 Use `set-specifier' to change this.
1279 See `default-gutter' for a description of a valid gutter instantiator.
1281 Note that, unless the `default-gutter-position' is `right', by
1282 default the height of the right gutter (controlled by
1283 `right-gutter-width') is 0; thus, a right gutter will not be
1284 displayed even if you provide a value for `right-gutter'.
1286 Vgutter[RIGHT_GUTTER] = Fmake_specifier (Qgutter);
1287 set_specifier_caching (Vgutter[RIGHT_GUTTER],
1288 offsetof (struct window, gutter[RIGHT_GUTTER]),
1289 right_gutter_specs_changed,
1292 /* initially, top inherits from default; this can be
1293 changed with `set-default-gutter-position'. */
1294 fb = list1 (Fcons (Qnil, Qnil));
1295 set_specifier_fallback (Vdefault_gutter, fb);
1296 set_specifier_fallback (Vgutter[TOP_GUTTER], Vdefault_gutter);
1297 set_specifier_fallback (Vgutter[BOTTOM_GUTTER], fb);
1298 set_specifier_fallback (Vgutter[LEFT_GUTTER], fb);
1299 set_specifier_fallback (Vgutter[RIGHT_GUTTER], fb);
1301 DEFVAR_SPECIFIER ("default-gutter-height", &Vdefault_gutter_height /*
1302 *Height of the default gutter, if it's oriented horizontally.
1303 This is a specifier; use `set-specifier' to change it.
1305 The position of the default gutter is specified by the function
1306 `set-default-gutter-position'. If the corresponding position-specific
1307 gutter thickness specifier (e.g. `top-gutter-height' if
1308 `default-gutter-position' is 'top) does not specify a thickness in a
1309 particular domain (a window or a frame), then the value of
1310 `default-gutter-height' or `default-gutter-width' (depending on the
1311 gutter orientation) in that domain, if any, will be used instead.
1313 Note that `default-gutter-height' is only used when
1314 `default-gutter-position' is 'top or 'bottom, and `default-gutter-width'
1315 is only used when `default-gutter-position' is 'left or 'right.
1317 Note that all of the position-specific gutter thickness specifiers
1318 have a fallback value of zero when they do not correspond to the
1319 default gutter. Therefore, you will have to set a non-zero thickness
1320 value if you want a position-specific gutter to be displayed.
1322 If you set the height to 'autodetect the size of the gutter will be
1323 calculated to be large enough to hold the contents of the gutter. This
1326 Vdefault_gutter_height = Fmake_specifier (Qgutter_size);
1327 set_specifier_caching (Vdefault_gutter_height,
1328 offsetof (struct window, default_gutter_height),
1329 default_gutter_size_changed_in_window,
1332 DEFVAR_SPECIFIER ("default-gutter-width", &Vdefault_gutter_width /*
1333 *Width of the default gutter, if it's oriented vertically.
1334 This is a specifier; use `set-specifier' to change it.
1336 See `default-gutter-height' for more information.
1338 Vdefault_gutter_width = Fmake_specifier (Qgutter_size);
1339 set_specifier_caching (Vdefault_gutter_width,
1340 offsetof (struct window, default_gutter_width),
1341 default_gutter_size_changed_in_window,
1344 DEFVAR_SPECIFIER ("top-gutter-height",
1345 &Vgutter_size[TOP_GUTTER] /*
1346 *Height of the top gutter.
1347 This is a specifier; use `set-specifier' to change it.
1349 See `default-gutter-height' for more information.
1351 Vgutter_size[TOP_GUTTER] = Fmake_specifier (Qgutter_size);
1352 set_specifier_caching (Vgutter_size[TOP_GUTTER],
1353 offsetof (struct window, gutter_size[TOP_GUTTER]),
1354 gutter_geometry_changed_in_window, 0, 0, 1);
1356 DEFVAR_SPECIFIER ("bottom-gutter-height",
1357 &Vgutter_size[BOTTOM_GUTTER] /*
1358 *Height of the bottom gutter.
1359 This is a specifier; use `set-specifier' to change it.
1361 See `default-gutter-height' for more information.
1363 Vgutter_size[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_size);
1364 set_specifier_caching (Vgutter_size[BOTTOM_GUTTER],
1365 offsetof (struct window, gutter_size[BOTTOM_GUTTER]),
1366 gutter_geometry_changed_in_window, 0, 0, 1);
1368 DEFVAR_SPECIFIER ("left-gutter-width",
1369 &Vgutter_size[LEFT_GUTTER] /*
1370 *Width of left gutter.
1371 This is a specifier; use `set-specifier' to change it.
1373 See `default-gutter-height' for more information.
1375 Vgutter_size[LEFT_GUTTER] = Fmake_specifier (Qgutter_size);
1376 set_specifier_caching (Vgutter_size[LEFT_GUTTER],
1377 offsetof (struct window, gutter_size[LEFT_GUTTER]),
1378 gutter_geometry_changed_in_window, 0, 0, 1);
1380 DEFVAR_SPECIFIER ("right-gutter-width",
1381 &Vgutter_size[RIGHT_GUTTER] /*
1382 *Width of right gutter.
1383 This is a specifier; use `set-specifier' to change it.
1385 See `default-gutter-height' for more information.
1387 Vgutter_size[RIGHT_GUTTER] = Fmake_specifier (Qgutter_size);
1388 set_specifier_caching (Vgutter_size[RIGHT_GUTTER],
1389 offsetof (struct window, gutter_size[RIGHT_GUTTER]),
1390 gutter_geometry_changed_in_window, 0, 0, 1);
1394 fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb);
1396 #ifdef HAVE_X_WINDOWS
1397 fb = Fcons (Fcons (list1 (Qx), Qautodetect), fb);
1399 #ifdef HAVE_MS_WINDOWS
1400 fb = Fcons (Fcons (list1 (Qmsprinter), Qautodetect), fb);
1401 fb = Fcons (Fcons (list1 (Qmswindows), Qautodetect), fb);
1404 set_specifier_fallback (Vdefault_gutter_height, fb);
1408 fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb);
1410 #ifdef HAVE_X_WINDOWS
1411 fb = Fcons (Fcons (list1 (Qx), Qautodetect), fb);
1413 #ifdef HAVE_MS_WINDOWS
1414 fb = Fcons (Fcons (list1 (Qmsprinter), Qautodetect), fb);
1415 fb = Fcons (Fcons (list1 (Qmswindows), Qautodetect), fb);
1418 set_specifier_fallback (Vdefault_gutter_width, fb);
1420 set_specifier_fallback (Vgutter_size[TOP_GUTTER], Vdefault_gutter_height);
1421 fb = list1 (Fcons (Qnil, Qzero));
1422 set_specifier_fallback (Vgutter_size[BOTTOM_GUTTER], fb);
1423 set_specifier_fallback (Vgutter_size[LEFT_GUTTER], fb);
1424 set_specifier_fallback (Vgutter_size[RIGHT_GUTTER], fb);
1426 DEFVAR_SPECIFIER ("default-gutter-border-width",
1427 &Vdefault_gutter_border_width /*
1428 *Width of the border around the default gutter.
1429 This is a specifier; use `set-specifier' to change it.
1431 The position of the default gutter is specified by the function
1432 `set-default-gutter-position'. If the corresponding position-specific
1433 gutter border width specifier (e.g. `top-gutter-border-width' if
1434 `default-gutter-position' is 'top) does not specify a border width in a
1435 particular domain (a window or a frame), then the value of
1436 `default-gutter-border-width' in that domain, if any, will be used
1440 Vdefault_gutter_border_width = Fmake_specifier (Qnatnum);
1441 set_specifier_caching (Vdefault_gutter_border_width,
1442 offsetof (struct window, default_gutter_border_width),
1443 default_gutter_border_width_changed_in_window,
1446 DEFVAR_SPECIFIER ("top-gutter-border-width",
1447 &Vgutter_border_width[TOP_GUTTER] /*
1448 *Border width of the top gutter.
1449 This is a specifier; use `set-specifier' to change it.
1451 See `default-gutter-height' for more information.
1453 Vgutter_border_width[TOP_GUTTER] = Fmake_specifier (Qnatnum);
1454 set_specifier_caching (Vgutter_border_width[TOP_GUTTER],
1455 offsetof (struct window,
1456 gutter_border_width[TOP_GUTTER]),
1457 gutter_geometry_changed_in_window, 0, 0, 0);
1459 DEFVAR_SPECIFIER ("bottom-gutter-border-width",
1460 &Vgutter_border_width[BOTTOM_GUTTER] /*
1461 *Border width of the bottom gutter.
1462 This is a specifier; use `set-specifier' to change it.
1464 See `default-gutter-height' for more information.
1466 Vgutter_border_width[BOTTOM_GUTTER] = Fmake_specifier (Qnatnum);
1467 set_specifier_caching (Vgutter_border_width[BOTTOM_GUTTER],
1468 offsetof (struct window,
1469 gutter_border_width[BOTTOM_GUTTER]),
1470 gutter_geometry_changed_in_window, 0, 0, 0);
1472 DEFVAR_SPECIFIER ("left-gutter-border-width",
1473 &Vgutter_border_width[LEFT_GUTTER] /*
1474 *Border width of left gutter.
1475 This is a specifier; use `set-specifier' to change it.
1477 See `default-gutter-height' for more information.
1479 Vgutter_border_width[LEFT_GUTTER] = Fmake_specifier (Qnatnum);
1480 set_specifier_caching (Vgutter_border_width[LEFT_GUTTER],
1481 offsetof (struct window,
1482 gutter_border_width[LEFT_GUTTER]),
1483 gutter_geometry_changed_in_window, 0, 0, 0);
1485 DEFVAR_SPECIFIER ("right-gutter-border-width",
1486 &Vgutter_border_width[RIGHT_GUTTER] /*
1487 *Border width of right gutter.
1488 This is a specifier; use `set-specifier' to change it.
1490 See `default-gutter-height' for more information.
1492 Vgutter_border_width[RIGHT_GUTTER] = Fmake_specifier (Qnatnum);
1493 set_specifier_caching (Vgutter_border_width[RIGHT_GUTTER],
1494 offsetof (struct window,
1495 gutter_border_width[RIGHT_GUTTER]),
1496 gutter_geometry_changed_in_window, 0, 0, 0);
1500 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
1502 #ifdef HAVE_X_WINDOWS
1503 fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_GUTTER_BORDER_WIDTH)), fb);
1505 #ifdef HAVE_MS_WINDOWS
1506 fb = Fcons (Fcons (list1 (Qmsprinter), Qzero), fb);
1507 fb = Fcons (Fcons (list1 (Qmswindows), make_int (DEFAULT_GUTTER_BORDER_WIDTH)), fb);
1510 set_specifier_fallback (Vdefault_gutter_border_width, fb);
1512 set_specifier_fallback (Vgutter_border_width[TOP_GUTTER], Vdefault_gutter_border_width);
1513 fb = list1 (Fcons (Qnil, Qzero));
1514 set_specifier_fallback (Vgutter_border_width[BOTTOM_GUTTER], fb);
1515 set_specifier_fallback (Vgutter_border_width[LEFT_GUTTER], fb);
1516 set_specifier_fallback (Vgutter_border_width[RIGHT_GUTTER], fb);
1518 DEFVAR_SPECIFIER ("default-gutter-visible-p", &Vdefault_gutter_visible_p /*
1519 *Whether the default gutter is visible.
1520 This is a specifier; use `set-specifier' to change it.
1522 The position of the default gutter is specified by the function
1523 `set-default-gutter-position'. If the corresponding position-specific
1524 gutter visibility specifier (e.g. `top-gutter-visible-p' if
1525 `default-gutter-position' is 'top) does not specify a visible-p value
1526 in a particular domain (a window or a frame), then the value of
1527 `default-gutter-visible-p' in that domain, if any, will be used
1530 `default-gutter-visible-p' and all of the position-specific gutter
1531 visibility specifiers have a fallback value of true.
1533 Vdefault_gutter_visible_p = Fmake_specifier (Qgutter_visible);
1534 set_specifier_caching (Vdefault_gutter_visible_p,
1535 offsetof (struct window,
1536 default_gutter_visible_p),
1537 default_gutter_visible_p_changed_in_window,
1540 DEFVAR_SPECIFIER ("top-gutter-visible-p",
1541 &Vgutter_visible_p[TOP_GUTTER] /*
1542 *Whether the top gutter is visible.
1543 This is a specifier; use `set-specifier' to change it.
1545 See `default-gutter-visible-p' for more information.
1547 Vgutter_visible_p[TOP_GUTTER] = Fmake_specifier (Qgutter_visible);
1548 set_specifier_caching (Vgutter_visible_p[TOP_GUTTER],
1549 offsetof (struct window,
1550 gutter_visible_p[TOP_GUTTER]),
1551 top_gutter_specs_changed, 0, 0, 0);
1553 DEFVAR_SPECIFIER ("bottom-gutter-visible-p",
1554 &Vgutter_visible_p[BOTTOM_GUTTER] /*
1555 *Whether the bottom gutter is visible.
1556 This is a specifier; use `set-specifier' to change it.
1558 See `default-gutter-visible-p' for more information.
1560 Vgutter_visible_p[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_visible);
1561 set_specifier_caching (Vgutter_visible_p[BOTTOM_GUTTER],
1562 offsetof (struct window,
1563 gutter_visible_p[BOTTOM_GUTTER]),
1564 bottom_gutter_specs_changed, 0, 0, 0);
1566 DEFVAR_SPECIFIER ("left-gutter-visible-p",
1567 &Vgutter_visible_p[LEFT_GUTTER] /*
1568 *Whether the left gutter is visible.
1569 This is a specifier; use `set-specifier' to change it.
1571 See `default-gutter-visible-p' for more information.
1573 Vgutter_visible_p[LEFT_GUTTER] = Fmake_specifier (Qgutter_visible);
1574 set_specifier_caching (Vgutter_visible_p[LEFT_GUTTER],
1575 offsetof (struct window,
1576 gutter_visible_p[LEFT_GUTTER]),
1577 left_gutter_specs_changed, 0, 0, 0);
1579 DEFVAR_SPECIFIER ("right-gutter-visible-p",
1580 &Vgutter_visible_p[RIGHT_GUTTER] /*
1581 *Whether the right gutter is visible.
1582 This is a specifier; use `set-specifier' to change it.
1584 See `default-gutter-visible-p' for more information.
1586 Vgutter_visible_p[RIGHT_GUTTER] = Fmake_specifier (Qgutter_visible);
1587 set_specifier_caching (Vgutter_visible_p[RIGHT_GUTTER],
1588 offsetof (struct window,
1589 gutter_visible_p[RIGHT_GUTTER]),
1590 right_gutter_specs_changed, 0, 0, 0);
1592 /* initially, top inherits from default; this can be
1593 changed with `set-default-gutter-position'. */
1594 fb = list1 (Fcons (Qnil, Qt));
1595 set_specifier_fallback (Vdefault_gutter_visible_p, fb);
1596 set_specifier_fallback (Vgutter_visible_p[TOP_GUTTER],
1597 Vdefault_gutter_visible_p);
1598 set_specifier_fallback (Vgutter_visible_p[BOTTOM_GUTTER], fb);
1599 set_specifier_fallback (Vgutter_visible_p[LEFT_GUTTER], fb);
1600 set_specifier_fallback (Vgutter_visible_p[RIGHT_GUTTER], fb);