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