comparison src/gutter.c @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents 8de8e3f6228a
children 576fb035e263
comparison
equal deleted inserted replaced
441:72a7cfa4a488 442:abe6d1db359e
1 /* Gutter implementation. 1 /* Gutter implementation.
2 Copyright (C) 1999 Andy Piper. 2 Copyright (C) 1999, 2000 Andy Piper.
3 3
4 This file is part of XEmacs. 4 This file is part of XEmacs.
5 5
6 XEmacs is free software; you can redistribute it and/or modify it 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 7 under the terms of the GNU General Public License as published by the
45 Lisp_Object Vdefault_gutter_border_width; 45 Lisp_Object Vdefault_gutter_border_width;
46 46
47 Lisp_Object Vdefault_gutter_position; 47 Lisp_Object Vdefault_gutter_position;
48 48
49 Lisp_Object Qgutter_size; 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);
50 55
51 #define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag) \ 56 #define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag) \
52 do { \ 57 do { \
53 switch (pos) \ 58 switch (pos) \
54 { \ 59 { \
81 return frame->left_gutter_was_visible; 86 return frame->left_gutter_was_visible;
82 case RIGHT_GUTTER: 87 case RIGHT_GUTTER:
83 return frame->right_gutter_was_visible; 88 return frame->right_gutter_was_visible;
84 default: 89 default:
85 abort (); 90 abort ();
86 } 91 return 0; /* To keep the compiler happy */
87 } 92 }
88 93 }
94
95 #if 0
89 static Lisp_Object 96 static Lisp_Object
90 frame_topmost_window (struct frame *f) 97 frame_topmost_window (struct frame *f)
91 { 98 {
92 Lisp_Object w = FRAME_ROOT_WINDOW (f); 99 Lisp_Object w = FRAME_ROOT_WINDOW (f);
93 100
98 } 105 }
99 } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild)); 106 } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild));
100 107
101 return w; 108 return w;
102 } 109 }
110 #endif
103 111
104 static Lisp_Object 112 static Lisp_Object
105 frame_bottommost_window (struct frame *f) 113 frame_bottommost_window (struct frame *f)
106 { 114 {
107 Lisp_Object w = FRAME_ROOT_WINDOW (f); 115 Lisp_Object w = FRAME_ROOT_WINDOW (f);
165 static void 173 static void
166 get_gutter_coords (struct frame *f, enum gutter_pos pos, int *x, int *y, 174 get_gutter_coords (struct frame *f, enum gutter_pos pos, int *x, int *y,
167 int *width, int *height) 175 int *width, int *height)
168 { 176 {
169 struct window 177 struct window
170 * top = XWINDOW (frame_topmost_window (f)),
171 * bot = XWINDOW (frame_bottommost_window (f)); 178 * bot = XWINDOW (frame_bottommost_window (f));
172 /* The top and bottom gutters take precedence over the left and 179 /* The top and bottom gutters take precedence over the left and
173 right. */ 180 right. */
174 switch (pos) 181 switch (pos)
175 { 182 {
176 case TOP_GUTTER: 183 case TOP_GUTTER:
177 *x = FRAME_LEFT_BORDER_END (f); 184 *x = FRAME_LEFT_BORDER_END (f);
178 *y = FRAME_TOP_BORDER_END (f); 185 *y = FRAME_TOP_BORDER_END (f);
179 *width = FRAME_RIGHT_BORDER_START (f) 186 *width = FRAME_RIGHT_BORDER_START (f)
180 - FRAME_LEFT_BORDER_END (f); 187 - FRAME_LEFT_BORDER_END (f);
181 *height = FRAME_TOP_GUTTER_BOUNDS (f); 188 *height = FRAME_TOP_GUTTER_BOUNDS (f);
182 break; 189 break;
183 190
184 case BOTTOM_GUTTER: 191 case BOTTOM_GUTTER:
185 *x = FRAME_LEFT_BORDER_END (f); 192 *x = FRAME_LEFT_BORDER_END (f);
186 *y = WINDOW_BOTTOM (bot) 193 *y = WINDOW_BOTTOM (bot);
187 - FRAME_BOTTOM_GUTTER_BOUNDS (f); 194 *width = FRAME_RIGHT_BORDER_START (f)
188 *width = FRAME_RIGHT_BORDER_START (f)
189 - FRAME_LEFT_BORDER_END (f); 195 - FRAME_LEFT_BORDER_END (f);
190 *height = FRAME_BOTTOM_GUTTER_BOUNDS (f); 196 *height = FRAME_BOTTOM_GUTTER_BOUNDS (f);
191 break; 197 break;
192 198
193 case LEFT_GUTTER: 199 case LEFT_GUTTER:
194 *x = FRAME_LEFT_BORDER_END (f); 200 *x = FRAME_LEFT_BORDER_END (f);
195 *y = WINDOW_TEXT_TOP (top); 201 *y = FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f);
196 *width = FRAME_LEFT_GUTTER_BOUNDS (f); 202 *width = FRAME_LEFT_GUTTER_BOUNDS (f);
197 *height = WINDOW_BOTTOM (bot) 203 *height = WINDOW_BOTTOM (bot)
198 - (WINDOW_TEXT_TOP (top) 204 - (FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f));
199 + FRAME_BOTTOM_GUTTER_BOUNDS (f));
200 break; 205 break;
201 206
202 case RIGHT_GUTTER: 207 case RIGHT_GUTTER:
203 *x = FRAME_RIGHT_BORDER_START (f) 208 *x = FRAME_RIGHT_BORDER_START (f)
204 - FRAME_RIGHT_GUTTER_BOUNDS (f); 209 - FRAME_RIGHT_GUTTER_BOUNDS (f);
205 *y = WINDOW_TEXT_TOP (top); 210 *y = FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f);
206 *width = FRAME_RIGHT_GUTTER_BOUNDS (f); 211 *width = FRAME_RIGHT_GUTTER_BOUNDS (f);
207 *height = WINDOW_BOTTOM (bot) 212 *height = WINDOW_BOTTOM (bot)
208 - (WINDOW_TEXT_TOP (top) 213 - (FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f));
209 + FRAME_BOTTOM_GUTTER_BOUNDS (f));
210 break; 214 break;
211 215
212 default: 216 default:
213 abort (); 217 abort ();
214 } 218 }
215 } 219 }
216 220
217 static void 221 /* Convert the gutter specifier into something we can actually
218 output_gutter (struct frame *f, enum gutter_pos pos) 222 display. */
223 static Lisp_Object construct_window_gutter_spec (struct window* w,
224 enum gutter_pos pos)
225 {
226 Lisp_Object rest, *args;
227 int nargs = 0;
228 Lisp_Object gutter = RAW_WINDOW_GUTTER (w, pos);
229
230 if (STRINGP (gutter) || NILP (gutter))
231 return gutter;
232
233 GET_LIST_LENGTH (gutter, nargs);
234 args = alloca_array (Lisp_Object, nargs >> 1);
235 nargs = 0;
236
237 for (rest = gutter; !NILP (rest); rest = XCDR (XCDR (rest)))
238 {
239 /* We only put things in the real gutter that are declared to be
240 visible. */
241 if (!CONSP (WINDOW_GUTTER_VISIBLE (w, pos))
242 ||
243 !NILP (Fmemq (XCAR (rest), WINDOW_GUTTER_VISIBLE (w, pos))))
244 {
245 args [nargs++] = XCAR (XCDR (rest));
246 }
247 }
248
249 return Fconcat (nargs, args);
250 }
251
252 static void
253 output_gutter (struct frame *f, enum gutter_pos pos, int force)
219 { 254 {
220 Lisp_Object frame; 255 Lisp_Object frame;
221 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); 256 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
222 struct device *d = XDEVICE (f->device); 257 struct device *d = XDEVICE (f->device);
223 struct window* w = XWINDOW (window); 258 struct window* w = XWINDOW (window);
224 int x, y, width, height, ypos; 259 int x, y, width, height, ypos;
225 int line, border_width; 260 int line, border_width;
226 face_index findex; 261 face_index findex;
227 display_line_dynarr* ddla, *cdla; 262 display_line_dynarr* ddla, *cdla;
228 struct display_line *dl; 263 struct display_line *dl = 0;
229 int cdla_len; 264 int cdla_len;
230 265
231 if (!WINDOW_LIVE_P (w)) 266 if (!WINDOW_LIVE_P (w))
232 return; 267 return;
233 268
234 border_width = FRAME_GUTTER_BORDER_WIDTH (f, pos); 269 border_width = FRAME_GUTTER_BORDER_WIDTH (f, pos);
235 findex = get_builtin_face_cache_index (w, Vgui_element_face); 270 findex = get_builtin_face_cache_index (w, Vwidget_face);
236 271
237 if (!f->current_display_lines) 272 if (!f->current_display_lines[pos])
238 f->current_display_lines = Dynarr_new (display_line); 273 f->current_display_lines[pos] = Dynarr_new (display_line);
239 if (!f->desired_display_lines) 274 if (!f->desired_display_lines[pos])
240 f->desired_display_lines = Dynarr_new (display_line); 275 f->desired_display_lines[pos] = Dynarr_new (display_line);
241 276
242 ddla = f->desired_display_lines; 277 ddla = f->desired_display_lines[pos];
243 cdla = f->current_display_lines; 278 cdla = f->current_display_lines[pos];
244 cdla_len = Dynarr_length (cdla); 279 cdla_len = Dynarr_length (cdla);
245 280
246 XSETFRAME (frame, f); 281 XSETFRAME (frame, f);
247 282
248 get_gutter_coords (f, pos, &x, &y, &width, &height); 283 get_gutter_coords (f, pos, &x, &y, &width, &height);
249 /* generate some display lines */ 284 /* generate some display lines */
250 generate_displayable_area (w, WINDOW_GUTTER (w, pos), 285 generate_displayable_area (w, WINDOW_GUTTER (w, pos),
251 x + border_width, y + border_width, 286 x + border_width, y + border_width,
252 width - 2 * border_width, 287 width - 2 * border_width,
253 height - 2 * border_width, ddla, 0, findex); 288 height - 2 * border_width, ddla, 0, findex);
254 /* Output each line. */ 289
255 for (line = 0; line < Dynarr_length (ddla); line++) 290 /* We only output the gutter if we think something of significance
256 { 291 has changed. This is, for example, because redisplay can cause
257 output_display_line (w, cdla, ddla, line, -1, -1); 292 new face cache elements to get added causing compare_runes to
258 } 293 fail because the findex for a particular face has changed. */
259 294 if (force || f->faces_changed || f->frame_changed ||
260 /* If the number of display lines has shrunk, adjust. */ 295 f->gutter_changed || f->glyphs_changed ||
261 if (cdla_len > Dynarr_length (ddla)) 296 f->size_changed || f->subwindows_changed ||
262 { 297 w->windows_changed || f->windows_structure_changed ||
263 Dynarr_length (cdla) = Dynarr_length (ddla); 298 cdla_len != Dynarr_length (ddla) ||
264 } 299 (f->extents_changed && w->gutter_extent_modiff[pos]))
265 300 {
266 /* grab coordinates of last line and blank after it. */ 301 #ifdef DEBUG_GUTTERS
267 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); 302 printf ("gutter redisplay triggered by %s\n", force ? "force" :
268 ypos = dl->ypos + dl->descent - dl->clip; 303 f->faces_changed ? "f->faces_changed" :
269 redisplay_clear_region (window, findex, x + border_width , ypos, 304 f->frame_changed ? "f->frame_changed" :
270 width - 2 * border_width, height - (ypos - y) - border_width); 305 f->gutter_changed ? "f->gutter_changed" :
271 /* bevel the gutter area if so desired */ 306 f->glyphs_changed ? "f->glyphs_changed" :
272 if (border_width != 0) 307 f->size_changed ? "f->size_changed" :
273 { 308 f->subwindows_changed ? "f->subwindows_changed" :
274 MAYBE_DEVMETH (d, bevel_area, 309 w->windows_changed ? "w->windows_changed" :
275 (w, findex, x, y, width, height, border_width, 310 f->windows_structure_changed ? "f->windows_structure_changed" :
276 EDGE_ALL, EDGE_BEVEL_OUT)); 311 cdla_len != Dynarr_length (ddla) ? "different display structures" :
277 } 312 f->extents_changed && w->gutter_extent_modiff[pos] ?
278 } 313 "f->extents_changed && w->gutter_extent_modiff[pos]" : "<null>");
279 314 #endif
280 /* sizing gutters is a pain so we try and help the user by detemining 315 /* Output each line. */
316 for (line = 0; line < Dynarr_length (ddla); line++)
317 {
318 output_display_line (w, cdla, ddla, line, -1, -1);
319 }
320
321 /* If the number of display lines has shrunk, adjust. */
322 if (cdla_len > Dynarr_length (ddla))
323 {
324 Dynarr_length (cdla) = Dynarr_length (ddla);
325 }
326
327 /* grab coordinates of last line and blank after it. */
328 if (Dynarr_length (ddla) > 0)
329 {
330 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1);
331 ypos = dl->ypos + dl->descent - dl->clip;
332 }
333 else
334 ypos = y;
335
336 redisplay_clear_region (window, findex, x + border_width , ypos,
337 width - 2 * border_width, height - (ypos - y) - border_width);
338 /* If, for some reason, we have more to display than we have
339 room for, and we are allowed to resize the gutter, then make
340 sure this happens before the next time we try and
341 output. This can happen when face font sizes change. */
342 if (dl && dl->clip > 0 && EQ (w->gutter_size[pos], Qautodetect))
343 {
344 /* #### Ideally we would just mark the specifier as dirty
345 and everything else would "just work". Unfortunately we have
346 two problems with this. One is that the specifier cache
347 won't be recalculated unless the specifier code thinks the
348 cached value has actually changed, even though we have
349 marked the specifier as dirty. Additionally, although doing
350 this results in a gutter size change, we never seem to get
351 back into redisplay so that the frame size can be updated. I
352 think this is because we are already in redisplay and later
353 on the frame will be marked as clean. Thus we also have to
354 force a pending recalculation of the frame size. */
355 w->gutter_size[pos] = Qnil;
356 Fset_specifier_dirty_flag (Vgutter_size[pos]);
357 update_gutter_geometry (f, pos);
358 }
359
360 /* bevel the gutter area if so desired */
361 if (border_width != 0)
362 {
363 MAYBE_DEVMETH (d, bevel_area,
364 (w, findex, x, y, width, height, border_width,
365 EDGE_ALL, EDGE_BEVEL_OUT));
366 }
367 }
368 else
369 {
370 /* Nothing of significance happened so sync the display line
371 structs. */
372 for (line = 0; line < Dynarr_length (ddla); line++)
373 {
374 sync_display_line_structs (w, line, 1, cdla, ddla);
375 }
376 }
377
378 w->gutter_extent_modiff [pos] = 0;
379 }
380
381 /* Sizing gutters is a pain so we try and help the user by determining
281 what height will accommodate all lines. This is useless on left and 382 what height will accommodate all lines. This is useless on left and
282 right gutters as we always have a maximal number of lines. */ 383 right gutters as we always have a maximal number of lines. */
283 static Lisp_Object 384 static Lisp_Object
284 calculate_gutter_size (struct window *w, enum gutter_pos pos) 385 calculate_gutter_size (struct window *w, enum gutter_pos pos)
285 { 386 {
286 struct frame* f = XFRAME (WINDOW_FRAME (w)); 387 struct frame* f = XFRAME (WINDOW_FRAME (w));
287 int ypos; 388 int ypos, count;
288 display_line_dynarr* ddla; 389 display_line_dynarr* ddla;
289 struct display_line *dl; 390 struct display_line *dl;
290 391
291 /* we cannot autodetect gutter sizes for the left and right as there 392 /* we cannot autodetect gutter sizes for the left and right as there
292 is no reasonable metric to use */ 393 is no reasonable metric to use */
293 assert (pos == TOP_GUTTER || pos == BOTTOM_GUTTER); 394 assert (pos == TOP_GUTTER || pos == BOTTOM_GUTTER);
294 /* degenerate case */ 395 /* degenerate case */
295 if (NILP (WINDOW_GUTTER (w, pos)) 396 if (NILP (RAW_WINDOW_GUTTER (w, pos))
296 || 397 ||
297 !FRAME_VISIBLE_P (f) 398 !FRAME_VISIBLE_P (f)
298 || 399 ||
299 NILP (w->buffer)) 400 NILP (w->buffer))
300 return Qnil; 401 return Qnil;
402
403 /* Redisplay code that we use relies on GC not happening. Make it
404 so. */
405 count = specpdl_depth ();
406 record_unwind_protect (restore_gc_inhibit,
407 make_int (gc_currently_forbidden));
408 gc_currently_forbidden = 1;
301 409
302 ddla = Dynarr_new (display_line); 410 ddla = Dynarr_new (display_line);
303 /* generate some display lines */ 411 /* generate some display lines */
304 generate_displayable_area (w, WINDOW_GUTTER (w, pos), 412 generate_displayable_area (w, WINDOW_GUTTER (w, pos),
305 FRAME_LEFT_BORDER_END (f), 413 FRAME_LEFT_BORDER_END (f),
306 0, 414 0,
307 FRAME_RIGHT_BORDER_START (f) 415 FRAME_RIGHT_BORDER_START (f)
308 - FRAME_LEFT_BORDER_END (f), 416 - FRAME_LEFT_BORDER_END (f),
309 200, 417 200,
310 ddla, 0, 0); 418 ddla, 0, 0);
419
420 /* Let GC happen again. */
421 unbind_to (count, Qnil);
422
311 /* grab coordinates of last line */ 423 /* grab coordinates of last line */
312 if (Dynarr_length (ddla)) 424 if (Dynarr_length (ddla))
313 { 425 {
314 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); 426 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1);
315 ypos = dl->ypos + dl->descent - dl->clip; 427 ypos = dl->ypos + dl->descent - dl->clip;
327 clear_gutter (struct frame *f, enum gutter_pos pos) 439 clear_gutter (struct frame *f, enum gutter_pos pos)
328 { 440 {
329 int x, y, width, height; 441 int x, y, width, height;
330 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); 442 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
331 face_index findex = get_builtin_face_cache_index (XWINDOW (window), 443 face_index findex = get_builtin_face_cache_index (XWINDOW (window),
332 Vgui_element_face); 444 Vwidget_face);
333 get_gutter_coords (f, pos, &x, &y, &width, &height); 445 get_gutter_coords (f, pos, &x, &y, &width, &height);
334 446
335 SET_GUTTER_WAS_VISIBLE_FLAG (f, pos, 0); 447 SET_GUTTER_WAS_VISIBLE_FLAG (f, pos, 0);
336 448
337 redisplay_clear_region (window, findex, x, y, width, height); 449 redisplay_clear_region (window, findex, x, y, width, height);
450 }
451
452 /* #### I don't currently believe that redisplay needs to mark the
453 glyphs in its structures since these will always be referenced from
454 somewhere else. However, I'm not sure enough to stake my life on it
455 at this point, so we do the safe thing. */
456
457 /* See the comment in image_instantiate_cache_result as to why marking
458 the glyph will also mark the image_instance. */
459 void
460 mark_gutters (struct frame* f)
461 {
462 enum gutter_pos pos;
463 GUTTER_POS_LOOP (pos)
464 {
465 if (f->current_display_lines[pos])
466 mark_redisplay_structs (f->current_display_lines[pos]);
467 /* #### Do we really need to mark the desired lines? */
468 if (f->desired_display_lines[pos])
469 mark_redisplay_structs (f->desired_display_lines[pos]);
470 }
471 }
472
473 /* This is called by extent_changed_for_redisplay, so that redisplay
474 knows exactly what extents have changed. */
475 void
476 gutter_extent_signal_changed_region_maybe (Lisp_Object obj,
477 Bufpos start, Bufpos end)
478 {
479 /* #### Start and end are currently ignored but could be used by a
480 more optimal gutter redisplay. We currently loop over all frames
481 here, this could be optimized. */
482 Lisp_Object frmcons, devcons, concons;
483
484 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
485 {
486 struct frame *f = XFRAME (XCAR (frmcons));
487 enum gutter_pos pos;
488 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
489 struct window* w = XWINDOW (window);
490
491 GUTTER_POS_LOOP (pos)
492 {
493 if (EQ (WINDOW_GUTTER (w, pos), obj))
494 {
495 w->gutter_extent_modiff[pos]++;
496 }
497 }
498 }
499 }
500
501 /* We have to change the gutter geometry separately to the gutter
502 update since it needs to occur outside of redisplay proper. */
503 static void
504 update_gutter_geometry (struct frame *f, enum gutter_pos pos)
505 {
506 /* If the gutter geometry has changed then re-layout the
507 frame. If we are in display there is almost no point in doing
508 anything else since the frame size changes will be delayed
509 until we are out of redisplay proper. */
510 if (FRAME_GUTTER_BOUNDS (f, pos) != f->current_gutter_bounds[pos])
511 {
512 int width, height;
513 pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f),
514 &width, &height);
515 change_frame_size (f, height, width, 0);
516 }
517
518 /* Mark sizes as up-to-date. */
519 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos);
520 }
521
522 void
523 update_frame_gutter_geometry (struct frame *f)
524 {
525 if (f->gutter_changed || f->windows_structure_changed)
526 {
527 enum gutter_pos pos;
528
529 /* If the gutter geometry has changed then re-layout the
530 frame. If we are in display there is almost no point in doing
531 anything else since the frame size changes will be delayed
532 until we are out of redisplay proper. */
533 GUTTER_POS_LOOP (pos)
534 {
535 update_gutter_geometry (f, pos);
536 }
537 }
338 } 538 }
339 539
340 void 540 void
341 update_frame_gutters (struct frame *f) 541 update_frame_gutters (struct frame *f)
342 { 542 {
343 if (f->gutter_changed || f->clear || 543 if (f->faces_changed || f->frame_changed ||
344 f->glyphs_changed || f->subwindows_changed || 544 f->gutter_changed || f->glyphs_changed ||
345 f->windows_changed || f->windows_structure_changed || 545 f->size_changed || f->subwindows_changed ||
346 f->extents_changed || f->faces_changed) 546 f->windows_changed || f->windows_structure_changed ||
547 f->extents_changed)
347 { 548 {
348 enum gutter_pos pos; 549 enum gutter_pos pos;
349 550
350 /* We don't actually care about these when outputting the gutter 551 /* We don't actually care about these when outputting the gutter
351 so locally disable them. */ 552 so locally disable them. */
352 int local_clip_changed = f->clip_changed; 553 int local_clip_changed = f->clip_changed;
353 int local_buffers_changed = f->buffers_changed; 554 int local_buffers_changed = f->buffers_changed;
354 f->clip_changed = 0; 555 f->clip_changed = 0;
356 557
357 /* and output */ 558 /* and output */
358 GUTTER_POS_LOOP (pos) 559 GUTTER_POS_LOOP (pos)
359 { 560 {
360 if (FRAME_GUTTER_VISIBLE (f, pos)) 561 if (FRAME_GUTTER_VISIBLE (f, pos))
361 output_gutter (f, pos); 562 output_gutter (f, pos, 0);
563
362 else if (gutter_was_visible (f, pos)) 564 else if (gutter_was_visible (f, pos))
363 clear_gutter (f, pos); 565 clear_gutter (f, pos);
364 } 566 }
567
365 f->clip_changed = local_clip_changed; 568 f->clip_changed = local_clip_changed;
366 f->buffers_changed = local_buffers_changed; 569 f->buffers_changed = local_buffers_changed;
367 f->gutter_changed = 0; 570 f->gutter_changed = 0;
368 } 571 }
369 } 572 }
370 573
371 void 574 void
372 reset_gutter_display_lines (struct frame* f) 575 reset_gutter_display_lines (struct frame* f)
373 { 576 {
374 if (f->current_display_lines) 577 enum gutter_pos pos;
375 Dynarr_reset (f->current_display_lines); 578 GUTTER_POS_LOOP (pos)
579 {
580 if (f->current_display_lines[pos])
581 Dynarr_reset (f->current_display_lines[pos]);
582 }
376 } 583 }
377 584
378 static void 585 static void
379 redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y, 586 redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y,
380 int width, int height) 587 int width, int height)
386 if (((y + height) < g_y) || (y > (g_y + g_height)) || !height || !width || !g_height || !g_width) 593 if (((y + height) < g_y) || (y > (g_y + g_height)) || !height || !width || !g_height || !g_width)
387 return; 594 return;
388 if (((x + width) < g_x) || (x > (g_x + g_width))) 595 if (((x + width) < g_x) || (x > (g_x + g_width)))
389 return; 596 return;
390 597
598 #ifdef DEBUG_WIDGETS
599 printf ("redrawing gutter after expose %d+%d, %dx%d\n",
600 x, y, width, height);
601 #endif
391 /* #### optimize this - redrawing the whole gutter for every expose 602 /* #### optimize this - redrawing the whole gutter for every expose
392 is very expensive. We reset the current display lines because if 603 is very expensive. We reset the current display lines because if
393 they're being exposed they are no longer current. */ 604 they're being exposed they are no longer current. */
394 reset_gutter_display_lines (f); 605 reset_gutter_display_lines (f);
395 606
396 /* Even if none of the gutter is in the area, the blank region at 607 /* Even if none of the gutter is in the area, the blank region at
397 the very least must be because the first thing we did is verify 608 the very least must be because the first thing we did is verify
398 that some portion of the gutter is in the exposed region. */ 609 that some portion of the gutter is in the exposed region. */
399 output_gutter (f, pos); 610 output_gutter (f, pos, 1);
400 } 611 }
401 612
402 void 613 void
403 redraw_exposed_gutters (struct frame *f, int x, int y, int width, 614 redraw_exposed_gutters (struct frame *f, int x, int y, int width,
404 int height) 615 int height)
405 { 616 {
406 enum gutter_pos pos; 617 enum gutter_pos pos;
618
619 /* We have to be "in display" when we output the gutter - make it
620 so. */
621 hold_frame_size_changes ();
407 GUTTER_POS_LOOP (pos) 622 GUTTER_POS_LOOP (pos)
408 { 623 {
409 if (FRAME_GUTTER_VISIBLE (f, pos)) 624 if (FRAME_GUTTER_VISIBLE (f, pos))
410 redraw_exposed_gutter (f, pos, x, y, width, height); 625 redraw_exposed_gutter (f, pos, x, y, width, height);
411 } 626 }
627 unhold_one_frame_size_changes (f);
412 } 628 }
413 629
414 void 630 void
415 free_frame_gutters (struct frame *f) 631 free_frame_gutters (struct frame *f)
416 { 632 {
417 if (f->current_display_lines) 633 enum gutter_pos pos;
418 { 634 GUTTER_POS_LOOP (pos)
419 free_display_lines (f->current_display_lines); 635 {
420 f->current_display_lines = 0; 636 if (f->current_display_lines[pos])
421 } 637 {
422 if (f->desired_display_lines) 638 free_display_lines (f->current_display_lines[pos]);
423 { 639 f->current_display_lines[pos] = 0;
424 free_display_lines (f->desired_display_lines); 640 }
425 f->desired_display_lines = 0; 641 if (f->desired_display_lines[pos])
642 {
643 free_display_lines (f->desired_display_lines[pos]);
644 f->desired_display_lines[pos] = 0;
645 }
426 } 646 }
427 } 647 }
428 648
429 static enum gutter_pos 649 static enum gutter_pos
430 decode_gutter_position (Lisp_Object position) 650 decode_gutter_position (Lisp_Object position)
464 : Vdefault_gutter_width); 684 : Vdefault_gutter_width);
465 set_specifier_fallback (Vgutter_border_width[cur], 685 set_specifier_fallback (Vgutter_border_width[cur],
466 list1 (Fcons (Qnil, Qzero))); 686 list1 (Fcons (Qnil, Qzero)));
467 set_specifier_fallback (Vgutter_border_width[new], 687 set_specifier_fallback (Vgutter_border_width[new],
468 Vdefault_gutter_border_width); 688 Vdefault_gutter_border_width);
689 /* We don't really want the left and right gutters to default to
690 visible. */
469 set_specifier_fallback (Vgutter_visible_p[cur], 691 set_specifier_fallback (Vgutter_visible_p[cur],
470 list1 (Fcons (Qnil, Qt))); 692 cur == TOP_GUTTER || cur == BOTTOM_GUTTER ?
693 list1 (Fcons (Qnil, Qt))
694 : list1 (Fcons (Qnil, Qnil)));
471 set_specifier_fallback (Vgutter_visible_p[new], 695 set_specifier_fallback (Vgutter_visible_p[new],
472 Vdefault_gutter_visible_p); 696 Vdefault_gutter_visible_p);
697
473 Vdefault_gutter_position = position; 698 Vdefault_gutter_position = position;
474 unhold_frame_size_changes (); 699 unhold_frame_size_changes ();
475 } 700 }
701
702 run_hook (Qdefault_gutter_position_changed_hook);
476 703
477 return position; 704 return position;
478 } 705 }
479 706
480 DEFUN ("default-gutter-position", Fdefault_gutter_position, 0, 0, 0, /* 707 DEFUN ("default-gutter-position", Fdefault_gutter_position, 0, 0, 0, /*
541 gutter_validate (Lisp_Object instantiator) 768 gutter_validate (Lisp_Object instantiator)
542 { 769 {
543 if (NILP (instantiator)) 770 if (NILP (instantiator))
544 return; 771 return;
545 772
773 /* Must be a string or a plist. */
774 if (!STRINGP (instantiator) && NILP (Fvalid_plist_p (instantiator)))
775 signal_simple_error ("Gutter spec must be string, plist or nil", instantiator);
776
546 if (!STRINGP (instantiator)) 777 if (!STRINGP (instantiator))
547 signal_simple_error ("Gutter spec must be string or nil", instantiator); 778 {
779 Lisp_Object rest;
780
781 for (rest = instantiator; !NILP (rest); rest = XCDR (XCDR (rest)))
782 {
783 if (!SYMBOLP (XCAR (rest))
784 || !STRINGP (XCAR (XCDR (rest))))
785 signal_simple_error ("Gutter plist spec must contain strings", instantiator);
786 }
787 }
548 } 788 }
549 789
550 DEFUN ("gutter-specifier-p", Fgutter_specifier_p, 1, 1, 0, /* 790 DEFUN ("gutter-specifier-p", Fgutter_specifier_p, 1, 1, 0, /*
551 Return non-nil if OBJECT is a gutter specifier. 791 Return non-nil if OBJECT is a gutter specifier.
552 Gutter specifiers are used to specify the format of a gutter. 792
553 The values of the variables `default-gutter', `top-gutter', 793 See `make-gutter-specifier' for a description of possible gutter
554 `left-gutter', `right-gutter', and `bottom-gutter' are always 794 instantiators.
555 gutter specifiers.
556
557 Valid gutter instantiators are called "gutter descriptors"
558 and are lists of vectors. See `default-gutter' for a description
559 of the exact format.
560 */ 795 */
561 (object)) 796 (object))
562 { 797 {
563 return GUTTER_SPECIFIERP (object) ? Qt : Qnil; 798 return GUTTER_SPECIFIERP (object) ? Qt : Qnil;
564 } 799 }
575 Fset_specifier_dirty_flag (real_one[pos]); 810 Fset_specifier_dirty_flag (real_one[pos]);
576 } 811 }
577 812
578 static void 813 static void
579 gutter_specs_changed (Lisp_Object specifier, struct window *w, 814 gutter_specs_changed (Lisp_Object specifier, struct window *w,
580 Lisp_Object oldval) 815 Lisp_Object oldval, enum gutter_pos pos)
816 {
817 w->real_gutter[pos] = construct_window_gutter_spec (w, pos);
818 w->real_gutter_size[pos] = w->gutter_size[pos];
819
820 if (EQ (w->real_gutter_size[pos], Qautodetect)
821 && !NILP (w->gutter_visible_p[pos]))
822 {
823 w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
824 }
825 MARK_GUTTER_CHANGED;
826 MARK_MODELINE_CHANGED;
827 MARK_WINDOWS_CHANGED (w);
828 }
829
830 /* We define all of these so we can access which actual gutter changed. */
831 static void
832 top_gutter_specs_changed (Lisp_Object specifier, struct window *w,
833 Lisp_Object oldval)
834 {
835 gutter_specs_changed (specifier, w, oldval, TOP_GUTTER);
836 }
837
838 static void
839 bottom_gutter_specs_changed (Lisp_Object specifier, struct window *w,
840 Lisp_Object oldval)
841 {
842 gutter_specs_changed (specifier, w, oldval, BOTTOM_GUTTER);
843 }
844
845 static void
846 left_gutter_specs_changed (Lisp_Object specifier, struct window *w,
847 Lisp_Object oldval)
848 {
849 gutter_specs_changed (specifier, w, oldval, LEFT_GUTTER);
850 }
851
852 static void
853 right_gutter_specs_changed (Lisp_Object specifier, struct window *w,
854 Lisp_Object oldval)
855 {
856 gutter_specs_changed (specifier, w, oldval, RIGHT_GUTTER);
857 }
858
859 static void
860 default_gutter_specs_changed (Lisp_Object specifier, struct window *w,
861 Lisp_Object oldval)
862 {
863 recompute_overlaying_specifier (Vgutter);
864 }
865
866 static void
867 gutter_geometry_changed_in_window (Lisp_Object specifier, struct window *w,
868 Lisp_Object oldval)
581 { 869 {
582 enum gutter_pos pos; 870 enum gutter_pos pos;
583 GUTTER_POS_LOOP (pos) 871 GUTTER_POS_LOOP (pos)
584 { 872 {
585 w->real_gutter_size[pos] = w->gutter_size[pos]; 873 w->real_gutter_size[pos] = w->gutter_size[pos];
587 && !NILP (w->gutter_visible_p[pos])) 875 && !NILP (w->gutter_visible_p[pos]))
588 { 876 {
589 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); 877 w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
590 } 878 }
591 } 879 }
880
592 MARK_GUTTER_CHANGED; 881 MARK_GUTTER_CHANGED;
593 MARK_WINDOWS_CHANGED (w); 882 MARK_MODELINE_CHANGED;
594 }
595
596 static void
597 default_gutter_specs_changed (Lisp_Object specifier, struct window *w,
598 Lisp_Object oldval)
599 {
600 recompute_overlaying_specifier (Vgutter);
601 }
602
603 static void
604 gutter_geometry_changed_in_window (Lisp_Object specifier, struct window *w,
605 Lisp_Object oldval)
606 {
607 enum gutter_pos pos;
608 GUTTER_POS_LOOP (pos)
609 {
610 w->real_gutter_size[pos] = w->gutter_size[pos];
611 if (EQ (w->real_gutter_size[pos], Qautodetect)
612 && !NILP (w->gutter_visible_p[pos]))
613 {
614 w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
615 }
616 }
617
618 MARK_GUTTER_CHANGED;
619 MARK_WINDOWS_CHANGED (w); 883 MARK_WINDOWS_CHANGED (w);
620 } 884 }
621 885
622 static void 886 static void
623 default_gutter_size_changed_in_window (Lisp_Object specifier, struct window *w, 887 default_gutter_size_changed_in_window (Lisp_Object specifier, struct window *w,
638 default_gutter_visible_p_changed_in_window (Lisp_Object specifier, 902 default_gutter_visible_p_changed_in_window (Lisp_Object specifier,
639 struct window *w, 903 struct window *w,
640 Lisp_Object oldval) 904 Lisp_Object oldval)
641 { 905 {
642 recompute_overlaying_specifier (Vgutter_visible_p); 906 recompute_overlaying_specifier (Vgutter_visible_p);
907 /* Need to reconstruct the gutter specifier as it is affected by the
908 visibility. */
909 recompute_overlaying_specifier (Vgutter);
643 } 910 }
644 911
645 912
646 DECLARE_SPECIFIER_TYPE (gutter_size); 913 DECLARE_SPECIFIER_TYPE (gutter_size);
647 #define GUTTER_SIZE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_size) 914 #define GUTTER_SIZE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_size)
657 signal_simple_error ("Gutter size must be an integer or 'autodetect", instantiator); 924 signal_simple_error ("Gutter size must be an integer or 'autodetect", instantiator);
658 } 925 }
659 926
660 DEFUN ("gutter-size-specifier-p", Fgutter_size_specifier_p, 1, 1, 0, /* 927 DEFUN ("gutter-size-specifier-p", Fgutter_size_specifier_p, 1, 1, 0, /*
661 Return non-nil if OBJECT is a gutter-size specifier. 928 Return non-nil if OBJECT is a gutter-size specifier.
929
930 See `make-gutter-size-specifier' for a description of possible gutter-size
931 instantiators.
662 */ 932 */
663 (object)) 933 (object))
664 { 934 {
665 return GUTTER_SIZE_SPECIFIERP (object) ? Qt : Qnil; 935 return GUTTER_SIZE_SPECIFIERP (object) ? Qt : Qnil;
936 }
937
938 DECLARE_SPECIFIER_TYPE (gutter_visible);
939 #define GUTTER_VISIBLE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_visible)
940 DEFINE_SPECIFIER_TYPE (gutter_visible);
941
942 static void
943 gutter_visible_validate (Lisp_Object instantiator)
944 {
945 if (NILP (instantiator))
946 return;
947
948 if (!NILP (instantiator) && !EQ (instantiator, Qt) && !CONSP (instantiator))
949 signal_simple_error ("Gutter visibility must be a boolean or list of symbols",
950 instantiator);
951
952 if (CONSP (instantiator))
953 {
954 Lisp_Object rest;
955
956 EXTERNAL_LIST_LOOP (rest, instantiator)
957 {
958 if (!SYMBOLP (XCAR (rest)))
959 signal_simple_error ("Gutter visibility must be a boolean or list of symbols",
960 instantiator);
961 }
962 }
963 }
964
965 DEFUN ("gutter-visible-specifier-p", Fgutter_visible_specifier_p, 1, 1, 0, /*
966 Return non-nil if OBJECT is a gutter-visible specifier.
967
968 See `make-gutter-visible-specifier' for a description of possible
969 gutter-visible instantiators.
970 */
971 (object))
972 {
973 return GUTTER_VISIBLE_SPECIFIERP (object) ? Qt : Qnil;
666 } 974 }
667 975
668 DEFUN ("redisplay-gutter-area", Fredisplay_gutter_area, 0, 0, 0, /* 976 DEFUN ("redisplay-gutter-area", Fredisplay_gutter_area, 0, 0, 0, /*
669 Ensure that all gutters are correctly showing their gutter specifier. 977 Ensure that all gutters are correctly showing their gutter specifier.
670 */ 978 */
679 987
680 DEVICE_FRAME_LOOP (frmcons, d) 988 DEVICE_FRAME_LOOP (frmcons, d)
681 { 989 {
682 struct frame *f = XFRAME (XCAR (frmcons)); 990 struct frame *f = XFRAME (XCAR (frmcons));
683 991
684 if (FRAME_REPAINT_P (f)) 992 MAYBE_DEVMETH (d, frame_output_begin, (f));
993
994 /* Sequence is quite important here. We not only want to
995 redisplay the gutter area but we also want to flush any
996 frame size changes out so that the gutter redisplay happens
997 in a kosha environment.
998
999 This is not only so that things look right but so that
1000 glyph redisplay optimization kicks in, by default display
1001 lines will be completely re-output if
1002 f->windows_structure_changed is 1, and this is true if
1003 frame size changes haven't been flushed out. Once frame
1004 size changes have been flushed out we then need to
1005 redisplay the frame in order to flush out pending window
1006 size changes. */
1007 update_frame_gutter_geometry (f);
1008
1009 if (f->windows_structure_changed)
1010 redisplay_frame (f, 1);
1011 else if (FRAME_REPAINT_P (f))
685 { 1012 {
1013 /* We have to be "in display" when we output the gutter
1014 - make it so. */
1015 hold_frame_size_changes ();
686 update_frame_gutters (f); 1016 update_frame_gutters (f);
1017 unhold_one_frame_size_changes (f);
687 } 1018 }
688 } 1019
689 1020 MAYBE_DEVMETH (d, frame_output_end, (f));
690 /* We now call the output_end routine for tty frames. We delay 1021 }
691 doing so in order to avoid cursor flicker. So much for 100% 1022
692 encapsulation. */ 1023 d->gutter_changed = 0;
693 if (DEVICE_TTY_P (d)) 1024 }
694 DEVMETH (d, output_end, (d)); 1025
695 } 1026 /* This is so that further changes to the gutters will trigger redisplay. */
1027 gutter_changed_set = 0;
1028 gutter_changed = 0;
696 1029
697 return Qnil; 1030 return Qnil;
698 } 1031 }
699 1032
700 void 1033 void
705 /* We are here as far in frame creation so cached specifiers are 1038 /* We are here as far in frame creation so cached specifiers are
706 already recomputed, and possibly modified by resource 1039 already recomputed, and possibly modified by resource
707 initialization. We need to recalculate autodetected gutters. */ 1040 initialization. We need to recalculate autodetected gutters. */
708 GUTTER_POS_LOOP (pos) 1041 GUTTER_POS_LOOP (pos)
709 { 1042 {
1043 w->real_gutter[pos] = construct_window_gutter_spec (w, pos);
710 w->real_gutter_size[pos] = w->gutter_size[pos]; 1044 w->real_gutter_size[pos] = w->gutter_size[pos];
711 if (EQ (w->gutter_size[pos], Qautodetect) 1045 if (EQ (w->gutter_size[pos], Qautodetect)
712 && !NILP (w->gutter_visible_p[pos])) 1046 && !NILP (w->gutter_visible_p[pos]))
713 { 1047 {
714 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); 1048 w->real_gutter_size [pos] = calculate_gutter_size (w, pos);
715 MARK_GUTTER_CHANGED; 1049 MARK_GUTTER_CHANGED;
716 MARK_WINDOWS_CHANGED (w); 1050 MARK_WINDOWS_CHANGED (w);
717 } 1051 }
718 } 1052 }
1053
1054 /* Keep a record of the current sizes of things. */
1055 GUTTER_POS_LOOP (pos)
1056 {
1057 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos);
1058 }
719 } 1059 }
720 1060
721 void 1061 void
722 syms_of_gutter (void) 1062 syms_of_gutter (void)
723 { 1063 {
724 DEFSUBR (Fgutter_specifier_p); 1064 DEFSUBR (Fgutter_specifier_p);
725 DEFSUBR (Fgutter_size_specifier_p); 1065 DEFSUBR (Fgutter_size_specifier_p);
1066 DEFSUBR (Fgutter_visible_specifier_p);
726 DEFSUBR (Fset_default_gutter_position); 1067 DEFSUBR (Fset_default_gutter_position);
727 DEFSUBR (Fdefault_gutter_position); 1068 DEFSUBR (Fdefault_gutter_position);
728 DEFSUBR (Fgutter_pixel_height); 1069 DEFSUBR (Fgutter_pixel_height);
729 DEFSUBR (Fgutter_pixel_width); 1070 DEFSUBR (Fgutter_pixel_width);
730 DEFSUBR (Fredisplay_gutter_area); 1071 DEFSUBR (Fredisplay_gutter_area);
731 1072
732 defsymbol (&Qgutter_size, "gutter-size"); 1073 defsymbol (&Qgutter_size, "gutter-size");
1074 defsymbol (&Qgutter_visible, "gutter-visible");
1075 defsymbol (&Qdefault_gutter_position_changed_hook,
1076 "default-gutter-position-changed-hook");
733 } 1077 }
734 1078
735 void 1079 void
736 vars_of_gutter (void) 1080 vars_of_gutter (void)
737 { 1081 {
743 1087
744 void 1088 void
745 specifier_type_create_gutter (void) 1089 specifier_type_create_gutter (void)
746 { 1090 {
747 INITIALIZE_SPECIFIER_TYPE (gutter, "gutter", "gutter-specifier-p"); 1091 INITIALIZE_SPECIFIER_TYPE (gutter, "gutter", "gutter-specifier-p");
748
749 SPECIFIER_HAS_METHOD (gutter, validate); 1092 SPECIFIER_HAS_METHOD (gutter, validate);
750 SPECIFIER_HAS_METHOD (gutter, after_change); 1093 SPECIFIER_HAS_METHOD (gutter, after_change);
751 1094
752 INITIALIZE_SPECIFIER_TYPE (gutter_size, "gutter-size", "gutter-size-specifier-p"); 1095 INITIALIZE_SPECIFIER_TYPE (gutter_size, "gutter-size", "gutter-size-specifier-p");
753
754 SPECIFIER_HAS_METHOD (gutter_size, validate); 1096 SPECIFIER_HAS_METHOD (gutter_size, validate);
1097
1098 INITIALIZE_SPECIFIER_TYPE (gutter_visible, "gutter-visible", "gutter-visible-specifier-p");
1099 SPECIFIER_HAS_METHOD (gutter_visible, validate);
755 } 1100 }
756 1101
757 void 1102 void
758 reinit_specifier_type_create_gutter (void) 1103 reinit_specifier_type_create_gutter (void)
759 { 1104 {
760 REINITIALIZE_SPECIFIER_TYPE (gutter); 1105 REINITIALIZE_SPECIFIER_TYPE (gutter);
761 REINITIALIZE_SPECIFIER_TYPE (gutter_size); 1106 REINITIALIZE_SPECIFIER_TYPE (gutter_size);
1107 REINITIALIZE_SPECIFIER_TYPE (gutter_visible);
762 } 1108 }
763 1109
764 void 1110 void
765 specifier_vars_of_gutter (void) 1111 specifier_vars_of_gutter (void)
766 { 1112 {
797 the visibility and thickness using `default-gutter-visible-p', 1143 the visibility and thickness using `default-gutter-visible-p',
798 `default-gutter-width', and `default-gutter-height', rather than 1144 `default-gutter-width', and `default-gutter-height', rather than
799 using position-specific specifiers. That way, you will get sane 1145 using position-specific specifiers. That way, you will get sane
800 behavior if the user changes the default gutter position. 1146 behavior if the user changes the default gutter position.
801 1147
802 The gutter value should be a string or nil. You can attach extents and 1148 The gutter value should be a string, a property list of strings or
803 glyphs to the string and hence display glyphs and text in other fonts 1149 nil. You can attach extents and glyphs to the string and hence display
804 in the gutter area. 1150 glyphs and text in other fonts in the gutter area. If the gutter value
805 1151 is a property list then the strings will be concatenated together
806 */ ); 1152 before being displayed. */ );
807 1153
808 Vdefault_gutter = Fmake_specifier (Qgutter); 1154 Vdefault_gutter = Fmake_specifier (Qgutter);
809 /* #### It would be even nicer if the specifier caching 1155 /* #### It would be even nicer if the specifier caching
810 automatically knew about specifier fallbacks, so we didn't 1156 automatically knew about specifier fallbacks, so we didn't
811 have to do it ourselves. */ 1157 have to do it ourselves. */
821 See `default-gutter' for a description of a valid gutter instantiator. 1167 See `default-gutter' for a description of a valid gutter instantiator.
822 */ ); 1168 */ );
823 Vgutter[TOP_GUTTER] = Fmake_specifier (Qgutter); 1169 Vgutter[TOP_GUTTER] = Fmake_specifier (Qgutter);
824 set_specifier_caching (Vgutter[TOP_GUTTER], 1170 set_specifier_caching (Vgutter[TOP_GUTTER],
825 offsetof (struct window, gutter[TOP_GUTTER]), 1171 offsetof (struct window, gutter[TOP_GUTTER]),
826 gutter_specs_changed, 1172 top_gutter_specs_changed,
827 0, 0); 1173 0, 0);
828 1174
829 DEFVAR_SPECIFIER ("bottom-gutter", 1175 DEFVAR_SPECIFIER ("bottom-gutter",
830 &Vgutter[BOTTOM_GUTTER] /* 1176 &Vgutter[BOTTOM_GUTTER] /*
831 Specifier for the gutter at the bottom of the frame. 1177 Specifier for the gutter at the bottom of the frame.
838 displayed even if you provide a value for `bottom-gutter'. 1184 displayed even if you provide a value for `bottom-gutter'.
839 */ ); 1185 */ );
840 Vgutter[BOTTOM_GUTTER] = Fmake_specifier (Qgutter); 1186 Vgutter[BOTTOM_GUTTER] = Fmake_specifier (Qgutter);
841 set_specifier_caching (Vgutter[BOTTOM_GUTTER], 1187 set_specifier_caching (Vgutter[BOTTOM_GUTTER],
842 offsetof (struct window, gutter[BOTTOM_GUTTER]), 1188 offsetof (struct window, gutter[BOTTOM_GUTTER]),
843 gutter_specs_changed, 1189 bottom_gutter_specs_changed,
844 0, 0); 1190 0, 0);
845 1191
846 DEFVAR_SPECIFIER ("left-gutter", 1192 DEFVAR_SPECIFIER ("left-gutter",
847 &Vgutter[LEFT_GUTTER] /* 1193 &Vgutter[LEFT_GUTTER] /*
848 Specifier for the gutter at the left edge of the frame. 1194 Specifier for the gutter at the left edge of the frame.
855 displayed even if you provide a value for `left-gutter'. 1201 displayed even if you provide a value for `left-gutter'.
856 */ ); 1202 */ );
857 Vgutter[LEFT_GUTTER] = Fmake_specifier (Qgutter); 1203 Vgutter[LEFT_GUTTER] = Fmake_specifier (Qgutter);
858 set_specifier_caching (Vgutter[LEFT_GUTTER], 1204 set_specifier_caching (Vgutter[LEFT_GUTTER],
859 offsetof (struct window, gutter[LEFT_GUTTER]), 1205 offsetof (struct window, gutter[LEFT_GUTTER]),
860 gutter_specs_changed, 1206 left_gutter_specs_changed,
861 0, 0); 1207 0, 0);
862 1208
863 DEFVAR_SPECIFIER ("right-gutter", 1209 DEFVAR_SPECIFIER ("right-gutter",
864 &Vgutter[RIGHT_GUTTER] /* 1210 &Vgutter[RIGHT_GUTTER] /*
865 Specifier for the gutter at the right edge of the frame. 1211 Specifier for the gutter at the right edge of the frame.
872 displayed even if you provide a value for `right-gutter'. 1218 displayed even if you provide a value for `right-gutter'.
873 */ ); 1219 */ );
874 Vgutter[RIGHT_GUTTER] = Fmake_specifier (Qgutter); 1220 Vgutter[RIGHT_GUTTER] = Fmake_specifier (Qgutter);
875 set_specifier_caching (Vgutter[RIGHT_GUTTER], 1221 set_specifier_caching (Vgutter[RIGHT_GUTTER],
876 offsetof (struct window, gutter[RIGHT_GUTTER]), 1222 offsetof (struct window, gutter[RIGHT_GUTTER]),
877 gutter_specs_changed, 1223 right_gutter_specs_changed,
878 0, 0); 1224 0, 0);
879 1225
880 /* initially, top inherits from default; this can be 1226 /* initially, top inherits from default; this can be
881 changed with `set-default-gutter-position'. */ 1227 changed with `set-default-gutter-position'. */
882 fb = list1 (Fcons (Qnil, Qnil)); 1228 fb = list1 (Fcons (Qnil, Qnil));
937 See `default-gutter-height' for more information. 1283 See `default-gutter-height' for more information.
938 */ ); 1284 */ );
939 Vgutter_size[TOP_GUTTER] = Fmake_specifier (Qgutter_size); 1285 Vgutter_size[TOP_GUTTER] = Fmake_specifier (Qgutter_size);
940 set_specifier_caching (Vgutter_size[TOP_GUTTER], 1286 set_specifier_caching (Vgutter_size[TOP_GUTTER],
941 offsetof (struct window, gutter_size[TOP_GUTTER]), 1287 offsetof (struct window, gutter_size[TOP_GUTTER]),
942 gutter_geometry_changed_in_window, 1288 gutter_geometry_changed_in_window, 0, 0);
943 0, 0);
944 1289
945 DEFVAR_SPECIFIER ("bottom-gutter-height", 1290 DEFVAR_SPECIFIER ("bottom-gutter-height",
946 &Vgutter_size[BOTTOM_GUTTER] /* 1291 &Vgutter_size[BOTTOM_GUTTER] /*
947 *Height of the bottom gutter. 1292 *Height of the bottom gutter.
948 This is a specifier; use `set-specifier' to change it. 1293 This is a specifier; use `set-specifier' to change it.
950 See `default-gutter-height' for more information. 1295 See `default-gutter-height' for more information.
951 */ ); 1296 */ );
952 Vgutter_size[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_size); 1297 Vgutter_size[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_size);
953 set_specifier_caching (Vgutter_size[BOTTOM_GUTTER], 1298 set_specifier_caching (Vgutter_size[BOTTOM_GUTTER],
954 offsetof (struct window, gutter_size[BOTTOM_GUTTER]), 1299 offsetof (struct window, gutter_size[BOTTOM_GUTTER]),
955 gutter_geometry_changed_in_window, 1300 gutter_geometry_changed_in_window, 0, 0);
956 0, 0);
957 1301
958 DEFVAR_SPECIFIER ("left-gutter-width", 1302 DEFVAR_SPECIFIER ("left-gutter-width",
959 &Vgutter_size[LEFT_GUTTER] /* 1303 &Vgutter_size[LEFT_GUTTER] /*
960 *Width of left gutter. 1304 *Width of left gutter.
961 This is a specifier; use `set-specifier' to change it. 1305 This is a specifier; use `set-specifier' to change it.
963 See `default-gutter-height' for more information. 1307 See `default-gutter-height' for more information.
964 */ ); 1308 */ );
965 Vgutter_size[LEFT_GUTTER] = Fmake_specifier (Qnatnum); 1309 Vgutter_size[LEFT_GUTTER] = Fmake_specifier (Qnatnum);
966 set_specifier_caching (Vgutter_size[LEFT_GUTTER], 1310 set_specifier_caching (Vgutter_size[LEFT_GUTTER],
967 offsetof (struct window, gutter_size[LEFT_GUTTER]), 1311 offsetof (struct window, gutter_size[LEFT_GUTTER]),
968 gutter_geometry_changed_in_window, 1312 gutter_geometry_changed_in_window, 0, 0);
969 0, 0);
970 1313
971 DEFVAR_SPECIFIER ("right-gutter-width", 1314 DEFVAR_SPECIFIER ("right-gutter-width",
972 &Vgutter_size[RIGHT_GUTTER] /* 1315 &Vgutter_size[RIGHT_GUTTER] /*
973 *Width of right gutter. 1316 *Width of right gutter.
974 This is a specifier; use `set-specifier' to change it. 1317 This is a specifier; use `set-specifier' to change it.
976 See `default-gutter-height' for more information. 1319 See `default-gutter-height' for more information.
977 */ ); 1320 */ );
978 Vgutter_size[RIGHT_GUTTER] = Fmake_specifier (Qnatnum); 1321 Vgutter_size[RIGHT_GUTTER] = Fmake_specifier (Qnatnum);
979 set_specifier_caching (Vgutter_size[RIGHT_GUTTER], 1322 set_specifier_caching (Vgutter_size[RIGHT_GUTTER],
980 offsetof (struct window, gutter_size[RIGHT_GUTTER]), 1323 offsetof (struct window, gutter_size[RIGHT_GUTTER]),
981 gutter_geometry_changed_in_window, 1324 gutter_geometry_changed_in_window, 0, 0);
982 0, 0);
983 1325
984 fb = Qnil; 1326 fb = Qnil;
985 #ifdef HAVE_TTY 1327 #ifdef HAVE_TTY
986 fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb); 1328 fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb);
987 #endif 1329 #endif
1002 #ifdef HAVE_X_WINDOWS 1344 #ifdef HAVE_X_WINDOWS
1003 fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_GUTTER_WIDTH)), fb); 1345 fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_GUTTER_WIDTH)), fb);
1004 #endif 1346 #endif
1005 #ifdef HAVE_MS_WINDOWS 1347 #ifdef HAVE_MS_WINDOWS
1006 fb = Fcons (Fcons (list1 (Qmsprinter), Qzero), fb); 1348 fb = Fcons (Fcons (list1 (Qmsprinter), Qzero), fb);
1007 fb = Fcons (Fcons (list1 (Qmswindows), 1349 fb = Fcons (Fcons (list1 (Qmswindows),
1008 make_int (DEFAULT_GUTTER_WIDTH)), fb); 1350 make_int (DEFAULT_GUTTER_WIDTH)), fb);
1009 #endif 1351 #endif
1010 if (!NILP (fb)) 1352 if (!NILP (fb))
1011 set_specifier_fallback (Vdefault_gutter_width, fb); 1353 set_specifier_fallback (Vdefault_gutter_width, fb);
1012 1354
1045 */ ); 1387 */ );
1046 Vgutter_border_width[TOP_GUTTER] = Fmake_specifier (Qnatnum); 1388 Vgutter_border_width[TOP_GUTTER] = Fmake_specifier (Qnatnum);
1047 set_specifier_caching (Vgutter_border_width[TOP_GUTTER], 1389 set_specifier_caching (Vgutter_border_width[TOP_GUTTER],
1048 offsetof (struct window, 1390 offsetof (struct window,
1049 gutter_border_width[TOP_GUTTER]), 1391 gutter_border_width[TOP_GUTTER]),
1050 gutter_geometry_changed_in_window, 1392 gutter_geometry_changed_in_window, 0, 0);
1051 0, 0);
1052 1393
1053 DEFVAR_SPECIFIER ("bottom-gutter-border-width", 1394 DEFVAR_SPECIFIER ("bottom-gutter-border-width",
1054 &Vgutter_border_width[BOTTOM_GUTTER] /* 1395 &Vgutter_border_width[BOTTOM_GUTTER] /*
1055 *Border width of the bottom gutter. 1396 *Border width of the bottom gutter.
1056 This is a specifier; use `set-specifier' to change it. 1397 This is a specifier; use `set-specifier' to change it.
1059 */ ); 1400 */ );
1060 Vgutter_border_width[BOTTOM_GUTTER] = Fmake_specifier (Qnatnum); 1401 Vgutter_border_width[BOTTOM_GUTTER] = Fmake_specifier (Qnatnum);
1061 set_specifier_caching (Vgutter_border_width[BOTTOM_GUTTER], 1402 set_specifier_caching (Vgutter_border_width[BOTTOM_GUTTER],
1062 offsetof (struct window, 1403 offsetof (struct window,
1063 gutter_border_width[BOTTOM_GUTTER]), 1404 gutter_border_width[BOTTOM_GUTTER]),
1064 gutter_geometry_changed_in_window, 1405 gutter_geometry_changed_in_window, 0, 0);
1065 0, 0);
1066 1406
1067 DEFVAR_SPECIFIER ("left-gutter-border-width", 1407 DEFVAR_SPECIFIER ("left-gutter-border-width",
1068 &Vgutter_border_width[LEFT_GUTTER] /* 1408 &Vgutter_border_width[LEFT_GUTTER] /*
1069 *Border width of left gutter. 1409 *Border width of left gutter.
1070 This is a specifier; use `set-specifier' to change it. 1410 This is a specifier; use `set-specifier' to change it.
1073 */ ); 1413 */ );
1074 Vgutter_border_width[LEFT_GUTTER] = Fmake_specifier (Qnatnum); 1414 Vgutter_border_width[LEFT_GUTTER] = Fmake_specifier (Qnatnum);
1075 set_specifier_caching (Vgutter_border_width[LEFT_GUTTER], 1415 set_specifier_caching (Vgutter_border_width[LEFT_GUTTER],
1076 offsetof (struct window, 1416 offsetof (struct window,
1077 gutter_border_width[LEFT_GUTTER]), 1417 gutter_border_width[LEFT_GUTTER]),
1078 gutter_geometry_changed_in_window, 1418 gutter_geometry_changed_in_window, 0, 0);
1079 0, 0);
1080 1419
1081 DEFVAR_SPECIFIER ("right-gutter-border-width", 1420 DEFVAR_SPECIFIER ("right-gutter-border-width",
1082 &Vgutter_border_width[RIGHT_GUTTER] /* 1421 &Vgutter_border_width[RIGHT_GUTTER] /*
1083 *Border width of right gutter. 1422 *Border width of right gutter.
1084 This is a specifier; use `set-specifier' to change it. 1423 This is a specifier; use `set-specifier' to change it.
1087 */ ); 1426 */ );
1088 Vgutter_border_width[RIGHT_GUTTER] = Fmake_specifier (Qnatnum); 1427 Vgutter_border_width[RIGHT_GUTTER] = Fmake_specifier (Qnatnum);
1089 set_specifier_caching (Vgutter_border_width[RIGHT_GUTTER], 1428 set_specifier_caching (Vgutter_border_width[RIGHT_GUTTER],
1090 offsetof (struct window, 1429 offsetof (struct window,
1091 gutter_border_width[RIGHT_GUTTER]), 1430 gutter_border_width[RIGHT_GUTTER]),
1092 gutter_geometry_changed_in_window, 1431 gutter_geometry_changed_in_window, 0, 0);
1093 0, 0);
1094 1432
1095 fb = Qnil; 1433 fb = Qnil;
1096 #ifdef HAVE_TTY 1434 #ifdef HAVE_TTY
1097 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb); 1435 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb);
1098 #endif 1436 #endif
1125 instead. 1463 instead.
1126 1464
1127 `default-gutter-visible-p' and all of the position-specific gutter 1465 `default-gutter-visible-p' and all of the position-specific gutter
1128 visibility specifiers have a fallback value of true. 1466 visibility specifiers have a fallback value of true.
1129 */ ); 1467 */ );
1130 Vdefault_gutter_visible_p = Fmake_specifier (Qboolean); 1468 Vdefault_gutter_visible_p = Fmake_specifier (Qgutter_visible);
1131 set_specifier_caching (Vdefault_gutter_visible_p, 1469 set_specifier_caching (Vdefault_gutter_visible_p,
1132 offsetof (struct window, 1470 offsetof (struct window,
1133 default_gutter_visible_p), 1471 default_gutter_visible_p),
1134 default_gutter_visible_p_changed_in_window, 1472 default_gutter_visible_p_changed_in_window,
1135 0, 0); 1473 0, 0);
1139 *Whether the top gutter is visible. 1477 *Whether the top gutter is visible.
1140 This is a specifier; use `set-specifier' to change it. 1478 This is a specifier; use `set-specifier' to change it.
1141 1479
1142 See `default-gutter-visible-p' for more information. 1480 See `default-gutter-visible-p' for more information.
1143 */ ); 1481 */ );
1144 Vgutter_visible_p[TOP_GUTTER] = Fmake_specifier (Qboolean); 1482 Vgutter_visible_p[TOP_GUTTER] = Fmake_specifier (Qgutter_visible);
1145 set_specifier_caching (Vgutter_visible_p[TOP_GUTTER], 1483 set_specifier_caching (Vgutter_visible_p[TOP_GUTTER],
1146 offsetof (struct window, 1484 offsetof (struct window,
1147 gutter_visible_p[TOP_GUTTER]), 1485 gutter_visible_p[TOP_GUTTER]),
1148 gutter_geometry_changed_in_window, 1486 top_gutter_specs_changed, 0, 0);
1149 0, 0);
1150 1487
1151 DEFVAR_SPECIFIER ("bottom-gutter-visible-p", 1488 DEFVAR_SPECIFIER ("bottom-gutter-visible-p",
1152 &Vgutter_visible_p[BOTTOM_GUTTER] /* 1489 &Vgutter_visible_p[BOTTOM_GUTTER] /*
1153 *Whether the bottom gutter is visible. 1490 *Whether the bottom gutter is visible.
1154 This is a specifier; use `set-specifier' to change it. 1491 This is a specifier; use `set-specifier' to change it.
1155 1492
1156 See `default-gutter-visible-p' for more information. 1493 See `default-gutter-visible-p' for more information.
1157 */ ); 1494 */ );
1158 Vgutter_visible_p[BOTTOM_GUTTER] = Fmake_specifier (Qboolean); 1495 Vgutter_visible_p[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_visible);
1159 set_specifier_caching (Vgutter_visible_p[BOTTOM_GUTTER], 1496 set_specifier_caching (Vgutter_visible_p[BOTTOM_GUTTER],
1160 offsetof (struct window, 1497 offsetof (struct window,
1161 gutter_visible_p[BOTTOM_GUTTER]), 1498 gutter_visible_p[BOTTOM_GUTTER]),
1162 gutter_geometry_changed_in_window, 1499 bottom_gutter_specs_changed, 0, 0);
1163 0, 0);
1164 1500
1165 DEFVAR_SPECIFIER ("left-gutter-visible-p", 1501 DEFVAR_SPECIFIER ("left-gutter-visible-p",
1166 &Vgutter_visible_p[LEFT_GUTTER] /* 1502 &Vgutter_visible_p[LEFT_GUTTER] /*
1167 *Whether the left gutter is visible. 1503 *Whether the left gutter is visible.
1168 This is a specifier; use `set-specifier' to change it. 1504 This is a specifier; use `set-specifier' to change it.
1169 1505
1170 See `default-gutter-visible-p' for more information. 1506 See `default-gutter-visible-p' for more information.
1171 */ ); 1507 */ );
1172 Vgutter_visible_p[LEFT_GUTTER] = Fmake_specifier (Qboolean); 1508 Vgutter_visible_p[LEFT_GUTTER] = Fmake_specifier (Qgutter_visible);
1173 set_specifier_caching (Vgutter_visible_p[LEFT_GUTTER], 1509 set_specifier_caching (Vgutter_visible_p[LEFT_GUTTER],
1174 offsetof (struct window, 1510 offsetof (struct window,
1175 gutter_visible_p[LEFT_GUTTER]), 1511 gutter_visible_p[LEFT_GUTTER]),
1176 gutter_geometry_changed_in_window, 1512 left_gutter_specs_changed, 0, 0);
1177 0, 0);
1178 1513
1179 DEFVAR_SPECIFIER ("right-gutter-visible-p", 1514 DEFVAR_SPECIFIER ("right-gutter-visible-p",
1180 &Vgutter_visible_p[RIGHT_GUTTER] /* 1515 &Vgutter_visible_p[RIGHT_GUTTER] /*
1181 *Whether the right gutter is visible. 1516 *Whether the right gutter is visible.
1182 This is a specifier; use `set-specifier' to change it. 1517 This is a specifier; use `set-specifier' to change it.
1183 1518
1184 See `default-gutter-visible-p' for more information. 1519 See `default-gutter-visible-p' for more information.
1185 */ ); 1520 */ );
1186 Vgutter_visible_p[RIGHT_GUTTER] = Fmake_specifier (Qboolean); 1521 Vgutter_visible_p[RIGHT_GUTTER] = Fmake_specifier (Qgutter_visible);
1187 set_specifier_caching (Vgutter_visible_p[RIGHT_GUTTER], 1522 set_specifier_caching (Vgutter_visible_p[RIGHT_GUTTER],
1188 offsetof (struct window, 1523 offsetof (struct window,
1189 gutter_visible_p[RIGHT_GUTTER]), 1524 gutter_visible_p[RIGHT_GUTTER]),
1190 gutter_geometry_changed_in_window, 1525 right_gutter_specs_changed, 0, 0);
1191 0, 0);
1192 1526
1193 /* initially, top inherits from default; this can be 1527 /* initially, top inherits from default; this can be
1194 changed with `set-default-gutter-position'. */ 1528 changed with `set-default-gutter-position'. */
1195 fb = list1 (Fcons (Qnil, Qt)); 1529 fb = list1 (Fcons (Qnil, Qt));
1196 set_specifier_fallback (Vdefault_gutter_visible_p, fb); 1530 set_specifier_fallback (Vdefault_gutter_visible_p, fb);