Mercurial > hg > xemacs-beta
annotate src/gutter.c @ 5043:d0c14ea98592
various frame-geometry fixes
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-02-15 Ben Wing <ben@xemacs.org>
* EmacsFrame.c:
* EmacsFrame.c (EmacsFrameResize):
* console-msw-impl.h:
* console-msw-impl.h (struct mswindows_frame):
* console-msw-impl.h (FRAME_MSWINDOWS_TARGET_RECT):
* device-tty.c:
* device-tty.c (tty_asynch_device_change):
* event-msw.c:
* event-msw.c (mswindows_wnd_proc):
* faces.c (Fface_list):
* faces.h:
* frame-gtk.c:
* frame-gtk.c (gtk_set_initial_frame_size):
* frame-gtk.c (gtk_set_frame_size):
* frame-msw.c:
* frame-msw.c (mswindows_init_frame_1):
* frame-msw.c (mswindows_set_frame_size):
* frame-msw.c (mswindows_size_frame_internal):
* frame-msw.c (msprinter_init_frame_3):
* frame.c:
* frame.c (enum):
* frame.c (Fmake_frame):
* frame.c (adjust_frame_size):
* frame.c (store_minibuf_frame_prop):
* frame.c (Fframe_property):
* frame.c (Fframe_properties):
* frame.c (Fframe_displayable_pixel_height):
* frame.c (Fframe_displayable_pixel_width):
* frame.c (internal_set_frame_size):
* frame.c (Fset_frame_height):
* frame.c (Fset_frame_pixel_height):
* frame.c (Fset_frame_displayable_pixel_height):
* frame.c (Fset_frame_width):
* frame.c (Fset_frame_pixel_width):
* frame.c (Fset_frame_displayable_pixel_width):
* frame.c (Fset_frame_size):
* frame.c (Fset_frame_pixel_size):
* frame.c (Fset_frame_displayable_pixel_size):
* frame.c (frame_conversion_internal_1):
* frame.c (get_frame_displayable_pixel_size):
* frame.c (change_frame_size_1):
* frame.c (change_frame_size):
* frame.c (generate_title_string):
* frame.h:
* gtk-xemacs.c:
* gtk-xemacs.c (gtk_xemacs_size_request):
* gtk-xemacs.c (gtk_xemacs_size_allocate):
* gtk-xemacs.c (gtk_xemacs_paint):
* gutter.c:
* gutter.c (update_gutter_geometry):
* redisplay.c (end_hold_frame_size_changes):
* redisplay.c (redisplay_frame):
* toolbar.c:
* toolbar.c (update_frame_toolbars_geometry):
* window.c:
* window.c (frame_pixsize_valid_p):
* window.c (check_frame_size):
Various fixes to frame geometry to make it a bit easier to understand
and fix some bugs.
1. IMPORTANT: Some renamings. Will need to be applied carefully to
the carbon repository, in the following order:
-- pixel_to_char_size -> pixel_to_frame_unit_size
-- char_to_pixel_size -> frame_unit_to_pixel_size
-- pixel_to_real_char_size -> pixel_to_char_size
-- char_to_real_pixel_size -> char_to_pixel_size
-- Reverse second and third arguments of change_frame_size() and
change_frame_size_1() to try to make functions consistent in
putting width before height.
-- Eliminate old round_size_to_char, because it didn't really
do anything differently from round_size_to_real_char()
-- round_size_to_real_char -> round_size_to_char; any places that
called the old round_size_to_char should just call the new one.
2. IMPORTANT FOR CARBON: The set_frame_size() method is now passed
sizes in "frame units", like all other frame-sizing functions,
rather than some hacked-up combination of char-cell units and
total pixel size. This only affects window systems that use
"pixelated geometry", and I'm not sure if Carbon is one of them.
MS Windows is pixelated, X and GTK are not. For pixelated-geometry
systems, the size in set_frame_size() is in displayable pixels
rather than total pixels and needs to be converted appropriately;
take a look at the changes made to mswindows_set_frame_size()
method if necessary.
3. Add a big long comment in frame.c describing how frame geometry
works.
4. Remove MS Windows-specific character height and width fields,
duplicative and unused.
5. frame-displayable-pixel-* and set-frame-displayable-pixel-*
didn't use to work on MS Windows, but they do now.
6. In general, clean up the handling of "pixelated geometry" so
that fewer functions have to worry about this. This is really
an abomination that should be removed entirely but that will
have to happen later. Fix some buggy code in
frame_conversion_internal() that happened to "work" because it
was countered by oppositely buggy code in change_frame_size().
7. Clean up some frame-size code in toolbar.c and use functions
already provided in frame.c instead of rolling its own.
8. Fix check_frame_size() in window.c, which formerly didn't take
pixelated geometry into account.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Mon, 15 Feb 2010 22:14:11 -0600 |
parents | 0d4c9d0f6a8d |
children | 548f1f47eb82 |
rev | line source |
---|---|
428 | 1 /* Gutter implementation. |
442 | 2 Copyright (C) 1999, 2000 Andy Piper. |
5043 | 3 Copyright (C) 2010 Ben Wing. |
428 | 4 |
5 This file is part of XEmacs. | |
6 | |
7 XEmacs is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
9 Free Software Foundation; either version 2, or (at your option) any | |
10 later version. | |
11 | |
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with XEmacs; see the file COPYING. If not, write to | |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 Boston, MA 02111-1307, USA. */ | |
21 | |
22 /* Synched up with: Not in FSF. */ | |
23 | |
24 /* written by Andy Piper <andy@xemacs.org> with specifiers partially | |
25 ripped-off from toolbar.c */ | |
26 | |
27 #include <config.h> | |
28 #include "lisp.h" | |
29 | |
30 #include "buffer.h" | |
872 | 31 #include "frame-impl.h" |
32 #include "device-impl.h" | |
428 | 33 #include "faces.h" |
34 #include "glyphs.h" | |
35 #include "redisplay.h" | |
36 #include "window.h" | |
37 #include "gutter.h" | |
38 | |
39 Lisp_Object Vgutter[4]; | |
40 Lisp_Object Vgutter_size[4]; | |
41 Lisp_Object Vgutter_visible_p[4]; | |
42 Lisp_Object Vgutter_border_width[4]; | |
43 | |
44 Lisp_Object Vdefault_gutter, Vdefault_gutter_visible_p; | |
45 Lisp_Object Vdefault_gutter_width, Vdefault_gutter_height; | |
46 Lisp_Object Vdefault_gutter_border_width; | |
47 | |
48 Lisp_Object Vdefault_gutter_position; | |
49 | |
50 Lisp_Object Qgutter_size; | |
442 | 51 Lisp_Object Qgutter_visible; |
52 Lisp_Object Qdefault_gutter_position_changed_hook; | |
53 | |
54 static void | |
55 update_gutter_geometry (struct frame *f, enum gutter_pos pos); | |
428 | 56 |
57 #define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag) \ | |
58 do { \ | |
59 switch (pos) \ | |
60 { \ | |
61 case TOP_GUTTER: \ | |
62 (frame)->top_gutter_was_visible = flag; \ | |
63 break; \ | |
64 case BOTTOM_GUTTER: \ | |
65 (frame)->bottom_gutter_was_visible = flag; \ | |
66 break; \ | |
67 case LEFT_GUTTER: \ | |
68 (frame)->left_gutter_was_visible = flag; \ | |
69 break; \ | |
70 case RIGHT_GUTTER: \ | |
71 (frame)->right_gutter_was_visible = flag; \ | |
72 break; \ | |
73 default: \ | |
2500 | 74 ABORT (); \ |
428 | 75 } \ |
76 } while (0) | |
77 | |
78 static int gutter_was_visible (struct frame* frame, enum gutter_pos pos) | |
79 { | |
80 switch (pos) | |
81 { | |
82 case TOP_GUTTER: | |
83 return frame->top_gutter_was_visible; | |
84 case BOTTOM_GUTTER: | |
85 return frame->bottom_gutter_was_visible; | |
86 case LEFT_GUTTER: | |
87 return frame->left_gutter_was_visible; | |
88 case RIGHT_GUTTER: | |
89 return frame->right_gutter_was_visible; | |
90 default: | |
2500 | 91 ABORT (); |
442 | 92 return 0; /* To keep the compiler happy */ |
428 | 93 } |
94 } | |
95 | |
442 | 96 #if 0 |
428 | 97 static Lisp_Object |
98 frame_topmost_window (struct frame *f) | |
99 { | |
100 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
101 | |
102 do { | |
103 while (!NILP (XWINDOW (w)->vchild)) | |
104 { | |
105 w = XWINDOW (w)->vchild; | |
106 } | |
107 } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild)); | |
108 | |
109 return w; | |
110 } | |
442 | 111 #endif |
428 | 112 |
113 static Lisp_Object | |
114 frame_bottommost_window (struct frame *f) | |
115 { | |
116 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
117 | |
118 do { | |
119 while (!NILP (XWINDOW (w)->vchild)) | |
120 { | |
121 w = XWINDOW (w)->vchild; | |
122 while (!NILP (XWINDOW (w)->next)) | |
123 { | |
124 w = XWINDOW (w)->next; | |
125 } | |
126 } | |
127 } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild)); | |
128 | |
129 return w; | |
130 } | |
131 | |
132 #if 0 | |
133 static Lisp_Object | |
134 frame_leftmost_window (struct frame *f) | |
135 { | |
136 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
137 | |
138 do { | |
139 while (!NILP (XWINDOW (w)->hchild)) | |
140 { | |
141 w = XWINDOW (w)->hchild; | |
142 } | |
143 } while (!NILP (XWINDOW (w)->vchild) && !NILP (w = XWINDOW (w)->vchild)); | |
144 | |
145 return w; | |
146 } | |
147 | |
148 static Lisp_Object | |
149 frame_rightmost_window (struct frame *f) | |
150 { | |
151 Lisp_Object w = FRAME_ROOT_WINDOW (f); | |
152 | |
153 do { | |
154 while (!NILP (XWINDOW (w)->hchild)) | |
155 { | |
156 w = XWINDOW (w)->hchild; | |
157 while (!NILP (XWINDOW (w)->next)) | |
158 { | |
159 w = XWINDOW (w)->next; | |
160 } | |
161 } | |
162 } while (!NILP (XWINDOW (w)->vchild) && !NILP (w = XWINDOW (w)->vchild)); | |
163 return w; | |
164 } | |
165 #endif | |
166 | |
167 /* calculate the coordinates of a gutter for the current frame and | |
168 selected window. we have to be careful in calculating this as we | |
169 need to use *two* windows, the currently selected window will give | |
170 us the actual height, width and contents of the gutter, but if we | |
171 use this for calculating the gutter positions we run into trouble | |
172 if it is not the window nearest the gutter. Instead we predetermine | |
173 the nearest window and then use that.*/ | |
174 static void | |
175 get_gutter_coords (struct frame *f, enum gutter_pos pos, int *x, int *y, | |
176 int *width, int *height) | |
177 { | |
178 struct window | |
179 * bot = XWINDOW (frame_bottommost_window (f)); | |
180 /* The top and bottom gutters take precedence over the left and | |
181 right. */ | |
182 switch (pos) | |
183 { | |
184 case TOP_GUTTER: | |
185 *x = FRAME_LEFT_BORDER_END (f); | |
186 *y = FRAME_TOP_BORDER_END (f); | |
442 | 187 *width = FRAME_RIGHT_BORDER_START (f) |
428 | 188 - FRAME_LEFT_BORDER_END (f); |
189 *height = FRAME_TOP_GUTTER_BOUNDS (f); | |
190 break; | |
191 | |
192 case BOTTOM_GUTTER: | |
193 *x = FRAME_LEFT_BORDER_END (f); | |
442 | 194 *y = WINDOW_BOTTOM (bot); |
195 *width = FRAME_RIGHT_BORDER_START (f) | |
428 | 196 - FRAME_LEFT_BORDER_END (f); |
197 *height = FRAME_BOTTOM_GUTTER_BOUNDS (f); | |
198 break; | |
199 | |
200 case LEFT_GUTTER: | |
201 *x = FRAME_LEFT_BORDER_END (f); | |
442 | 202 *y = FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f); |
428 | 203 *width = FRAME_LEFT_GUTTER_BOUNDS (f); |
204 *height = WINDOW_BOTTOM (bot) | |
442 | 205 - (FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f)); |
428 | 206 break; |
442 | 207 |
428 | 208 case RIGHT_GUTTER: |
209 *x = FRAME_RIGHT_BORDER_START (f) | |
210 - FRAME_RIGHT_GUTTER_BOUNDS (f); | |
442 | 211 *y = FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f); |
428 | 212 *width = FRAME_RIGHT_GUTTER_BOUNDS (f); |
213 *height = WINDOW_BOTTOM (bot) | |
442 | 214 - (FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f)); |
428 | 215 break; |
216 | |
217 default: | |
2500 | 218 ABORT (); |
428 | 219 } |
220 } | |
221 | |
446 | 222 /* |
223 display_boxes_in_gutter_p | |
224 | |
225 Determine whether the required display_glyph_area is completely | |
226 inside the gutter. -1 means the display_box is not in the gutter. 1 | |
227 means the display_box and the display_glyph_area are in the | |
228 window. 0 means the display_box is in the gutter but the | |
229 display_glyph_area is not. */ | |
230 int display_boxes_in_gutter_p (struct frame *f, struct display_box* db, | |
231 struct display_glyph_area* dga) | |
232 { | |
233 enum gutter_pos pos; | |
234 GUTTER_POS_LOOP (pos) | |
235 { | |
236 if (FRAME_GUTTER_VISIBLE (f, pos)) | |
237 { | |
238 int x, y, width, height; | |
239 get_gutter_coords (f, pos, &x, &y, &width, &height); | |
240 if (db->xpos + dga->xoffset >= x | |
241 && | |
242 db->ypos + dga->yoffset >= y | |
243 && | |
244 db->xpos + dga->xoffset + dga->width <= x + width | |
245 && | |
246 db->ypos + dga->yoffset + dga->height <= y + height) | |
247 return 1; | |
248 else if (db->xpos >= x && db->ypos >= y | |
249 && db->xpos + db->width <= x + width | |
250 && db->ypos + db->height <= y + height) | |
251 return 0; | |
252 } | |
253 } | |
254 return -1; | |
255 } | |
256 | |
442 | 257 /* Convert the gutter specifier into something we can actually |
258 display. */ | |
259 static Lisp_Object construct_window_gutter_spec (struct window* w, | |
260 enum gutter_pos pos) | |
261 { | |
262 Lisp_Object rest, *args; | |
263 int nargs = 0; | |
264 Lisp_Object gutter = RAW_WINDOW_GUTTER (w, pos); | |
265 | |
266 if (STRINGP (gutter) || NILP (gutter)) | |
267 return gutter; | |
268 | |
269 GET_LIST_LENGTH (gutter, nargs); | |
270 args = alloca_array (Lisp_Object, nargs >> 1); | |
271 nargs = 0; | |
272 | |
273 for (rest = gutter; !NILP (rest); rest = XCDR (XCDR (rest))) | |
274 { | |
275 /* We only put things in the real gutter that are declared to be | |
4186 | 276 visible. */ |
442 | 277 if (!CONSP (WINDOW_GUTTER_VISIBLE (w, pos)) |
278 || | |
279 !NILP (Fmemq (XCAR (rest), WINDOW_GUTTER_VISIBLE (w, pos)))) | |
280 { | |
281 args [nargs++] = XCAR (XCDR (rest)); | |
282 } | |
283 } | |
284 | |
285 return Fconcat (nargs, args); | |
286 } | |
287 | |
444 | 288 /* Sizing gutters is a pain so we try and help the user by determining |
289 what height will accommodate all lines. This is useless on left and | |
290 right gutters as we always have a maximal number of lines. */ | |
291 static int | |
292 calculate_gutter_size_from_display_lines (enum gutter_pos pos, | |
293 display_line_dynarr* ddla) | |
294 { | |
295 int size = 0; | |
296 struct display_line *dl; | |
297 | |
298 /* For top and bottom the calculation is easy. */ | |
299 if (pos == TOP_GUTTER || pos == BOTTOM_GUTTER) | |
300 { | |
301 /* grab coordinates of last line */ | |
302 if (Dynarr_length (ddla)) | |
303 { | |
304 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); | |
4186 | 305 size = (dl->ypos + dl->descent - dl->clip) |
4967 | 306 - (Dynarr_begin (ddla)->ypos - Dynarr_begin (ddla)->ascent); |
444 | 307 } |
308 } | |
309 /* For left and right we have to do some maths. */ | |
310 else | |
311 { | |
312 int start_pos = 0, end_pos = 0, line; | |
313 for (line = 0; line < Dynarr_length (ddla); line++) | |
314 { | |
315 int block; | |
316 dl = Dynarr_atp (ddla, line); | |
317 | |
318 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++) | |
319 { | |
320 struct display_block *db = Dynarr_atp (dl->display_blocks, block); | |
321 | |
322 if (db->type == TEXT) | |
323 { | |
324 start_pos = min (db->start_pos, start_pos); | |
325 end_pos = max (db->end_pos, end_pos); | |
326 } | |
327 } | |
328 } | |
329 size = end_pos - start_pos; | |
330 } | |
331 | |
332 return size; | |
333 } | |
334 | |
335 static Lisp_Object | |
336 calculate_gutter_size (struct window *w, enum gutter_pos pos) | |
337 { | |
338 struct frame* f = XFRAME (WINDOW_FRAME (w)); | |
1318 | 339 display_line_dynarr *ddla; |
444 | 340 Lisp_Object ret = Qnil; |
341 | |
1318 | 342 /* Callers need to handle this. */ |
343 assert (!in_display); | |
444 | 344 /* degenerate case */ |
345 if (NILP (RAW_WINDOW_GUTTER (w, pos)) | |
346 || | |
347 !FRAME_VISIBLE_P (f) | |
348 || | |
349 NILP (w->buffer)) | |
350 return Qnil; | |
351 | |
1318 | 352 if (!in_display) |
353 { | |
354 int count; | |
355 | |
356 /* We are calling directly into redisplay from the outside, so turn on | |
357 critical section protection. */ | |
358 count = enter_redisplay_critical_section (); | |
444 | 359 |
1318 | 360 ddla = Dynarr_new (display_line); |
361 /* generate some display lines */ | |
362 generate_displayable_area (w, WINDOW_GUTTER (w, pos), | |
363 FRAME_LEFT_BORDER_END (f), | |
364 FRAME_TOP_BORDER_END (f), | |
365 FRAME_RIGHT_BORDER_START (f) | |
366 - FRAME_LEFT_BORDER_END (f), | |
367 FRAME_BOTTOM_BORDER_START (f) | |
368 - FRAME_TOP_BORDER_END (f), | |
4186 | 369 ddla, 0, DEFAULT_INDEX); |
444 | 370 |
1318 | 371 /* Let GC happen again. */ |
372 exit_redisplay_critical_section (count); | |
444 | 373 |
1318 | 374 ret = make_int (calculate_gutter_size_from_display_lines (pos, ddla)); |
375 free_display_lines (ddla); | |
376 } | |
444 | 377 |
378 return ret; | |
379 } | |
380 | |
428 | 381 static void |
442 | 382 output_gutter (struct frame *f, enum gutter_pos pos, int force) |
428 | 383 { |
384 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
385 struct device *d = XDEVICE (f->device); | |
386 struct window* w = XWINDOW (window); | |
387 int x, y, width, height, ypos; | |
440 | 388 int line, border_width; |
389 face_index findex; | |
428 | 390 display_line_dynarr* ddla, *cdla; |
442 | 391 struct display_line *dl = 0; |
428 | 392 int cdla_len; |
393 | |
440 | 394 if (!WINDOW_LIVE_P (w)) |
395 return; | |
396 | |
397 border_width = FRAME_GUTTER_BORDER_WIDTH (f, pos); | |
442 | 398 findex = get_builtin_face_cache_index (w, Vwidget_face); |
440 | 399 |
442 | 400 if (!f->current_display_lines[pos]) |
401 f->current_display_lines[pos] = Dynarr_new (display_line); | |
402 if (!f->desired_display_lines[pos]) | |
403 f->desired_display_lines[pos] = Dynarr_new (display_line); | |
428 | 404 |
442 | 405 ddla = f->desired_display_lines[pos]; |
406 cdla = f->current_display_lines[pos]; | |
428 | 407 cdla_len = Dynarr_length (cdla); |
408 | |
409 get_gutter_coords (f, pos, &x, &y, &width, &height); | |
410 /* generate some display lines */ | |
411 generate_displayable_area (w, WINDOW_GUTTER (w, pos), | |
412 x + border_width, y + border_width, | |
442 | 413 width - 2 * border_width, |
428 | 414 height - 2 * border_width, ddla, 0, findex); |
442 | 415 |
416 /* We only output the gutter if we think something of significance | |
417 has changed. This is, for example, because redisplay can cause | |
418 new face cache elements to get added causing compare_runes to | |
419 fail because the findex for a particular face has changed. */ | |
420 if (force || f->faces_changed || f->frame_changed || | |
421 f->gutter_changed || f->glyphs_changed || | |
422 f->size_changed || f->subwindows_changed || | |
423 w->windows_changed || f->windows_structure_changed || | |
424 cdla_len != Dynarr_length (ddla) || | |
425 (f->extents_changed && w->gutter_extent_modiff[pos])) | |
428 | 426 { |
442 | 427 #ifdef DEBUG_GUTTERS |
4186 | 428 stderr_out ("gutter redisplay [%s %dx%d@%d+%d] triggered by %s,\n", |
639 | 429 pos == TOP_GUTTER ? "TOP" : |
430 pos == BOTTOM_GUTTER ? "BOTTOM" : | |
431 pos == LEFT_GUTTER ? "LEFT" : "RIGHT", | |
446 | 432 width, height, x, y, force ? "force" : |
442 | 433 f->faces_changed ? "f->faces_changed" : |
434 f->frame_changed ? "f->frame_changed" : | |
435 f->gutter_changed ? "f->gutter_changed" : | |
436 f->glyphs_changed ? "f->glyphs_changed" : | |
437 f->size_changed ? "f->size_changed" : | |
438 f->subwindows_changed ? "f->subwindows_changed" : | |
439 w->windows_changed ? "w->windows_changed" : | |
440 f->windows_structure_changed ? "f->windows_structure_changed" : | |
441 cdla_len != Dynarr_length (ddla) ? "different display structures" : | |
442 f->extents_changed && w->gutter_extent_modiff[pos] ? | |
443 "f->extents_changed && w->gutter_extent_modiff[pos]" : "<null>"); | |
444 #endif | |
445 /* Output each line. */ | |
446 for (line = 0; line < Dynarr_length (ddla); line++) | |
447 { | |
448 output_display_line (w, cdla, ddla, line, -1, -1); | |
449 } | |
450 | |
451 /* If the number of display lines has shrunk, adjust. */ | |
452 if (cdla_len > Dynarr_length (ddla)) | |
453 { | |
4967 | 454 Dynarr_set_length (cdla, Dynarr_length (ddla)); |
442 | 455 } |
456 | |
457 /* grab coordinates of last line and blank after it. */ | |
458 if (Dynarr_length (ddla) > 0) | |
459 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4186
diff
changeset
|
460 dl = Dynarr_lastp (ddla); |
442 | 461 ypos = dl->ypos + dl->descent - dl->clip; |
462 } | |
463 else | |
464 ypos = y; | |
428 | 465 |
442 | 466 redisplay_clear_region (window, findex, x + border_width , ypos, |
467 width - 2 * border_width, height - (ypos - y) - border_width); | |
468 /* If, for some reason, we have more to display than we have | |
4186 | 469 room for, and we are allowed to resize the gutter, then make |
470 sure this happens before the next time we try and | |
471 output. This can happen when face font sizes change. */ | |
472 if (dl && EQ (w->gutter_size[pos], Qautodetect) | |
444 | 473 && (dl->clip > 0 || |
4186 | 474 calculate_gutter_size_from_display_lines (pos, ddla) > |
444 | 475 WINDOW_GUTTER_SIZE_INTERNAL (w, pos))) |
442 | 476 { |
477 /* #### Ideally we would just mark the specifier as dirty | |
478 and everything else would "just work". Unfortunately we have | |
479 two problems with this. One is that the specifier cache | |
480 won't be recalculated unless the specifier code thinks the | |
481 cached value has actually changed, even though we have | |
482 marked the specifier as dirty. Additionally, although doing | |
483 this results in a gutter size change, we never seem to get | |
484 back into redisplay so that the frame size can be updated. I | |
485 think this is because we are already in redisplay and later | |
486 on the frame will be marked as clean. Thus we also have to | |
487 force a pending recalculation of the frame size. */ | |
488 w->gutter_size[pos] = Qnil; | |
489 Fset_specifier_dirty_flag (Vgutter_size[pos]); | |
490 update_gutter_geometry (f, pos); | |
491 } | |
492 | |
493 /* bevel the gutter area if so desired */ | |
494 if (border_width != 0) | |
495 { | |
496 MAYBE_DEVMETH (d, bevel_area, | |
497 (w, findex, x, y, width, height, border_width, | |
498 EDGE_ALL, EDGE_BEVEL_OUT)); | |
499 } | |
500 } | |
501 else | |
428 | 502 { |
442 | 503 /* Nothing of significance happened so sync the display line |
4186 | 504 structs. */ |
442 | 505 for (line = 0; line < Dynarr_length (ddla); line++) |
506 { | |
507 sync_display_line_structs (w, line, 1, cdla, ddla); | |
508 } | |
428 | 509 } |
510 | |
442 | 511 w->gutter_extent_modiff [pos] = 0; |
428 | 512 } |
513 | |
514 static void | |
515 clear_gutter (struct frame *f, enum gutter_pos pos) | |
516 { | |
517 int x, y, width, height; | |
518 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
519 face_index findex = get_builtin_face_cache_index (XWINDOW (window), | |
442 | 520 Vwidget_face); |
428 | 521 get_gutter_coords (f, pos, &x, &y, &width, &height); |
522 | |
523 SET_GUTTER_WAS_VISIBLE_FLAG (f, pos, 0); | |
524 | |
525 redisplay_clear_region (window, findex, x, y, width, height); | |
526 } | |
527 | |
617 | 528 /* [[#### I don't currently believe that redisplay needs to mark the |
442 | 529 glyphs in its structures since these will always be referenced from |
530 somewhere else. However, I'm not sure enough to stake my life on it | |
617 | 531 at this point, so we do the safe thing.]] |
532 | |
533 ALWAYS mark everything. --ben */ | |
442 | 534 |
535 /* See the comment in image_instantiate_cache_result as to why marking | |
536 the glyph will also mark the image_instance. */ | |
537 void | |
617 | 538 mark_gutters (struct frame *f) |
442 | 539 { |
540 enum gutter_pos pos; | |
541 GUTTER_POS_LOOP (pos) | |
542 { | |
543 if (f->current_display_lines[pos]) | |
544 mark_redisplay_structs (f->current_display_lines[pos]); | |
617 | 545 /* [[#### Do we really need to mark the desired lines?]] |
4186 | 546 ALWAYS mark everything. --ben */ |
442 | 547 if (f->desired_display_lines[pos]) |
548 mark_redisplay_structs (f->desired_display_lines[pos]); | |
549 } | |
550 } | |
551 | |
552 /* This is called by extent_changed_for_redisplay, so that redisplay | |
553 knows exactly what extents have changed. */ | |
554 void | |
555 gutter_extent_signal_changed_region_maybe (Lisp_Object obj, | |
2286 | 556 Charbpos UNUSED (start), |
557 Charbpos UNUSED (end)) | |
442 | 558 { |
559 /* #### Start and end are currently ignored but could be used by a | |
560 more optimal gutter redisplay. We currently loop over all frames | |
561 here, this could be optimized. */ | |
562 Lisp_Object frmcons, devcons, concons; | |
563 | |
564 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
565 { | |
566 struct frame *f = XFRAME (XCAR (frmcons)); | |
567 enum gutter_pos pos; | |
568 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
569 struct window* w = XWINDOW (window); | |
570 | |
571 GUTTER_POS_LOOP (pos) | |
572 { | |
573 if (EQ (WINDOW_GUTTER (w, pos), obj)) | |
574 { | |
575 w->gutter_extent_modiff[pos]++; | |
576 } | |
577 } | |
578 } | |
579 } | |
580 | |
581 /* We have to change the gutter geometry separately to the gutter | |
582 update since it needs to occur outside of redisplay proper. */ | |
583 static void | |
584 update_gutter_geometry (struct frame *f, enum gutter_pos pos) | |
585 { | |
586 /* If the gutter geometry has changed then re-layout the | |
587 frame. If we are in display there is almost no point in doing | |
588 anything else since the frame size changes will be delayed | |
589 until we are out of redisplay proper. */ | |
590 if (FRAME_GUTTER_BOUNDS (f, pos) != f->current_gutter_bounds[pos]) | |
591 { | |
592 int width, height; | |
5043 | 593 pixel_to_frame_unit_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f), |
442 | 594 &width, &height); |
5043 | 595 change_frame_size (f, width, height, 0); |
905 | 596 MARK_FRAME_LAYOUT_CHANGED (f); |
442 | 597 } |
598 | |
599 /* Mark sizes as up-to-date. */ | |
600 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos); | |
601 } | |
602 | |
603 void | |
604 update_frame_gutter_geometry (struct frame *f) | |
605 { | |
4186 | 606 if (f->gutter_changed |
607 || f->frame_layout_changed | |
905 | 608 || f->windows_structure_changed) |
442 | 609 { |
610 enum gutter_pos pos; | |
611 | |
612 /* If the gutter geometry has changed then re-layout the | |
4186 | 613 frame. If we are in display there is almost no point in doing |
614 anything else since the frame size changes will be delayed | |
615 until we are out of redisplay proper. */ | |
442 | 616 GUTTER_POS_LOOP (pos) |
617 { | |
618 update_gutter_geometry (f, pos); | |
619 } | |
620 } | |
621 } | |
622 | |
428 | 623 void |
624 update_frame_gutters (struct frame *f) | |
625 { | |
442 | 626 if (f->faces_changed || f->frame_changed || |
627 f->gutter_changed || f->glyphs_changed || | |
628 f->size_changed || f->subwindows_changed || | |
629 f->windows_changed || f->windows_structure_changed || | |
905 | 630 f->extents_changed || f->frame_layout_changed) |
428 | 631 { |
632 enum gutter_pos pos; | |
442 | 633 |
428 | 634 /* We don't actually care about these when outputting the gutter |
4186 | 635 so locally disable them. */ |
428 | 636 int local_clip_changed = f->clip_changed; |
637 int local_buffers_changed = f->buffers_changed; | |
638 f->clip_changed = 0; | |
639 f->buffers_changed = 0; | |
640 | |
641 /* and output */ | |
642 GUTTER_POS_LOOP (pos) | |
643 { | |
644 if (FRAME_GUTTER_VISIBLE (f, pos)) | |
442 | 645 output_gutter (f, pos, 0); |
646 | |
428 | 647 else if (gutter_was_visible (f, pos)) |
442 | 648 clear_gutter (f, pos); |
428 | 649 } |
442 | 650 |
428 | 651 f->clip_changed = local_clip_changed; |
652 f->buffers_changed = local_buffers_changed; | |
653 f->gutter_changed = 0; | |
654 } | |
655 } | |
656 | |
657 void | |
658 reset_gutter_display_lines (struct frame* f) | |
659 { | |
442 | 660 enum gutter_pos pos; |
661 GUTTER_POS_LOOP (pos) | |
662 { | |
663 if (f->current_display_lines[pos]) | |
664 Dynarr_reset (f->current_display_lines[pos]); | |
665 } | |
428 | 666 } |
667 | |
668 static void | |
669 redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y, | |
670 int width, int height) | |
671 { | |
672 int g_x, g_y, g_width, g_height; | |
673 | |
674 get_gutter_coords (f, pos, &g_x, &g_y, &g_width, &g_height); | |
675 | |
676 if (((y + height) < g_y) || (y > (g_y + g_height)) || !height || !width || !g_height || !g_width) | |
677 return; | |
678 if (((x + width) < g_x) || (x > (g_x + g_width))) | |
679 return; | |
680 | |
442 | 681 #ifdef DEBUG_WIDGETS |
639 | 682 stderr_out ("redrawing gutter after expose %d+%d, %dx%d\n", |
442 | 683 x, y, width, height); |
684 #endif | |
428 | 685 /* #### optimize this - redrawing the whole gutter for every expose |
686 is very expensive. We reset the current display lines because if | |
687 they're being exposed they are no longer current. */ | |
688 reset_gutter_display_lines (f); | |
689 | |
690 /* Even if none of the gutter is in the area, the blank region at | |
691 the very least must be because the first thing we did is verify | |
692 that some portion of the gutter is in the exposed region. */ | |
442 | 693 output_gutter (f, pos, 1); |
428 | 694 } |
695 | |
696 void | |
697 redraw_exposed_gutters (struct frame *f, int x, int y, int width, | |
698 int height) | |
699 { | |
700 enum gutter_pos pos; | |
442 | 701 |
1318 | 702 /* We are already inside the critical section -- our caller did that. */ |
428 | 703 GUTTER_POS_LOOP (pos) |
704 { | |
705 if (FRAME_GUTTER_VISIBLE (f, pos)) | |
706 redraw_exposed_gutter (f, pos, x, y, width, height); | |
707 } | |
708 } | |
709 | |
710 void | |
711 free_frame_gutters (struct frame *f) | |
712 { | |
442 | 713 enum gutter_pos pos; |
714 GUTTER_POS_LOOP (pos) | |
428 | 715 { |
442 | 716 if (f->current_display_lines[pos]) |
717 { | |
718 free_display_lines (f->current_display_lines[pos]); | |
719 f->current_display_lines[pos] = 0; | |
720 } | |
721 if (f->desired_display_lines[pos]) | |
722 { | |
723 free_display_lines (f->desired_display_lines[pos]); | |
724 f->desired_display_lines[pos] = 0; | |
725 } | |
428 | 726 } |
727 } | |
728 | |
729 static enum gutter_pos | |
730 decode_gutter_position (Lisp_Object position) | |
731 { | |
732 if (EQ (position, Qtop)) return TOP_GUTTER; | |
733 if (EQ (position, Qbottom)) return BOTTOM_GUTTER; | |
734 if (EQ (position, Qleft)) return LEFT_GUTTER; | |
735 if (EQ (position, Qright)) return RIGHT_GUTTER; | |
563 | 736 invalid_constant ("Invalid gutter position", position); |
428 | 737 |
1204 | 738 RETURN_NOT_REACHED (TOP_GUTTER); |
428 | 739 } |
740 | |
741 DEFUN ("set-default-gutter-position", Fset_default_gutter_position, 1, 1, 0, /* | |
742 Set the position that the `default-gutter' will be displayed at. | |
3025 | 743 Valid positions are `top', `bottom', `left' and `right'. |
428 | 744 See `default-gutter-position'. |
745 */ | |
746 (position)) | |
747 { | |
748 enum gutter_pos cur = decode_gutter_position (Vdefault_gutter_position); | |
3025 | 749 enum gutter_pos new_ = decode_gutter_position (position); |
428 | 750 |
3025 | 751 if (cur != new_) |
428 | 752 { |
753 /* The following calls will automatically cause the dirty | |
754 flags to be set; we delay frame size changes to avoid | |
755 lots of frame flickering. */ | |
756 /* #### I think this should be GC protected. -sb */ | |
1318 | 757 int depth = begin_hold_frame_size_changes (); |
758 | |
428 | 759 set_specifier_fallback (Vgutter[cur], list1 (Fcons (Qnil, Qnil))); |
3025 | 760 set_specifier_fallback (Vgutter[new_], Vdefault_gutter); |
428 | 761 set_specifier_fallback (Vgutter_size[cur], list1 (Fcons (Qnil, Qzero))); |
3025 | 762 set_specifier_fallback (Vgutter_size[new_], |
763 new_ == TOP_GUTTER || new_ == BOTTOM_GUTTER | |
428 | 764 ? Vdefault_gutter_height |
765 : Vdefault_gutter_width); | |
766 set_specifier_fallback (Vgutter_border_width[cur], | |
767 list1 (Fcons (Qnil, Qzero))); | |
3025 | 768 set_specifier_fallback (Vgutter_border_width[new_], |
428 | 769 Vdefault_gutter_border_width); |
444 | 770 set_specifier_fallback (Vgutter_visible_p[cur], list1 (Fcons (Qnil, Qt))); |
3025 | 771 set_specifier_fallback (Vgutter_visible_p[new_], Vdefault_gutter_visible_p); |
1318 | 772 Vdefault_gutter_position = position; |
442 | 773 |
1318 | 774 unbind_to (depth); |
428 | 775 } |
776 | |
442 | 777 run_hook (Qdefault_gutter_position_changed_hook); |
778 | |
428 | 779 return position; |
780 } | |
781 | |
782 DEFUN ("default-gutter-position", Fdefault_gutter_position, 0, 0, 0, /* | |
783 Return the position that the `default-gutter' will be displayed at. | |
784 The `default-gutter' will only be displayed here if the corresponding | |
785 position-specific gutter specifier does not provide a value. | |
786 */ | |
787 ()) | |
788 { | |
789 return Vdefault_gutter_position; | |
790 } | |
791 | |
792 DEFUN ("gutter-pixel-width", Fgutter_pixel_width, 0, 2, 0, /* | |
793 Return the pixel width of the gutter at POS in LOCALE. | |
794 POS defaults to the default gutter position. LOCALE defaults to | |
795 the current window. | |
796 */ | |
797 (pos, locale)) | |
798 { | |
799 int x, y, width, height; | |
800 enum gutter_pos p = TOP_GUTTER; | |
801 struct frame *f = decode_frame (FW_FRAME (locale)); | |
802 | |
803 if (NILP (pos)) | |
804 pos = Vdefault_gutter_position; | |
805 p = decode_gutter_position (pos); | |
806 | |
807 get_gutter_coords (f, p, &x, &y, &width, &height); | |
808 width -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2); | |
809 | |
810 return make_int (width); | |
811 } | |
812 | |
813 DEFUN ("gutter-pixel-height", Fgutter_pixel_height, 0, 2, 0, /* | |
814 Return the pixel height of the gutter at POS in LOCALE. | |
815 POS defaults to the default gutter position. LOCALE defaults to | |
816 the current window. | |
817 */ | |
818 (pos, locale)) | |
819 { | |
820 int x, y, width, height; | |
821 enum gutter_pos p = TOP_GUTTER; | |
822 struct frame *f = decode_frame (FW_FRAME (locale)); | |
823 | |
824 if (NILP (pos)) | |
825 pos = Vdefault_gutter_position; | |
826 p = decode_gutter_position (pos); | |
827 | |
828 get_gutter_coords (f, p, &x, &y, &width, &height); | |
829 height -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2); | |
830 | |
831 return make_int (height); | |
832 } | |
833 | |
834 DEFINE_SPECIFIER_TYPE (gutter); | |
835 | |
836 static void | |
2286 | 837 gutter_after_change (Lisp_Object UNUSED (specifier), |
838 Lisp_Object UNUSED (locale)) | |
428 | 839 { |
840 MARK_GUTTER_CHANGED; | |
841 } | |
842 | |
843 static void | |
844 gutter_validate (Lisp_Object instantiator) | |
845 { | |
846 if (NILP (instantiator)) | |
847 return; | |
848 | |
442 | 849 /* Must be a string or a plist. */ |
850 if (!STRINGP (instantiator) && NILP (Fvalid_plist_p (instantiator))) | |
563 | 851 sferror ("Gutter spec must be string, plist or nil", instantiator); |
442 | 852 |
428 | 853 if (!STRINGP (instantiator)) |
442 | 854 { |
855 Lisp_Object rest; | |
856 | |
857 for (rest = instantiator; !NILP (rest); rest = XCDR (XCDR (rest))) | |
858 { | |
859 if (!SYMBOLP (XCAR (rest)) | |
860 || !STRINGP (XCAR (XCDR (rest)))) | |
563 | 861 sferror ("Gutter plist spec must contain strings", instantiator); |
442 | 862 } |
863 } | |
428 | 864 } |
865 | |
866 DEFUN ("gutter-specifier-p", Fgutter_specifier_p, 1, 1, 0, /* | |
867 Return non-nil if OBJECT is a gutter specifier. | |
868 | |
442 | 869 See `make-gutter-specifier' for a description of possible gutter |
870 instantiators. | |
428 | 871 */ |
872 (object)) | |
873 { | |
874 return GUTTER_SPECIFIERP (object) ? Qt : Qnil; | |
875 } | |
876 | |
877 | |
878 /* | |
879 Helper for invalidating the real specifier when default | |
880 specifier caching changes | |
881 */ | |
882 static void | |
883 recompute_overlaying_specifier (Lisp_Object real_one[4]) | |
884 { | |
885 enum gutter_pos pos = decode_gutter_position (Vdefault_gutter_position); | |
886 Fset_specifier_dirty_flag (real_one[pos]); | |
887 } | |
888 | |
1318 | 889 static void gutter_specs_changed (Lisp_Object specifier, struct window *w, |
890 Lisp_Object oldval, enum gutter_pos pos); | |
891 | |
892 static void | |
893 gutter_specs_changed_1 (Lisp_Object arg) | |
894 { | |
895 gutter_specs_changed (X1ST (arg), XWINDOW (X2ND (arg)), | |
896 X3RD (arg), (enum gutter_pos) XINT (X4TH (arg))); | |
897 free_list (arg); | |
898 } | |
899 | |
428 | 900 static void |
901 gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
1318 | 902 Lisp_Object oldval, enum gutter_pos pos) |
428 | 903 { |
1318 | 904 if (in_display) |
905 register_post_redisplay_action (gutter_specs_changed_1, | |
906 list4 (specifier, wrap_window (w), | |
907 oldval, make_int (pos))); | |
908 else | |
909 { | |
910 w->real_gutter[pos] = construct_window_gutter_spec (w, pos); | |
911 w->real_gutter_size[pos] = w->gutter_size[pos]; | |
442 | 912 |
1318 | 913 if (EQ (w->real_gutter_size[pos], Qautodetect) |
914 && !NILP (w->gutter_visible_p[pos])) | |
915 { | |
916 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); | |
917 } | |
918 MARK_GUTTER_CHANGED; | |
919 MARK_MODELINE_CHANGED; | |
920 MARK_WINDOWS_CHANGED (w); | |
428 | 921 } |
922 } | |
923 | |
442 | 924 /* We define all of these so we can access which actual gutter changed. */ |
925 static void | |
926 top_gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
927 Lisp_Object oldval) | |
928 { | |
929 gutter_specs_changed (specifier, w, oldval, TOP_GUTTER); | |
930 } | |
931 | |
932 static void | |
933 bottom_gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
934 Lisp_Object oldval) | |
935 { | |
936 gutter_specs_changed (specifier, w, oldval, BOTTOM_GUTTER); | |
937 } | |
938 | |
939 static void | |
940 left_gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
941 Lisp_Object oldval) | |
942 { | |
943 gutter_specs_changed (specifier, w, oldval, LEFT_GUTTER); | |
944 } | |
945 | |
946 static void | |
947 right_gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
948 Lisp_Object oldval) | |
949 { | |
950 gutter_specs_changed (specifier, w, oldval, RIGHT_GUTTER); | |
951 } | |
952 | |
428 | 953 static void |
2286 | 954 default_gutter_specs_changed (Lisp_Object UNUSED (specifier), |
955 struct window *UNUSED (w), | |
956 Lisp_Object UNUSED (oldval)) | |
428 | 957 { |
958 recompute_overlaying_specifier (Vgutter); | |
959 } | |
960 | |
1318 | 961 static void gutter_geometry_changed_in_window (Lisp_Object specifier, |
962 struct window *w, | |
963 Lisp_Object oldval); | |
964 | |
965 static void | |
966 gutter_geometry_changed_in_window_1 (Lisp_Object arg) | |
967 { | |
968 gutter_geometry_changed_in_window (X1ST (arg), XWINDOW (X2ND (arg)), | |
969 X3RD (arg)); | |
970 free_list (arg); | |
971 } | |
972 | |
428 | 973 static void |
974 gutter_geometry_changed_in_window (Lisp_Object specifier, struct window *w, | |
975 Lisp_Object oldval) | |
976 { | |
1318 | 977 if (in_display) |
978 register_post_redisplay_action (gutter_geometry_changed_in_window_1, | |
979 list3 (specifier, wrap_window (w), | |
980 oldval)); | |
981 else | |
428 | 982 { |
1318 | 983 enum gutter_pos pos; |
984 GUTTER_POS_LOOP (pos) | |
428 | 985 { |
1318 | 986 w->real_gutter_size[pos] = w->gutter_size[pos]; |
987 if (EQ (w->real_gutter_size[pos], Qautodetect) | |
988 && !NILP (w->gutter_visible_p[pos])) | |
989 { | |
990 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); | |
991 } | |
428 | 992 } |
442 | 993 |
1318 | 994 MARK_GUTTER_CHANGED; |
995 MARK_MODELINE_CHANGED; | |
996 MARK_WINDOWS_CHANGED (w); | |
997 } | |
428 | 998 } |
999 | |
1000 static void | |
2286 | 1001 default_gutter_size_changed_in_window (Lisp_Object UNUSED (specifier), |
1002 struct window *UNUSED (w), | |
1003 Lisp_Object UNUSED (oldval)) | |
428 | 1004 { |
1005 recompute_overlaying_specifier (Vgutter_size); | |
1006 } | |
1007 | |
1008 static void | |
2286 | 1009 default_gutter_border_width_changed_in_window (Lisp_Object UNUSED (specifier), |
1010 struct window *UNUSED (w), | |
1011 Lisp_Object UNUSED (oldval)) | |
428 | 1012 { |
1013 recompute_overlaying_specifier (Vgutter_border_width); | |
1014 } | |
1015 | |
1016 static void | |
2286 | 1017 default_gutter_visible_p_changed_in_window (Lisp_Object UNUSED (specifier), |
1018 struct window *UNUSED (w), | |
1019 Lisp_Object UNUSED (oldval)) | |
428 | 1020 { |
1021 recompute_overlaying_specifier (Vgutter_visible_p); | |
442 | 1022 /* Need to reconstruct the gutter specifier as it is affected by the |
1023 visibility. */ | |
1024 recompute_overlaying_specifier (Vgutter); | |
428 | 1025 } |
1026 | |
1027 | |
1028 DECLARE_SPECIFIER_TYPE (gutter_size); | |
1029 #define GUTTER_SIZE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_size) | |
1030 DEFINE_SPECIFIER_TYPE (gutter_size); | |
1031 | |
1032 static void | |
1033 gutter_size_validate (Lisp_Object instantiator) | |
1034 { | |
1035 if (NILP (instantiator)) | |
1036 return; | |
1037 | |
1038 if (!INTP (instantiator) && !EQ (instantiator, Qautodetect)) | |
3025 | 1039 invalid_argument ("Gutter size must be an integer or `autodetect'", instantiator); |
428 | 1040 } |
1041 | |
1042 DEFUN ("gutter-size-specifier-p", Fgutter_size_specifier_p, 1, 1, 0, /* | |
1043 Return non-nil if OBJECT is a gutter-size specifier. | |
442 | 1044 |
1045 See `make-gutter-size-specifier' for a description of possible gutter-size | |
1046 instantiators. | |
428 | 1047 */ |
1048 (object)) | |
1049 { | |
1050 return GUTTER_SIZE_SPECIFIERP (object) ? Qt : Qnil; | |
1051 } | |
1052 | |
442 | 1053 DECLARE_SPECIFIER_TYPE (gutter_visible); |
1054 #define GUTTER_VISIBLE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_visible) | |
1055 DEFINE_SPECIFIER_TYPE (gutter_visible); | |
1056 | |
1057 static void | |
1058 gutter_visible_validate (Lisp_Object instantiator) | |
1059 { | |
1060 if (NILP (instantiator)) | |
1061 return; | |
1062 | |
1063 if (!NILP (instantiator) && !EQ (instantiator, Qt) && !CONSP (instantiator)) | |
563 | 1064 invalid_argument ("Gutter visibility must be a boolean or list of symbols", |
442 | 1065 instantiator); |
1066 | |
1067 if (CONSP (instantiator)) | |
1068 { | |
2367 | 1069 EXTERNAL_LIST_LOOP_2 (elt, instantiator) |
442 | 1070 { |
2367 | 1071 if (!SYMBOLP (elt)) |
563 | 1072 invalid_argument ("Gutter visibility must be a boolean or list of symbols", |
442 | 1073 instantiator); |
1074 } | |
1075 } | |
1076 } | |
1077 | |
1078 DEFUN ("gutter-visible-specifier-p", Fgutter_visible_specifier_p, 1, 1, 0, /* | |
1079 Return non-nil if OBJECT is a gutter-visible specifier. | |
1080 | |
1081 See `make-gutter-visible-specifier' for a description of possible | |
1082 gutter-visible instantiators. | |
1083 */ | |
1084 (object)) | |
1085 { | |
1086 return GUTTER_VISIBLE_SPECIFIERP (object) ? Qt : Qnil; | |
1087 } | |
1088 | |
428 | 1089 DEFUN ("redisplay-gutter-area", Fredisplay_gutter_area, 0, 0, 0, /* |
1090 Ensure that all gutters are correctly showing their gutter specifier. | |
1091 */ | |
1092 ()) | |
1093 { | |
1094 Lisp_Object devcons, concons; | |
1095 | |
1318 | 1096 /* Can't reentrantly enter redisplay */ |
1097 if (in_display) | |
1098 return Qnil; | |
1099 | |
428 | 1100 DEVICE_LOOP_NO_BREAK (devcons, concons) |
1101 { | |
1102 struct device *d = XDEVICE (XCAR (devcons)); | |
1103 Lisp_Object frmcons; | |
1104 | |
1105 DEVICE_FRAME_LOOP (frmcons, d) | |
1106 { | |
1107 struct frame *f = XFRAME (XCAR (frmcons)); | |
1108 | |
442 | 1109 MAYBE_DEVMETH (d, frame_output_begin, (f)); |
1110 | |
1111 /* Sequence is quite important here. We not only want to | |
1112 redisplay the gutter area but we also want to flush any | |
1113 frame size changes out so that the gutter redisplay happens | |
1114 in a kosha environment. | |
1115 | |
1116 This is not only so that things look right but so that | |
1117 glyph redisplay optimization kicks in, by default display | |
1118 lines will be completely re-output if | |
1119 f->windows_structure_changed is 1, and this is true if | |
1120 frame size changes haven't been flushed out. Once frame | |
1121 size changes have been flushed out we then need to | |
1122 redisplay the frame in order to flush out pending window | |
1123 size changes. */ | |
1124 update_frame_gutter_geometry (f); | |
428 | 1125 |
442 | 1126 if (f->windows_structure_changed) |
1127 redisplay_frame (f, 1); | |
1128 else if (FRAME_REPAINT_P (f)) | |
1129 { | |
853 | 1130 int depth; |
1131 | |
442 | 1132 /* We have to be "in display" when we output the gutter |
4186 | 1133 - make it so. */ |
853 | 1134 depth = enter_redisplay_critical_section (); |
442 | 1135 update_frame_gutters (f); |
853 | 1136 exit_redisplay_critical_section (depth); |
442 | 1137 } |
1138 | |
1139 MAYBE_DEVMETH (d, frame_output_end, (f)); | |
1140 } | |
1141 | |
1142 d->gutter_changed = 0; | |
428 | 1143 } |
1144 | |
442 | 1145 /* This is so that further changes to the gutters will trigger redisplay. */ |
1146 gutter_changed_set = 0; | |
1147 gutter_changed = 0; | |
1148 | |
428 | 1149 return Qnil; |
1150 } | |
1151 | |
1152 void | |
1153 init_frame_gutters (struct frame *f) | |
1154 { | |
1155 enum gutter_pos pos; | |
1156 struct window* w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)); | |
1157 /* We are here as far in frame creation so cached specifiers are | |
1158 already recomputed, and possibly modified by resource | |
1159 initialization. We need to recalculate autodetected gutters. */ | |
1160 GUTTER_POS_LOOP (pos) | |
1161 { | |
442 | 1162 w->real_gutter[pos] = construct_window_gutter_spec (w, pos); |
428 | 1163 w->real_gutter_size[pos] = w->gutter_size[pos]; |
1164 if (EQ (w->gutter_size[pos], Qautodetect) | |
1165 && !NILP (w->gutter_visible_p[pos])) | |
1166 { | |
1167 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); | |
1168 MARK_GUTTER_CHANGED; | |
1169 MARK_WINDOWS_CHANGED (w); | |
1170 } | |
1171 } | |
442 | 1172 |
1173 /* Keep a record of the current sizes of things. */ | |
1174 GUTTER_POS_LOOP (pos) | |
1175 { | |
1176 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos); | |
1177 } | |
428 | 1178 } |
1179 | |
1180 void | |
1181 syms_of_gutter (void) | |
1182 { | |
1183 DEFSUBR (Fgutter_specifier_p); | |
1184 DEFSUBR (Fgutter_size_specifier_p); | |
442 | 1185 DEFSUBR (Fgutter_visible_specifier_p); |
428 | 1186 DEFSUBR (Fset_default_gutter_position); |
1187 DEFSUBR (Fdefault_gutter_position); | |
1188 DEFSUBR (Fgutter_pixel_height); | |
1189 DEFSUBR (Fgutter_pixel_width); | |
1190 DEFSUBR (Fredisplay_gutter_area); | |
1191 | |
563 | 1192 DEFSYMBOL (Qgutter_size); |
1193 DEFSYMBOL (Qgutter_visible); | |
1194 DEFSYMBOL (Qdefault_gutter_position_changed_hook); | |
428 | 1195 } |
1196 | |
1197 void | |
1198 vars_of_gutter (void) | |
1199 { | |
1200 staticpro (&Vdefault_gutter_position); | |
1201 Vdefault_gutter_position = Qtop; | |
1202 | |
1203 Fprovide (Qgutter); | |
1204 } | |
1205 | |
1206 void | |
1207 specifier_type_create_gutter (void) | |
1208 { | |
1209 INITIALIZE_SPECIFIER_TYPE (gutter, "gutter", "gutter-specifier-p"); | |
1210 SPECIFIER_HAS_METHOD (gutter, validate); | |
1211 SPECIFIER_HAS_METHOD (gutter, after_change); | |
1212 | |
1213 INITIALIZE_SPECIFIER_TYPE (gutter_size, "gutter-size", "gutter-size-specifier-p"); | |
442 | 1214 SPECIFIER_HAS_METHOD (gutter_size, validate); |
428 | 1215 |
442 | 1216 INITIALIZE_SPECIFIER_TYPE (gutter_visible, "gutter-visible", "gutter-visible-specifier-p"); |
1217 SPECIFIER_HAS_METHOD (gutter_visible, validate); | |
428 | 1218 } |
1219 | |
1220 void | |
1221 reinit_specifier_type_create_gutter (void) | |
1222 { | |
1223 REINITIALIZE_SPECIFIER_TYPE (gutter); | |
1224 REINITIALIZE_SPECIFIER_TYPE (gutter_size); | |
442 | 1225 REINITIALIZE_SPECIFIER_TYPE (gutter_visible); |
428 | 1226 } |
1227 | |
1228 void | |
1229 specifier_vars_of_gutter (void) | |
1230 { | |
1231 Lisp_Object fb; | |
1232 | |
1233 DEFVAR_SPECIFIER ("default-gutter", &Vdefault_gutter /* | |
1234 Specifier for a fallback gutter. | |
1235 Use `set-specifier' to change this. | |
1236 | |
1237 The position of this gutter is specified in the function | |
1238 `default-gutter-position'. If the corresponding position-specific | |
3025 | 1239 gutter (e.g. `top-gutter' if `default-gutter-position' is `top') |
428 | 1240 does not specify a gutter in a particular domain (usually a window), |
1241 then the value of `default-gutter' in that domain, if any, will be | |
1242 used instead. | |
1243 | |
1244 Note that the gutter at any particular position will not be | |
1245 displayed unless its visibility flag is true and its thickness | |
1246 \(width or height, depending on orientation) is non-zero. The | |
1247 visibility is controlled by the specifiers `top-gutter-visible-p', | |
1248 `bottom-gutter-visible-p', `left-gutter-visible-p', and | |
1249 `right-gutter-visible-p', and the thickness is controlled by the | |
1250 specifiers `top-gutter-height', `bottom-gutter-height', | |
1251 `left-gutter-width', and `right-gutter-width'. | |
1252 | |
1253 Note that one of the four visibility specifiers inherits from | |
1254 `default-gutter-visibility' and one of the four thickness | |
1255 specifiers inherits from either `default-gutter-width' or | |
1256 `default-gutter-height' (depending on orientation), just | |
1257 like for the gutter description specifiers (e.g. `top-gutter') | |
1258 mentioned above. | |
1259 | |
1260 Therefore, if you are setting `default-gutter', you should control | |
1261 the visibility and thickness using `default-gutter-visible-p', | |
1262 `default-gutter-width', and `default-gutter-height', rather than | |
1263 using position-specific specifiers. That way, you will get sane | |
1264 behavior if the user changes the default gutter position. | |
1265 | |
442 | 1266 The gutter value should be a string, a property list of strings or |
1267 nil. You can attach extents and glyphs to the string and hence display | |
1268 glyphs and text in other fonts in the gutter area. If the gutter value | |
1269 is a property list then the strings will be concatenated together | |
1270 before being displayed. */ ); | |
428 | 1271 |
1272 Vdefault_gutter = Fmake_specifier (Qgutter); | |
1273 /* #### It would be even nicer if the specifier caching | |
1274 automatically knew about specifier fallbacks, so we didn't | |
1275 have to do it ourselves. */ | |
1276 set_specifier_caching (Vdefault_gutter, | |
438 | 1277 offsetof (struct window, default_gutter), |
428 | 1278 default_gutter_specs_changed, |
444 | 1279 0, 0, 1); |
428 | 1280 |
1281 DEFVAR_SPECIFIER ("top-gutter", | |
1282 &Vgutter[TOP_GUTTER] /* | |
1283 Specifier for the gutter at the top of the frame. | |
1284 Use `set-specifier' to change this. | |
1285 See `default-gutter' for a description of a valid gutter instantiator. | |
1286 */ ); | |
1287 Vgutter[TOP_GUTTER] = Fmake_specifier (Qgutter); | |
1288 set_specifier_caching (Vgutter[TOP_GUTTER], | |
438 | 1289 offsetof (struct window, gutter[TOP_GUTTER]), |
442 | 1290 top_gutter_specs_changed, |
444 | 1291 0, 0, 1); |
428 | 1292 |
1293 DEFVAR_SPECIFIER ("bottom-gutter", | |
1294 &Vgutter[BOTTOM_GUTTER] /* | |
1295 Specifier for the gutter at the bottom of the frame. | |
1296 Use `set-specifier' to change this. | |
1297 See `default-gutter' for a description of a valid gutter instantiator. | |
1298 | |
1299 Note that, unless the `default-gutter-position' is `bottom', by | |
1300 default the height of the bottom gutter (controlled by | |
1301 `bottom-gutter-height') is 0; thus, a bottom gutter will not be | |
1302 displayed even if you provide a value for `bottom-gutter'. | |
1303 */ ); | |
1304 Vgutter[BOTTOM_GUTTER] = Fmake_specifier (Qgutter); | |
1305 set_specifier_caching (Vgutter[BOTTOM_GUTTER], | |
438 | 1306 offsetof (struct window, gutter[BOTTOM_GUTTER]), |
442 | 1307 bottom_gutter_specs_changed, |
444 | 1308 0, 0, 1); |
428 | 1309 |
1310 DEFVAR_SPECIFIER ("left-gutter", | |
1311 &Vgutter[LEFT_GUTTER] /* | |
1312 Specifier for the gutter at the left edge of the frame. | |
1313 Use `set-specifier' to change this. | |
1314 See `default-gutter' for a description of a valid gutter instantiator. | |
1315 | |
1316 Note that, unless the `default-gutter-position' is `left', by | |
1317 default the height of the left gutter (controlled by | |
1318 `left-gutter-width') is 0; thus, a left gutter will not be | |
1319 displayed even if you provide a value for `left-gutter'. | |
1320 */ ); | |
1321 Vgutter[LEFT_GUTTER] = Fmake_specifier (Qgutter); | |
1322 set_specifier_caching (Vgutter[LEFT_GUTTER], | |
438 | 1323 offsetof (struct window, gutter[LEFT_GUTTER]), |
442 | 1324 left_gutter_specs_changed, |
444 | 1325 0, 0, 1); |
428 | 1326 |
1327 DEFVAR_SPECIFIER ("right-gutter", | |
1328 &Vgutter[RIGHT_GUTTER] /* | |
1329 Specifier for the gutter at the right edge of the frame. | |
1330 Use `set-specifier' to change this. | |
1331 See `default-gutter' for a description of a valid gutter instantiator. | |
1332 | |
1333 Note that, unless the `default-gutter-position' is `right', by | |
1334 default the height of the right gutter (controlled by | |
1335 `right-gutter-width') is 0; thus, a right gutter will not be | |
1336 displayed even if you provide a value for `right-gutter'. | |
1337 */ ); | |
1338 Vgutter[RIGHT_GUTTER] = Fmake_specifier (Qgutter); | |
1339 set_specifier_caching (Vgutter[RIGHT_GUTTER], | |
438 | 1340 offsetof (struct window, gutter[RIGHT_GUTTER]), |
442 | 1341 right_gutter_specs_changed, |
444 | 1342 0, 0, 1); |
428 | 1343 |
1344 /* initially, top inherits from default; this can be | |
1345 changed with `set-default-gutter-position'. */ | |
1346 fb = list1 (Fcons (Qnil, Qnil)); | |
1347 set_specifier_fallback (Vdefault_gutter, fb); | |
1348 set_specifier_fallback (Vgutter[TOP_GUTTER], Vdefault_gutter); | |
1349 set_specifier_fallback (Vgutter[BOTTOM_GUTTER], fb); | |
1350 set_specifier_fallback (Vgutter[LEFT_GUTTER], fb); | |
1351 set_specifier_fallback (Vgutter[RIGHT_GUTTER], fb); | |
1352 | |
1353 DEFVAR_SPECIFIER ("default-gutter-height", &Vdefault_gutter_height /* | |
1354 *Height of the default gutter, if it's oriented horizontally. | |
1355 This is a specifier; use `set-specifier' to change it. | |
1356 | |
1357 The position of the default gutter is specified by the function | |
1358 `set-default-gutter-position'. If the corresponding position-specific | |
1359 gutter thickness specifier (e.g. `top-gutter-height' if | |
3025 | 1360 `default-gutter-position' is `top') does not specify a thickness in a |
428 | 1361 particular domain (a window or a frame), then the value of |
1362 `default-gutter-height' or `default-gutter-width' (depending on the | |
1363 gutter orientation) in that domain, if any, will be used instead. | |
1364 | |
1365 Note that `default-gutter-height' is only used when | |
3025 | 1366 `default-gutter-position' is `top' or `bottom', and `default-gutter-width' |
1367 is only used when `default-gutter-position' is `left' or `right'. | |
428 | 1368 |
1369 Note that all of the position-specific gutter thickness specifiers | |
1370 have a fallback value of zero when they do not correspond to the | |
1371 default gutter. Therefore, you will have to set a non-zero thickness | |
1372 value if you want a position-specific gutter to be displayed. | |
1373 | |
3025 | 1374 If you set the height to `autodetect' the size of the gutter will be |
428 | 1375 calculated to be large enough to hold the contents of the gutter. This |
1376 is the default. | |
1377 */ ); | |
1378 Vdefault_gutter_height = Fmake_specifier (Qgutter_size); | |
1379 set_specifier_caching (Vdefault_gutter_height, | |
438 | 1380 offsetof (struct window, default_gutter_height), |
428 | 1381 default_gutter_size_changed_in_window, |
444 | 1382 0, 0, 1); |
428 | 1383 |
1384 DEFVAR_SPECIFIER ("default-gutter-width", &Vdefault_gutter_width /* | |
1385 *Width of the default gutter, if it's oriented vertically. | |
1386 This is a specifier; use `set-specifier' to change it. | |
1387 | |
1388 See `default-gutter-height' for more information. | |
1389 */ ); | |
444 | 1390 Vdefault_gutter_width = Fmake_specifier (Qgutter_size); |
428 | 1391 set_specifier_caching (Vdefault_gutter_width, |
438 | 1392 offsetof (struct window, default_gutter_width), |
428 | 1393 default_gutter_size_changed_in_window, |
444 | 1394 0, 0, 1); |
428 | 1395 |
1396 DEFVAR_SPECIFIER ("top-gutter-height", | |
1397 &Vgutter_size[TOP_GUTTER] /* | |
1398 *Height of the top gutter. | |
1399 This is a specifier; use `set-specifier' to change it. | |
1400 | |
1401 See `default-gutter-height' for more information. | |
1402 */ ); | |
1403 Vgutter_size[TOP_GUTTER] = Fmake_specifier (Qgutter_size); | |
1404 set_specifier_caching (Vgutter_size[TOP_GUTTER], | |
438 | 1405 offsetof (struct window, gutter_size[TOP_GUTTER]), |
444 | 1406 gutter_geometry_changed_in_window, 0, 0, 1); |
428 | 1407 |
1408 DEFVAR_SPECIFIER ("bottom-gutter-height", | |
1409 &Vgutter_size[BOTTOM_GUTTER] /* | |
1410 *Height of the bottom gutter. | |
1411 This is a specifier; use `set-specifier' to change it. | |
1412 | |
1413 See `default-gutter-height' for more information. | |
1414 */ ); | |
1415 Vgutter_size[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_size); | |
1416 set_specifier_caching (Vgutter_size[BOTTOM_GUTTER], | |
438 | 1417 offsetof (struct window, gutter_size[BOTTOM_GUTTER]), |
444 | 1418 gutter_geometry_changed_in_window, 0, 0, 1); |
428 | 1419 |
1420 DEFVAR_SPECIFIER ("left-gutter-width", | |
1421 &Vgutter_size[LEFT_GUTTER] /* | |
1422 *Width of left gutter. | |
1423 This is a specifier; use `set-specifier' to change it. | |
1424 | |
1425 See `default-gutter-height' for more information. | |
1426 */ ); | |
444 | 1427 Vgutter_size[LEFT_GUTTER] = Fmake_specifier (Qgutter_size); |
428 | 1428 set_specifier_caching (Vgutter_size[LEFT_GUTTER], |
438 | 1429 offsetof (struct window, gutter_size[LEFT_GUTTER]), |
444 | 1430 gutter_geometry_changed_in_window, 0, 0, 1); |
428 | 1431 |
1432 DEFVAR_SPECIFIER ("right-gutter-width", | |
1433 &Vgutter_size[RIGHT_GUTTER] /* | |
1434 *Width of right gutter. | |
1435 This is a specifier; use `set-specifier' to change it. | |
1436 | |
1437 See `default-gutter-height' for more information. | |
1438 */ ); | |
444 | 1439 Vgutter_size[RIGHT_GUTTER] = Fmake_specifier (Qgutter_size); |
428 | 1440 set_specifier_caching (Vgutter_size[RIGHT_GUTTER], |
438 | 1441 offsetof (struct window, gutter_size[RIGHT_GUTTER]), |
444 | 1442 gutter_geometry_changed_in_window, 0, 0, 1); |
428 | 1443 |
1444 fb = Qnil; | |
1445 #ifdef HAVE_TTY | |
1446 fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb); | |
1447 #endif | |
462 | 1448 #ifdef HAVE_GTK |
1449 fb = Fcons (Fcons (list1 (Qgtk), Qautodetect), fb); | |
1450 #endif | |
428 | 1451 #ifdef HAVE_X_WINDOWS |
1452 fb = Fcons (Fcons (list1 (Qx), Qautodetect), fb); | |
1453 #endif | |
1454 #ifdef HAVE_MS_WINDOWS | |
440 | 1455 fb = Fcons (Fcons (list1 (Qmsprinter), Qautodetect), fb); |
428 | 1456 fb = Fcons (Fcons (list1 (Qmswindows), Qautodetect), fb); |
1457 #endif | |
1458 if (!NILP (fb)) | |
1459 set_specifier_fallback (Vdefault_gutter_height, fb); | |
1460 | |
1461 fb = Qnil; | |
1462 #ifdef HAVE_TTY | |
444 | 1463 fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb); |
428 | 1464 #endif |
1465 #ifdef HAVE_X_WINDOWS | |
444 | 1466 fb = Fcons (Fcons (list1 (Qx), Qautodetect), fb); |
428 | 1467 #endif |
462 | 1468 #ifdef HAVE_GTK |
1469 fb = Fcons (Fcons (list1 (Qgtk), Qautodetect), fb); | |
1470 #endif | |
428 | 1471 #ifdef HAVE_MS_WINDOWS |
444 | 1472 fb = Fcons (Fcons (list1 (Qmsprinter), Qautodetect), fb); |
1473 fb = Fcons (Fcons (list1 (Qmswindows), Qautodetect), fb); | |
428 | 1474 #endif |
1475 if (!NILP (fb)) | |
1476 set_specifier_fallback (Vdefault_gutter_width, fb); | |
1477 | |
1478 set_specifier_fallback (Vgutter_size[TOP_GUTTER], Vdefault_gutter_height); | |
1479 fb = list1 (Fcons (Qnil, Qzero)); | |
1480 set_specifier_fallback (Vgutter_size[BOTTOM_GUTTER], fb); | |
1481 set_specifier_fallback (Vgutter_size[LEFT_GUTTER], fb); | |
1482 set_specifier_fallback (Vgutter_size[RIGHT_GUTTER], fb); | |
1483 | |
1484 DEFVAR_SPECIFIER ("default-gutter-border-width", | |
1485 &Vdefault_gutter_border_width /* | |
1486 *Width of the border around the default gutter. | |
1487 This is a specifier; use `set-specifier' to change it. | |
1488 | |
1489 The position of the default gutter is specified by the function | |
1490 `set-default-gutter-position'. If the corresponding position-specific | |
1491 gutter border width specifier (e.g. `top-gutter-border-width' if | |
3025 | 1492 `default-gutter-position' is `top') does not specify a border width in a |
428 | 1493 particular domain (a window or a frame), then the value of |
1494 `default-gutter-border-width' in that domain, if any, will be used | |
1495 instead. | |
1496 | |
1497 */ ); | |
1498 Vdefault_gutter_border_width = Fmake_specifier (Qnatnum); | |
1499 set_specifier_caching (Vdefault_gutter_border_width, | |
438 | 1500 offsetof (struct window, default_gutter_border_width), |
428 | 1501 default_gutter_border_width_changed_in_window, |
444 | 1502 0, 0, 0); |
428 | 1503 |
1504 DEFVAR_SPECIFIER ("top-gutter-border-width", | |
1505 &Vgutter_border_width[TOP_GUTTER] /* | |
1506 *Border width of the top gutter. | |
1507 This is a specifier; use `set-specifier' to change it. | |
1508 | |
1509 See `default-gutter-height' for more information. | |
1510 */ ); | |
1511 Vgutter_border_width[TOP_GUTTER] = Fmake_specifier (Qnatnum); | |
1512 set_specifier_caching (Vgutter_border_width[TOP_GUTTER], | |
438 | 1513 offsetof (struct window, |
1514 gutter_border_width[TOP_GUTTER]), | |
444 | 1515 gutter_geometry_changed_in_window, 0, 0, 0); |
428 | 1516 |
1517 DEFVAR_SPECIFIER ("bottom-gutter-border-width", | |
1518 &Vgutter_border_width[BOTTOM_GUTTER] /* | |
1519 *Border width of the bottom gutter. | |
1520 This is a specifier; use `set-specifier' to change it. | |
1521 | |
1522 See `default-gutter-height' for more information. | |
1523 */ ); | |
1524 Vgutter_border_width[BOTTOM_GUTTER] = Fmake_specifier (Qnatnum); | |
1525 set_specifier_caching (Vgutter_border_width[BOTTOM_GUTTER], | |
438 | 1526 offsetof (struct window, |
1527 gutter_border_width[BOTTOM_GUTTER]), | |
444 | 1528 gutter_geometry_changed_in_window, 0, 0, 0); |
428 | 1529 |
1530 DEFVAR_SPECIFIER ("left-gutter-border-width", | |
1531 &Vgutter_border_width[LEFT_GUTTER] /* | |
1532 *Border width of left gutter. | |
1533 This is a specifier; use `set-specifier' to change it. | |
1534 | |
1535 See `default-gutter-height' for more information. | |
1536 */ ); | |
1537 Vgutter_border_width[LEFT_GUTTER] = Fmake_specifier (Qnatnum); | |
1538 set_specifier_caching (Vgutter_border_width[LEFT_GUTTER], | |
438 | 1539 offsetof (struct window, |
1540 gutter_border_width[LEFT_GUTTER]), | |
444 | 1541 gutter_geometry_changed_in_window, 0, 0, 0); |
428 | 1542 |
1543 DEFVAR_SPECIFIER ("right-gutter-border-width", | |
1544 &Vgutter_border_width[RIGHT_GUTTER] /* | |
1545 *Border width of right gutter. | |
1546 This is a specifier; use `set-specifier' to change it. | |
1547 | |
1548 See `default-gutter-height' for more information. | |
1549 */ ); | |
1550 Vgutter_border_width[RIGHT_GUTTER] = Fmake_specifier (Qnatnum); | |
1551 set_specifier_caching (Vgutter_border_width[RIGHT_GUTTER], | |
438 | 1552 offsetof (struct window, |
1553 gutter_border_width[RIGHT_GUTTER]), | |
444 | 1554 gutter_geometry_changed_in_window, 0, 0, 0); |
428 | 1555 |
1556 fb = Qnil; | |
1557 #ifdef HAVE_TTY | |
1558 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb); | |
1559 #endif | |
1560 #ifdef HAVE_X_WINDOWS | |
1561 fb = Fcons (Fcons (list1 (Qx), make_int (DEFAULT_GUTTER_BORDER_WIDTH)), fb); | |
1562 #endif | |
1563 #ifdef HAVE_MS_WINDOWS | |
440 | 1564 fb = Fcons (Fcons (list1 (Qmsprinter), Qzero), fb); |
428 | 1565 fb = Fcons (Fcons (list1 (Qmswindows), make_int (DEFAULT_GUTTER_BORDER_WIDTH)), fb); |
1566 #endif | |
1567 if (!NILP (fb)) | |
1568 set_specifier_fallback (Vdefault_gutter_border_width, fb); | |
1569 | |
1570 set_specifier_fallback (Vgutter_border_width[TOP_GUTTER], Vdefault_gutter_border_width); | |
1571 fb = list1 (Fcons (Qnil, Qzero)); | |
1572 set_specifier_fallback (Vgutter_border_width[BOTTOM_GUTTER], fb); | |
1573 set_specifier_fallback (Vgutter_border_width[LEFT_GUTTER], fb); | |
1574 set_specifier_fallback (Vgutter_border_width[RIGHT_GUTTER], fb); | |
1575 | |
1576 DEFVAR_SPECIFIER ("default-gutter-visible-p", &Vdefault_gutter_visible_p /* | |
1577 *Whether the default gutter is visible. | |
1578 This is a specifier; use `set-specifier' to change it. | |
1579 | |
1580 The position of the default gutter is specified by the function | |
1581 `set-default-gutter-position'. If the corresponding position-specific | |
1582 gutter visibility specifier (e.g. `top-gutter-visible-p' if | |
3025 | 1583 `default-gutter-position' is `top') does not specify a visible-p value |
428 | 1584 in a particular domain (a window or a frame), then the value of |
1585 `default-gutter-visible-p' in that domain, if any, will be used | |
1586 instead. | |
1587 | |
1588 `default-gutter-visible-p' and all of the position-specific gutter | |
1589 visibility specifiers have a fallback value of true. | |
1590 */ ); | |
442 | 1591 Vdefault_gutter_visible_p = Fmake_specifier (Qgutter_visible); |
428 | 1592 set_specifier_caching (Vdefault_gutter_visible_p, |
438 | 1593 offsetof (struct window, |
1594 default_gutter_visible_p), | |
428 | 1595 default_gutter_visible_p_changed_in_window, |
444 | 1596 0, 0, 0); |
428 | 1597 |
1598 DEFVAR_SPECIFIER ("top-gutter-visible-p", | |
1599 &Vgutter_visible_p[TOP_GUTTER] /* | |
1600 *Whether the top gutter is visible. | |
1601 This is a specifier; use `set-specifier' to change it. | |
1602 | |
1603 See `default-gutter-visible-p' for more information. | |
1604 */ ); | |
442 | 1605 Vgutter_visible_p[TOP_GUTTER] = Fmake_specifier (Qgutter_visible); |
428 | 1606 set_specifier_caching (Vgutter_visible_p[TOP_GUTTER], |
438 | 1607 offsetof (struct window, |
1608 gutter_visible_p[TOP_GUTTER]), | |
444 | 1609 top_gutter_specs_changed, 0, 0, 0); |
428 | 1610 |
1611 DEFVAR_SPECIFIER ("bottom-gutter-visible-p", | |
1612 &Vgutter_visible_p[BOTTOM_GUTTER] /* | |
1613 *Whether the bottom gutter is visible. | |
1614 This is a specifier; use `set-specifier' to change it. | |
1615 | |
1616 See `default-gutter-visible-p' for more information. | |
1617 */ ); | |
442 | 1618 Vgutter_visible_p[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_visible); |
428 | 1619 set_specifier_caching (Vgutter_visible_p[BOTTOM_GUTTER], |
438 | 1620 offsetof (struct window, |
1621 gutter_visible_p[BOTTOM_GUTTER]), | |
444 | 1622 bottom_gutter_specs_changed, 0, 0, 0); |
428 | 1623 |
1624 DEFVAR_SPECIFIER ("left-gutter-visible-p", | |
1625 &Vgutter_visible_p[LEFT_GUTTER] /* | |
1626 *Whether the left gutter is visible. | |
1627 This is a specifier; use `set-specifier' to change it. | |
1628 | |
1629 See `default-gutter-visible-p' for more information. | |
1630 */ ); | |
442 | 1631 Vgutter_visible_p[LEFT_GUTTER] = Fmake_specifier (Qgutter_visible); |
428 | 1632 set_specifier_caching (Vgutter_visible_p[LEFT_GUTTER], |
438 | 1633 offsetof (struct window, |
1634 gutter_visible_p[LEFT_GUTTER]), | |
444 | 1635 left_gutter_specs_changed, 0, 0, 0); |
428 | 1636 |
1637 DEFVAR_SPECIFIER ("right-gutter-visible-p", | |
1638 &Vgutter_visible_p[RIGHT_GUTTER] /* | |
1639 *Whether the right gutter is visible. | |
1640 This is a specifier; use `set-specifier' to change it. | |
1641 | |
1642 See `default-gutter-visible-p' for more information. | |
1643 */ ); | |
442 | 1644 Vgutter_visible_p[RIGHT_GUTTER] = Fmake_specifier (Qgutter_visible); |
428 | 1645 set_specifier_caching (Vgutter_visible_p[RIGHT_GUTTER], |
438 | 1646 offsetof (struct window, |
1647 gutter_visible_p[RIGHT_GUTTER]), | |
444 | 1648 right_gutter_specs_changed, 0, 0, 0); |
428 | 1649 |
1650 /* initially, top inherits from default; this can be | |
1651 changed with `set-default-gutter-position'. */ | |
1652 fb = list1 (Fcons (Qnil, Qt)); | |
1653 set_specifier_fallback (Vdefault_gutter_visible_p, fb); | |
1654 set_specifier_fallback (Vgutter_visible_p[TOP_GUTTER], | |
1655 Vdefault_gutter_visible_p); | |
1656 set_specifier_fallback (Vgutter_visible_p[BOTTOM_GUTTER], fb); | |
1657 set_specifier_fallback (Vgutter_visible_p[LEFT_GUTTER], fb); | |
1658 set_specifier_fallback (Vgutter_visible_p[RIGHT_GUTTER], fb); | |
1659 } |