Mercurial > hg > xemacs-beta
comparison src/gutter.c @ 398:74fd4e045ea6 r21-2-29
Import from CVS: tag r21-2-29
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:13:30 +0200 |
parents | |
children | a86b2b5e0111 |
comparison
equal
deleted
inserted
replaced
397:f4aeb21a5bad | 398:74fd4e045ea6 |
---|---|
1 /* Gutter implementation. | |
2 Copyright (C) 1999 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 | |
51 #define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag) \ | |
52 do { \ | |
53 switch (pos) \ | |
54 { \ | |
55 case TOP_GUTTER: \ | |
56 (frame)->top_gutter_was_visible = flag; \ | |
57 break; \ | |
58 case BOTTOM_GUTTER: \ | |
59 (frame)->bottom_gutter_was_visible = flag; \ | |
60 break; \ | |
61 case LEFT_GUTTER: \ | |
62 (frame)->left_gutter_was_visible = flag; \ | |
63 break; \ | |
64 case RIGHT_GUTTER: \ | |
65 (frame)->right_gutter_was_visible = flag; \ | |
66 break; \ | |
67 default: \ | |
68 abort (); \ | |
69 } \ | |
70 } while (0) | |
71 | |
72 static int gutter_was_visible (struct frame* frame, enum gutter_pos pos) | |
73 { | |
74 switch (pos) | |
75 { | |
76 case TOP_GUTTER: | |
77 return frame->top_gutter_was_visible; | |
78 case BOTTOM_GUTTER: | |
79 return frame->bottom_gutter_was_visible; | |
80 case LEFT_GUTTER: | |
81 return frame->left_gutter_was_visible; | |
82 case RIGHT_GUTTER: | |
83 return frame->right_gutter_was_visible; | |
84 default: | |
85 abort (); | |
86 } | |
87 } | |
88 | |
89 static Lisp_Object | |
90 frame_topmost_window (struct frame *f) | |
91 { | |
92 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
93 | |
94 do { | |
95 while (!NILP (XWINDOW (w)->vchild)) | |
96 { | |
97 w = XWINDOW (w)->vchild; | |
98 } | |
99 } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild)); | |
100 | |
101 return w; | |
102 } | |
103 | |
104 static Lisp_Object | |
105 frame_bottommost_window (struct frame *f) | |
106 { | |
107 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
108 | |
109 do { | |
110 while (!NILP (XWINDOW (w)->vchild)) | |
111 { | |
112 w = XWINDOW (w)->vchild; | |
113 while (!NILP (XWINDOW (w)->next)) | |
114 { | |
115 w = XWINDOW (w)->next; | |
116 } | |
117 } | |
118 } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild)); | |
119 | |
120 return w; | |
121 } | |
122 | |
123 #if 0 | |
124 static Lisp_Object | |
125 frame_leftmost_window (struct frame *f) | |
126 { | |
127 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
128 | |
129 do { | |
130 while (!NILP (XWINDOW (w)->hchild)) | |
131 { | |
132 w = XWINDOW (w)->hchild; | |
133 } | |
134 } while (!NILP (XWINDOW (w)->vchild) && !NILP (w = XWINDOW (w)->vchild)); | |
135 | |
136 return w; | |
137 } | |
138 | |
139 static Lisp_Object | |
140 frame_rightmost_window (struct frame *f) | |
141 { | |
142 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
143 | |
144 do { | |
145 while (!NILP (XWINDOW (w)->hchild)) | |
146 { | |
147 w = XWINDOW (w)->hchild; | |
148 while (!NILP (XWINDOW (w)->next)) | |
149 { | |
150 w = XWINDOW (w)->next; | |
151 } | |
152 } | |
153 } while (!NILP (XWINDOW (w)->vchild) && !NILP (w = XWINDOW (w)->vchild)); | |
154 return w; | |
155 } | |
156 #endif | |
157 | |
158 /* calculate the coordinates of a gutter for the current frame and | |
159 selected window. we have to be careful in calculating this as we | |
160 need to use *two* windows, the currently selected window will give | |
161 us the actual height, width and contents of the gutter, but if we | |
162 use this for calculating the gutter positions we run into trouble | |
163 if it is not the window nearest the gutter. Instead we predetermine | |
164 the nearest window and then use that.*/ | |
165 static void | |
166 get_gutter_coords (struct frame *f, enum gutter_pos pos, int *x, int *y, | |
167 int *width, int *height) | |
168 { | |
169 struct window | |
170 * top = XWINDOW (frame_topmost_window (f)), | |
171 * bot = XWINDOW (frame_bottommost_window (f)); | |
172 /* The top and bottom gutters take precedence over the left and | |
173 right. */ | |
174 switch (pos) | |
175 { | |
176 case TOP_GUTTER: | |
177 *x = FRAME_LEFT_BORDER_END (f); | |
178 *y = FRAME_TOP_BORDER_END (f); | |
179 *width = FRAME_RIGHT_BORDER_START (f) | |
180 - FRAME_LEFT_BORDER_END (f); | |
181 *height = FRAME_TOP_GUTTER_BOUNDS (f); | |
182 break; | |
183 | |
184 case BOTTOM_GUTTER: | |
185 *x = FRAME_LEFT_BORDER_END (f); | |
186 *y = WINDOW_BOTTOM (bot) | |
187 - FRAME_BOTTOM_GUTTER_BOUNDS (f); | |
188 *width = FRAME_RIGHT_BORDER_START (f) | |
189 - FRAME_LEFT_BORDER_END (f); | |
190 *height = FRAME_BOTTOM_GUTTER_BOUNDS (f); | |
191 break; | |
192 | |
193 case LEFT_GUTTER: | |
194 *x = FRAME_LEFT_BORDER_END (f); | |
195 *y = WINDOW_TEXT_TOP (top); | |
196 *width = FRAME_LEFT_GUTTER_BOUNDS (f); | |
197 *height = WINDOW_BOTTOM (bot) | |
198 - (WINDOW_TEXT_TOP (top) | |
199 + FRAME_BOTTOM_GUTTER_BOUNDS (f)); | |
200 break; | |
201 | |
202 case RIGHT_GUTTER: | |
203 *x = FRAME_RIGHT_BORDER_START (f) | |
204 - FRAME_RIGHT_GUTTER_BOUNDS (f); | |
205 *y = WINDOW_TEXT_TOP (top); | |
206 *width = FRAME_RIGHT_GUTTER_BOUNDS (f); | |
207 *height = WINDOW_BOTTOM (bot) | |
208 - (WINDOW_TEXT_TOP (top) | |
209 + FRAME_BOTTOM_GUTTER_BOUNDS (f)); | |
210 break; | |
211 | |
212 default: | |
213 abort (); | |
214 } | |
215 } | |
216 | |
217 static void | |
218 output_gutter (struct frame *f, enum gutter_pos pos) | |
219 { | |
220 Lisp_Object frame; | |
221 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
222 struct device *d = XDEVICE (f->device); | |
223 struct window* w = XWINDOW (window); | |
224 int x, y, width, height, ypos; | |
225 int line, border_width; | |
226 face_index findex; | |
227 display_line_dynarr* ddla, *cdla; | |
228 struct display_line *dl; | |
229 int cdla_len; | |
230 | |
231 if (!WINDOW_LIVE_P (w)) | |
232 return; | |
233 | |
234 border_width = FRAME_GUTTER_BORDER_WIDTH (f, pos); | |
235 findex = get_builtin_face_cache_index (w, Vgui_element_face); | |
236 | |
237 if (!f->current_display_lines) | |
238 f->current_display_lines = Dynarr_new (display_line); | |
239 if (!f->desired_display_lines) | |
240 f->desired_display_lines = Dynarr_new (display_line); | |
241 | |
242 ddla = f->desired_display_lines; | |
243 cdla = f->current_display_lines; | |
244 cdla_len = Dynarr_length (cdla); | |
245 | |
246 XSETFRAME (frame, f); | |
247 | |
248 get_gutter_coords (f, pos, &x, &y, &width, &height); | |
249 /* generate some display lines */ | |
250 generate_displayable_area (w, WINDOW_GUTTER (w, pos), | |
251 x + border_width, y + border_width, | |
252 width - 2 * border_width, | |
253 height - 2 * border_width, ddla, 0, findex); | |
254 /* Output each line. */ | |
255 for (line = 0; line < Dynarr_length (ddla); line++) | |
256 { | |
257 output_display_line (w, cdla, ddla, line, -1, -1); | |
258 } | |
259 | |
260 /* If the number of display lines has shrunk, adjust. */ | |
261 if (cdla_len > Dynarr_length (ddla)) | |
262 { | |
263 Dynarr_length (cdla) = Dynarr_length (ddla); | |
264 } | |
265 | |
266 /* grab coordinates of last line and blank after it. */ | |
267 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); | |
268 ypos = dl->ypos + dl->descent - dl->clip; | |
269 redisplay_clear_region (window, findex, x + border_width , ypos, | |
270 width - 2 * border_width, height - (ypos - y) - border_width); | |
271 /* bevel the gutter area if so desired */ | |
272 if (border_width != 0) | |
273 { | |
274 MAYBE_DEVMETH (d, bevel_area, | |
275 (w, findex, x, y, width, height, border_width, | |
276 EDGE_ALL, EDGE_BEVEL_OUT)); | |
277 } | |
278 } | |
279 | |
280 /* sizing gutters is a pain so we try and help the user by detemining | |
281 what height will accommodate all lines. This is useless on left and | |
282 right gutters as we always have a maximal number of lines. */ | |
283 static Lisp_Object | |
284 calculate_gutter_size (struct window *w, enum gutter_pos pos) | |
285 { | |
286 struct frame* f = XFRAME (WINDOW_FRAME (w)); | |
287 int ypos; | |
288 display_line_dynarr* ddla; | |
289 struct display_line *dl; | |
290 | |
291 /* we cannot autodetect gutter sizes for the left and right as there | |
292 is no reasonable metric to use */ | |
293 assert (pos == TOP_GUTTER || pos == BOTTOM_GUTTER); | |
294 /* degenerate case */ | |
295 if (NILP (WINDOW_GUTTER (w, pos)) | |
296 || | |
297 !FRAME_VISIBLE_P (f) | |
298 || | |
299 NILP (w->buffer)) | |
300 return Qnil; | |
301 | |
302 ddla = Dynarr_new (display_line); | |
303 /* generate some display lines */ | |
304 generate_displayable_area (w, WINDOW_GUTTER (w, pos), | |
305 FRAME_LEFT_BORDER_END (f), | |
306 0, | |
307 FRAME_RIGHT_BORDER_START (f) | |
308 - FRAME_LEFT_BORDER_END (f), | |
309 200, | |
310 ddla, 0, 0); | |
311 /* grab coordinates of last line */ | |
312 if (Dynarr_length (ddla)) | |
313 { | |
314 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); | |
315 ypos = dl->ypos + dl->descent - dl->clip; | |
316 free_display_lines (ddla); | |
317 return make_int (ypos); | |
318 } | |
319 else | |
320 { | |
321 free_display_lines (ddla); | |
322 return Qnil; | |
323 } | |
324 } | |
325 | |
326 static void | |
327 clear_gutter (struct frame *f, enum gutter_pos pos) | |
328 { | |
329 int x, y, width, height; | |
330 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
331 face_index findex = get_builtin_face_cache_index (XWINDOW (window), | |
332 Vgui_element_face); | |
333 get_gutter_coords (f, pos, &x, &y, &width, &height); | |
334 | |
335 SET_GUTTER_WAS_VISIBLE_FLAG (f, pos, 0); | |
336 | |
337 redisplay_clear_region (window, findex, x, y, width, height); | |
338 } | |
339 | |
340 void | |
341 update_frame_gutters (struct frame *f) | |
342 { | |
343 if (f->gutter_changed || f->clear || | |
344 f->glyphs_changed || f->subwindows_changed || | |
345 f->windows_changed || f->windows_structure_changed || | |
346 f->extents_changed || f->faces_changed) | |
347 { | |
348 enum gutter_pos pos; | |
349 | |
350 /* We don't actually care about these when outputting the gutter | |
351 so locally disable them. */ | |
352 int local_clip_changed = f->clip_changed; | |
353 int local_buffers_changed = f->buffers_changed; | |
354 f->clip_changed = 0; | |
355 f->buffers_changed = 0; | |
356 | |
357 /* and output */ | |
358 GUTTER_POS_LOOP (pos) | |
359 { | |
360 if (FRAME_GUTTER_VISIBLE (f, pos)) | |
361 output_gutter (f, pos); | |
362 else if (gutter_was_visible (f, pos)) | |
363 clear_gutter (f, pos); | |
364 } | |
365 f->clip_changed = local_clip_changed; | |
366 f->buffers_changed = local_buffers_changed; | |
367 f->gutter_changed = 0; | |
368 } | |
369 } | |
370 | |
371 void | |
372 reset_gutter_display_lines (struct frame* f) | |
373 { | |
374 if (f->current_display_lines) | |
375 Dynarr_reset (f->current_display_lines); | |
376 } | |
377 | |
378 static void | |
379 redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y, | |
380 int width, int height) | |
381 { | |
382 int g_x, g_y, g_width, g_height; | |
383 | |
384 get_gutter_coords (f, pos, &g_x, &g_y, &g_width, &g_height); | |
385 | |
386 if (((y + height) < g_y) || (y > (g_y + g_height)) || !height || !width || !g_height || !g_width) | |
387 return; | |
388 if (((x + width) < g_x) || (x > (g_x + g_width))) | |
389 return; | |
390 | |
391 /* #### optimize this - redrawing the whole gutter for every expose | |
392 is very expensive. We reset the current display lines because if | |
393 they're being exposed they are no longer current. */ | |
394 reset_gutter_display_lines (f); | |
395 | |
396 /* 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 | |
398 that some portion of the gutter is in the exposed region. */ | |
399 output_gutter (f, pos); | |
400 } | |
401 | |
402 void | |
403 redraw_exposed_gutters (struct frame *f, int x, int y, int width, | |
404 int height) | |
405 { | |
406 enum gutter_pos pos; | |
407 GUTTER_POS_LOOP (pos) | |
408 { | |
409 if (FRAME_GUTTER_VISIBLE (f, pos)) | |
410 redraw_exposed_gutter (f, pos, x, y, width, height); | |
411 } | |
412 } | |
413 | |
414 void | |
415 free_frame_gutters (struct frame *f) | |
416 { | |
417 if (f->current_display_lines) | |
418 { | |
419 free_display_lines (f->current_display_lines); | |
420 f->current_display_lines = 0; | |
421 } | |
422 if (f->desired_display_lines) | |
423 { | |
424 free_display_lines (f->desired_display_lines); | |
425 f->desired_display_lines = 0; | |
426 } | |
427 } | |
428 | |
429 static enum gutter_pos | |
430 decode_gutter_position (Lisp_Object position) | |
431 { | |
432 if (EQ (position, Qtop)) return TOP_GUTTER; | |
433 if (EQ (position, Qbottom)) return BOTTOM_GUTTER; | |
434 if (EQ (position, Qleft)) return LEFT_GUTTER; | |
435 if (EQ (position, Qright)) return RIGHT_GUTTER; | |
436 signal_simple_error ("Invalid gutter position", position); | |
437 | |
438 return TOP_GUTTER; /* not reached */ | |
439 } | |
440 | |
441 DEFUN ("set-default-gutter-position", Fset_default_gutter_position, 1, 1, 0, /* | |
442 Set the position that the `default-gutter' will be displayed at. | |
443 Valid positions are 'top, 'bottom, 'left and 'right. | |
444 See `default-gutter-position'. | |
445 */ | |
446 (position)) | |
447 { | |
448 enum gutter_pos cur = decode_gutter_position (Vdefault_gutter_position); | |
449 enum gutter_pos new = decode_gutter_position (position); | |
450 | |
451 if (cur != new) | |
452 { | |
453 /* The following calls will automatically cause the dirty | |
454 flags to be set; we delay frame size changes to avoid | |
455 lots of frame flickering. */ | |
456 /* #### I think this should be GC protected. -sb */ | |
457 hold_frame_size_changes (); | |
458 set_specifier_fallback (Vgutter[cur], list1 (Fcons (Qnil, Qnil))); | |
459 set_specifier_fallback (Vgutter[new], Vdefault_gutter); | |
460 set_specifier_fallback (Vgutter_size[cur], list1 (Fcons (Qnil, Qzero))); | |
461 set_specifier_fallback (Vgutter_size[new], | |
462 new == TOP_GUTTER || new == BOTTOM_GUTTER | |
463 ? Vdefault_gutter_height | |
464 : Vdefault_gutter_width); | |
465 set_specifier_fallback (Vgutter_border_width[cur], | |
466 list1 (Fcons (Qnil, Qzero))); | |
467 set_specifier_fallback (Vgutter_border_width[new], | |
468 Vdefault_gutter_border_width); | |
469 set_specifier_fallback (Vgutter_visible_p[cur], | |
470 list1 (Fcons (Qnil, Qt))); | |
471 set_specifier_fallback (Vgutter_visible_p[new], | |
472 Vdefault_gutter_visible_p); | |
473 Vdefault_gutter_position = position; | |
474 unhold_frame_size_changes (); | |
475 } | |
476 | |
477 return position; | |
478 } | |
479 | |
480 DEFUN ("default-gutter-position", Fdefault_gutter_position, 0, 0, 0, /* | |
481 Return the position that the `default-gutter' will be displayed at. | |
482 The `default-gutter' will only be displayed here if the corresponding | |
483 position-specific gutter specifier does not provide a value. | |
484 */ | |
485 ()) | |
486 { | |
487 return Vdefault_gutter_position; | |
488 } | |
489 | |
490 DEFUN ("gutter-pixel-width", Fgutter_pixel_width, 0, 2, 0, /* | |
491 Return the pixel width of the gutter at POS in LOCALE. | |
492 POS defaults to the default gutter position. LOCALE defaults to | |
493 the current window. | |
494 */ | |
495 (pos, locale)) | |
496 { | |
497 int x, y, width, height; | |
498 enum gutter_pos p = TOP_GUTTER; | |
499 struct frame *f = decode_frame (FW_FRAME (locale)); | |
500 | |
501 if (NILP (pos)) | |
502 pos = Vdefault_gutter_position; | |
503 p = decode_gutter_position (pos); | |
504 | |
505 get_gutter_coords (f, p, &x, &y, &width, &height); | |
506 width -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2); | |
507 | |
508 return make_int (width); | |
509 } | |
510 | |
511 DEFUN ("gutter-pixel-height", Fgutter_pixel_height, 0, 2, 0, /* | |
512 Return the pixel height of the gutter at POS in LOCALE. | |
513 POS defaults to the default gutter position. LOCALE defaults to | |
514 the current window. | |
515 */ | |
516 (pos, locale)) | |
517 { | |
518 int x, y, width, height; | |
519 enum gutter_pos p = TOP_GUTTER; | |
520 struct frame *f = decode_frame (FW_FRAME (locale)); | |
521 | |
522 if (NILP (pos)) | |
523 pos = Vdefault_gutter_position; | |
524 p = decode_gutter_position (pos); | |
525 | |
526 get_gutter_coords (f, p, &x, &y, &width, &height); | |
527 height -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2); | |
528 | |
529 return make_int (height); | |
530 } | |
531 | |
532 DEFINE_SPECIFIER_TYPE (gutter); | |
533 | |
534 static void | |
535 gutter_after_change (Lisp_Object specifier, Lisp_Object locale) | |
536 { | |
537 MARK_GUTTER_CHANGED; | |
538 } | |
539 | |
540 static void | |
541 gutter_validate (Lisp_Object instantiator) | |
542 { | |
543 if (NILP (instantiator)) | |
544 return; | |
545 | |
546 if (!STRINGP (instantiator)) | |
547 signal_simple_error ("Gutter spec must be string or nil", instantiator); | |
548 } | |
549 | |
550 DEFUN ("gutter-specifier-p", Fgutter_specifier_p, 1, 1, 0, /* | |
551 Return non-nil if OBJECT is a gutter specifier. | |
552 Gutter specifiers are used to specify the format of a gutter. | |
553 The values of the variables `default-gutter', `top-gutter', | |
554 `left-gutter', `right-gutter', and `bottom-gutter' are always | |
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 */ | |
561 (object)) | |
562 { | |
563 return GUTTER_SPECIFIERP (object) ? Qt : Qnil; | |
564 } | |
565 | |
566 | |
567 /* | |
568 Helper for invalidating the real specifier when default | |
569 specifier caching changes | |
570 */ | |
571 static void | |
572 recompute_overlaying_specifier (Lisp_Object real_one[4]) | |
573 { | |
574 enum gutter_pos pos = decode_gutter_position (Vdefault_gutter_position); | |
575 Fset_specifier_dirty_flag (real_one[pos]); | |
576 } | |
577 | |
578 static void | |
579 gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
580 Lisp_Object oldval) | |
581 { | |
582 enum gutter_pos pos; | |
583 GUTTER_POS_LOOP (pos) | |
584 { | |
585 w->real_gutter_size[pos] = w->gutter_size[pos]; | |
586 if (EQ (w->real_gutter_size[pos], Qautodetect) | |
587 && !NILP (w->gutter_visible_p[pos])) | |
588 { | |
589 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); | |
590 } | |
591 } | |
592 MARK_GUTTER_CHANGED; | |
593 MARK_WINDOWS_CHANGED (w); | |
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); | |
620 } | |
621 | |
622 static void | |
623 default_gutter_size_changed_in_window (Lisp_Object specifier, struct window *w, | |
624 Lisp_Object oldval) | |
625 { | |
626 recompute_overlaying_specifier (Vgutter_size); | |
627 } | |
628 | |
629 static void | |
630 default_gutter_border_width_changed_in_window (Lisp_Object specifier, | |
631 struct window *w, | |
632 Lisp_Object oldval) | |
633 { | |
634 recompute_overlaying_specifier (Vgutter_border_width); | |
635 } | |
636 | |
637 static void | |
638 default_gutter_visible_p_changed_in_window (Lisp_Object specifier, | |
639 struct window *w, | |
640 Lisp_Object oldval) | |
641 { | |
642 recompute_overlaying_specifier (Vgutter_visible_p); | |
643 } | |
644 | |
645 | |
646 DECLARE_SPECIFIER_TYPE (gutter_size); | |
647 #define GUTTER_SIZE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_size) | |
648 DEFINE_SPECIFIER_TYPE (gutter_size); | |
649 | |
650 static void | |
651 gutter_size_validate (Lisp_Object instantiator) | |
652 { | |
653 if (NILP (instantiator)) | |
654 return; | |
655 | |
656 if (!INTP (instantiator) && !EQ (instantiator, Qautodetect)) | |
657 signal_simple_error ("Gutter size must be an integer or 'autodetect", instantiator); | |
658 } | |
659 | |
660 DEFUN ("gutter-size-specifier-p", Fgutter_size_specifier_p, 1, 1, 0, /* | |
661 Return non-nil if OBJECT is a gutter-size specifier. | |
662 */ | |
663 (object)) | |
664 { | |
665 return GUTTER_SIZE_SPECIFIERP (object) ? Qt : Qnil; | |
666 } | |
667 | |
668 DEFUN ("redisplay-gutter-area", Fredisplay_gutter_area, 0, 0, 0, /* | |
669 Ensure that all gutters are correctly showing their gutter specifier. | |
670 */ | |
671 ()) | |
672 { | |
673 Lisp_Object devcons, concons; | |
674 | |
675 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
676 { | |
677 struct device *d = XDEVICE (XCAR (devcons)); | |
678 Lisp_Object frmcons; | |
679 | |
680 DEVICE_FRAME_LOOP (frmcons, d) | |
681 { | |
682 struct frame *f = XFRAME (XCAR (frmcons)); | |
683 | |
684 if (FRAME_REPAINT_P (f)) | |
685 { | |
686 update_frame_gutters (f); | |
687 } | |
688 } | |
689 | |
690 /* We now call the output_end routine for tty frames. We delay | |
691 doing so in order to avoid cursor flicker. So much for 100% | |
692 encapsulation. */ | |
693 if (DEVICE_TTY_P (d)) | |
694 DEVMETH (d, output_end, (d)); | |
695 } | |
696 | |
697 return Qnil; | |
698 } | |
699 | |
700 void | |
701 init_frame_gutters (struct frame *f) | |
702 { | |
703 enum gutter_pos pos; | |
704 struct window* w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)); | |
705 /* We are here as far in frame creation so cached specifiers are | |
706 already recomputed, and possibly modified by resource | |
707 initialization. We need to recalculate autodetected gutters. */ | |
708 GUTTER_POS_LOOP (pos) | |
709 { | |
710 w->real_gutter_size[pos] = w->gutter_size[pos]; | |
711 if (EQ (w->gutter_size[pos], Qautodetect) | |
712 && !NILP (w->gutter_visible_p[pos])) | |
713 { | |
714 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); | |
715 MARK_GUTTER_CHANGED; | |
716 MARK_WINDOWS_CHANGED (w); | |
717 } | |
718 } | |
719 } | |
720 | |
721 void | |
722 syms_of_gutter (void) | |
723 { | |
724 DEFSUBR (Fgutter_specifier_p); | |
725 DEFSUBR (Fgutter_size_specifier_p); | |
726 DEFSUBR (Fset_default_gutter_position); | |
727 DEFSUBR (Fdefault_gutter_position); | |
728 DEFSUBR (Fgutter_pixel_height); | |
729 DEFSUBR (Fgutter_pixel_width); | |
730 DEFSUBR (Fredisplay_gutter_area); | |
731 | |
732 defsymbol (&Qgutter_size, "gutter-size"); | |
733 } | |
734 | |
735 void | |
736 vars_of_gutter (void) | |
737 { | |
738 staticpro (&Vdefault_gutter_position); | |
739 Vdefault_gutter_position = Qtop; | |
740 | |
741 Fprovide (Qgutter); | |
742 } | |
743 | |
744 void | |
745 specifier_type_create_gutter (void) | |
746 { | |
747 INITIALIZE_SPECIFIER_TYPE (gutter, "gutter", "gutter-specifier-p"); | |
748 | |
749 SPECIFIER_HAS_METHOD (gutter, validate); | |
750 SPECIFIER_HAS_METHOD (gutter, after_change); | |
751 | |
752 INITIALIZE_SPECIFIER_TYPE (gutter_size, "gutter-size", "gutter-size-specifier-p"); | |
753 | |
754 SPECIFIER_HAS_METHOD (gutter_size, validate); | |
755 } | |
756 | |
757 void | |
758 reinit_specifier_type_create_gutter (void) | |
759 { | |
760 REINITIALIZE_SPECIFIER_TYPE (gutter); | |
761 REINITIALIZE_SPECIFIER_TYPE (gutter_size); | |
762 } | |
763 | |
764 void | |
765 specifier_vars_of_gutter (void) | |
766 { | |
767 Lisp_Object fb; | |
768 | |
769 DEFVAR_SPECIFIER ("default-gutter", &Vdefault_gutter /* | |
770 Specifier for a fallback gutter. | |
771 Use `set-specifier' to change this. | |
772 | |
773 The position of this gutter is specified in the function | |
774 `default-gutter-position'. If the corresponding position-specific | |
775 gutter (e.g. `top-gutter' if `default-gutter-position' is 'top) | |
776 does not specify a gutter in a particular domain (usually a window), | |
777 then the value of `default-gutter' in that domain, if any, will be | |
778 used instead. | |
779 | |
780 Note that the gutter at any particular position will not be | |
781 displayed unless its visibility flag is true and its thickness | |
782 \(width or height, depending on orientation) is non-zero. The | |
783 visibility is controlled by the specifiers `top-gutter-visible-p', | |
784 `bottom-gutter-visible-p', `left-gutter-visible-p', and | |
785 `right-gutter-visible-p', and the thickness is controlled by the | |
786 specifiers `top-gutter-height', `bottom-gutter-height', | |
787 `left-gutter-width', and `right-gutter-width'. | |
788 | |
789 Note that one of the four visibility specifiers inherits from | |
790 `default-gutter-visibility' and one of the four thickness | |
791 specifiers inherits from either `default-gutter-width' or | |
792 `default-gutter-height' (depending on orientation), just | |
793 like for the gutter description specifiers (e.g. `top-gutter') | |
794 mentioned above. | |
795 | |
796 Therefore, if you are setting `default-gutter', you should control | |
797 the visibility and thickness using `default-gutter-visible-p', | |
798 `default-gutter-width', and `default-gutter-height', rather than | |
799 using position-specific specifiers. That way, you will get sane | |
800 behavior if the user changes the default gutter position. | |
801 | |
802 The gutter value should be a string or nil. You can attach extents and | |
803 glyphs to the string and hence display glyphs and text in other fonts | |
804 in the gutter area. | |
805 | |
806 */ ); | |
807 | |
808 Vdefault_gutter = Fmake_specifier (Qgutter); | |
809 /* #### It would be even nicer if the specifier caching | |
810 automatically knew about specifier fallbacks, so we didn't | |
811 have to do it ourselves. */ | |
812 set_specifier_caching (Vdefault_gutter, | |
813 offsetof (struct window, default_gutter), | |
814 default_gutter_specs_changed, | |
815 0, 0); | |
816 | |
817 DEFVAR_SPECIFIER ("top-gutter", | |
818 &Vgutter[TOP_GUTTER] /* | |
819 Specifier for the gutter at the top of the frame. | |
820 Use `set-specifier' to change this. | |
821 See `default-gutter' for a description of a valid gutter instantiator. | |
822 */ ); | |
823 Vgutter[TOP_GUTTER] = Fmake_specifier (Qgutter); | |
824 set_specifier_caching (Vgutter[TOP_GUTTER], | |
825 offsetof (struct window, gutter[TOP_GUTTER]), | |
826 gutter_specs_changed, | |
827 0, 0); | |
828 | |
829 DEFVAR_SPECIFIER ("bottom-gutter", | |
830 &Vgutter[BOTTOM_GUTTER] /* | |
831 Specifier for the gutter at the bottom of the frame. | |
832 Use `set-specifier' to change this. | |
833 See `default-gutter' for a description of a valid gutter instantiator. | |
834 | |
835 Note that, unless the `default-gutter-position' is `bottom', by | |
836 default the height of the bottom gutter (controlled by | |
837 `bottom-gutter-height') is 0; thus, a bottom gutter will not be | |
838 displayed even if you provide a value for `bottom-gutter'. | |
839 */ ); | |
840 Vgutter[BOTTOM_GUTTER] = Fmake_specifier (Qgutter); | |
841 set_specifier_caching (Vgutter[BOTTOM_GUTTER], | |
842 offsetof (struct window, gutter[BOTTOM_GUTTER]), | |
843 gutter_specs_changed, | |
844 0, 0); | |
845 | |
846 DEFVAR_SPECIFIER ("left-gutter", | |
847 &Vgutter[LEFT_GUTTER] /* | |
848 Specifier for the gutter at the left edge of the frame. | |
849 Use `set-specifier' to change this. | |
850 See `default-gutter' for a description of a valid gutter instantiator. | |
851 | |
852 Note that, unless the `default-gutter-position' is `left', by | |
853 default the height of the left gutter (controlled by | |
854 `left-gutter-width') is 0; thus, a left gutter will not be | |
855 displayed even if you provide a value for `left-gutter'. | |
856 */ ); | |
857 Vgutter[LEFT_GUTTER] = Fmake_specifier (Qgutter); | |
858 set_specifier_caching (Vgutter[LEFT_GUTTER], | |
859 offsetof (struct window, gutter[LEFT_GUTTER]), | |
860 gutter_specs_changed, | |
861 0, 0); | |
862 | |
863 DEFVAR_SPECIFIER ("right-gutter", | |
864 &Vgutter[RIGHT_GUTTER] /* | |
865 Specifier for the gutter at the right edge of the frame. | |
866 Use `set-specifier' to change this. | |
867 See `default-gutter' for a description of a valid gutter instantiator. | |
868 | |
869 Note that, unless the `default-gutter-position' is `right', by | |
870 default the height of the right gutter (controlled by | |
871 `right-gutter-width') is 0; thus, a right gutter will not be | |
872 displayed even if you provide a value for `right-gutter'. | |
873 */ ); | |
874 Vgutter[RIGHT_GUTTER] = Fmake_specifier (Qgutter); | |
875 set_specifier_caching (Vgutter[RIGHT_GUTTER], | |
876 offsetof (struct window, gutter[RIGHT_GUTTER]), | |
877 gutter_specs_changed, | |
878 0, 0); | |
879 | |
880 /* initially, top inherits from default; this can be | |
881 changed with `set-default-gutter-position'. */ | |
882 fb = list1 (Fcons (Qnil, Qnil)); | |
883 set_specifier_fallback (Vdefault_gutter, fb); | |
884 set_specifier_fallback (Vgutter[TOP_GUTTER], Vdefault_gutter); | |
885 set_specifier_fallback (Vgutter[BOTTOM_GUTTER], fb); | |
886 set_specifier_fallback (Vgutter[LEFT_GUTTER], fb); | |
887 set_specifier_fallback (Vgutter[RIGHT_GUTTER], fb); | |
888 | |
889 DEFVAR_SPECIFIER ("default-gutter-height", &Vdefault_gutter_height /* | |
890 *Height of the default gutter, if it's oriented horizontally. | |
891 This is a specifier; use `set-specifier' to change it. | |
892 | |
893 The position of the default gutter is specified by the function | |
894 `set-default-gutter-position'. If the corresponding position-specific | |
895 gutter thickness specifier (e.g. `top-gutter-height' if | |
896 `default-gutter-position' is 'top) does not specify a thickness in a | |
897 particular domain (a window or a frame), then the value of | |
898 `default-gutter-height' or `default-gutter-width' (depending on the | |
899 gutter orientation) in that domain, if any, will be used instead. | |
900 | |
901 Note that `default-gutter-height' is only used when | |
902 `default-gutter-position' is 'top or 'bottom, and `default-gutter-width' | |
903 is only used when `default-gutter-position' is 'left or 'right. | |
904 | |
905 Note that all of the position-specific gutter thickness specifiers | |
906 have a fallback value of zero when they do not correspond to the | |
907 default gutter. Therefore, you will have to set a non-zero thickness | |
908 value if you want a position-specific gutter to be displayed. | |
909 | |
910 If you set the height to 'autodetect the size of the gutter will be | |
911 calculated to be large enough to hold the contents of the gutter. This | |
912 is the default. | |
913 */ ); | |
914 Vdefault_gutter_height = Fmake_specifier (Qgutter_size); | |
915 set_specifier_caching (Vdefault_gutter_height, | |
916 offsetof (struct window, default_gutter_height), | |
917 default_gutter_size_changed_in_window, | |
918 0, 0); | |
919 | |
920 DEFVAR_SPECIFIER ("default-gutter-width", &Vdefault_gutter_width /* | |
921 *Width of the default gutter, if it's oriented vertically. | |
922 This is a specifier; use `set-specifier' to change it. | |
923 | |
924 See `default-gutter-height' for more information. | |
925 */ ); | |
926 Vdefault_gutter_width = Fmake_specifier (Qnatnum); | |
927 set_specifier_caching (Vdefault_gutter_width, | |
928 offsetof (struct window, default_gutter_width), | |
929 default_gutter_size_changed_in_window, | |
930 0, 0); | |
931 | |
932 DEFVAR_SPECIFIER ("top-gutter-height", | |
933 &Vgutter_size[TOP_GUTTER] /* | |
934 *Height of the top gutter. | |
935 This is a specifier; use `set-specifier' to change it. | |
936 | |
937 See `default-gutter-height' for more information. | |
938 */ ); | |
939 Vgutter_size[TOP_GUTTER] = Fmake_specifier (Qgutter_size); | |
940 set_specifier_caching (Vgutter_size[TOP_GUTTER], | |
941 offsetof (struct window, gutter_size[TOP_GUTTER]), | |
942 gutter_geometry_changed_in_window, | |
943 0, 0); | |
944 | |
945 DEFVAR_SPECIFIER ("bottom-gutter-height", | |
946 &Vgutter_size[BOTTOM_GUTTER] /* | |
947 *Height of the bottom gutter. | |
948 This is a specifier; use `set-specifier' to change it. | |
949 | |
950 See `default-gutter-height' for more information. | |
951 */ ); | |
952 Vgutter_size[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_size); | |
953 set_specifier_caching (Vgutter_size[BOTTOM_GUTTER], | |
954 offsetof (struct window, gutter_size[BOTTOM_GUTTER]), | |
955 gutter_geometry_changed_in_window, | |
956 0, 0); | |
957 | |
958 DEFVAR_SPECIFIER ("left-gutter-width", | |
959 &Vgutter_size[LEFT_GUTTER] /* | |
960 *Width of left gutter. | |
961 This is a specifier; use `set-specifier' to change it. | |
962 | |
963 See `default-gutter-height' for more information. | |
964 */ ); | |
965 Vgutter_size[LEFT_GUTTER] = Fmake_specifier (Qnatnum); | |
966 set_specifier_caching (Vgutter_size[LEFT_GUTTER], | |
967 offsetof (struct window, gutter_size[LEFT_GUTTER]), | |
968 gutter_geometry_changed_in_window, | |
969 0, 0); | |
970 | |
971 DEFVAR_SPECIFIER ("right-gutter-width", | |
972 &Vgutter_size[RIGHT_GUTTER] /* | |
973 *Width of right gutter. | |
974 This is a specifier; use `set-specifier' to change it. | |
975 | |
976 See `default-gutter-height' for more information. | |
977 */ ); | |
978 Vgutter_size[RIGHT_GUTTER] = Fmake_specifier (Qnatnum); | |
979 set_specifier_caching (Vgutter_size[RIGHT_GUTTER], | |
980 offsetof (struct window, gutter_size[RIGHT_GUTTER]), | |
981 gutter_geometry_changed_in_window, | |
982 0, 0); | |
983 | |
984 fb = Qnil; | |
985 #ifdef HAVE_TTY | |
986 fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb); | |
987 #endif | |
988 #ifdef HAVE_X_WINDOWS | |
989 fb = Fcons (Fcons (list1 (Qx), Qautodetect), fb); | |
990 #endif | |
991 #ifdef HAVE_MS_WINDOWS | |
992 fb = Fcons (Fcons (list1 (Qmsprinter), Qautodetect), fb); | |
993 fb = Fcons (Fcons (list1 (Qmswindows), Qautodetect), fb); | |
994 #endif | |
995 if (!NILP (fb)) | |
996 set_specifier_fallback (Vdefault_gutter_height, fb); | |
997 | |
998 fb = Qnil; | |
999 #ifdef HAVE_TTY | |
1000 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb); | |
1001 #endif | |
1002 #ifdef HAVE_X_WINDOWS | |
1003 fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_GUTTER_WIDTH)), fb); | |
1004 #endif | |
1005 #ifdef HAVE_MS_WINDOWS | |
1006 fb = Fcons (Fcons (list1 (Qmsprinter), Qzero), fb); | |
1007 fb = Fcons (Fcons (list1 (Qmswindows), | |
1008 make_int (DEFAULT_GUTTER_WIDTH)), fb); | |
1009 #endif | |
1010 if (!NILP (fb)) | |
1011 set_specifier_fallback (Vdefault_gutter_width, fb); | |
1012 | |
1013 set_specifier_fallback (Vgutter_size[TOP_GUTTER], Vdefault_gutter_height); | |
1014 fb = list1 (Fcons (Qnil, Qzero)); | |
1015 set_specifier_fallback (Vgutter_size[BOTTOM_GUTTER], fb); | |
1016 set_specifier_fallback (Vgutter_size[LEFT_GUTTER], fb); | |
1017 set_specifier_fallback (Vgutter_size[RIGHT_GUTTER], fb); | |
1018 | |
1019 DEFVAR_SPECIFIER ("default-gutter-border-width", | |
1020 &Vdefault_gutter_border_width /* | |
1021 *Width of the border around the default gutter. | |
1022 This is a specifier; use `set-specifier' to change it. | |
1023 | |
1024 The position of the default gutter is specified by the function | |
1025 `set-default-gutter-position'. If the corresponding position-specific | |
1026 gutter border width specifier (e.g. `top-gutter-border-width' if | |
1027 `default-gutter-position' is 'top) does not specify a border width in a | |
1028 particular domain (a window or a frame), then the value of | |
1029 `default-gutter-border-width' in that domain, if any, will be used | |
1030 instead. | |
1031 | |
1032 */ ); | |
1033 Vdefault_gutter_border_width = Fmake_specifier (Qnatnum); | |
1034 set_specifier_caching (Vdefault_gutter_border_width, | |
1035 offsetof (struct window, default_gutter_border_width), | |
1036 default_gutter_border_width_changed_in_window, | |
1037 0, 0); | |
1038 | |
1039 DEFVAR_SPECIFIER ("top-gutter-border-width", | |
1040 &Vgutter_border_width[TOP_GUTTER] /* | |
1041 *Border width of the top gutter. | |
1042 This is a specifier; use `set-specifier' to change it. | |
1043 | |
1044 See `default-gutter-height' for more information. | |
1045 */ ); | |
1046 Vgutter_border_width[TOP_GUTTER] = Fmake_specifier (Qnatnum); | |
1047 set_specifier_caching (Vgutter_border_width[TOP_GUTTER], | |
1048 offsetof (struct window, | |
1049 gutter_border_width[TOP_GUTTER]), | |
1050 gutter_geometry_changed_in_window, | |
1051 0, 0); | |
1052 | |
1053 DEFVAR_SPECIFIER ("bottom-gutter-border-width", | |
1054 &Vgutter_border_width[BOTTOM_GUTTER] /* | |
1055 *Border width of the bottom gutter. | |
1056 This is a specifier; use `set-specifier' to change it. | |
1057 | |
1058 See `default-gutter-height' for more information. | |
1059 */ ); | |
1060 Vgutter_border_width[BOTTOM_GUTTER] = Fmake_specifier (Qnatnum); | |
1061 set_specifier_caching (Vgutter_border_width[BOTTOM_GUTTER], | |
1062 offsetof (struct window, | |
1063 gutter_border_width[BOTTOM_GUTTER]), | |
1064 gutter_geometry_changed_in_window, | |
1065 0, 0); | |
1066 | |
1067 DEFVAR_SPECIFIER ("left-gutter-border-width", | |
1068 &Vgutter_border_width[LEFT_GUTTER] /* | |
1069 *Border width of left gutter. | |
1070 This is a specifier; use `set-specifier' to change it. | |
1071 | |
1072 See `default-gutter-height' for more information. | |
1073 */ ); | |
1074 Vgutter_border_width[LEFT_GUTTER] = Fmake_specifier (Qnatnum); | |
1075 set_specifier_caching (Vgutter_border_width[LEFT_GUTTER], | |
1076 offsetof (struct window, | |
1077 gutter_border_width[LEFT_GUTTER]), | |
1078 gutter_geometry_changed_in_window, | |
1079 0, 0); | |
1080 | |
1081 DEFVAR_SPECIFIER ("right-gutter-border-width", | |
1082 &Vgutter_border_width[RIGHT_GUTTER] /* | |
1083 *Border width of right gutter. | |
1084 This is a specifier; use `set-specifier' to change it. | |
1085 | |
1086 See `default-gutter-height' for more information. | |
1087 */ ); | |
1088 Vgutter_border_width[RIGHT_GUTTER] = Fmake_specifier (Qnatnum); | |
1089 set_specifier_caching (Vgutter_border_width[RIGHT_GUTTER], | |
1090 offsetof (struct window, | |
1091 gutter_border_width[RIGHT_GUTTER]), | |
1092 gutter_geometry_changed_in_window, | |
1093 0, 0); | |
1094 | |
1095 fb = Qnil; | |
1096 #ifdef HAVE_TTY | |
1097 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb); | |
1098 #endif | |
1099 #ifdef HAVE_X_WINDOWS | |
1100 fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_GUTTER_BORDER_WIDTH)), fb); | |
1101 #endif | |
1102 #ifdef HAVE_MS_WINDOWS | |
1103 fb = Fcons (Fcons (list1 (Qmsprinter), Qzero), fb); | |
1104 fb = Fcons (Fcons (list1 (Qmswindows), make_int (DEFAULT_GUTTER_BORDER_WIDTH)), fb); | |
1105 #endif | |
1106 if (!NILP (fb)) | |
1107 set_specifier_fallback (Vdefault_gutter_border_width, fb); | |
1108 | |
1109 set_specifier_fallback (Vgutter_border_width[TOP_GUTTER], Vdefault_gutter_border_width); | |
1110 fb = list1 (Fcons (Qnil, Qzero)); | |
1111 set_specifier_fallback (Vgutter_border_width[BOTTOM_GUTTER], fb); | |
1112 set_specifier_fallback (Vgutter_border_width[LEFT_GUTTER], fb); | |
1113 set_specifier_fallback (Vgutter_border_width[RIGHT_GUTTER], fb); | |
1114 | |
1115 DEFVAR_SPECIFIER ("default-gutter-visible-p", &Vdefault_gutter_visible_p /* | |
1116 *Whether the default gutter is visible. | |
1117 This is a specifier; use `set-specifier' to change it. | |
1118 | |
1119 The position of the default gutter is specified by the function | |
1120 `set-default-gutter-position'. If the corresponding position-specific | |
1121 gutter visibility specifier (e.g. `top-gutter-visible-p' if | |
1122 `default-gutter-position' is 'top) does not specify a visible-p value | |
1123 in a particular domain (a window or a frame), then the value of | |
1124 `default-gutter-visible-p' in that domain, if any, will be used | |
1125 instead. | |
1126 | |
1127 `default-gutter-visible-p' and all of the position-specific gutter | |
1128 visibility specifiers have a fallback value of true. | |
1129 */ ); | |
1130 Vdefault_gutter_visible_p = Fmake_specifier (Qboolean); | |
1131 set_specifier_caching (Vdefault_gutter_visible_p, | |
1132 offsetof (struct window, | |
1133 default_gutter_visible_p), | |
1134 default_gutter_visible_p_changed_in_window, | |
1135 0, 0); | |
1136 | |
1137 DEFVAR_SPECIFIER ("top-gutter-visible-p", | |
1138 &Vgutter_visible_p[TOP_GUTTER] /* | |
1139 *Whether the top gutter is visible. | |
1140 This is a specifier; use `set-specifier' to change it. | |
1141 | |
1142 See `default-gutter-visible-p' for more information. | |
1143 */ ); | |
1144 Vgutter_visible_p[TOP_GUTTER] = Fmake_specifier (Qboolean); | |
1145 set_specifier_caching (Vgutter_visible_p[TOP_GUTTER], | |
1146 offsetof (struct window, | |
1147 gutter_visible_p[TOP_GUTTER]), | |
1148 gutter_geometry_changed_in_window, | |
1149 0, 0); | |
1150 | |
1151 DEFVAR_SPECIFIER ("bottom-gutter-visible-p", | |
1152 &Vgutter_visible_p[BOTTOM_GUTTER] /* | |
1153 *Whether the bottom gutter is visible. | |
1154 This is a specifier; use `set-specifier' to change it. | |
1155 | |
1156 See `default-gutter-visible-p' for more information. | |
1157 */ ); | |
1158 Vgutter_visible_p[BOTTOM_GUTTER] = Fmake_specifier (Qboolean); | |
1159 set_specifier_caching (Vgutter_visible_p[BOTTOM_GUTTER], | |
1160 offsetof (struct window, | |
1161 gutter_visible_p[BOTTOM_GUTTER]), | |
1162 gutter_geometry_changed_in_window, | |
1163 0, 0); | |
1164 | |
1165 DEFVAR_SPECIFIER ("left-gutter-visible-p", | |
1166 &Vgutter_visible_p[LEFT_GUTTER] /* | |
1167 *Whether the left gutter is visible. | |
1168 This is a specifier; use `set-specifier' to change it. | |
1169 | |
1170 See `default-gutter-visible-p' for more information. | |
1171 */ ); | |
1172 Vgutter_visible_p[LEFT_GUTTER] = Fmake_specifier (Qboolean); | |
1173 set_specifier_caching (Vgutter_visible_p[LEFT_GUTTER], | |
1174 offsetof (struct window, | |
1175 gutter_visible_p[LEFT_GUTTER]), | |
1176 gutter_geometry_changed_in_window, | |
1177 0, 0); | |
1178 | |
1179 DEFVAR_SPECIFIER ("right-gutter-visible-p", | |
1180 &Vgutter_visible_p[RIGHT_GUTTER] /* | |
1181 *Whether the right gutter is visible. | |
1182 This is a specifier; use `set-specifier' to change it. | |
1183 | |
1184 See `default-gutter-visible-p' for more information. | |
1185 */ ); | |
1186 Vgutter_visible_p[RIGHT_GUTTER] = Fmake_specifier (Qboolean); | |
1187 set_specifier_caching (Vgutter_visible_p[RIGHT_GUTTER], | |
1188 offsetof (struct window, | |
1189 gutter_visible_p[RIGHT_GUTTER]), | |
1190 gutter_geometry_changed_in_window, | |
1191 0, 0); | |
1192 | |
1193 /* initially, top inherits from default; this can be | |
1194 changed with `set-default-gutter-position'. */ | |
1195 fb = list1 (Fcons (Qnil, Qt)); | |
1196 set_specifier_fallback (Vdefault_gutter_visible_p, fb); | |
1197 set_specifier_fallback (Vgutter_visible_p[TOP_GUTTER], | |
1198 Vdefault_gutter_visible_p); | |
1199 set_specifier_fallback (Vgutter_visible_p[BOTTOM_GUTTER], fb); | |
1200 set_specifier_fallback (Vgutter_visible_p[LEFT_GUTTER], fb); | |
1201 set_specifier_fallback (Vgutter_visible_p[RIGHT_GUTTER], fb); | |
1202 } |