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: \
+ − 73 abort (); \
+ − 74 } \
+ − 75 } while (0)
+ − 76
+ − 77 static int gutter_was_visible (struct frame* frame, enum gutter_pos pos)
+ − 78 {
+ − 79 switch (pos)
+ − 80 {
+ − 81 case TOP_GUTTER:
+ − 82 return frame->top_gutter_was_visible;
+ − 83 case BOTTOM_GUTTER:
+ − 84 return frame->bottom_gutter_was_visible;
+ − 85 case LEFT_GUTTER:
+ − 86 return frame->left_gutter_was_visible;
+ − 87 case RIGHT_GUTTER:
+ − 88 return frame->right_gutter_was_visible;
+ − 89 default:
+ − 90 abort ();
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:
+ − 217 abort ();
+ − 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
+ − 275 visible. */
+ − 276 if (!CONSP (WINDOW_GUTTER_VISIBLE (w, pos))
+ − 277 ||
+ − 278 !NILP (Fmemq (XCAR (rest), WINDOW_GUTTER_VISIBLE (w, pos))))
+ − 279 {
+ − 280 args [nargs++] = XCAR (XCDR (rest));
+ − 281 }
+ − 282 }
+ − 283
+ − 284 return Fconcat (nargs, args);
+ − 285 }
+ − 286
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);
+ − 304 size = (dl->ypos + dl->descent - dl->clip)
+ − 305 - (Dynarr_atp (ddla, 0)->ypos - Dynarr_atp (ddla, 0)->ascent);
+ − 306 }
+ − 307 }
+ − 308 /* For left and right we have to do some maths. */
+ − 309 else
+ − 310 {
+ − 311 int start_pos = 0, end_pos = 0, line;
+ − 312 for (line = 0; line < Dynarr_length (ddla); line++)
+ − 313 {
+ − 314 int block;
+ − 315 dl = Dynarr_atp (ddla, line);
+ − 316
+ − 317 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
+ − 318 {
+ − 319 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
+ − 320
+ − 321 if (db->type == TEXT)
+ − 322 {
+ − 323 start_pos = min (db->start_pos, start_pos);
+ − 324 end_pos = max (db->end_pos, end_pos);
+ − 325 }
+ − 326 }
+ − 327 }
+ − 328 size = end_pos - start_pos;
+ − 329 }
+ − 330
+ − 331 return size;
+ − 332 }
+ − 333
+ − 334 static Lisp_Object
+ − 335 calculate_gutter_size (struct window *w, enum gutter_pos pos)
+ − 336 {
+ − 337 struct frame* f = XFRAME (WINDOW_FRAME (w));
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),
+ − 368 ddla, 0, 0);
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 frame;
+ − 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
793
+ − 409 frame = wrap_frame (f);
428
+ − 410
+ − 411 get_gutter_coords (f, pos, &x, &y, &width, &height);
+ − 412 /* generate some display lines */
+ − 413 generate_displayable_area (w, WINDOW_GUTTER (w, pos),
+ − 414 x + border_width, y + border_width,
442
+ − 415 width - 2 * border_width,
428
+ − 416 height - 2 * border_width, ddla, 0, findex);
442
+ − 417
+ − 418 /* We only output the gutter if we think something of significance
+ − 419 has changed. This is, for example, because redisplay can cause
+ − 420 new face cache elements to get added causing compare_runes to
+ − 421 fail because the findex for a particular face has changed. */
+ − 422 if (force || f->faces_changed || f->frame_changed ||
+ − 423 f->gutter_changed || f->glyphs_changed ||
+ − 424 f->size_changed || f->subwindows_changed ||
+ − 425 w->windows_changed || f->windows_structure_changed ||
+ − 426 cdla_len != Dynarr_length (ddla) ||
+ − 427 (f->extents_changed && w->gutter_extent_modiff[pos]))
428
+ − 428 {
442
+ − 429 #ifdef DEBUG_GUTTERS
639
+ − 430 stderr_out ("gutter redisplay [%s %dx%d@%d+%d] triggered by %s,\n",
+ − 431 pos == TOP_GUTTER ? "TOP" :
+ − 432 pos == BOTTOM_GUTTER ? "BOTTOM" :
+ − 433 pos == LEFT_GUTTER ? "LEFT" : "RIGHT",
446
+ − 434 width, height, x, y, force ? "force" :
442
+ − 435 f->faces_changed ? "f->faces_changed" :
+ − 436 f->frame_changed ? "f->frame_changed" :
+ − 437 f->gutter_changed ? "f->gutter_changed" :
+ − 438 f->glyphs_changed ? "f->glyphs_changed" :
+ − 439 f->size_changed ? "f->size_changed" :
+ − 440 f->subwindows_changed ? "f->subwindows_changed" :
+ − 441 w->windows_changed ? "w->windows_changed" :
+ − 442 f->windows_structure_changed ? "f->windows_structure_changed" :
+ − 443 cdla_len != Dynarr_length (ddla) ? "different display structures" :
+ − 444 f->extents_changed && w->gutter_extent_modiff[pos] ?
+ − 445 "f->extents_changed && w->gutter_extent_modiff[pos]" : "<null>");
+ − 446 #endif
+ − 447 /* Output each line. */
+ − 448 for (line = 0; line < Dynarr_length (ddla); line++)
+ − 449 {
+ − 450 output_display_line (w, cdla, ddla, line, -1, -1);
+ − 451 }
+ − 452
+ − 453 /* If the number of display lines has shrunk, adjust. */
+ − 454 if (cdla_len > Dynarr_length (ddla))
+ − 455 {
+ − 456 Dynarr_length (cdla) = Dynarr_length (ddla);
+ − 457 }
+ − 458
+ − 459 /* grab coordinates of last line and blank after it. */
+ − 460 if (Dynarr_length (ddla) > 0)
+ − 461 {
+ − 462 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1);
+ − 463 ypos = dl->ypos + dl->descent - dl->clip;
+ − 464 }
+ − 465 else
+ − 466 ypos = y;
428
+ − 467
442
+ − 468 redisplay_clear_region (window, findex, x + border_width , ypos,
+ − 469 width - 2 * border_width, height - (ypos - y) - border_width);
+ − 470 /* If, for some reason, we have more to display than we have
+ − 471 room for, and we are allowed to resize the gutter, then make
+ − 472 sure this happens before the next time we try and
+ − 473 output. This can happen when face font sizes change. */
444
+ − 474 if (dl && EQ (w->gutter_size[pos], Qautodetect)
+ − 475 && (dl->clip > 0 ||
+ − 476 calculate_gutter_size_from_display_lines (pos, ddla) >
+ − 477 WINDOW_GUTTER_SIZE_INTERNAL (w, pos)))
442
+ − 478 {
+ − 479 /* #### Ideally we would just mark the specifier as dirty
+ − 480 and everything else would "just work". Unfortunately we have
+ − 481 two problems with this. One is that the specifier cache
+ − 482 won't be recalculated unless the specifier code thinks the
+ − 483 cached value has actually changed, even though we have
+ − 484 marked the specifier as dirty. Additionally, although doing
+ − 485 this results in a gutter size change, we never seem to get
+ − 486 back into redisplay so that the frame size can be updated. I
+ − 487 think this is because we are already in redisplay and later
+ − 488 on the frame will be marked as clean. Thus we also have to
+ − 489 force a pending recalculation of the frame size. */
+ − 490 w->gutter_size[pos] = Qnil;
+ − 491 Fset_specifier_dirty_flag (Vgutter_size[pos]);
+ − 492 update_gutter_geometry (f, pos);
+ − 493 }
+ − 494
+ − 495 /* bevel the gutter area if so desired */
+ − 496 if (border_width != 0)
+ − 497 {
+ − 498 MAYBE_DEVMETH (d, bevel_area,
+ − 499 (w, findex, x, y, width, height, border_width,
+ − 500 EDGE_ALL, EDGE_BEVEL_OUT));
+ − 501 }
+ − 502 }
+ − 503 else
428
+ − 504 {
442
+ − 505 /* Nothing of significance happened so sync the display line
+ − 506 structs. */
+ − 507 for (line = 0; line < Dynarr_length (ddla); line++)
+ − 508 {
+ − 509 sync_display_line_structs (w, line, 1, cdla, ddla);
+ − 510 }
428
+ − 511 }
+ − 512
442
+ − 513 w->gutter_extent_modiff [pos] = 0;
428
+ − 514 }
+ − 515
+ − 516 static void
+ − 517 clear_gutter (struct frame *f, enum gutter_pos pos)
+ − 518 {
+ − 519 int x, y, width, height;
+ − 520 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
+ − 521 face_index findex = get_builtin_face_cache_index (XWINDOW (window),
442
+ − 522 Vwidget_face);
428
+ − 523 get_gutter_coords (f, pos, &x, &y, &width, &height);
+ − 524
+ − 525 SET_GUTTER_WAS_VISIBLE_FLAG (f, pos, 0);
+ − 526
+ − 527 redisplay_clear_region (window, findex, x, y, width, height);
+ − 528 }
+ − 529
617
+ − 530 /* [[#### I don't currently believe that redisplay needs to mark the
442
+ − 531 glyphs in its structures since these will always be referenced from
+ − 532 somewhere else. However, I'm not sure enough to stake my life on it
617
+ − 533 at this point, so we do the safe thing.]]
+ − 534
+ − 535 ALWAYS mark everything. --ben */
442
+ − 536
+ − 537 /* See the comment in image_instantiate_cache_result as to why marking
+ − 538 the glyph will also mark the image_instance. */
+ − 539 void
617
+ − 540 mark_gutters (struct frame *f)
442
+ − 541 {
+ − 542 enum gutter_pos pos;
+ − 543 GUTTER_POS_LOOP (pos)
+ − 544 {
+ − 545 if (f->current_display_lines[pos])
+ − 546 mark_redisplay_structs (f->current_display_lines[pos]);
617
+ − 547 /* [[#### Do we really need to mark the desired lines?]]
+ − 548 ALWAYS mark everything. --ben */
442
+ − 549 if (f->desired_display_lines[pos])
+ − 550 mark_redisplay_structs (f->desired_display_lines[pos]);
+ − 551 }
+ − 552 }
+ − 553
+ − 554 /* This is called by extent_changed_for_redisplay, so that redisplay
+ − 555 knows exactly what extents have changed. */
+ − 556 void
+ − 557 gutter_extent_signal_changed_region_maybe (Lisp_Object obj,
665
+ − 558 Charbpos start, Charbpos end)
442
+ − 559 {
+ − 560 /* #### Start and end are currently ignored but could be used by a
+ − 561 more optimal gutter redisplay. We currently loop over all frames
+ − 562 here, this could be optimized. */
+ − 563 Lisp_Object frmcons, devcons, concons;
+ − 564
+ − 565 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
+ − 566 {
+ − 567 struct frame *f = XFRAME (XCAR (frmcons));
+ − 568 enum gutter_pos pos;
+ − 569 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
+ − 570 struct window* w = XWINDOW (window);
+ − 571
+ − 572 GUTTER_POS_LOOP (pos)
+ − 573 {
+ − 574 if (EQ (WINDOW_GUTTER (w, pos), obj))
+ − 575 {
+ − 576 w->gutter_extent_modiff[pos]++;
+ − 577 }
+ − 578 }
+ − 579 }
+ − 580 }
+ − 581
+ − 582 /* We have to change the gutter geometry separately to the gutter
+ − 583 update since it needs to occur outside of redisplay proper. */
+ − 584 static void
+ − 585 update_gutter_geometry (struct frame *f, enum gutter_pos pos)
+ − 586 {
+ − 587 /* If the gutter geometry has changed then re-layout the
+ − 588 frame. If we are in display there is almost no point in doing
+ − 589 anything else since the frame size changes will be delayed
+ − 590 until we are out of redisplay proper. */
+ − 591 if (FRAME_GUTTER_BOUNDS (f, pos) != f->current_gutter_bounds[pos])
+ − 592 {
+ − 593 int width, height;
+ − 594 pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f),
+ − 595 &width, &height);
+ − 596 change_frame_size (f, height, width, 0);
905
+ − 597 MARK_FRAME_LAYOUT_CHANGED (f);
442
+ − 598 }
+ − 599
+ − 600 /* Mark sizes as up-to-date. */
+ − 601 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos);
+ − 602 }
+ − 603
+ − 604 void
+ − 605 update_frame_gutter_geometry (struct frame *f)
+ − 606 {
905
+ − 607 if (f->gutter_changed
+ − 608 || f->frame_layout_changed
+ − 609 || f->windows_structure_changed)
442
+ − 610 {
+ − 611 enum gutter_pos pos;
+ − 612
+ − 613 /* If the gutter geometry has changed then re-layout the
+ − 614 frame. If we are in display there is almost no point in doing
+ − 615 anything else since the frame size changes will be delayed
+ − 616 until we are out of redisplay proper. */
+ − 617 GUTTER_POS_LOOP (pos)
+ − 618 {
+ − 619 update_gutter_geometry (f, pos);
+ − 620 }
+ − 621 }
+ − 622 }
+ − 623
428
+ − 624 void
+ − 625 update_frame_gutters (struct frame *f)
+ − 626 {
442
+ − 627 if (f->faces_changed || f->frame_changed ||
+ − 628 f->gutter_changed || f->glyphs_changed ||
+ − 629 f->size_changed || f->subwindows_changed ||
+ − 630 f->windows_changed || f->windows_structure_changed ||
905
+ − 631 f->extents_changed || f->frame_layout_changed)
428
+ − 632 {
+ − 633 enum gutter_pos pos;
442
+ − 634
428
+ − 635 /* We don't actually care about these when outputting the gutter
+ − 636 so locally disable them. */
+ − 637 int local_clip_changed = f->clip_changed;
+ − 638 int local_buffers_changed = f->buffers_changed;
+ − 639 f->clip_changed = 0;
+ − 640 f->buffers_changed = 0;
+ − 641
+ − 642 /* and output */
+ − 643 GUTTER_POS_LOOP (pos)
+ − 644 {
+ − 645 if (FRAME_GUTTER_VISIBLE (f, pos))
442
+ − 646 output_gutter (f, pos, 0);
+ − 647
428
+ − 648 else if (gutter_was_visible (f, pos))
442
+ − 649 clear_gutter (f, pos);
428
+ − 650 }
442
+ − 651
428
+ − 652 f->clip_changed = local_clip_changed;
+ − 653 f->buffers_changed = local_buffers_changed;
+ − 654 f->gutter_changed = 0;
+ − 655 }
+ − 656 }
+ − 657
+ − 658 void
+ − 659 reset_gutter_display_lines (struct frame* f)
+ − 660 {
442
+ − 661 enum gutter_pos pos;
+ − 662 GUTTER_POS_LOOP (pos)
+ − 663 {
+ − 664 if (f->current_display_lines[pos])
+ − 665 Dynarr_reset (f->current_display_lines[pos]);
+ − 666 }
428
+ − 667 }
+ − 668
+ − 669 static void
+ − 670 redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y,
+ − 671 int width, int height)
+ − 672 {
+ − 673 int g_x, g_y, g_width, g_height;
+ − 674
+ − 675 get_gutter_coords (f, pos, &g_x, &g_y, &g_width, &g_height);
+ − 676
+ − 677 if (((y + height) < g_y) || (y > (g_y + g_height)) || !height || !width || !g_height || !g_width)
+ − 678 return;
+ − 679 if (((x + width) < g_x) || (x > (g_x + g_width)))
+ − 680 return;
+ − 681
442
+ − 682 #ifdef DEBUG_WIDGETS
639
+ − 683 stderr_out ("redrawing gutter after expose %d+%d, %dx%d\n",
442
+ − 684 x, y, width, height);
+ − 685 #endif
428
+ − 686 /* #### optimize this - redrawing the whole gutter for every expose
+ − 687 is very expensive. We reset the current display lines because if
+ − 688 they're being exposed they are no longer current. */
+ − 689 reset_gutter_display_lines (f);
+ − 690
+ − 691 /* Even if none of the gutter is in the area, the blank region at
+ − 692 the very least must be because the first thing we did is verify
+ − 693 that some portion of the gutter is in the exposed region. */
442
+ − 694 output_gutter (f, pos, 1);
428
+ − 695 }
+ − 696
+ − 697 void
+ − 698 redraw_exposed_gutters (struct frame *f, int x, int y, int width,
+ − 699 int height)
+ − 700 {
+ − 701 enum gutter_pos pos;
442
+ − 702
1318
+ − 703 /* We are already inside the critical section -- our caller did that. */
428
+ − 704 GUTTER_POS_LOOP (pos)
+ − 705 {
+ − 706 if (FRAME_GUTTER_VISIBLE (f, pos))
+ − 707 redraw_exposed_gutter (f, pos, x, y, width, height);
+ − 708 }
+ − 709 }
+ − 710
+ − 711 void
+ − 712 free_frame_gutters (struct frame *f)
+ − 713 {
442
+ − 714 enum gutter_pos pos;
+ − 715 GUTTER_POS_LOOP (pos)
428
+ − 716 {
442
+ − 717 if (f->current_display_lines[pos])
+ − 718 {
+ − 719 free_display_lines (f->current_display_lines[pos]);
+ − 720 f->current_display_lines[pos] = 0;
+ − 721 }
+ − 722 if (f->desired_display_lines[pos])
+ − 723 {
+ − 724 free_display_lines (f->desired_display_lines[pos]);
+ − 725 f->desired_display_lines[pos] = 0;
+ − 726 }
428
+ − 727 }
+ − 728 }
+ − 729
+ − 730 static enum gutter_pos
+ − 731 decode_gutter_position (Lisp_Object position)
+ − 732 {
+ − 733 if (EQ (position, Qtop)) return TOP_GUTTER;
+ − 734 if (EQ (position, Qbottom)) return BOTTOM_GUTTER;
+ − 735 if (EQ (position, Qleft)) return LEFT_GUTTER;
+ − 736 if (EQ (position, Qright)) return RIGHT_GUTTER;
563
+ − 737 invalid_constant ("Invalid gutter position", position);
428
+ − 738
1204
+ − 739 RETURN_NOT_REACHED (TOP_GUTTER);
428
+ − 740 }
+ − 741
+ − 742 DEFUN ("set-default-gutter-position", Fset_default_gutter_position, 1, 1, 0, /*
+ − 743 Set the position that the `default-gutter' will be displayed at.
+ − 744 Valid positions are 'top, 'bottom, 'left and 'right.
+ − 745 See `default-gutter-position'.
+ − 746 */
+ − 747 (position))
+ − 748 {
+ − 749 enum gutter_pos cur = decode_gutter_position (Vdefault_gutter_position);
+ − 750 enum gutter_pos new = decode_gutter_position (position);
+ − 751
+ − 752 if (cur != new)
+ − 753 {
+ − 754 /* The following calls will automatically cause the dirty
+ − 755 flags to be set; we delay frame size changes to avoid
+ − 756 lots of frame flickering. */
+ − 757 /* #### I think this should be GC protected. -sb */
1318
+ − 758 int depth = begin_hold_frame_size_changes ();
+ − 759
428
+ − 760 set_specifier_fallback (Vgutter[cur], list1 (Fcons (Qnil, Qnil)));
+ − 761 set_specifier_fallback (Vgutter[new], Vdefault_gutter);
+ − 762 set_specifier_fallback (Vgutter_size[cur], list1 (Fcons (Qnil, Qzero)));
+ − 763 set_specifier_fallback (Vgutter_size[new],
+ − 764 new == TOP_GUTTER || new == BOTTOM_GUTTER
+ − 765 ? Vdefault_gutter_height
+ − 766 : Vdefault_gutter_width);
+ − 767 set_specifier_fallback (Vgutter_border_width[cur],
+ − 768 list1 (Fcons (Qnil, Qzero)));
+ − 769 set_specifier_fallback (Vgutter_border_width[new],
+ − 770 Vdefault_gutter_border_width);
444
+ − 771 set_specifier_fallback (Vgutter_visible_p[cur], list1 (Fcons (Qnil, Qt)));
+ − 772 set_specifier_fallback (Vgutter_visible_p[new], Vdefault_gutter_visible_p);
1318
+ − 773 Vdefault_gutter_position = position;
442
+ − 774
1318
+ − 775 unbind_to (depth);
428
+ − 776 }
+ − 777
442
+ − 778 run_hook (Qdefault_gutter_position_changed_hook);
+ − 779
428
+ − 780 return position;
+ − 781 }
+ − 782
+ − 783 DEFUN ("default-gutter-position", Fdefault_gutter_position, 0, 0, 0, /*
+ − 784 Return the position that the `default-gutter' will be displayed at.
+ − 785 The `default-gutter' will only be displayed here if the corresponding
+ − 786 position-specific gutter specifier does not provide a value.
+ − 787 */
+ − 788 ())
+ − 789 {
+ − 790 return Vdefault_gutter_position;
+ − 791 }
+ − 792
+ − 793 DEFUN ("gutter-pixel-width", Fgutter_pixel_width, 0, 2, 0, /*
+ − 794 Return the pixel width of the gutter at POS in LOCALE.
+ − 795 POS defaults to the default gutter position. LOCALE defaults to
+ − 796 the current window.
+ − 797 */
+ − 798 (pos, locale))
+ − 799 {
+ − 800 int x, y, width, height;
+ − 801 enum gutter_pos p = TOP_GUTTER;
+ − 802 struct frame *f = decode_frame (FW_FRAME (locale));
+ − 803
+ − 804 if (NILP (pos))
+ − 805 pos = Vdefault_gutter_position;
+ − 806 p = decode_gutter_position (pos);
+ − 807
+ − 808 get_gutter_coords (f, p, &x, &y, &width, &height);
+ − 809 width -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2);
+ − 810
+ − 811 return make_int (width);
+ − 812 }
+ − 813
+ − 814 DEFUN ("gutter-pixel-height", Fgutter_pixel_height, 0, 2, 0, /*
+ − 815 Return the pixel height of the gutter at POS in LOCALE.
+ − 816 POS defaults to the default gutter position. LOCALE defaults to
+ − 817 the current window.
+ − 818 */
+ − 819 (pos, locale))
+ − 820 {
+ − 821 int x, y, width, height;
+ − 822 enum gutter_pos p = TOP_GUTTER;
+ − 823 struct frame *f = decode_frame (FW_FRAME (locale));
+ − 824
+ − 825 if (NILP (pos))
+ − 826 pos = Vdefault_gutter_position;
+ − 827 p = decode_gutter_position (pos);
+ − 828
+ − 829 get_gutter_coords (f, p, &x, &y, &width, &height);
+ − 830 height -= (FRAME_GUTTER_BORDER_WIDTH (f, p) * 2);
+ − 831
+ − 832 return make_int (height);
+ − 833 }
+ − 834
+ − 835 DEFINE_SPECIFIER_TYPE (gutter);
+ − 836
+ − 837 static void
+ − 838 gutter_after_change (Lisp_Object specifier, Lisp_Object locale)
+ − 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
+ − 954 default_gutter_specs_changed (Lisp_Object specifier, struct window *w,
+ − 955 Lisp_Object oldval)
+ − 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
+ − 1000 default_gutter_size_changed_in_window (Lisp_Object specifier, struct window *w,
+ − 1001 Lisp_Object oldval)
+ − 1002 {
+ − 1003 recompute_overlaying_specifier (Vgutter_size);
+ − 1004 }
+ − 1005
+ − 1006 static void
+ − 1007 default_gutter_border_width_changed_in_window (Lisp_Object specifier,
+ − 1008 struct window *w,
+ − 1009 Lisp_Object oldval)
+ − 1010 {
+ − 1011 recompute_overlaying_specifier (Vgutter_border_width);
+ − 1012 }
+ − 1013
+ − 1014 static void
+ − 1015 default_gutter_visible_p_changed_in_window (Lisp_Object specifier,
+ − 1016 struct window *w,
+ − 1017 Lisp_Object oldval)
+ − 1018 {
+ − 1019 recompute_overlaying_specifier (Vgutter_visible_p);
442
+ − 1020 /* Need to reconstruct the gutter specifier as it is affected by the
+ − 1021 visibility. */
+ − 1022 recompute_overlaying_specifier (Vgutter);
428
+ − 1023 }
+ − 1024
+ − 1025
+ − 1026 DECLARE_SPECIFIER_TYPE (gutter_size);
+ − 1027 #define GUTTER_SIZE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_size)
+ − 1028 DEFINE_SPECIFIER_TYPE (gutter_size);
+ − 1029
+ − 1030 static void
+ − 1031 gutter_size_validate (Lisp_Object instantiator)
+ − 1032 {
+ − 1033 if (NILP (instantiator))
+ − 1034 return;
+ − 1035
+ − 1036 if (!INTP (instantiator) && !EQ (instantiator, Qautodetect))
563
+ − 1037 invalid_argument ("Gutter size must be an integer or 'autodetect", instantiator);
428
+ − 1038 }
+ − 1039
+ − 1040 DEFUN ("gutter-size-specifier-p", Fgutter_size_specifier_p, 1, 1, 0, /*
+ − 1041 Return non-nil if OBJECT is a gutter-size specifier.
442
+ − 1042
+ − 1043 See `make-gutter-size-specifier' for a description of possible gutter-size
+ − 1044 instantiators.
428
+ − 1045 */
+ − 1046 (object))
+ − 1047 {
+ − 1048 return GUTTER_SIZE_SPECIFIERP (object) ? Qt : Qnil;
+ − 1049 }
+ − 1050
442
+ − 1051 DECLARE_SPECIFIER_TYPE (gutter_visible);
+ − 1052 #define GUTTER_VISIBLE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_visible)
+ − 1053 DEFINE_SPECIFIER_TYPE (gutter_visible);
+ − 1054
+ − 1055 static void
+ − 1056 gutter_visible_validate (Lisp_Object instantiator)
+ − 1057 {
+ − 1058 if (NILP (instantiator))
+ − 1059 return;
+ − 1060
+ − 1061 if (!NILP (instantiator) && !EQ (instantiator, Qt) && !CONSP (instantiator))
563
+ − 1062 invalid_argument ("Gutter visibility must be a boolean or list of symbols",
442
+ − 1063 instantiator);
+ − 1064
+ − 1065 if (CONSP (instantiator))
+ − 1066 {
+ − 1067 Lisp_Object rest;
+ − 1068
+ − 1069 EXTERNAL_LIST_LOOP (rest, instantiator)
+ − 1070 {
+ − 1071 if (!SYMBOLP (XCAR (rest)))
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
+ − 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
+ − 1239 gutter (e.g. `top-gutter' if `default-gutter-position' is 'top)
+ − 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
+ − 1360 `default-gutter-position' is 'top) does not specify a thickness in a
+ − 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
+ − 1366 `default-gutter-position' is 'top or 'bottom, and `default-gutter-width'
+ − 1367 is only used when `default-gutter-position' is 'left or 'right.
+ − 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
+ − 1374 If you set the height to 'autodetect the size of the gutter will be
+ − 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
+ − 1492 `default-gutter-position' is 'top) does not specify a border width in a
+ − 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
+ − 1583 `default-gutter-position' is 'top) does not specify a visible-p value
+ − 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 }