This commit was manufactured by cvs2svn to create branch 'XEmacs-21_4'.
[chise/xemacs-chise.git.1] / src / gutter.c
1 /* Gutter implementation.
2    Copyright (C) 1999, 2000 Andy Piper.
3
4 This file is part of XEmacs.
5
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING.  If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21 /* Synched up with: Not in FSF. */
22
23 /* written by Andy Piper <andy@xemacs.org> with specifiers partially
24    ripped-off from toolbar.c */
25
26 #include <config.h>
27 #include "lisp.h"
28
29 #include "buffer.h"
30 #include "frame.h"
31 #include "device.h"
32 #include "faces.h"
33 #include "glyphs.h"
34 #include "redisplay.h"
35 #include "window.h"
36 #include "gutter.h"
37
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];
42
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;
46
47 Lisp_Object Vdefault_gutter_position;
48
49 Lisp_Object Qgutter_size;
50 Lisp_Object Qgutter_visible;
51 Lisp_Object Qdefault_gutter_position_changed_hook;
52
53 static void
54 update_gutter_geometry (struct frame *f, enum gutter_pos pos);
55
56 #define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag)   \
57   do {                                                  \
58     switch (pos)                                        \
59       {                                                 \
60       case TOP_GUTTER:                                  \
61         (frame)->top_gutter_was_visible = flag;         \
62         break;                                          \
63       case BOTTOM_GUTTER:                               \
64         (frame)->bottom_gutter_was_visible = flag;      \
65         break;                                          \
66       case LEFT_GUTTER:                                 \
67         (frame)->left_gutter_was_visible = flag;        \
68         break;                                          \
69       case RIGHT_GUTTER:                                \
70         (frame)->right_gutter_was_visible = flag;       \
71         break;                                          \
72       default:                                          \
73         abort ();                                       \
74       }                                                 \
75   } while (0)
76
77 static int gutter_was_visible (struct frame* frame, enum gutter_pos pos)
78 {
79   switch (pos)
80     {
81     case TOP_GUTTER:
82       return frame->top_gutter_was_visible;
83     case BOTTOM_GUTTER:
84       return frame->bottom_gutter_was_visible;
85     case LEFT_GUTTER:
86       return frame->left_gutter_was_visible;
87     case RIGHT_GUTTER:
88       return frame->right_gutter_was_visible;
89     default:
90       abort ();
91         return 0;       /* To keep the compiler happy */
92     }
93 }
94
95 #if 0
96 static Lisp_Object
97 frame_topmost_window (struct frame *f)
98 {
99   Lisp_Object w = FRAME_ROOT_WINDOW (f);
100
101   do {
102     while (!NILP (XWINDOW (w)->vchild))
103       {
104         w = XWINDOW (w)->vchild;
105       }
106   } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild));
107
108   return w;
109 }
110 #endif
111
112 static Lisp_Object
113 frame_bottommost_window (struct frame *f)
114 {
115   Lisp_Object w = FRAME_ROOT_WINDOW (f);
116
117   do {
118     while (!NILP (XWINDOW (w)->vchild))
119       {
120         w = XWINDOW (w)->vchild;
121         while (!NILP (XWINDOW (w)->next))
122           {
123             w = XWINDOW (w)->next;
124           }
125       }
126   } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild));
127
128   return w;
129 }
130
131 #if 0
132 static Lisp_Object
133 frame_leftmost_window (struct frame *f)
134 {
135   Lisp_Object w = FRAME_ROOT_WINDOW (f);
136
137   do {
138     while (!NILP (XWINDOW (w)->hchild))
139       {
140         w = XWINDOW (w)->hchild;
141       }
142   } while (!NILP (XWINDOW (w)->vchild) && !NILP (w = XWINDOW (w)->vchild));
143
144   return w;
145 }
146
147 static Lisp_Object
148 frame_rightmost_window (struct frame *f)
149 {
150   Lisp_Object w = FRAME_ROOT_WINDOW (f);
151
152   do {
153     while (!NILP (XWINDOW (w)->hchild))
154       {
155         w = XWINDOW (w)->hchild;
156         while (!NILP (XWINDOW (w)->next))
157           {
158             w = XWINDOW (w)->next;
159           }
160       }
161   } while (!NILP (XWINDOW (w)->vchild) && !NILP (w = XWINDOW (w)->vchild));
162   return w;
163 }
164 #endif
165
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.*/
173 static void
174 get_gutter_coords (struct frame *f, enum gutter_pos pos, int *x, int *y,
175                    int *width, int *height)
176 {
177   struct window
178     * bot = XWINDOW (frame_bottommost_window (f));
179   /* The top and bottom gutters take precedence over the left and
180      right. */
181   switch (pos)
182     {
183     case TOP_GUTTER:
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);
189       break;
190
191     case BOTTOM_GUTTER:
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);
197       break;
198
199     case LEFT_GUTTER:
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));
205       break;
206
207     case RIGHT_GUTTER:
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));
214       break;
215
216     default:
217       abort ();
218     }
219 }
220
221 /*
222  display_boxes_in_gutter_p
223
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)
231 {
232   enum gutter_pos pos;
233   GUTTER_POS_LOOP (pos)
234     {
235       if (FRAME_GUTTER_VISIBLE (f, pos))
236         {
237           int x, y, width, height;
238           get_gutter_coords (f, pos, &x, &y, &width, &height);
239           if (db->xpos + dga->xoffset >= x
240               &&
241               db->ypos + dga->yoffset >= y
242               &&
243               db->xpos + dga->xoffset + dga->width <= x + width
244               &&
245               db->ypos + dga->yoffset + dga->height <= y + height)
246             return 1;
247           else if (db->xpos >= x && db->ypos >= y
248                    && db->xpos + db->width <= x + width
249                    && db->ypos + db->height <= y + height)
250             return 0;
251         }
252     }
253   return -1;
254 }
255
256 /* Convert the gutter specifier into something we can actually
257    display. */
258 static Lisp_Object construct_window_gutter_spec (struct window* w,
259                                                  enum gutter_pos pos)
260 {
261   Lisp_Object rest, *args;
262   int nargs = 0;
263   Lisp_Object gutter = RAW_WINDOW_GUTTER (w, pos);
264
265   if (STRINGP (gutter) || NILP (gutter))
266     return gutter;
267
268   GET_LIST_LENGTH (gutter, nargs);
269   args = alloca_array (Lisp_Object, nargs >> 1);
270   nargs = 0;
271
272   for (rest = gutter; !NILP (rest); rest = XCDR (XCDR (rest)))
273     {
274       /* We only put things in the real gutter that are declared to be
275          visible. */
276       if (!CONSP (WINDOW_GUTTER_VISIBLE (w, pos))
277           ||
278           !NILP (Fmemq (XCAR (rest), WINDOW_GUTTER_VISIBLE (w, pos))))
279         {
280           args [nargs++] = XCAR (XCDR (rest));
281         }
282     }
283
284   return Fconcat (nargs, args);
285 }
286
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. */
290 static int
291 calculate_gutter_size_from_display_lines (enum gutter_pos pos,
292                                           display_line_dynarr* ddla)
293 {
294   int size = 0;
295   struct display_line *dl;
296
297   /* For top and bottom the calculation is easy. */
298   if (pos == TOP_GUTTER || pos == BOTTOM_GUTTER)
299     {
300       /* grab coordinates of last line  */
301       if (Dynarr_length (ddla))
302         {
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);
306         }
307     }
308   /* For left and right we have to do some maths. */
309   else
310     {
311       int start_pos = 0, end_pos = 0, line;
312       for (line = 0; line < Dynarr_length (ddla); line++)
313         {
314           int block;
315           dl = Dynarr_atp (ddla, line);
316
317           for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
318             {
319               struct display_block *db = Dynarr_atp (dl->display_blocks, block);
320
321               if (db->type == TEXT)
322                 {
323                   start_pos = min (db->start_pos, start_pos);
324                   end_pos = max (db->end_pos, end_pos);
325                 }
326             }
327         }
328       size = end_pos - start_pos;
329     }
330
331   return size;
332 }
333
334 static Lisp_Object
335 calculate_gutter_size (struct window *w, enum gutter_pos pos)
336 {
337   struct frame* f = XFRAME (WINDOW_FRAME (w));
338   int count;
339   display_line_dynarr* ddla;
340   Lisp_Object ret = Qnil;
341
342   /* degenerate case */
343   if (NILP (RAW_WINDOW_GUTTER (w, pos))
344       ||
345       !FRAME_VISIBLE_P (f)
346       ||
347       NILP (w->buffer))
348     return Qnil;
349
350   /* Redisplay code that we use relies on GC not happening. Make it
351      so. */
352   count = specpdl_depth ();
353   record_unwind_protect (restore_gc_inhibit,
354                          make_int (gc_currently_forbidden));
355   gc_currently_forbidden = 1;
356
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),
366                              ddla, 0, 0);
367
368   /* Let GC happen again. */
369   unbind_to (count, Qnil);
370
371   ret = make_int (calculate_gutter_size_from_display_lines (pos, ddla));
372   free_display_lines (ddla);
373
374   return ret;
375 }
376
377 static void
378 output_gutter (struct frame *f, enum gutter_pos pos, int force)
379 {
380   Lisp_Object frame;
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;
386   face_index findex;
387   display_line_dynarr* ddla, *cdla;
388   struct display_line *dl = 0;
389   int cdla_len;
390
391   if (!WINDOW_LIVE_P (w))
392     return;
393
394   border_width = FRAME_GUTTER_BORDER_WIDTH (f, pos);
395   findex = get_builtin_face_cache_index (w, Vwidget_face);
396
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);
401
402   ddla = f->desired_display_lines[pos];
403   cdla = f->current_display_lines[pos];
404   cdla_len = Dynarr_length (cdla);
405
406   XSETFRAME (frame, f);
407
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);
414
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]))
425     {
426 #ifdef DEBUG_GUTTERS
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>");
440 #endif
441       /* Output each line. */
442       for (line = 0; line < Dynarr_length (ddla); line++)
443         {
444           output_display_line (w, cdla, ddla, line, -1, -1);
445         }
446
447       /* If the number of display lines has shrunk, adjust. */
448       if (cdla_len > Dynarr_length (ddla))
449         {
450           Dynarr_length (cdla) = Dynarr_length (ddla);
451         }
452
453       /* grab coordinates of last line and blank after it. */
454       if (Dynarr_length (ddla) > 0)
455         {
456           dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1);
457           ypos = dl->ypos + dl->descent - dl->clip;
458         }
459       else
460         ypos = y;
461
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) 
469           && (dl->clip > 0 ||
470               calculate_gutter_size_from_display_lines (pos, ddla) > 
471               WINDOW_GUTTER_SIZE_INTERNAL (w, pos)))
472         {
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);
487         }
488
489       /* bevel the gutter area if so desired */
490       if (border_width != 0)
491         {
492           MAYBE_DEVMETH (d, bevel_area,
493                          (w, findex, x, y, width, height, border_width,
494                           EDGE_ALL, EDGE_BEVEL_OUT));
495         }
496     }
497   else
498     {
499       /* Nothing of significance happened so sync the display line
500          structs. */
501       for (line = 0; line < Dynarr_length (ddla); line++)
502         {
503           sync_display_line_structs (w, line, 1, cdla, ddla);
504         }
505     }
506
507   w->gutter_extent_modiff [pos] = 0;
508 }
509
510 static void
511 clear_gutter (struct frame *f, enum gutter_pos pos)
512 {
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),
516                                                     Vwidget_face);
517   get_gutter_coords (f, pos, &x, &y, &width, &height);
518
519   SET_GUTTER_WAS_VISIBLE_FLAG (f, pos, 0);
520
521   redisplay_clear_region (window, findex, x, y, width, height);
522 }
523
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. */
528
529 /* See the comment in image_instantiate_cache_result as to why marking
530    the glyph will also mark the image_instance. */
531 void
532 mark_gutters (struct frame* f)
533 {
534   enum gutter_pos pos;
535   GUTTER_POS_LOOP (pos)
536     {
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]);
542     }
543 }
544
545 /* This is called by extent_changed_for_redisplay, so that redisplay
546    knows exactly what extents have changed. */
547 void
548 gutter_extent_signal_changed_region_maybe (Lisp_Object obj,
549                                            Bufpos start, Bufpos end)
550 {
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;
555
556   FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
557     {
558       struct frame *f = XFRAME (XCAR (frmcons));
559       enum gutter_pos pos;
560       Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
561       struct window* w = XWINDOW (window);
562
563       GUTTER_POS_LOOP (pos)
564         {
565           if (EQ (WINDOW_GUTTER (w, pos), obj))
566             {
567               w->gutter_extent_modiff[pos]++;
568             }
569         }
570     }
571 }
572
573 /* We have to change the gutter geometry separately to the gutter
574    update since it needs to occur outside of redisplay proper. */
575 static void
576 update_gutter_geometry (struct frame *f, enum gutter_pos pos)
577 {
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])
583     {
584       int width, height;
585       pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f),
586                           &width, &height);
587       change_frame_size (f, height, width, 0);
588     }
589
590   /* Mark sizes as up-to-date. */
591   f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos);
592 }
593
594 void
595 update_frame_gutter_geometry (struct frame *f)
596 {
597   if (f->gutter_changed || f->windows_structure_changed)
598     {
599       enum gutter_pos pos;
600
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)
606         {
607           update_gutter_geometry (f, pos);
608         }
609     }
610 }
611
612 void
613 update_frame_gutters (struct frame *f)
614 {
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 ||
619       f->extents_changed)
620     {
621       enum gutter_pos pos;
622
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;
627       f->clip_changed = 0;
628       f->buffers_changed = 0;
629
630       /* and output */
631       GUTTER_POS_LOOP (pos)
632         {
633           if (FRAME_GUTTER_VISIBLE (f, pos))
634               output_gutter (f, pos, 0);
635
636           else if (gutter_was_visible (f, pos))
637               clear_gutter (f, pos);
638         }
639
640       f->clip_changed = local_clip_changed;
641       f->buffers_changed = local_buffers_changed;
642       f->gutter_changed = 0;
643     }
644 }
645
646 void
647 reset_gutter_display_lines (struct frame* f)
648 {
649   enum gutter_pos pos;
650   GUTTER_POS_LOOP (pos)
651     {
652       if (f->current_display_lines[pos])
653         Dynarr_reset (f->current_display_lines[pos]);
654     }
655 }
656
657 static void
658 redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y,
659                        int width, int height)
660 {
661   int g_x, g_y, g_width, g_height;
662
663   get_gutter_coords (f, pos, &g_x, &g_y, &g_width, &g_height);
664
665   if (((y + height) < g_y) || (y > (g_y + g_height)) || !height || !width || !g_height || !g_width)
666     return;
667   if (((x + width) < g_x) || (x > (g_x + g_width)))
668     return;
669
670 #ifdef DEBUG_WIDGETS
671   printf ("redrawing gutter after expose %d+%d, %dx%d\n",
672           x, y, width, height);
673 #endif
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);
678
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);
683 }
684
685 void
686 redraw_exposed_gutters (struct frame *f, int x, int y, int width,
687                         int height)
688 {
689   enum gutter_pos pos;
690
691   /* We have to be "in display" when we output the gutter - make it
692      so. */
693   hold_frame_size_changes ();
694   GUTTER_POS_LOOP (pos)
695     {
696       if (FRAME_GUTTER_VISIBLE (f, pos))
697         redraw_exposed_gutter (f, pos, x, y, width, height);
698     }
699   unhold_one_frame_size_changes (f);
700 }
701
702 void
703 free_frame_gutters (struct frame *f)
704 {
705   enum gutter_pos pos;
706   GUTTER_POS_LOOP (pos)
707     {
708       if (f->current_display_lines[pos])
709         {
710           free_display_lines (f->current_display_lines[pos]);
711           f->current_display_lines[pos] = 0;
712         }
713       if (f->desired_display_lines[pos])
714         {
715           free_display_lines (f->desired_display_lines[pos]);
716           f->desired_display_lines[pos] = 0;
717         }
718     }
719 }
720
721 static enum gutter_pos
722 decode_gutter_position (Lisp_Object position)
723 {
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);
729
730   return TOP_GUTTER; /* not reached */
731 }
732
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'.
737 */
738        (position))
739 {
740   enum gutter_pos cur = decode_gutter_position (Vdefault_gutter_position);
741   enum gutter_pos new = decode_gutter_position (position);
742
743   if (cur != new)
744     {
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);
763
764       Vdefault_gutter_position = position;
765       unhold_frame_size_changes ();
766     }
767
768   run_hook (Qdefault_gutter_position_changed_hook);
769
770   return position;
771 }
772
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.
777 */
778        ())
779 {
780   return Vdefault_gutter_position;
781 }
782
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
786 the current window.
787 */
788        (pos, locale))
789 {
790   int x, y, width, height;
791   enum gutter_pos p = TOP_GUTTER;
792   struct frame *f = decode_frame (FW_FRAME (locale));
793
794   if (NILP (pos))
795     pos = Vdefault_gutter_position;
796   p = decode_gutter_position (pos);
797
798   get_gutter_coords (f, p, &x, &y, &width, &height);
799   width -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2);
800
801   return make_int (width);
802 }
803
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
807 the current window.
808 */
809        (pos, locale))
810 {
811   int x, y, width, height;
812   enum gutter_pos p = TOP_GUTTER;
813   struct frame *f = decode_frame (FW_FRAME (locale));
814
815   if (NILP (pos))
816     pos = Vdefault_gutter_position;
817   p = decode_gutter_position (pos);
818
819   get_gutter_coords (f, p, &x, &y, &width, &height);
820   height -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2);
821
822   return make_int (height);
823 }
824
825 DEFINE_SPECIFIER_TYPE (gutter);
826
827 static void
828 gutter_after_change (Lisp_Object specifier, Lisp_Object locale)
829 {
830   MARK_GUTTER_CHANGED;
831 }
832
833 static void
834 gutter_validate (Lisp_Object instantiator)
835 {
836   if (NILP (instantiator))
837     return;
838
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);
842
843   if (!STRINGP (instantiator))
844     {
845       Lisp_Object rest;
846
847       for (rest = instantiator; !NILP (rest); rest = XCDR (XCDR (rest)))
848         {
849           if (!SYMBOLP (XCAR (rest))
850               || !STRINGP (XCAR (XCDR (rest))))
851             signal_simple_error ("Gutter plist spec must contain strings", instantiator);
852         }
853     }
854 }
855
856 DEFUN ("gutter-specifier-p", Fgutter_specifier_p, 1, 1, 0, /*
857 Return non-nil if OBJECT is a gutter specifier.
858
859 See `make-gutter-specifier' for a description of possible gutter
860 instantiators.
861 */
862        (object))
863 {
864   return GUTTER_SPECIFIERP (object) ? Qt : Qnil;
865 }
866
867 \f
868 /*
869   Helper for invalidating the real specifier when default
870   specifier caching changes
871 */
872 static void
873 recompute_overlaying_specifier (Lisp_Object real_one[4])
874 {
875   enum gutter_pos pos = decode_gutter_position (Vdefault_gutter_position);
876   Fset_specifier_dirty_flag (real_one[pos]);
877 }
878
879 static void
880 gutter_specs_changed (Lisp_Object specifier, struct window *w,
881                        Lisp_Object oldval, enum gutter_pos pos)
882 {
883   w->real_gutter[pos] = construct_window_gutter_spec (w, pos);
884   w->real_gutter_size[pos] = w->gutter_size[pos];
885
886   if (EQ (w->real_gutter_size[pos], Qautodetect)
887       && !NILP (w->gutter_visible_p[pos]))
888     {
889       w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
890     }
891   MARK_GUTTER_CHANGED;
892   MARK_MODELINE_CHANGED;
893   MARK_WINDOWS_CHANGED (w);
894 }
895
896 /* We define all of these so we can access which actual gutter changed. */
897 static void
898 top_gutter_specs_changed (Lisp_Object specifier, struct window *w,
899                           Lisp_Object oldval)
900 {
901   gutter_specs_changed (specifier, w, oldval, TOP_GUTTER);
902 }
903
904 static void
905 bottom_gutter_specs_changed (Lisp_Object specifier, struct window *w,
906                              Lisp_Object oldval)
907 {
908   gutter_specs_changed (specifier, w, oldval, BOTTOM_GUTTER);
909 }
910
911 static void
912 left_gutter_specs_changed (Lisp_Object specifier, struct window *w,
913                            Lisp_Object oldval)
914 {
915   gutter_specs_changed (specifier, w, oldval, LEFT_GUTTER);
916 }
917
918 static void
919 right_gutter_specs_changed (Lisp_Object specifier, struct window *w,
920                             Lisp_Object oldval)
921 {
922   gutter_specs_changed (specifier, w, oldval, RIGHT_GUTTER);
923 }
924
925 static void
926 default_gutter_specs_changed (Lisp_Object specifier, struct window *w,
927                                Lisp_Object oldval)
928 {
929   recompute_overlaying_specifier (Vgutter);
930 }
931
932 static void
933 gutter_geometry_changed_in_window (Lisp_Object specifier, struct window *w,
934                                     Lisp_Object oldval)
935 {
936   enum gutter_pos pos;
937   GUTTER_POS_LOOP (pos)
938     {
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]))
942         {
943           w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
944         }
945     }
946
947   MARK_GUTTER_CHANGED;
948   MARK_MODELINE_CHANGED;
949   MARK_WINDOWS_CHANGED (w);
950 }
951
952 static void
953 default_gutter_size_changed_in_window (Lisp_Object specifier, struct window *w,
954                                         Lisp_Object oldval)
955 {
956   recompute_overlaying_specifier (Vgutter_size);
957 }
958
959 static void
960 default_gutter_border_width_changed_in_window (Lisp_Object specifier,
961                                                 struct window *w,
962                                                 Lisp_Object oldval)
963 {
964   recompute_overlaying_specifier (Vgutter_border_width);
965 }
966
967 static void
968 default_gutter_visible_p_changed_in_window (Lisp_Object specifier,
969                                              struct window *w,
970                                              Lisp_Object oldval)
971 {
972   recompute_overlaying_specifier (Vgutter_visible_p);
973   /* Need to reconstruct the gutter specifier as it is affected by the
974      visibility. */
975   recompute_overlaying_specifier (Vgutter);
976 }
977
978
979 DECLARE_SPECIFIER_TYPE (gutter_size);
980 #define GUTTER_SIZE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_size)
981 DEFINE_SPECIFIER_TYPE (gutter_size);
982
983 static void
984 gutter_size_validate (Lisp_Object instantiator)
985 {
986   if (NILP (instantiator))
987     return;
988
989   if (!INTP (instantiator) && !EQ (instantiator, Qautodetect))
990     signal_simple_error ("Gutter size must be an integer or 'autodetect", instantiator);
991 }
992
993 DEFUN ("gutter-size-specifier-p", Fgutter_size_specifier_p, 1, 1, 0, /*
994 Return non-nil if OBJECT is a gutter-size specifier.
995
996 See `make-gutter-size-specifier' for a description of possible gutter-size
997 instantiators.
998 */
999        (object))
1000 {
1001   return GUTTER_SIZE_SPECIFIERP (object) ? Qt : Qnil;
1002 }
1003
1004 DECLARE_SPECIFIER_TYPE (gutter_visible);
1005 #define GUTTER_VISIBLE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_visible)
1006 DEFINE_SPECIFIER_TYPE (gutter_visible);
1007
1008 static void
1009 gutter_visible_validate (Lisp_Object instantiator)
1010 {
1011   if (NILP (instantiator))
1012     return;
1013
1014   if (!NILP (instantiator) && !EQ (instantiator, Qt) && !CONSP (instantiator))
1015     signal_simple_error ("Gutter visibility must be a boolean or list of symbols",
1016                          instantiator);
1017
1018   if (CONSP (instantiator))
1019     {
1020       Lisp_Object rest;
1021
1022       EXTERNAL_LIST_LOOP (rest, instantiator)
1023         {
1024           if (!SYMBOLP (XCAR (rest)))
1025               signal_simple_error ("Gutter visibility must be a boolean or list of symbols",
1026                                    instantiator);
1027         }
1028     }
1029 }
1030
1031 DEFUN ("gutter-visible-specifier-p", Fgutter_visible_specifier_p, 1, 1, 0, /*
1032 Return non-nil if OBJECT is a gutter-visible specifier.
1033
1034 See `make-gutter-visible-specifier' for a description of possible
1035 gutter-visible instantiators.
1036 */
1037        (object))
1038 {
1039   return GUTTER_VISIBLE_SPECIFIERP (object) ? Qt : Qnil;
1040 }
1041
1042 DEFUN ("redisplay-gutter-area", Fredisplay_gutter_area, 0, 0, 0, /*
1043 Ensure that all gutters are correctly showing their gutter specifier.
1044 */
1045        ())
1046 {
1047   Lisp_Object devcons, concons;
1048
1049   DEVICE_LOOP_NO_BREAK (devcons, concons)
1050     {
1051       struct device *d = XDEVICE (XCAR (devcons));
1052       Lisp_Object frmcons;
1053
1054       DEVICE_FRAME_LOOP (frmcons, d)
1055         {
1056           struct frame *f = XFRAME (XCAR (frmcons));
1057
1058           MAYBE_DEVMETH (d, frame_output_begin, (f));
1059
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.
1064
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
1072            size changes. */
1073           update_frame_gutter_geometry (f);
1074
1075           if (f->windows_structure_changed)
1076             redisplay_frame (f, 1);
1077           else if (FRAME_REPAINT_P (f))
1078             {
1079               /* We have to be "in display" when we output the gutter
1080                  - make it so. */
1081               hold_frame_size_changes ();
1082               update_frame_gutters (f);
1083               unhold_one_frame_size_changes (f);
1084             }
1085
1086           MAYBE_DEVMETH (d, frame_output_end, (f));
1087       }
1088
1089       d->gutter_changed = 0;
1090     }
1091
1092   /* This is so that further changes to the gutters will trigger redisplay. */
1093   gutter_changed_set = 0;
1094   gutter_changed = 0;
1095
1096   return Qnil;
1097 }
1098
1099 void
1100 init_frame_gutters (struct frame *f)
1101 {
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)
1108     {
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]))
1113         {
1114           w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
1115           MARK_GUTTER_CHANGED;
1116           MARK_WINDOWS_CHANGED (w);
1117         }
1118     }
1119
1120   /* Keep a record of the current sizes of things. */
1121   GUTTER_POS_LOOP (pos)
1122     {
1123       f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos);
1124     }
1125 }
1126
1127 void
1128 syms_of_gutter (void)
1129 {
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);
1138
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");
1143 }
1144
1145 void
1146 vars_of_gutter (void)
1147 {
1148   staticpro (&Vdefault_gutter_position);
1149   Vdefault_gutter_position = Qtop;
1150
1151   Fprovide (Qgutter);
1152 }
1153
1154 void
1155 specifier_type_create_gutter (void)
1156 {
1157   INITIALIZE_SPECIFIER_TYPE (gutter, "gutter", "gutter-specifier-p");
1158   SPECIFIER_HAS_METHOD (gutter, validate);
1159   SPECIFIER_HAS_METHOD (gutter, after_change);
1160
1161   INITIALIZE_SPECIFIER_TYPE (gutter_size, "gutter-size", "gutter-size-specifier-p");
1162   SPECIFIER_HAS_METHOD (gutter_size, validate);
1163
1164   INITIALIZE_SPECIFIER_TYPE (gutter_visible, "gutter-visible", "gutter-visible-specifier-p");
1165   SPECIFIER_HAS_METHOD (gutter_visible, validate);
1166 }
1167
1168 void
1169 reinit_specifier_type_create_gutter (void)
1170 {
1171   REINITIALIZE_SPECIFIER_TYPE (gutter);
1172   REINITIALIZE_SPECIFIER_TYPE (gutter_size);
1173   REINITIALIZE_SPECIFIER_TYPE (gutter_visible);
1174 }
1175
1176 void
1177 specifier_vars_of_gutter (void)
1178 {
1179   Lisp_Object fb;
1180
1181   DEFVAR_SPECIFIER ("default-gutter", &Vdefault_gutter /*
1182 Specifier for a fallback gutter.
1183 Use `set-specifier' to change this.
1184
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
1190 used instead.
1191
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'.
1200
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')
1206 mentioned above.
1207
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.
1213
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.  */ );
1219
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,
1227                          0, 0, 1);
1228
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.
1234 */ );
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,
1239                          0, 0, 1);
1240
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.
1246
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'.
1251 */ );
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,
1256                          0, 0, 1);
1257
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.
1263
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'.
1268 */ );
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,
1273                          0, 0, 1);
1274
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.
1280
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'.
1285 */ );
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,
1290                          0, 0, 1);
1291
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);
1300
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.
1304
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.
1312
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.
1316
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.
1321
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
1324 is the default.
1325 */ );
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,
1330                          0, 0, 1);
1331
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.
1335
1336 See `default-gutter-height' for more information.
1337 */ );
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,
1342                          0, 0, 1);
1343
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.
1348
1349 See `default-gutter-height' for more information.
1350 */ );
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);
1355
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.
1360
1361 See `default-gutter-height' for more information.
1362 */ );
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);
1367
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.
1372
1373 See `default-gutter-height' for more information.
1374 */ );
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);
1379
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.
1384
1385 See `default-gutter-height' for more information.
1386 */ );
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);
1391
1392   fb = Qnil;
1393 #ifdef HAVE_TTY
1394   fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb);
1395 #endif
1396 #ifdef HAVE_X_WINDOWS
1397   fb = Fcons (Fcons (list1 (Qx), Qautodetect), fb);
1398 #endif
1399 #ifdef HAVE_MS_WINDOWS
1400   fb = Fcons (Fcons (list1 (Qmsprinter), Qautodetect), fb);
1401   fb = Fcons (Fcons (list1 (Qmswindows), Qautodetect), fb);
1402 #endif
1403   if (!NILP (fb))
1404     set_specifier_fallback (Vdefault_gutter_height, fb);
1405
1406   fb = Qnil;
1407 #ifdef HAVE_TTY
1408   fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb);
1409 #endif
1410 #ifdef HAVE_X_WINDOWS
1411   fb = Fcons (Fcons (list1 (Qx), Qautodetect), fb);
1412 #endif
1413 #ifdef HAVE_MS_WINDOWS
1414   fb = Fcons (Fcons (list1 (Qmsprinter), Qautodetect), fb);
1415   fb = Fcons (Fcons (list1 (Qmswindows), Qautodetect), fb);
1416 #endif
1417   if (!NILP (fb))
1418     set_specifier_fallback (Vdefault_gutter_width, fb);
1419
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);
1425
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.
1430
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
1437 instead.
1438
1439 */ );
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,
1444                          0, 0, 0);
1445
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.
1450
1451 See `default-gutter-height' for more information.
1452 */ );
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);
1458
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.
1463
1464 See `default-gutter-height' for more information.
1465 */ );
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);
1471
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.
1476
1477 See `default-gutter-height' for more information.
1478 */ );
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);
1484
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.
1489
1490 See `default-gutter-height' for more information.
1491 */ );
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);
1497
1498   fb = Qnil;
1499 #ifdef HAVE_TTY
1500   fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
1501 #endif
1502 #ifdef HAVE_X_WINDOWS
1503   fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_GUTTER_BORDER_WIDTH)), fb);
1504 #endif
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);
1508 #endif
1509   if (!NILP (fb))
1510     set_specifier_fallback (Vdefault_gutter_border_width, fb);
1511
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);
1517
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.
1521
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
1528 instead.
1529
1530 `default-gutter-visible-p' and all of the position-specific gutter
1531 visibility specifiers have a fallback value of true.
1532 */ );
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,
1538                          0, 0, 0);
1539
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.
1544
1545 See `default-gutter-visible-p' for more information.
1546 */ );
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);
1552
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.
1557
1558 See `default-gutter-visible-p' for more information.
1559 */ );
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);
1565
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.
1570
1571 See `default-gutter-visible-p' for more information.
1572 */ );
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);
1578
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.
1583
1584 See `default-gutter-visible-p' for more information.
1585 */ );
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);
1591
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);
1601 }