1 /* Gutter implementation.
2 Copyright (C) 1999, 2000 Andy Piper.
4 This file is part of SXEmacs
6 SXEmacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 SXEmacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 /* Synched up with: Not in FSF. */
22 /* written by Andy Piper <andy@xemacs.org> with specifiers partially
23 ripped-off from toolbar.c */
33 #include "redisplay.h"
37 Lisp_Object Vgutter[4];
38 Lisp_Object Vgutter_size[4];
39 Lisp_Object Vgutter_visible_p[4];
40 Lisp_Object Vgutter_border_width[4];
42 Lisp_Object Vdefault_gutter, Vdefault_gutter_visible_p;
43 Lisp_Object Vdefault_gutter_width, Vdefault_gutter_height;
44 Lisp_Object Vdefault_gutter_border_width;
46 Lisp_Object Vdefault_gutter_position;
48 Lisp_Object Qgutter_size;
49 Lisp_Object Qgutter_visible;
50 Lisp_Object Qdefault_gutter_position_changed_hook;
52 static void update_gutter_geometry(struct frame *f, enum gutter_pos pos);
54 #define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag) \
59 (frame)->top_gutter_was_visible = flag; \
62 (frame)->bottom_gutter_was_visible = flag; \
65 (frame)->left_gutter_was_visible = flag; \
68 (frame)->right_gutter_was_visible = flag; \
75 static int gutter_was_visible(struct frame *frame, enum gutter_pos pos)
79 return frame->top_gutter_was_visible;
81 return frame->bottom_gutter_was_visible;
83 return frame->left_gutter_was_visible;
85 return frame->right_gutter_was_visible;
88 return 0; /* To keep the compiler happy */
93 static Lisp_Object frame_topmost_window(struct frame *f)
95 Lisp_Object w = FRAME_ROOT_WINDOW(f);
98 while (!NILP(XWINDOW(w)->vchild)) {
99 w = XWINDOW(w)->vchild;
101 } while (!NILP(XWINDOW(w)->hchild) && !NILP(w = XWINDOW(w)->hchild));
107 static Lisp_Object frame_bottommost_window(struct frame *f)
109 Lisp_Object w = FRAME_ROOT_WINDOW(f);
112 while (!NILP(XWINDOW(w)->vchild)) {
113 w = XWINDOW(w)->vchild;
114 while (!NILP(XWINDOW(w)->next)) {
115 w = XWINDOW(w)->next;
118 } while (!NILP(XWINDOW(w)->hchild) && !NILP(w = XWINDOW(w)->hchild));
124 static Lisp_Object frame_leftmost_window(struct frame *f)
126 Lisp_Object w = FRAME_ROOT_WINDOW(f);
129 while (!NILP(XWINDOW(w)->hchild)) {
130 w = XWINDOW(w)->hchild;
132 } while (!NILP(XWINDOW(w)->vchild) && !NILP(w = XWINDOW(w)->vchild));
137 static Lisp_Object frame_rightmost_window(struct frame *f)
139 Lisp_Object w = FRAME_ROOT_WINDOW(f);
142 while (!NILP(XWINDOW(w)->hchild)) {
143 w = XWINDOW(w)->hchild;
144 while (!NILP(XWINDOW(w)->next)) {
145 w = XWINDOW(w)->next;
148 } while (!NILP(XWINDOW(w)->vchild) && !NILP(w = XWINDOW(w)->vchild));
153 /* calculate the coordinates of a gutter for the current frame and
154 selected window. we have to be careful in calculating this as we
155 need to use *two* windows, the currently selected window will give
156 us the actual height, width and contents of the gutter, but if we
157 use this for calculating the gutter positions we run into trouble
158 if it is not the window nearest the gutter. Instead we predetermine
159 the nearest window and then use that.*/
161 get_gutter_coords(struct frame *f, enum gutter_pos pos, int *x, int *y,
162 int *width, int *height)
164 Lisp_Object tmp = frame_bottommost_window(f);
165 struct window *bot = XWINDOW(tmp);
166 /* The top and bottom gutters take precedence over the left and
170 *x = FRAME_LEFT_BORDER_END(f);
171 *y = FRAME_TOP_BORDER_END(f);
172 *width = FRAME_RIGHT_BORDER_START(f)
173 - FRAME_LEFT_BORDER_END(f);
174 *height = FRAME_TOP_GUTTER_BOUNDS(f);
178 *x = FRAME_LEFT_BORDER_END(f);
179 *y = WINDOW_BOTTOM(bot);
180 *width = FRAME_RIGHT_BORDER_START(f)
181 - FRAME_LEFT_BORDER_END(f);
182 *height = FRAME_BOTTOM_GUTTER_BOUNDS(f);
186 *x = FRAME_LEFT_BORDER_END(f);
187 *y = FRAME_TOP_BORDER_END(f) + FRAME_TOP_GUTTER_BOUNDS(f);
188 *width = FRAME_LEFT_GUTTER_BOUNDS(f);
189 *height = WINDOW_BOTTOM(bot)
190 - (FRAME_TOP_BORDER_END(f) + FRAME_TOP_GUTTER_BOUNDS(f));
194 *x = FRAME_RIGHT_BORDER_START(f)
195 - FRAME_RIGHT_GUTTER_BOUNDS(f);
196 *y = FRAME_TOP_BORDER_END(f) + FRAME_TOP_GUTTER_BOUNDS(f);
197 *width = FRAME_RIGHT_GUTTER_BOUNDS(f);
198 *height = WINDOW_BOTTOM(bot)
199 - (FRAME_TOP_BORDER_END(f) + FRAME_TOP_GUTTER_BOUNDS(f));
208 display_boxes_in_gutter_p
210 Determine whether the required display_glyph_area is completely
211 inside the gutter. -1 means the display_box is not in the gutter. 1
212 means the display_box and the display_glyph_area are in the
213 window. 0 means the display_box is in the gutter but the
214 display_glyph_area is not. */
215 int display_boxes_in_gutter_p(struct frame *f, struct display_box *db,
216 struct display_glyph_area *dga)
219 GUTTER_POS_LOOP(pos) {
220 if (FRAME_GUTTER_VISIBLE(f, pos)) {
221 int x, y, width, height;
222 get_gutter_coords(f, pos, &x, &y, &width, &height);
223 if (db->xpos + dga->xoffset >= x
225 db->ypos + dga->yoffset >= y
227 db->xpos + dga->xoffset + dga->width <= x + width
229 db->ypos + dga->yoffset + dga->height <= y + height)
231 else if (db->xpos >= x && db->ypos >= y
232 && db->xpos + db->width <= x + width
233 && db->ypos + db->height <= y + height)
240 /* Convert the gutter specifier into something we can actually
242 static Lisp_Object construct_window_gutter_spec(struct window *w,
245 Lisp_Object rest, *args;
247 Lisp_Object gutter = RAW_WINDOW_GUTTER(w, pos);
249 if (STRINGP(gutter) || NILP(gutter))
252 GET_LIST_LENGTH(gutter, nargs);
253 args = alloca_array(Lisp_Object, nargs >> 1);
256 for (rest = gutter; !NILP(rest); rest = XCDR(XCDR(rest))) {
257 /* We only put things in the real gutter that are declared to be
259 if (!CONSP(WINDOW_GUTTER_VISIBLE(w, pos))
260 || !NILP(Fmemq(XCAR(rest), WINDOW_GUTTER_VISIBLE(w, pos)))) {
261 args[nargs++] = XCAR(XCDR(rest));
265 return Fconcat(nargs, args);
268 /* Sizing gutters is a pain so we try and help the user by determining
269 what height will accommodate all lines. This is useless on left and
270 right gutters as we always have a maximal number of lines. */
272 calculate_gutter_size_from_display_lines(enum gutter_pos pos,
273 display_line_dynarr * ddla)
276 struct display_line *dl;
278 /* For top and bottom the calculation is easy. */
279 if (pos == TOP_GUTTER || pos == BOTTOM_GUTTER) {
280 /* grab coordinates of last line */
281 if (Dynarr_length(ddla)) {
282 dl = Dynarr_atp(ddla, Dynarr_length(ddla) - 1);
283 size = (dl->ypos + dl->descent - dl->clip)
284 - (Dynarr_atp(ddla, 0)->ypos -
285 Dynarr_atp(ddla, 0)->ascent);
288 /* For left and right we have to do some maths. */
290 int start_pos = 0, end_pos = 0, line;
291 for (line = 0; line < Dynarr_length(ddla); line++) {
293 dl = Dynarr_atp(ddla, line);
296 block < Dynarr_largest(dl->display_blocks);
298 struct display_block *db =
299 Dynarr_atp(dl->display_blocks, block);
301 if (db->type == TEXT) {
303 min(db->start_pos, start_pos);
304 end_pos = max(db->end_pos, end_pos);
308 size = end_pos - start_pos;
314 static Lisp_Object calculate_gutter_size(struct window *w, enum gutter_pos pos)
316 struct frame *f = XFRAME(WINDOW_FRAME(w));
318 display_line_dynarr *ddla;
319 Lisp_Object ret = Qnil;
321 /* degenerate case */
322 if (NILP(RAW_WINDOW_GUTTER(w, pos))
323 || !FRAME_VISIBLE_P(f)
327 /* Redisplay code that we use relies on GC not happening. Make it
329 count = specpdl_depth();
330 record_unwind_protect(restore_gc_inhibit,
331 make_int(gc_currently_forbidden));
332 gc_currently_forbidden = 1;
334 ddla = Dynarr_new(display_line);
335 /* generate some display lines */
336 generate_displayable_area(w, WINDOW_GUTTER(w, pos),
337 FRAME_LEFT_BORDER_END(f),
338 FRAME_TOP_BORDER_END(f),
339 FRAME_RIGHT_BORDER_START(f)
340 - FRAME_LEFT_BORDER_END(f),
341 FRAME_BOTTOM_BORDER_START(f)
342 - FRAME_TOP_BORDER_END(f), ddla, 0, 0);
344 /* Let GC happen again. */
345 unbind_to(count, Qnil);
347 ret = make_int(calculate_gutter_size_from_display_lines(pos, ddla));
348 free_display_lines(ddla);
353 static void output_gutter(struct frame *f, enum gutter_pos pos, int force)
356 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW(f);
357 struct device *d = XDEVICE(f->device);
358 struct window *w = XWINDOW(window);
359 int x, y, width, height, ypos;
360 int line, border_width;
362 display_line_dynarr *ddla, *cdla;
363 struct display_line *dl = 0;
366 if (!WINDOW_LIVE_P(w))
369 border_width = FRAME_GUTTER_BORDER_WIDTH(f, pos);
370 findex = get_builtin_face_cache_index(w, Vwidget_face);
372 if (!f->current_display_lines[pos])
373 f->current_display_lines[pos] = Dynarr_new(display_line);
374 if (!f->desired_display_lines[pos])
375 f->desired_display_lines[pos] = Dynarr_new(display_line);
377 ddla = f->desired_display_lines[pos];
378 cdla = f->current_display_lines[pos];
379 cdla_len = Dynarr_length(cdla);
383 get_gutter_coords(f, pos, &x, &y, &width, &height);
384 /* generate some display lines */
385 generate_displayable_area(w, WINDOW_GUTTER(w, pos),
386 x + border_width, y + border_width,
387 width - 2 * border_width,
388 height - 2 * border_width, ddla, 0, findex);
390 /* We only output the gutter if we think something of significance
391 has changed. This is, for example, because redisplay can cause
392 new face cache elements to get added causing compare_runes to
393 fail because the findex for a particular face has changed. */
394 if (force || f->faces_changed || f->frame_changed ||
395 f->gutter_changed || f->glyphs_changed ||
396 f->size_changed || f->subwindows_changed ||
397 w->windows_changed || f->windows_structure_changed ||
398 cdla_len != Dynarr_length(ddla) ||
399 (f->extents_changed && w->gutter_extent_modiff[pos])) {
401 printf("gutter redisplay [%dx%d@%d+%d] triggered by %s,\n",
402 width, height, x, y, force ? "force" :
403 f->faces_changed ? "f->faces_changed" :
404 f->frame_changed ? "f->frame_changed" :
405 f->gutter_changed ? "f->gutter_changed" :
406 f->glyphs_changed ? "f->glyphs_changed" :
407 f->size_changed ? "f->size_changed" :
408 f->subwindows_changed ? "f->subwindows_changed" :
409 w->windows_changed ? "w->windows_changed" :
411 windows_structure_changed ?
412 "f->windows_structure_changed" : cdla_len !=
413 Dynarr_length(ddla) ? "different display structures" :
416 gutter_extent_modiff[pos] ?
417 "f->extents_changed && w->gutter_extent_modiff[pos]" :
420 /* Output each line. */
421 for (line = 0; line < Dynarr_length(ddla); line++) {
422 output_display_line(w, cdla, ddla, line, -1, -1);
425 /* If the number of display lines has shrunk, adjust. */
426 if (cdla_len > Dynarr_length(ddla)) {
427 Dynarr_length(cdla) = Dynarr_length(ddla);
430 /* grab coordinates of last line and blank after it. */
431 if (Dynarr_length(ddla) > 0) {
432 dl = Dynarr_atp(ddla, Dynarr_length(ddla) - 1);
433 ypos = dl->ypos + dl->descent - dl->clip;
437 redisplay_clear_region(window, findex, x + border_width, ypos,
438 width - 2 * border_width,
439 height - (ypos - y) - border_width);
440 /* If, for some reason, we have more to display than we have
441 room for, and we are allowed to resize the gutter, then make
442 sure this happens before the next time we try and
443 output. This can happen when face font sizes change. */
444 if (dl && EQ(w->gutter_size[pos], Qautodetect)
446 calculate_gutter_size_from_display_lines(pos, ddla) >
447 WINDOW_GUTTER_SIZE_INTERNAL(w, pos))) {
448 /* #### Ideally we would just mark the specifier as dirty
449 and everything else would "just work". Unfortunately we have
450 two problems with this. One is that the specifier cache
451 won't be recalculated unless the specifier code thinks the
452 cached value has actually changed, even though we have
453 marked the specifier as dirty. Additionally, although doing
454 this results in a gutter size change, we never seem to get
455 back into redisplay so that the frame size can be updated. I
456 think this is because we are already in redisplay and later
457 on the frame will be marked as clean. Thus we also have to
458 force a pending recalculation of the frame size. */
459 w->gutter_size[pos] = Qnil;
460 Fset_specifier_dirty_flag(Vgutter_size[pos]);
461 update_gutter_geometry(f, pos);
464 /* bevel the gutter area if so desired */
465 if (border_width != 0) {
466 MAYBE_DEVMETH(d, bevel_area,
467 (w, findex, x, y, width, height,
468 border_width, EDGE_ALL, EDGE_BEVEL_OUT));
471 /* Nothing of significance happened so sync the display line
473 for (line = 0; line < Dynarr_length(ddla); line++) {
474 sync_display_line_structs(w, line, 1, cdla, ddla);
478 w->gutter_extent_modiff[pos] = 0;
481 static void clear_gutter(struct frame *f, enum gutter_pos pos)
483 int x, y, width, height;
484 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW(f);
485 face_index findex = get_builtin_face_cache_index(XWINDOW(window),
487 get_gutter_coords(f, pos, &x, &y, &width, &height);
489 SET_GUTTER_WAS_VISIBLE_FLAG(f, pos, 0);
491 redisplay_clear_region(window, findex, x, y, width, height);
494 /* #### I don't currently believe that redisplay needs to mark the
495 glyphs in its structures since these will always be referenced from
496 somewhere else. However, I'm not sure enough to stake my life on it
497 at this point, so we do the safe thing. */
499 /* See the comment in image_instantiate_cache_result as to why marking
500 the glyph will also mark the image_instance. */
501 void mark_gutters(struct frame *f)
504 GUTTER_POS_LOOP(pos) {
505 if (f->current_display_lines[pos])
506 mark_redisplay_structs(f->current_display_lines[pos]);
507 /* #### Do we really need to mark the desired lines? */
508 if (f->desired_display_lines[pos])
509 mark_redisplay_structs(f->desired_display_lines[pos]);
513 /* This is called by extent_changed_for_redisplay, so that redisplay
514 knows exactly what extents have changed. */
516 gutter_extent_signal_changed_region_maybe(Lisp_Object obj,
517 Bufpos start, Bufpos end)
519 /* #### Start and end are currently ignored but could be used by a
520 more optimal gutter redisplay. We currently loop over all frames
521 here, this could be optimized. */
522 Lisp_Object frmcons, devcons, concons;
524 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons) {
525 struct frame *f = XFRAME(XCAR(frmcons));
527 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW(f);
528 struct window *w = XWINDOW(window);
530 GUTTER_POS_LOOP(pos) {
531 if (EQ(WINDOW_GUTTER(w, pos), obj)) {
532 w->gutter_extent_modiff[pos]++;
538 /* We have to change the gutter geometry separately to the gutter
539 update since it needs to occur outside of redisplay proper. */
540 static void 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]) {
548 pixel_to_char_size(f, FRAME_PIXWIDTH(f), FRAME_PIXHEIGHT(f),
550 change_frame_size(f, height, width, 0);
551 MARK_FRAME_LAYOUT_CHANGED(f);
554 /* Mark sizes as up-to-date. */
555 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS(f, pos);
558 void update_frame_gutter_geometry(struct frame *f)
560 if (f->gutter_changed
561 || f->frame_layout_changed || f->windows_structure_changed) {
564 /* If the gutter geometry has changed then re-layout the
565 frame. If we are in display there is almost no point in doing
566 anything else since the frame size changes will be delayed
567 until we are out of redisplay proper. */
568 GUTTER_POS_LOOP(pos) {
569 update_gutter_geometry(f, pos);
574 void update_frame_gutters(struct frame *f)
576 if (f->faces_changed || f->frame_changed ||
577 f->gutter_changed || f->glyphs_changed ||
578 f->size_changed || f->subwindows_changed ||
579 f->windows_changed || f->windows_structure_changed ||
580 f->extents_changed || f->frame_layout_changed) {
583 /* We don't actually care about these when outputting the gutter
584 so locally disable them. */
585 int local_clip_changed = f->clip_changed;
586 int local_buffers_changed = f->buffers_changed;
588 f->buffers_changed = 0;
591 GUTTER_POS_LOOP(pos) {
592 if (FRAME_GUTTER_VISIBLE(f, pos))
593 output_gutter(f, pos, 0);
595 else if (gutter_was_visible(f, pos))
596 clear_gutter(f, pos);
599 f->clip_changed = local_clip_changed;
600 f->buffers_changed = local_buffers_changed;
601 f->gutter_changed = 0;
605 void reset_gutter_display_lines(struct frame *f)
608 GUTTER_POS_LOOP(pos) {
609 if (f->current_display_lines[pos])
610 Dynarr_reset(f->current_display_lines[pos]);
615 redraw_exposed_gutter(struct frame *f, enum gutter_pos pos, int x, int y,
616 int width, int height)
618 int g_x, g_y, g_width, g_height;
620 get_gutter_coords(f, pos, &g_x, &g_y, &g_width, &g_height);
622 if (((y + height) < g_y) || (y > (g_y + g_height)) || !height || !width
623 || !g_height || !g_width)
625 if (((x + width) < g_x) || (x > (g_x + g_width)))
629 printf("redrawing gutter after expose %d+%d, %dx%d\n",
630 x, y, width, height);
632 /* #### optimize this - redrawing the whole gutter for every expose
633 is very expensive. We reset the current display lines because if
634 they're being exposed they are no longer current. */
635 reset_gutter_display_lines(f);
637 /* Even if none of the gutter is in the area, the blank region at
638 the very least must be because the first thing we did is verify
639 that some portion of the gutter is in the exposed region. */
640 output_gutter(f, pos, 1);
644 redraw_exposed_gutters(struct frame *f, int x, int y, int width, int height)
648 /* We have to be "in display" when we output the gutter - make it
650 hold_frame_size_changes();
651 GUTTER_POS_LOOP(pos) {
652 if (FRAME_GUTTER_VISIBLE(f, pos))
653 redraw_exposed_gutter(f, pos, x, y, width, height);
655 unhold_one_frame_size_changes(f);
658 void free_frame_gutters(struct frame *f)
661 GUTTER_POS_LOOP(pos) {
662 if (f->current_display_lines[pos]) {
663 free_display_lines(f->current_display_lines[pos]);
664 f->current_display_lines[pos] = 0;
666 if (f->desired_display_lines[pos]) {
667 free_display_lines(f->desired_display_lines[pos]);
668 f->desired_display_lines[pos] = 0;
673 static enum gutter_pos decode_gutter_position(Lisp_Object position)
675 if (EQ(position, Qtop))
677 if (EQ(position, Qbottom))
678 return BOTTOM_GUTTER;
679 if (EQ(position, Qleft))
681 if (EQ(position, Qright))
683 signal_simple_error("Invalid gutter position", position);
685 return TOP_GUTTER; /* not reached */
688 DEFUN("set-default-gutter-position", Fset_default_gutter_position, 1, 1, 0, /*
689 Set the position that the `default-gutter' will be displayed at.
690 Valid positions are 'top, 'bottom, 'left and 'right.
691 See `default-gutter-position'.
695 enum gutter_pos cur = decode_gutter_position(Vdefault_gutter_position);
696 enum gutter_pos new = decode_gutter_position(position);
699 /* The following calls will automatically cause the dirty
700 flags to be set; we delay frame size changes to avoid
701 lots of frame flickering. */
702 /* #### I think this should be GC protected. -sb */
703 hold_frame_size_changes();
704 set_specifier_fallback(Vgutter[cur], list1(Fcons(Qnil, Qnil)));
705 set_specifier_fallback(Vgutter[new], Vdefault_gutter);
706 set_specifier_fallback(Vgutter_size[cur],
707 list1(Fcons(Qnil, Qzero)));
708 set_specifier_fallback(Vgutter_size[new], new == TOP_GUTTER
710 BOTTOM_GUTTER ? Vdefault_gutter_height :
711 Vdefault_gutter_width);
712 set_specifier_fallback(Vgutter_border_width[cur],
713 list1(Fcons(Qnil, Qzero)));
714 set_specifier_fallback(Vgutter_border_width[new],
715 Vdefault_gutter_border_width);
716 set_specifier_fallback(Vgutter_visible_p[cur],
717 list1(Fcons(Qnil, Qt)));
718 set_specifier_fallback(Vgutter_visible_p[new],
719 Vdefault_gutter_visible_p);
721 Vdefault_gutter_position = position;
722 unhold_frame_size_changes();
725 run_hook(Qdefault_gutter_position_changed_hook);
730 DEFUN("default-gutter-position", Fdefault_gutter_position, 0, 0, 0, /*
731 Return the position that the `default-gutter' will be displayed at.
732 The `default-gutter' will only be displayed here if the corresponding
733 position-specific gutter specifier does not provide a value.
737 return Vdefault_gutter_position;
740 DEFUN("gutter-pixel-width", Fgutter_pixel_width, 0, 2, 0, /*
741 Return the pixel width of the gutter at POS in LOCALE.
742 POS defaults to the default gutter position. LOCALE defaults to
747 int x, y, width, height;
748 enum gutter_pos p = TOP_GUTTER;
749 struct frame *f = decode_frame(FW_FRAME(locale));
752 pos = Vdefault_gutter_position;
753 p = decode_gutter_position(pos);
755 get_gutter_coords(f, p, &x, &y, &width, &height);
756 width -= (FRAME_GUTTER_BORDER_WIDTH(f, p) * 2);
758 return make_int(width);
761 DEFUN("gutter-pixel-height", Fgutter_pixel_height, 0, 2, 0, /*
762 Return the pixel height of the gutter at POS in LOCALE.
763 POS defaults to the default gutter position. LOCALE defaults to
768 int x, y, width, height;
769 enum gutter_pos p = TOP_GUTTER;
770 struct frame *f = decode_frame(FW_FRAME(locale));
773 pos = Vdefault_gutter_position;
774 p = decode_gutter_position(pos);
776 get_gutter_coords(f, p, &x, &y, &width, &height);
777 height -= (FRAME_GUTTER_BORDER_WIDTH(f, p) * 2);
779 return make_int(height);
782 DEFINE_SPECIFIER_TYPE(gutter);
784 static void gutter_after_change(Lisp_Object specifier, Lisp_Object locale)
789 static void gutter_validate(Lisp_Object instantiator)
791 if (NILP(instantiator))
794 /* Must be a string or a plist. */
795 if (!STRINGP(instantiator) && NILP(Fvalid_plist_p(instantiator)))
796 signal_simple_error("Gutter spec must be string, plist or nil",
799 if (!STRINGP(instantiator)) {
802 for (rest = instantiator; !NILP(rest); rest = XCDR(XCDR(rest))) {
803 if (!SYMBOLP(XCAR(rest))
804 || !STRINGP(XCAR(XCDR(rest))))
806 ("Gutter plist spec must contain strings",
812 DEFUN("gutter-specifier-p", Fgutter_specifier_p, 1, 1, 0, /*
813 Return non-nil if OBJECT is a gutter specifier.
815 See `make-gutter-specifier' for a description of possible gutter
820 return GUTTER_SPECIFIERP(object) ? Qt : Qnil;
824 Helper for invalidating the real specifier when default
825 specifier caching changes
827 static void recompute_overlaying_specifier(Lisp_Object real_one[4])
829 enum gutter_pos pos = decode_gutter_position(Vdefault_gutter_position);
830 Fset_specifier_dirty_flag(real_one[pos]);
834 gutter_specs_changed(Lisp_Object specifier, struct window *w,
835 Lisp_Object oldval, enum gutter_pos pos)
837 w->real_gutter[pos] = construct_window_gutter_spec(w, pos);
838 w->real_gutter_size[pos] = w->gutter_size[pos];
840 if (EQ(w->real_gutter_size[pos], Qautodetect)
841 && !NILP(w->gutter_visible_p[pos])) {
842 w->real_gutter_size[pos] = calculate_gutter_size(w, pos);
845 MARK_MODELINE_CHANGED;
846 MARK_WINDOWS_CHANGED(w);
849 /* We define all of these so we can access which actual gutter changed. */
851 top_gutter_specs_changed(Lisp_Object specifier, struct window *w,
854 gutter_specs_changed(specifier, w, oldval, TOP_GUTTER);
858 bottom_gutter_specs_changed(Lisp_Object specifier, struct window *w,
861 gutter_specs_changed(specifier, w, oldval, BOTTOM_GUTTER);
865 left_gutter_specs_changed(Lisp_Object specifier, struct window *w,
868 gutter_specs_changed(specifier, w, oldval, LEFT_GUTTER);
872 right_gutter_specs_changed(Lisp_Object specifier, struct window *w,
875 gutter_specs_changed(specifier, w, oldval, RIGHT_GUTTER);
879 default_gutter_specs_changed(Lisp_Object specifier, struct window *w,
882 recompute_overlaying_specifier(Vgutter);
886 gutter_geometry_changed_in_window(Lisp_Object specifier, struct window *w,
890 GUTTER_POS_LOOP(pos) {
891 w->real_gutter_size[pos] = w->gutter_size[pos];
892 if (EQ(w->real_gutter_size[pos], Qautodetect)
893 && !NILP(w->gutter_visible_p[pos])) {
894 w->real_gutter_size[pos] =
895 calculate_gutter_size(w, pos);
900 MARK_MODELINE_CHANGED;
901 MARK_WINDOWS_CHANGED(w);
905 default_gutter_size_changed_in_window(Lisp_Object specifier, struct window *w,
908 recompute_overlaying_specifier(Vgutter_size);
912 default_gutter_border_width_changed_in_window(Lisp_Object specifier,
916 recompute_overlaying_specifier(Vgutter_border_width);
920 default_gutter_visible_p_changed_in_window(Lisp_Object specifier,
921 struct window *w, Lisp_Object oldval)
923 recompute_overlaying_specifier(Vgutter_visible_p);
924 /* Need to reconstruct the gutter specifier as it is affected by the
926 recompute_overlaying_specifier(Vgutter);
929 DECLARE_SPECIFIER_TYPE(gutter_size);
930 #define GUTTER_SIZE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_size)
931 DEFINE_SPECIFIER_TYPE(gutter_size);
933 static void gutter_size_validate(Lisp_Object instantiator)
935 if (NILP(instantiator))
938 if (!INTP(instantiator) && !EQ(instantiator, Qautodetect))
940 ("Gutter size must be an integer or 'autodetect",
944 DEFUN("gutter-size-specifier-p", Fgutter_size_specifier_p, 1, 1, 0, /*
945 Return non-nil if OBJECT is a gutter-size specifier.
947 See `make-gutter-size-specifier' for a description of possible gutter-size
952 return GUTTER_SIZE_SPECIFIERP(object) ? Qt : Qnil;
955 DECLARE_SPECIFIER_TYPE(gutter_visible);
956 #define GUTTER_VISIBLE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_visible)
957 DEFINE_SPECIFIER_TYPE(gutter_visible);
959 static void gutter_visible_validate(Lisp_Object instantiator)
961 if (NILP(instantiator))
964 if (!NILP(instantiator) && !EQ(instantiator, Qt)
965 && !CONSP(instantiator))
967 ("Gutter visibility must be a boolean or list of symbols",
970 if (CONSP(instantiator)) {
973 EXTERNAL_LIST_LOOP(rest, instantiator) {
974 if (!SYMBOLP(XCAR(rest)))
976 ("Gutter visibility must be a boolean or list of symbols",
982 DEFUN("gutter-visible-specifier-p", Fgutter_visible_specifier_p, 1, 1, 0, /*
983 Return non-nil if OBJECT is a gutter-visible specifier.
985 See `make-gutter-visible-specifier' for a description of possible
986 gutter-visible instantiators.
990 return GUTTER_VISIBLE_SPECIFIERP(object) ? Qt : Qnil;
993 DEFUN("redisplay-gutter-area", Fredisplay_gutter_area, 0, 0, 0, /*
994 Ensure that all gutters are correctly showing their gutter specifier.
998 Lisp_Object devcons, concons;
1000 DEVICE_LOOP_NO_BREAK(devcons, concons) {
1001 struct device *d = XDEVICE(XCAR(devcons));
1002 Lisp_Object frmcons;
1004 DEVICE_FRAME_LOOP(frmcons, d) {
1005 struct frame *f = XFRAME(XCAR(frmcons));
1007 MAYBE_DEVMETH(d, frame_output_begin, (f));
1009 /* Sequence is quite important here. We not only want to
1010 redisplay the gutter area but we also want to flush any
1011 frame size changes out so that the gutter redisplay happens
1012 in a kosha environment.
1014 This is not only so that things look right but so that
1015 glyph redisplay optimization kicks in, by default display
1016 lines will be completely re-output if
1017 f->windows_structure_changed is 1, and this is true if
1018 frame size changes haven't been flushed out. Once frame
1019 size changes have been flushed out we then need to
1020 redisplay the frame in order to flush out pending window
1022 update_frame_gutter_geometry(f);
1024 if (f->windows_structure_changed)
1025 redisplay_frame(f, 1);
1026 else if (FRAME_REPAINT_P(f)) {
1027 /* We have to be "in display" when we output the gutter
1029 hold_frame_size_changes();
1030 update_frame_gutters(f);
1031 unhold_one_frame_size_changes(f);
1034 MAYBE_DEVMETH(d, frame_output_end, (f));
1037 d->gutter_changed = 0;
1040 /* This is so that further changes to the gutters will trigger redisplay. */
1041 gutter_changed_set = 0;
1047 void init_frame_gutters(struct frame *f)
1049 enum gutter_pos pos;
1050 struct window *w = XWINDOW(FRAME_LAST_NONMINIBUF_WINDOW(f));
1051 /* We are here as far in frame creation so cached specifiers are
1052 already recomputed, and possibly modified by resource
1053 initialization. We need to recalculate autodetected gutters. */
1054 GUTTER_POS_LOOP(pos) {
1055 w->real_gutter[pos] = construct_window_gutter_spec(w, pos);
1056 w->real_gutter_size[pos] = w->gutter_size[pos];
1057 if (EQ(w->gutter_size[pos], Qautodetect)
1058 && !NILP(w->gutter_visible_p[pos])) {
1059 w->real_gutter_size[pos] =
1060 calculate_gutter_size(w, pos);
1061 MARK_GUTTER_CHANGED;
1062 MARK_WINDOWS_CHANGED(w);
1066 /* Keep a record of the current sizes of things. */
1067 GUTTER_POS_LOOP(pos) {
1068 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS(f, pos);
1072 void syms_of_gutter(void)
1074 DEFSUBR(Fgutter_specifier_p);
1075 DEFSUBR(Fgutter_size_specifier_p);
1076 DEFSUBR(Fgutter_visible_specifier_p);
1077 DEFSUBR(Fset_default_gutter_position);
1078 DEFSUBR(Fdefault_gutter_position);
1079 DEFSUBR(Fgutter_pixel_height);
1080 DEFSUBR(Fgutter_pixel_width);
1081 DEFSUBR(Fredisplay_gutter_area);
1083 defsymbol(&Qgutter_size, "gutter-size");
1084 defsymbol(&Qgutter_visible, "gutter-visible");
1085 defsymbol(&Qdefault_gutter_position_changed_hook,
1086 "default-gutter-position-changed-hook");
1089 void vars_of_gutter(void)
1091 staticpro(&Vdefault_gutter_position);
1092 Vdefault_gutter_position = Qtop;
1097 void specifier_type_create_gutter(void)
1099 INITIALIZE_SPECIFIER_TYPE(gutter, "gutter", "gutter-specifier-p");
1100 SPECIFIER_HAS_METHOD(gutter, validate);
1101 SPECIFIER_HAS_METHOD(gutter, after_change);
1103 INITIALIZE_SPECIFIER_TYPE(gutter_size, "gutter-size",
1104 "gutter-size-specifier-p");
1105 SPECIFIER_HAS_METHOD(gutter_size, validate);
1107 INITIALIZE_SPECIFIER_TYPE(gutter_visible, "gutter-visible",
1108 "gutter-visible-specifier-p");
1109 SPECIFIER_HAS_METHOD(gutter_visible, validate);
1112 void reinit_specifier_type_create_gutter(void)
1114 REINITIALIZE_SPECIFIER_TYPE(gutter);
1115 REINITIALIZE_SPECIFIER_TYPE(gutter_size);
1116 REINITIALIZE_SPECIFIER_TYPE(gutter_visible);
1119 void specifier_vars_of_gutter(void)
1123 DEFVAR_SPECIFIER("default-gutter", &Vdefault_gutter /*
1124 Specifier for a fallback gutter.
1125 Use `set-specifier' to change this.
1127 The position of this gutter is specified in the function
1128 `default-gutter-position'. If the corresponding position-specific
1129 gutter (e.g. `top-gutter' if `default-gutter-position' is 'top)
1130 does not specify a gutter in a particular domain (usually a window),
1131 then the value of `default-gutter' in that domain, if any, will be
1134 Note that the gutter at any particular position will not be
1135 displayed unless its visibility flag is true and its thickness
1136 \(width or height, depending on orientation) is non-zero. The
1137 visibility is controlled by the specifiers `top-gutter-visible-p',
1138 `bottom-gutter-visible-p', `left-gutter-visible-p', and
1139 `right-gutter-visible-p', and the thickness is controlled by the
1140 specifiers `top-gutter-height', `bottom-gutter-height',
1141 `left-gutter-width', and `right-gutter-width'.
1143 Note that one of the four visibility specifiers inherits from
1144 `default-gutter-visibility' and one of the four thickness
1145 specifiers inherits from either `default-gutter-width' or
1146 `default-gutter-height' (depending on orientation), just
1147 like for the gutter description specifiers (e.g. `top-gutter')
1150 Therefore, if you are setting `default-gutter', you should control
1151 the visibility and thickness using `default-gutter-visible-p',
1152 `default-gutter-width', and `default-gutter-height', rather than
1153 using position-specific specifiers. That way, you will get sane
1154 behavior if the user changes the default gutter position.
1156 The gutter value should be a string, a property list of strings or
1157 nil. You can attach extents and glyphs to the string and hence display
1158 glyphs and text in other fonts in the gutter area. If the gutter value
1159 is a property list then the strings will be concatenated together
1160 before being displayed. */ );
1162 Vdefault_gutter = Fmake_specifier(Qgutter);
1163 /* #### It would be even nicer if the specifier caching
1164 automatically knew about specifier fallbacks, so we didn't
1165 have to do it ourselves. */
1166 set_specifier_caching(Vdefault_gutter,
1167 offsetof(struct window, default_gutter),
1168 default_gutter_specs_changed, 0, 0, 1);
1170 DEFVAR_SPECIFIER("top-gutter", &Vgutter[TOP_GUTTER] /*
1171 Specifier for the gutter at the top of the frame.
1172 Use `set-specifier' to change this.
1173 See `default-gutter' for a description of a valid gutter instantiator.
1175 Vgutter[TOP_GUTTER] = Fmake_specifier(Qgutter);
1176 set_specifier_caching(Vgutter[TOP_GUTTER],
1177 offsetof(struct window, gutter[TOP_GUTTER]),
1178 top_gutter_specs_changed, 0, 0, 1);
1180 DEFVAR_SPECIFIER("bottom-gutter", &Vgutter[BOTTOM_GUTTER] /*
1181 Specifier for the gutter at the bottom of the frame.
1182 Use `set-specifier' to change this.
1183 See `default-gutter' for a description of a valid gutter instantiator.
1185 Note that, unless the `default-gutter-position' is `bottom', by
1186 default the height of the bottom gutter (controlled by
1187 `bottom-gutter-height') is 0; thus, a bottom gutter will not be
1188 displayed even if you provide a value for `bottom-gutter'.
1190 Vgutter[BOTTOM_GUTTER] = Fmake_specifier(Qgutter);
1191 set_specifier_caching(Vgutter[BOTTOM_GUTTER],
1192 offsetof(struct window, gutter[BOTTOM_GUTTER]),
1193 bottom_gutter_specs_changed, 0, 0, 1);
1195 DEFVAR_SPECIFIER("left-gutter", &Vgutter[LEFT_GUTTER] /*
1196 Specifier for the gutter at the left edge of the frame.
1197 Use `set-specifier' to change this.
1198 See `default-gutter' for a description of a valid gutter instantiator.
1200 Note that, unless the `default-gutter-position' is `left', by
1201 default the height of the left gutter (controlled by
1202 `left-gutter-width') is 0; thus, a left gutter will not be
1203 displayed even if you provide a value for `left-gutter'.
1205 Vgutter[LEFT_GUTTER] = Fmake_specifier(Qgutter);
1206 set_specifier_caching(Vgutter[LEFT_GUTTER],
1207 offsetof(struct window, gutter[LEFT_GUTTER]),
1208 left_gutter_specs_changed, 0, 0, 1);
1210 DEFVAR_SPECIFIER("right-gutter", &Vgutter[RIGHT_GUTTER] /*
1211 Specifier for the gutter at the right edge of the frame.
1212 Use `set-specifier' to change this.
1213 See `default-gutter' for a description of a valid gutter instantiator.
1215 Note that, unless the `default-gutter-position' is `right', by
1216 default the height of the right gutter (controlled by
1217 `right-gutter-width') is 0; thus, a right gutter will not be
1218 displayed even if you provide a value for `right-gutter'.
1220 Vgutter[RIGHT_GUTTER] = Fmake_specifier(Qgutter);
1221 set_specifier_caching(Vgutter[RIGHT_GUTTER],
1222 offsetof(struct window, gutter[RIGHT_GUTTER]),
1223 right_gutter_specs_changed, 0, 0, 1);
1225 /* initially, top inherits from default; this can be
1226 changed with `set-default-gutter-position'. */
1227 fb = list1(Fcons(Qnil, Qnil));
1228 set_specifier_fallback(Vdefault_gutter, fb);
1229 set_specifier_fallback(Vgutter[TOP_GUTTER], Vdefault_gutter);
1230 set_specifier_fallback(Vgutter[BOTTOM_GUTTER], fb);
1231 set_specifier_fallback(Vgutter[LEFT_GUTTER], fb);
1232 set_specifier_fallback(Vgutter[RIGHT_GUTTER], fb);
1234 DEFVAR_SPECIFIER("default-gutter-height", &Vdefault_gutter_height /*
1235 *Height of the default gutter, if it's oriented horizontally.
1236 This is a specifier; use `set-specifier' to change it.
1238 The position of the default gutter is specified by the function
1239 `set-default-gutter-position'. If the corresponding position-specific
1240 gutter thickness specifier (e.g. `top-gutter-height' if
1241 `default-gutter-position' is 'top) does not specify a thickness in a
1242 particular domain (a window or a frame), then the value of
1243 `default-gutter-height' or `default-gutter-width' (depending on the
1244 gutter orientation) in that domain, if any, will be used instead.
1246 Note that `default-gutter-height' is only used when
1247 `default-gutter-position' is 'top or 'bottom, and `default-gutter-width'
1248 is only used when `default-gutter-position' is 'left or 'right.
1250 Note that all of the position-specific gutter thickness specifiers
1251 have a fallback value of zero when they do not correspond to the
1252 default gutter. Therefore, you will have to set a non-zero thickness
1253 value if you want a position-specific gutter to be displayed.
1255 If you set the height to 'autodetect the size of the gutter will be
1256 calculated to be large enough to hold the contents of the gutter. This
1259 Vdefault_gutter_height = Fmake_specifier(Qgutter_size);
1260 set_specifier_caching(Vdefault_gutter_height,
1261 offsetof(struct window, default_gutter_height),
1262 default_gutter_size_changed_in_window, 0, 0, 1);
1264 DEFVAR_SPECIFIER("default-gutter-width", &Vdefault_gutter_width /*
1265 *Width of the default gutter, if it's oriented vertically.
1266 This is a specifier; use `set-specifier' to change it.
1268 See `default-gutter-height' for more information.
1270 Vdefault_gutter_width = Fmake_specifier(Qgutter_size);
1271 set_specifier_caching(Vdefault_gutter_width,
1272 offsetof(struct window, default_gutter_width),
1273 default_gutter_size_changed_in_window, 0, 0, 1);
1275 DEFVAR_SPECIFIER("top-gutter-height", &Vgutter_size[TOP_GUTTER] /*
1276 *Height of the top gutter.
1277 This is a specifier; use `set-specifier' to change it.
1279 See `default-gutter-height' for more information.
1281 Vgutter_size[TOP_GUTTER] = Fmake_specifier(Qgutter_size);
1282 set_specifier_caching(Vgutter_size[TOP_GUTTER],
1283 offsetof(struct window, gutter_size[TOP_GUTTER]),
1284 gutter_geometry_changed_in_window, 0, 0, 1);
1286 DEFVAR_SPECIFIER("bottom-gutter-height", &Vgutter_size[BOTTOM_GUTTER] /*
1287 *Height of the bottom gutter.
1288 This is a specifier; use `set-specifier' to change it.
1290 See `default-gutter-height' for more information.
1292 Vgutter_size[BOTTOM_GUTTER] = Fmake_specifier(Qgutter_size);
1293 set_specifier_caching(Vgutter_size[BOTTOM_GUTTER],
1294 offsetof(struct window,
1295 gutter_size[BOTTOM_GUTTER]),
1296 gutter_geometry_changed_in_window, 0, 0, 1);
1298 DEFVAR_SPECIFIER("left-gutter-width", &Vgutter_size[LEFT_GUTTER] /*
1299 *Width of left gutter.
1300 This is a specifier; use `set-specifier' to change it.
1302 See `default-gutter-height' for more information.
1304 Vgutter_size[LEFT_GUTTER] = Fmake_specifier(Qgutter_size);
1305 set_specifier_caching(Vgutter_size[LEFT_GUTTER],
1306 offsetof(struct window, gutter_size[LEFT_GUTTER]),
1307 gutter_geometry_changed_in_window, 0, 0, 1);
1309 DEFVAR_SPECIFIER("right-gutter-width", &Vgutter_size[RIGHT_GUTTER] /*
1310 *Width of right gutter.
1311 This is a specifier; use `set-specifier' to change it.
1313 See `default-gutter-height' for more information.
1315 Vgutter_size[RIGHT_GUTTER] = Fmake_specifier(Qgutter_size);
1316 set_specifier_caching(Vgutter_size[RIGHT_GUTTER],
1317 offsetof(struct window,
1318 gutter_size[RIGHT_GUTTER]),
1319 gutter_geometry_changed_in_window, 0, 0, 1);
1323 fb = Fcons(Fcons(list1(Qtty), Qautodetect), fb);
1325 #ifdef HAVE_X_WINDOWS
1326 fb = Fcons(Fcons(list1(Qx), Qautodetect), fb);
1329 set_specifier_fallback(Vdefault_gutter_height, fb);
1333 fb = Fcons(Fcons(list1(Qtty), Qautodetect), fb);
1335 #ifdef HAVE_X_WINDOWS
1336 fb = Fcons(Fcons(list1(Qx), Qautodetect), fb);
1339 set_specifier_fallback(Vdefault_gutter_width, fb);
1341 set_specifier_fallback(Vgutter_size[TOP_GUTTER],
1342 Vdefault_gutter_height);
1343 fb = list1(Fcons(Qnil, Qzero));
1344 set_specifier_fallback(Vgutter_size[BOTTOM_GUTTER], fb);
1345 set_specifier_fallback(Vgutter_size[LEFT_GUTTER], fb);
1346 set_specifier_fallback(Vgutter_size[RIGHT_GUTTER], fb);
1348 DEFVAR_SPECIFIER("default-gutter-border-width", &Vdefault_gutter_border_width /*
1349 *Width of the border around the default gutter.
1350 This is a specifier; use `set-specifier' to change it.
1352 The position of the default gutter is specified by the function
1353 `set-default-gutter-position'. If the corresponding position-specific
1354 gutter border width specifier (e.g. `top-gutter-border-width' if
1355 `default-gutter-position' is 'top) does not specify a border width in a
1356 particular domain (a window or a frame), then the value of
1357 `default-gutter-border-width' in that domain, if any, will be used
1361 Vdefault_gutter_border_width = Fmake_specifier(Qnatnum);
1362 set_specifier_caching(Vdefault_gutter_border_width,
1363 offsetof(struct window,
1364 default_gutter_border_width),
1365 default_gutter_border_width_changed_in_window, 0,
1368 DEFVAR_SPECIFIER("top-gutter-border-width", &Vgutter_border_width[TOP_GUTTER] /*
1369 *Border width of the top gutter.
1370 This is a specifier; use `set-specifier' to change it.
1372 See `default-gutter-height' for more information.
1374 Vgutter_border_width[TOP_GUTTER] = Fmake_specifier(Qnatnum);
1375 set_specifier_caching(Vgutter_border_width[TOP_GUTTER],
1376 offsetof(struct window,
1377 gutter_border_width[TOP_GUTTER]),
1378 gutter_geometry_changed_in_window, 0, 0, 0);
1380 DEFVAR_SPECIFIER("bottom-gutter-border-width", &Vgutter_border_width[BOTTOM_GUTTER] /*
1381 *Border width of the bottom gutter.
1382 This is a specifier; use `set-specifier' to change it.
1384 See `default-gutter-height' for more information.
1386 Vgutter_border_width[BOTTOM_GUTTER] = Fmake_specifier(Qnatnum);
1387 set_specifier_caching(Vgutter_border_width[BOTTOM_GUTTER],
1388 offsetof(struct window,
1389 gutter_border_width[BOTTOM_GUTTER]),
1390 gutter_geometry_changed_in_window, 0, 0, 0);
1392 DEFVAR_SPECIFIER("left-gutter-border-width", &Vgutter_border_width[LEFT_GUTTER] /*
1393 *Border width of left gutter.
1394 This is a specifier; use `set-specifier' to change it.
1396 See `default-gutter-height' for more information.
1398 Vgutter_border_width[LEFT_GUTTER] = Fmake_specifier(Qnatnum);
1399 set_specifier_caching(Vgutter_border_width[LEFT_GUTTER],
1400 offsetof(struct window,
1401 gutter_border_width[LEFT_GUTTER]),
1402 gutter_geometry_changed_in_window, 0, 0, 0);
1404 DEFVAR_SPECIFIER("right-gutter-border-width", &Vgutter_border_width[RIGHT_GUTTER] /*
1405 *Border width of right gutter.
1406 This is a specifier; use `set-specifier' to change it.
1408 See `default-gutter-height' for more information.
1410 Vgutter_border_width[RIGHT_GUTTER] = Fmake_specifier(Qnatnum);
1411 set_specifier_caching(Vgutter_border_width[RIGHT_GUTTER],
1412 offsetof(struct window,
1413 gutter_border_width[RIGHT_GUTTER]),
1414 gutter_geometry_changed_in_window, 0, 0, 0);
1418 fb = Fcons(Fcons(list1(Qtty), Qzero), fb);
1420 #ifdef HAVE_X_WINDOWS
1421 fb = Fcons(Fcons(list1(Qx), make_int(DEFAULT_GUTTER_BORDER_WIDTH)), fb);
1424 set_specifier_fallback(Vdefault_gutter_border_width, fb);
1426 set_specifier_fallback(Vgutter_border_width[TOP_GUTTER],
1427 Vdefault_gutter_border_width);
1428 fb = list1(Fcons(Qnil, Qzero));
1429 set_specifier_fallback(Vgutter_border_width[BOTTOM_GUTTER], fb);
1430 set_specifier_fallback(Vgutter_border_width[LEFT_GUTTER], fb);
1431 set_specifier_fallback(Vgutter_border_width[RIGHT_GUTTER], fb);
1433 DEFVAR_SPECIFIER("default-gutter-visible-p", &Vdefault_gutter_visible_p /*
1434 *Whether the default gutter is visible.
1435 This is a specifier; use `set-specifier' to change it.
1437 The position of the default gutter is specified by the function
1438 `set-default-gutter-position'. If the corresponding position-specific
1439 gutter visibility specifier (e.g. `top-gutter-visible-p' if
1440 `default-gutter-position' is 'top) does not specify a visible-p value
1441 in a particular domain (a window or a frame), then the value of
1442 `default-gutter-visible-p' in that domain, if any, will be used
1445 `default-gutter-visible-p' and all of the position-specific gutter
1446 visibility specifiers have a fallback value of true.
1448 Vdefault_gutter_visible_p = Fmake_specifier(Qgutter_visible);
1449 set_specifier_caching(Vdefault_gutter_visible_p,
1450 offsetof(struct window,
1451 default_gutter_visible_p),
1452 default_gutter_visible_p_changed_in_window,
1455 DEFVAR_SPECIFIER("top-gutter-visible-p", &Vgutter_visible_p[TOP_GUTTER] /*
1456 *Whether the top gutter is visible.
1457 This is a specifier; use `set-specifier' to change it.
1459 See `default-gutter-visible-p' for more information.
1461 Vgutter_visible_p[TOP_GUTTER] = Fmake_specifier(Qgutter_visible);
1462 set_specifier_caching(Vgutter_visible_p[TOP_GUTTER],
1463 offsetof(struct window,
1464 gutter_visible_p[TOP_GUTTER]),
1465 top_gutter_specs_changed, 0, 0, 0);
1467 DEFVAR_SPECIFIER("bottom-gutter-visible-p", &Vgutter_visible_p[BOTTOM_GUTTER] /*
1468 *Whether the bottom gutter is visible.
1469 This is a specifier; use `set-specifier' to change it.
1471 See `default-gutter-visible-p' for more information.
1473 Vgutter_visible_p[BOTTOM_GUTTER] = Fmake_specifier(Qgutter_visible);
1474 set_specifier_caching(Vgutter_visible_p[BOTTOM_GUTTER],
1475 offsetof(struct window,
1476 gutter_visible_p[BOTTOM_GUTTER]),
1477 bottom_gutter_specs_changed, 0, 0, 0);
1479 DEFVAR_SPECIFIER("left-gutter-visible-p", &Vgutter_visible_p[LEFT_GUTTER] /*
1480 *Whether the left gutter is visible.
1481 This is a specifier; use `set-specifier' to change it.
1483 See `default-gutter-visible-p' for more information.
1485 Vgutter_visible_p[LEFT_GUTTER] = Fmake_specifier(Qgutter_visible);
1486 set_specifier_caching(Vgutter_visible_p[LEFT_GUTTER],
1487 offsetof(struct window,
1488 gutter_visible_p[LEFT_GUTTER]),
1489 left_gutter_specs_changed, 0, 0, 0);
1491 DEFVAR_SPECIFIER("right-gutter-visible-p", &Vgutter_visible_p[RIGHT_GUTTER] /*
1492 *Whether the right gutter is visible.
1493 This is a specifier; use `set-specifier' to change it.
1495 See `default-gutter-visible-p' for more information.
1497 Vgutter_visible_p[RIGHT_GUTTER] = Fmake_specifier(Qgutter_visible);
1498 set_specifier_caching(Vgutter_visible_p[RIGHT_GUTTER],
1499 offsetof(struct window,
1500 gutter_visible_p[RIGHT_GUTTER]),
1501 right_gutter_specs_changed, 0, 0, 0);
1503 /* initially, top inherits from default; this can be
1504 changed with `set-default-gutter-position'. */
1505 fb = list1(Fcons(Qnil, Qt));
1506 set_specifier_fallback(Vdefault_gutter_visible_p, fb);
1507 set_specifier_fallback(Vgutter_visible_p[TOP_GUTTER],
1508 Vdefault_gutter_visible_p);
1509 set_specifier_fallback(Vgutter_visible_p[BOTTOM_GUTTER], fb);
1510 set_specifier_fallback(Vgutter_visible_p[LEFT_GUTTER], fb);
1511 set_specifier_fallback(Vgutter_visible_p[RIGHT_GUTTER], fb);