Mercurial > hg > xemacs-beta
comparison src/gutter.c @ 404:2f8bb876ab1d r21-2-32
Import from CVS: tag r21-2-32
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:16:07 +0200 |
parents | a86b2b5e0111 |
children | b8cc9ab3f761 |
comparison
equal
deleted
inserted
replaced
403:9f011ab08d48 | 404:2f8bb876ab1d |
---|---|
1 /* Gutter implementation. | 1 /* Gutter implementation. |
2 Copyright (C) 1999 Andy Piper. | 2 Copyright (C) 1999, 2000 Andy Piper. |
3 | 3 |
4 This file is part of XEmacs. | 4 This file is part of XEmacs. |
5 | 5 |
6 XEmacs is free software; you can redistribute it and/or modify it | 6 XEmacs is free software; you can redistribute it and/or modify it |
7 under the terms of the GNU General Public License as published by the | 7 under the terms of the GNU General Public License as published by the |
45 Lisp_Object Vdefault_gutter_border_width; | 45 Lisp_Object Vdefault_gutter_border_width; |
46 | 46 |
47 Lisp_Object Vdefault_gutter_position; | 47 Lisp_Object Vdefault_gutter_position; |
48 | 48 |
49 Lisp_Object Qgutter_size; | 49 Lisp_Object Qgutter_size; |
50 Lisp_Object Qgutter_visible; | |
51 Lisp_Object Qdefault_gutter_position_changed_hook; | |
50 | 52 |
51 #define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag) \ | 53 #define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag) \ |
52 do { \ | 54 do { \ |
53 switch (pos) \ | 55 switch (pos) \ |
54 { \ | 56 { \ |
84 default: | 86 default: |
85 abort (); | 87 abort (); |
86 } | 88 } |
87 } | 89 } |
88 | 90 |
91 #if 0 | |
89 static Lisp_Object | 92 static Lisp_Object |
90 frame_topmost_window (struct frame *f) | 93 frame_topmost_window (struct frame *f) |
91 { | 94 { |
92 Lisp_Object w = FRAME_ROOT_WINDOW (f); | 95 Lisp_Object w = FRAME_ROOT_WINDOW (f); |
93 | 96 |
98 } | 101 } |
99 } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild)); | 102 } while (!NILP (XWINDOW (w)->hchild) && !NILP (w = XWINDOW (w)->hchild)); |
100 | 103 |
101 return w; | 104 return w; |
102 } | 105 } |
106 #endif | |
103 | 107 |
104 static Lisp_Object | 108 static Lisp_Object |
105 frame_bottommost_window (struct frame *f) | 109 frame_bottommost_window (struct frame *f) |
106 { | 110 { |
107 Lisp_Object w = FRAME_ROOT_WINDOW (f); | 111 Lisp_Object w = FRAME_ROOT_WINDOW (f); |
165 static void | 169 static void |
166 get_gutter_coords (struct frame *f, enum gutter_pos pos, int *x, int *y, | 170 get_gutter_coords (struct frame *f, enum gutter_pos pos, int *x, int *y, |
167 int *width, int *height) | 171 int *width, int *height) |
168 { | 172 { |
169 struct window | 173 struct window |
170 * top = XWINDOW (frame_topmost_window (f)), | |
171 * bot = XWINDOW (frame_bottommost_window (f)); | 174 * bot = XWINDOW (frame_bottommost_window (f)); |
172 /* The top and bottom gutters take precedence over the left and | 175 /* The top and bottom gutters take precedence over the left and |
173 right. */ | 176 right. */ |
174 switch (pos) | 177 switch (pos) |
175 { | 178 { |
181 *height = FRAME_TOP_GUTTER_BOUNDS (f); | 184 *height = FRAME_TOP_GUTTER_BOUNDS (f); |
182 break; | 185 break; |
183 | 186 |
184 case BOTTOM_GUTTER: | 187 case BOTTOM_GUTTER: |
185 *x = FRAME_LEFT_BORDER_END (f); | 188 *x = FRAME_LEFT_BORDER_END (f); |
186 *y = WINDOW_BOTTOM (bot) | 189 *y = WINDOW_BOTTOM (bot); |
187 - FRAME_BOTTOM_GUTTER_BOUNDS (f); | |
188 *width = FRAME_RIGHT_BORDER_START (f) | 190 *width = FRAME_RIGHT_BORDER_START (f) |
189 - FRAME_LEFT_BORDER_END (f); | 191 - FRAME_LEFT_BORDER_END (f); |
190 *height = FRAME_BOTTOM_GUTTER_BOUNDS (f); | 192 *height = FRAME_BOTTOM_GUTTER_BOUNDS (f); |
191 break; | 193 break; |
192 | 194 |
193 case LEFT_GUTTER: | 195 case LEFT_GUTTER: |
194 *x = FRAME_LEFT_BORDER_END (f); | 196 *x = FRAME_LEFT_BORDER_END (f); |
195 *y = WINDOW_TEXT_TOP (top); | 197 *y = FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f); |
196 *width = FRAME_LEFT_GUTTER_BOUNDS (f); | 198 *width = FRAME_LEFT_GUTTER_BOUNDS (f); |
197 *height = WINDOW_BOTTOM (bot) | 199 *height = WINDOW_BOTTOM (bot) |
198 - (WINDOW_TEXT_TOP (top) | 200 - (FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f)); |
199 + FRAME_BOTTOM_GUTTER_BOUNDS (f)); | |
200 break; | 201 break; |
201 | 202 |
202 case RIGHT_GUTTER: | 203 case RIGHT_GUTTER: |
203 *x = FRAME_RIGHT_BORDER_START (f) | 204 *x = FRAME_RIGHT_BORDER_START (f) |
204 - FRAME_RIGHT_GUTTER_BOUNDS (f); | 205 - FRAME_RIGHT_GUTTER_BOUNDS (f); |
205 *y = WINDOW_TEXT_TOP (top); | 206 *y = FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f); |
206 *width = FRAME_RIGHT_GUTTER_BOUNDS (f); | 207 *width = FRAME_RIGHT_GUTTER_BOUNDS (f); |
207 *height = WINDOW_BOTTOM (bot) | 208 *height = WINDOW_BOTTOM (bot) |
208 - (WINDOW_TEXT_TOP (top) | 209 - (FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f)); |
209 + FRAME_BOTTOM_GUTTER_BOUNDS (f)); | |
210 break; | 210 break; |
211 | 211 |
212 default: | 212 default: |
213 abort (); | 213 abort (); |
214 } | 214 } |
215 } | 215 } |
216 | 216 |
217 static void | 217 /* Convert the gutter specifier into something we can actually |
218 output_gutter (struct frame *f, enum gutter_pos pos) | 218 display. */ |
219 static Lisp_Object construct_window_gutter_spec (struct window* w, | |
220 enum gutter_pos pos) | |
221 { | |
222 Lisp_Object rest, *args; | |
223 int nargs = 0; | |
224 Lisp_Object gutter = RAW_WINDOW_GUTTER (w, pos); | |
225 | |
226 if (STRINGP (gutter) || NILP (gutter)) | |
227 return gutter; | |
228 | |
229 GET_LIST_LENGTH (gutter, nargs); | |
230 args = alloca_array (Lisp_Object, nargs >> 1); | |
231 nargs = 0; | |
232 | |
233 for (rest = gutter; !NILP (rest); rest = XCDR (XCDR (rest))) | |
234 { | |
235 /* We only put things in the real gutter that are declared to be | |
236 visible. */ | |
237 if (!CONSP (WINDOW_GUTTER_VISIBLE (w, pos)) | |
238 || | |
239 !NILP (Fmemq (XCAR (rest), WINDOW_GUTTER_VISIBLE (w, pos)))) | |
240 { | |
241 args [nargs++] = XCAR (XCDR (rest)); | |
242 } | |
243 } | |
244 | |
245 return Fconcat (nargs, args); | |
246 } | |
247 | |
248 static void | |
249 output_gutter (struct frame *f, enum gutter_pos pos, int force) | |
219 { | 250 { |
220 Lisp_Object frame; | 251 Lisp_Object frame; |
221 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); | 252 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); |
222 struct device *d = XDEVICE (f->device); | 253 struct device *d = XDEVICE (f->device); |
223 struct window* w = XWINDOW (window); | 254 struct window* w = XWINDOW (window); |
230 | 261 |
231 if (!WINDOW_LIVE_P (w)) | 262 if (!WINDOW_LIVE_P (w)) |
232 return; | 263 return; |
233 | 264 |
234 border_width = FRAME_GUTTER_BORDER_WIDTH (f, pos); | 265 border_width = FRAME_GUTTER_BORDER_WIDTH (f, pos); |
235 findex = get_builtin_face_cache_index (w, Vgui_element_face); | 266 findex = get_builtin_face_cache_index (w, Vwidget_face); |
236 | 267 |
237 if (!f->current_display_lines) | 268 if (!f->current_display_lines[pos]) |
238 f->current_display_lines = Dynarr_new (display_line); | 269 f->current_display_lines[pos] = Dynarr_new (display_line); |
239 if (!f->desired_display_lines) | 270 if (!f->desired_display_lines[pos]) |
240 f->desired_display_lines = Dynarr_new (display_line); | 271 f->desired_display_lines[pos] = Dynarr_new (display_line); |
241 | 272 |
242 ddla = f->desired_display_lines; | 273 ddla = f->desired_display_lines[pos]; |
243 cdla = f->current_display_lines; | 274 cdla = f->current_display_lines[pos]; |
244 cdla_len = Dynarr_length (cdla); | 275 cdla_len = Dynarr_length (cdla); |
245 | 276 |
246 XSETFRAME (frame, f); | 277 XSETFRAME (frame, f); |
247 | 278 |
248 get_gutter_coords (f, pos, &x, &y, &width, &height); | 279 get_gutter_coords (f, pos, &x, &y, &width, &height); |
249 /* generate some display lines */ | 280 /* generate some display lines */ |
250 generate_displayable_area (w, WINDOW_GUTTER (w, pos), | 281 generate_displayable_area (w, WINDOW_GUTTER (w, pos), |
251 x + border_width, y + border_width, | 282 x + border_width, y + border_width, |
252 width - 2 * border_width, | 283 width - 2 * border_width, |
253 height - 2 * border_width, ddla, 0, findex); | 284 height - 2 * border_width, ddla, 0, findex); |
254 /* Output each line. */ | 285 |
255 for (line = 0; line < Dynarr_length (ddla); line++) | 286 /* We only output the gutter if we think something of significance |
256 { | 287 has changed. This is, for example, because redisplay can cause |
257 output_display_line (w, cdla, ddla, line, -1, -1); | 288 new face cache elements to get added causing compare_runes to |
258 } | 289 fail because the findex for a particular face has changed. */ |
259 | 290 if (force || f->faces_changed || f->frame_changed || |
260 /* If the number of display lines has shrunk, adjust. */ | 291 f->gutter_changed || f->glyphs_changed || |
261 if (cdla_len > Dynarr_length (ddla)) | 292 f->size_changed || f->subwindows_changed || |
262 { | 293 w->windows_changed || f->windows_structure_changed || |
263 Dynarr_length (cdla) = Dynarr_length (ddla); | 294 cdla_len != Dynarr_length (ddla) || |
264 } | 295 (f->extents_changed && w->gutter_extent_modiff[pos])) |
265 | 296 { |
266 /* grab coordinates of last line and blank after it. */ | 297 #ifdef DEBUG_GUTTERS |
267 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); | 298 printf ("gutter redisplay triggered by %s\n", force ? "force" : |
268 ypos = dl->ypos + dl->descent - dl->clip; | 299 f->faces_changed ? "f->faces_changed" : |
269 redisplay_clear_region (window, findex, x + border_width , ypos, | 300 f->frame_changed ? "f->frame_changed" : |
270 width - 2 * border_width, height - (ypos - y) - border_width); | 301 f->gutter_changed ? "f->gutter_changed" : |
271 /* bevel the gutter area if so desired */ | 302 f->glyphs_changed ? "f->glyphs_changed" : |
272 if (border_width != 0) | 303 f->size_changed ? "f->size_changed" : |
273 { | 304 f->subwindows_changed ? "f->subwindows_changed" : |
274 MAYBE_DEVMETH (d, bevel_area, | 305 w->windows_changed ? "w->windows_changed" : |
275 (w, findex, x, y, width, height, border_width, | 306 f->windows_structure_changed ? "f->windows_structure_changed" : |
276 EDGE_ALL, EDGE_BEVEL_OUT)); | 307 cdla_len != Dynarr_length (ddla) ? "different display structures" : |
277 } | 308 f->extents_changed && w->gutter_extent_modiff[pos] ? |
278 } | 309 "f->extents_changed && w->gutter_extent_modiff[pos]" : "<null>"); |
279 | 310 #endif |
280 /* sizing gutters is a pain so we try and help the user by detemining | 311 /* Output each line. */ |
312 for (line = 0; line < Dynarr_length (ddla); line++) | |
313 { | |
314 output_display_line (w, cdla, ddla, line, -1, -1); | |
315 } | |
316 | |
317 /* If the number of display lines has shrunk, adjust. */ | |
318 if (cdla_len > Dynarr_length (ddla)) | |
319 { | |
320 Dynarr_length (cdla) = Dynarr_length (ddla); | |
321 } | |
322 | |
323 /* grab coordinates of last line and blank after it. */ | |
324 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); | |
325 ypos = dl->ypos + dl->descent - dl->clip; | |
326 redisplay_clear_region (window, findex, x + border_width , ypos, | |
327 width - 2 * border_width, height - (ypos - y) - border_width); | |
328 /* bevel the gutter area if so desired */ | |
329 if (border_width != 0) | |
330 { | |
331 MAYBE_DEVMETH (d, bevel_area, | |
332 (w, findex, x, y, width, height, border_width, | |
333 EDGE_ALL, EDGE_BEVEL_OUT)); | |
334 } | |
335 } | |
336 else | |
337 { | |
338 /* Nothing of significance happened so sync the display line | |
339 structs. */ | |
340 for (line = 0; line < Dynarr_length (ddla); line++) | |
341 { | |
342 sync_display_line_structs (w, line, 1, cdla, ddla); | |
343 } | |
344 } | |
345 | |
346 w->gutter_extent_modiff [pos] = 0; | |
347 } | |
348 | |
349 /* Sizing gutters is a pain so we try and help the user by detemining | |
281 what height will accommodate all lines. This is useless on left and | 350 what height will accommodate all lines. This is useless on left and |
282 right gutters as we always have a maximal number of lines. */ | 351 right gutters as we always have a maximal number of lines. */ |
283 static Lisp_Object | 352 static Lisp_Object |
284 calculate_gutter_size (struct window *w, enum gutter_pos pos) | 353 calculate_gutter_size (struct window *w, enum gutter_pos pos) |
285 { | 354 { |
286 struct frame* f = XFRAME (WINDOW_FRAME (w)); | 355 struct frame* f = XFRAME (WINDOW_FRAME (w)); |
287 int ypos; | 356 int ypos, count; |
288 display_line_dynarr* ddla; | 357 display_line_dynarr* ddla; |
289 struct display_line *dl; | 358 struct display_line *dl; |
290 | 359 |
291 /* we cannot autodetect gutter sizes for the left and right as there | 360 /* we cannot autodetect gutter sizes for the left and right as there |
292 is no reasonable metric to use */ | 361 is no reasonable metric to use */ |
293 assert (pos == TOP_GUTTER || pos == BOTTOM_GUTTER); | 362 assert (pos == TOP_GUTTER || pos == BOTTOM_GUTTER); |
294 /* degenerate case */ | 363 /* degenerate case */ |
295 if (NILP (WINDOW_GUTTER (w, pos)) | 364 if (NILP (RAW_WINDOW_GUTTER (w, pos)) |
296 || | 365 || |
297 !FRAME_VISIBLE_P (f) | 366 !FRAME_VISIBLE_P (f) |
298 || | 367 || |
299 NILP (w->buffer)) | 368 NILP (w->buffer)) |
300 return Qnil; | 369 return Qnil; |
370 | |
371 /* Redisplay code that we use relies on GC not happening. Make it | |
372 so. */ | |
373 count = specpdl_depth (); | |
374 record_unwind_protect (restore_gc_inhibit, | |
375 make_int (gc_currently_forbidden)); | |
376 gc_currently_forbidden = 1; | |
301 | 377 |
302 ddla = Dynarr_new (display_line); | 378 ddla = Dynarr_new (display_line); |
303 /* generate some display lines */ | 379 /* generate some display lines */ |
304 generate_displayable_area (w, WINDOW_GUTTER (w, pos), | 380 generate_displayable_area (w, WINDOW_GUTTER (w, pos), |
305 FRAME_LEFT_BORDER_END (f), | 381 FRAME_LEFT_BORDER_END (f), |
306 0, | 382 0, |
307 FRAME_RIGHT_BORDER_START (f) | 383 FRAME_RIGHT_BORDER_START (f) |
308 - FRAME_LEFT_BORDER_END (f), | 384 - FRAME_LEFT_BORDER_END (f), |
309 200, | 385 200, |
310 ddla, 0, 0); | 386 ddla, 0, 0); |
387 | |
388 /* Let GC happen again. */ | |
389 unbind_to (count, Qnil); | |
390 | |
311 /* grab coordinates of last line */ | 391 /* grab coordinates of last line */ |
312 if (Dynarr_length (ddla)) | 392 if (Dynarr_length (ddla)) |
313 { | 393 { |
314 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); | 394 dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); |
315 ypos = dl->ypos + dl->descent - dl->clip; | 395 ypos = dl->ypos + dl->descent - dl->clip; |
327 clear_gutter (struct frame *f, enum gutter_pos pos) | 407 clear_gutter (struct frame *f, enum gutter_pos pos) |
328 { | 408 { |
329 int x, y, width, height; | 409 int x, y, width, height; |
330 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); | 410 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); |
331 face_index findex = get_builtin_face_cache_index (XWINDOW (window), | 411 face_index findex = get_builtin_face_cache_index (XWINDOW (window), |
332 Vgui_element_face); | 412 Vwidget_face); |
333 get_gutter_coords (f, pos, &x, &y, &width, &height); | 413 get_gutter_coords (f, pos, &x, &y, &width, &height); |
334 | 414 |
335 SET_GUTTER_WAS_VISIBLE_FLAG (f, pos, 0); | 415 SET_GUTTER_WAS_VISIBLE_FLAG (f, pos, 0); |
336 | 416 |
337 redisplay_clear_region (window, findex, x, y, width, height); | 417 redisplay_clear_region (window, findex, x, y, width, height); |
345 /* See the comment in image_instantiate_cache_result as to why marking | 425 /* See the comment in image_instantiate_cache_result as to why marking |
346 the glyph will also mark the image_instance. */ | 426 the glyph will also mark the image_instance. */ |
347 void | 427 void |
348 mark_gutters (struct frame* f) | 428 mark_gutters (struct frame* f) |
349 { | 429 { |
350 if (f->current_display_lines) | 430 enum gutter_pos pos; |
351 mark_redisplay_structs (f->current_display_lines); | 431 GUTTER_POS_LOOP (pos) |
352 if (f->desired_display_lines) | 432 { |
353 mark_redisplay_structs (f->desired_display_lines); | 433 if (f->current_display_lines[pos]) |
434 mark_redisplay_structs (f->current_display_lines[pos]); | |
435 /* #### Do we really need to mark the desired lines? */ | |
436 if (f->desired_display_lines[pos]) | |
437 mark_redisplay_structs (f->desired_display_lines[pos]); | |
438 } | |
439 } | |
440 | |
441 /* This is called by extent_changed_for_redisplay, so that redisplay | |
442 knows exactly what extents have changed. */ | |
443 void | |
444 gutter_extent_signal_changed_region_maybe (Lisp_Object obj, | |
445 Bufpos start, Bufpos end) | |
446 { | |
447 /* #### Start and end are currently ignored but could be used by a | |
448 more optimal gutter redisplay. We currently loop over all frames | |
449 here, this could be optimized. */ | |
450 Lisp_Object frmcons, devcons, concons; | |
451 | |
452 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
453 { | |
454 struct frame *f = XFRAME (XCAR (frmcons)); | |
455 enum gutter_pos pos; | |
456 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
457 struct window* w = XWINDOW (window); | |
458 | |
459 GUTTER_POS_LOOP (pos) | |
460 { | |
461 if (EQ (WINDOW_GUTTER (w, pos), obj)) | |
462 { | |
463 w->gutter_extent_modiff[pos]++; | |
464 } | |
465 } | |
466 } | |
467 } | |
468 | |
469 /* We have to change the gutter geometry separately to the gutter | |
470 update since it needs to occur outside of redisplay proper. */ | |
471 void | |
472 update_frame_gutter_geometry (struct frame *f) | |
473 { | |
474 if (f->gutter_changed || f->windows_structure_changed) | |
475 { | |
476 enum gutter_pos pos; | |
477 | |
478 /* If the gutter geometry has changed then re-layout the | |
479 frame. If we are in display there is almost no point in doing | |
480 anything else since the frame size changes will be delayed | |
481 until we are out of redisplay proper. */ | |
482 GUTTER_POS_LOOP (pos) | |
483 { | |
484 if (FRAME_GUTTER_BOUNDS (f, pos) != f->current_gutter_bounds[pos]) | |
485 { | |
486 int width, height; | |
487 pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f), | |
488 &width, &height); | |
489 change_frame_size (f, height, width, 0); | |
490 break; | |
491 } | |
492 } | |
493 | |
494 GUTTER_POS_LOOP (pos) | |
495 { | |
496 /* Mark sizes as up-to-date. */ | |
497 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos); | |
498 } | |
499 } | |
354 } | 500 } |
355 | 501 |
356 void | 502 void |
357 update_frame_gutters (struct frame *f) | 503 update_frame_gutters (struct frame *f) |
358 { | 504 { |
359 if (f->gutter_changed || f->clear || | 505 if (f->faces_changed || f->frame_changed || |
360 f->glyphs_changed || f->subwindows_changed || | 506 f->gutter_changed || f->glyphs_changed || |
361 f->windows_changed || f->windows_structure_changed || | 507 f->size_changed || f->subwindows_changed || |
362 f->extents_changed || f->faces_changed) | 508 f->windows_changed || f->windows_structure_changed || |
509 f->extents_changed) | |
363 { | 510 { |
364 enum gutter_pos pos; | 511 enum gutter_pos pos; |
365 | 512 |
366 /* We don't actually care about these when outputting the gutter | 513 /* We don't actually care about these when outputting the gutter |
367 so locally disable them. */ | 514 so locally disable them. */ |
372 | 519 |
373 /* and output */ | 520 /* and output */ |
374 GUTTER_POS_LOOP (pos) | 521 GUTTER_POS_LOOP (pos) |
375 { | 522 { |
376 if (FRAME_GUTTER_VISIBLE (f, pos)) | 523 if (FRAME_GUTTER_VISIBLE (f, pos)) |
377 output_gutter (f, pos); | 524 output_gutter (f, pos, 0); |
525 | |
378 else if (gutter_was_visible (f, pos)) | 526 else if (gutter_was_visible (f, pos)) |
379 clear_gutter (f, pos); | 527 clear_gutter (f, pos); |
380 } | 528 } |
529 | |
381 f->clip_changed = local_clip_changed; | 530 f->clip_changed = local_clip_changed; |
382 f->buffers_changed = local_buffers_changed; | 531 f->buffers_changed = local_buffers_changed; |
383 f->gutter_changed = 0; | 532 f->gutter_changed = 0; |
384 } | 533 } |
385 } | 534 } |
386 | 535 |
387 void | 536 void |
388 reset_gutter_display_lines (struct frame* f) | 537 reset_gutter_display_lines (struct frame* f) |
389 { | 538 { |
390 if (f->current_display_lines) | 539 enum gutter_pos pos; |
391 Dynarr_reset (f->current_display_lines); | 540 GUTTER_POS_LOOP (pos) |
541 { | |
542 if (f->current_display_lines[pos]) | |
543 Dynarr_reset (f->current_display_lines[pos]); | |
544 } | |
392 } | 545 } |
393 | 546 |
394 static void | 547 static void |
395 redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y, | 548 redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y, |
396 int width, int height) | 549 int width, int height) |
410 reset_gutter_display_lines (f); | 563 reset_gutter_display_lines (f); |
411 | 564 |
412 /* Even if none of the gutter is in the area, the blank region at | 565 /* Even if none of the gutter is in the area, the blank region at |
413 the very least must be because the first thing we did is verify | 566 the very least must be because the first thing we did is verify |
414 that some portion of the gutter is in the exposed region. */ | 567 that some portion of the gutter is in the exposed region. */ |
415 output_gutter (f, pos); | 568 output_gutter (f, pos, 1); |
416 } | 569 } |
417 | 570 |
418 void | 571 void |
419 redraw_exposed_gutters (struct frame *f, int x, int y, int width, | 572 redraw_exposed_gutters (struct frame *f, int x, int y, int width, |
420 int height) | 573 int height) |
428 } | 581 } |
429 | 582 |
430 void | 583 void |
431 free_frame_gutters (struct frame *f) | 584 free_frame_gutters (struct frame *f) |
432 { | 585 { |
433 if (f->current_display_lines) | 586 enum gutter_pos pos; |
434 { | 587 GUTTER_POS_LOOP (pos) |
435 free_display_lines (f->current_display_lines); | 588 { |
436 f->current_display_lines = 0; | 589 if (f->current_display_lines[pos]) |
437 } | 590 { |
438 if (f->desired_display_lines) | 591 free_display_lines (f->current_display_lines[pos]); |
439 { | 592 f->current_display_lines[pos] = 0; |
440 free_display_lines (f->desired_display_lines); | 593 } |
441 f->desired_display_lines = 0; | 594 if (f->desired_display_lines[pos]) |
595 { | |
596 free_display_lines (f->desired_display_lines[pos]); | |
597 f->desired_display_lines[pos] = 0; | |
598 } | |
442 } | 599 } |
443 } | 600 } |
444 | 601 |
445 static enum gutter_pos | 602 static enum gutter_pos |
446 decode_gutter_position (Lisp_Object position) | 603 decode_gutter_position (Lisp_Object position) |
480 : Vdefault_gutter_width); | 637 : Vdefault_gutter_width); |
481 set_specifier_fallback (Vgutter_border_width[cur], | 638 set_specifier_fallback (Vgutter_border_width[cur], |
482 list1 (Fcons (Qnil, Qzero))); | 639 list1 (Fcons (Qnil, Qzero))); |
483 set_specifier_fallback (Vgutter_border_width[new], | 640 set_specifier_fallback (Vgutter_border_width[new], |
484 Vdefault_gutter_border_width); | 641 Vdefault_gutter_border_width); |
642 /* We don't realy want the left and right gutters to default to | |
643 visible. */ | |
485 set_specifier_fallback (Vgutter_visible_p[cur], | 644 set_specifier_fallback (Vgutter_visible_p[cur], |
486 list1 (Fcons (Qnil, Qt))); | 645 cur == TOP_GUTTER || cur == BOTTOM_GUTTER ? |
646 list1 (Fcons (Qnil, Qt)) | |
647 : list1 (Fcons (Qnil, Qnil))); | |
487 set_specifier_fallback (Vgutter_visible_p[new], | 648 set_specifier_fallback (Vgutter_visible_p[new], |
488 Vdefault_gutter_visible_p); | 649 Vdefault_gutter_visible_p); |
650 | |
489 Vdefault_gutter_position = position; | 651 Vdefault_gutter_position = position; |
490 unhold_frame_size_changes (); | 652 unhold_frame_size_changes (); |
491 } | 653 } |
492 | 654 |
655 run_hook (Qdefault_gutter_position_changed_hook); | |
656 | |
493 return position; | 657 return position; |
494 } | 658 } |
495 | 659 |
496 DEFUN ("default-gutter-position", Fdefault_gutter_position, 0, 0, 0, /* | 660 DEFUN ("default-gutter-position", Fdefault_gutter_position, 0, 0, 0, /* |
497 Return the position that the `default-gutter' will be displayed at. | 661 Return the position that the `default-gutter' will be displayed at. |
556 static void | 720 static void |
557 gutter_validate (Lisp_Object instantiator) | 721 gutter_validate (Lisp_Object instantiator) |
558 { | 722 { |
559 if (NILP (instantiator)) | 723 if (NILP (instantiator)) |
560 return; | 724 return; |
725 | |
726 /* Must be a string or a plist. */ | |
727 if (!STRINGP (instantiator) && NILP (Fvalid_plist_p (instantiator))) | |
728 signal_simple_error ("Gutter spec must be string, plist or nil", instantiator); | |
561 | 729 |
562 if (!STRINGP (instantiator)) | 730 if (!STRINGP (instantiator)) |
563 signal_simple_error ("Gutter spec must be string or nil", instantiator); | 731 { |
732 Lisp_Object rest; | |
733 | |
734 for (rest = instantiator; !NILP (rest); rest = XCDR (XCDR (rest))) | |
735 { | |
736 if (!SYMBOLP (XCAR (rest)) | |
737 || !STRINGP (XCAR (XCDR (rest)))) | |
738 signal_simple_error ("Gutter plist spec must contain strings", instantiator); | |
739 } | |
740 } | |
564 } | 741 } |
565 | 742 |
566 DEFUN ("gutter-specifier-p", Fgutter_specifier_p, 1, 1, 0, /* | 743 DEFUN ("gutter-specifier-p", Fgutter_specifier_p, 1, 1, 0, /* |
567 Return non-nil if OBJECT is a gutter specifier. | 744 Return non-nil if OBJECT is a gutter specifier. |
568 Gutter specifiers are used to specify the format of a gutter. | 745 Gutter specifiers are used to specify the format of a gutter. |
569 The values of the variables `default-gutter', `top-gutter', | 746 The values of the variables `default-gutter', `top-gutter', |
570 `left-gutter', `right-gutter', and `bottom-gutter' are always | 747 `left-gutter', `right-gutter', and `bottom-gutter' are always |
571 gutter specifiers. | 748 gutter specifiers. |
572 | 749 |
573 Valid gutter instantiators are called "gutter descriptors" | 750 Valid gutter instantiators are called "gutter descriptors" and are |
574 and are lists of vectors. See `default-gutter' for a description | 751 either strings or property-lists of strings. See `default-gutter' for |
575 of the exact format. | 752 a description of the exact format. |
576 */ | 753 */ |
577 (object)) | 754 (object)) |
578 { | 755 { |
579 return GUTTER_SPECIFIERP (object) ? Qt : Qnil; | 756 return GUTTER_SPECIFIERP (object) ? Qt : Qnil; |
580 } | 757 } |
591 Fset_specifier_dirty_flag (real_one[pos]); | 768 Fset_specifier_dirty_flag (real_one[pos]); |
592 } | 769 } |
593 | 770 |
594 static void | 771 static void |
595 gutter_specs_changed (Lisp_Object specifier, struct window *w, | 772 gutter_specs_changed (Lisp_Object specifier, struct window *w, |
596 Lisp_Object oldval) | 773 Lisp_Object oldval, enum gutter_pos pos) |
774 { | |
775 w->real_gutter[pos] = construct_window_gutter_spec (w, pos); | |
776 w->real_gutter_size[pos] = w->gutter_size[pos]; | |
777 | |
778 if (EQ (w->real_gutter_size[pos], Qautodetect) | |
779 && !NILP (w->gutter_visible_p[pos])) | |
780 { | |
781 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); | |
782 } | |
783 MARK_GUTTER_CHANGED; | |
784 MARK_MODELINE_CHANGED; | |
785 MARK_WINDOWS_CHANGED (w); | |
786 } | |
787 | |
788 /* We define all of these so we can access which actual gutter changed. */ | |
789 static void | |
790 top_gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
791 Lisp_Object oldval) | |
792 { | |
793 gutter_specs_changed (specifier, w, oldval, TOP_GUTTER); | |
794 } | |
795 | |
796 static void | |
797 bottom_gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
798 Lisp_Object oldval) | |
799 { | |
800 gutter_specs_changed (specifier, w, oldval, BOTTOM_GUTTER); | |
801 } | |
802 | |
803 static void | |
804 left_gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
805 Lisp_Object oldval) | |
806 { | |
807 gutter_specs_changed (specifier, w, oldval, LEFT_GUTTER); | |
808 } | |
809 | |
810 static void | |
811 right_gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
812 Lisp_Object oldval) | |
813 { | |
814 gutter_specs_changed (specifier, w, oldval, RIGHT_GUTTER); | |
815 } | |
816 | |
817 static void | |
818 default_gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
819 Lisp_Object oldval) | |
820 { | |
821 recompute_overlaying_specifier (Vgutter); | |
822 } | |
823 | |
824 static void | |
825 gutter_geometry_changed_in_window (Lisp_Object specifier, struct window *w, | |
826 Lisp_Object oldval) | |
597 { | 827 { |
598 enum gutter_pos pos; | 828 enum gutter_pos pos; |
599 GUTTER_POS_LOOP (pos) | 829 GUTTER_POS_LOOP (pos) |
600 { | 830 { |
601 w->real_gutter_size[pos] = w->gutter_size[pos]; | 831 w->real_gutter_size[pos] = w->gutter_size[pos]; |
603 && !NILP (w->gutter_visible_p[pos])) | 833 && !NILP (w->gutter_visible_p[pos])) |
604 { | 834 { |
605 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); | 835 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); |
606 } | 836 } |
607 } | 837 } |
608 MARK_GUTTER_CHANGED; | |
609 MARK_WINDOWS_CHANGED (w); | |
610 } | |
611 | |
612 static void | |
613 default_gutter_specs_changed (Lisp_Object specifier, struct window *w, | |
614 Lisp_Object oldval) | |
615 { | |
616 recompute_overlaying_specifier (Vgutter); | |
617 } | |
618 | |
619 static void | |
620 gutter_geometry_changed_in_window (Lisp_Object specifier, struct window *w, | |
621 Lisp_Object oldval) | |
622 { | |
623 enum gutter_pos pos; | |
624 GUTTER_POS_LOOP (pos) | |
625 { | |
626 w->real_gutter_size[pos] = w->gutter_size[pos]; | |
627 if (EQ (w->real_gutter_size[pos], Qautodetect) | |
628 && !NILP (w->gutter_visible_p[pos])) | |
629 { | |
630 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); | |
631 } | |
632 } | |
633 | 838 |
634 MARK_GUTTER_CHANGED; | 839 MARK_GUTTER_CHANGED; |
840 MARK_MODELINE_CHANGED; | |
635 MARK_WINDOWS_CHANGED (w); | 841 MARK_WINDOWS_CHANGED (w); |
636 } | 842 } |
637 | 843 |
638 static void | 844 static void |
639 default_gutter_size_changed_in_window (Lisp_Object specifier, struct window *w, | 845 default_gutter_size_changed_in_window (Lisp_Object specifier, struct window *w, |
654 default_gutter_visible_p_changed_in_window (Lisp_Object specifier, | 860 default_gutter_visible_p_changed_in_window (Lisp_Object specifier, |
655 struct window *w, | 861 struct window *w, |
656 Lisp_Object oldval) | 862 Lisp_Object oldval) |
657 { | 863 { |
658 recompute_overlaying_specifier (Vgutter_visible_p); | 864 recompute_overlaying_specifier (Vgutter_visible_p); |
865 /* Need to reconstruct the gutter specifier as it is affected by the | |
866 visibility. */ | |
867 recompute_overlaying_specifier (Vgutter); | |
659 } | 868 } |
660 | 869 |
661 | 870 |
662 DECLARE_SPECIFIER_TYPE (gutter_size); | 871 DECLARE_SPECIFIER_TYPE (gutter_size); |
663 #define GUTTER_SIZE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_size) | 872 #define GUTTER_SIZE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_size) |
673 signal_simple_error ("Gutter size must be an integer or 'autodetect", instantiator); | 882 signal_simple_error ("Gutter size must be an integer or 'autodetect", instantiator); |
674 } | 883 } |
675 | 884 |
676 DEFUN ("gutter-size-specifier-p", Fgutter_size_specifier_p, 1, 1, 0, /* | 885 DEFUN ("gutter-size-specifier-p", Fgutter_size_specifier_p, 1, 1, 0, /* |
677 Return non-nil if OBJECT is a gutter-size specifier. | 886 Return non-nil if OBJECT is a gutter-size specifier. |
887 | |
888 Gutter-size specifiers are used to specify the size of a gutter. The | |
889 values of the variables `default-gutter-size', `top-gutter-size', | |
890 `left-gutter-size', `right-gutter-size', and `bottom-gutter-size' are | |
891 always gutter-size specifiers. | |
892 | |
893 Valid gutter-size instantiators are either integers or the special | |
894 symbol 'autodetect. If a gutter-size is set to 'autodetect them the | |
895 size of the gutter will be adjusted to just accomodate the gutters | |
896 contents. 'autodetect only works for top and bottom gutters. | |
678 */ | 897 */ |
679 (object)) | 898 (object)) |
680 { | 899 { |
681 return GUTTER_SIZE_SPECIFIERP (object) ? Qt : Qnil; | 900 return GUTTER_SIZE_SPECIFIERP (object) ? Qt : Qnil; |
901 } | |
902 | |
903 DECLARE_SPECIFIER_TYPE (gutter_visible); | |
904 #define GUTTER_VISIBLE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_visible) | |
905 DEFINE_SPECIFIER_TYPE (gutter_visible); | |
906 | |
907 static void | |
908 gutter_visible_validate (Lisp_Object instantiator) | |
909 { | |
910 if (NILP (instantiator)) | |
911 return; | |
912 | |
913 if (!NILP (instantiator) && !EQ (instantiator, Qt) && !CONSP (instantiator)) | |
914 signal_simple_error ("Gutter visibility must be a boolean or list of symbols", | |
915 instantiator); | |
916 | |
917 if (CONSP (instantiator)) | |
918 { | |
919 Lisp_Object rest; | |
920 | |
921 EXTERNAL_LIST_LOOP (rest, instantiator) | |
922 { | |
923 if (!SYMBOLP (XCAR (rest))) | |
924 signal_simple_error ("Gutter visibility must be a boolean or list of symbols", | |
925 instantiator); | |
926 } | |
927 } | |
928 } | |
929 | |
930 DEFUN ("gutter-visible-specifier-p", Fgutter_visible_specifier_p, 1, 1, 0, /* | |
931 Return non-nil if OBJECT is a gutter-visible specifier. | |
932 | |
933 Gutter-visible specifiers are used to specify the visibility of a | |
934 gutter. The values of the variables `default-gutter-visible-p', | |
935 `top-gutter-visible-p', `left-gutter-visible-p', | |
936 `right-gutter-visible-p', and `bottom-gutter-visible-p' are always | |
937 gutter-visible specifiers. | |
938 | |
939 Valid gutter-visible instantiators are t, nil or a list of symbols. | |
940 If a gutter-visible instantiator is set to a list of symbols, and the | |
941 correspondong gutter specification is a property-list strings, then | |
942 elements of the gutter specification will only be visible if the | |
943 corresponding symbol occurs in the gutter-visible instantiator. | |
944 */ | |
945 (object)) | |
946 { | |
947 return GUTTER_VISIBLE_SPECIFIERP (object) ? Qt : Qnil; | |
682 } | 948 } |
683 | 949 |
684 DEFUN ("redisplay-gutter-area", Fredisplay_gutter_area, 0, 0, 0, /* | 950 DEFUN ("redisplay-gutter-area", Fredisplay_gutter_area, 0, 0, 0, /* |
685 Ensure that all gutters are correctly showing their gutter specifier. | 951 Ensure that all gutters are correctly showing their gutter specifier. |
686 */ | 952 */ |
694 Lisp_Object frmcons; | 960 Lisp_Object frmcons; |
695 | 961 |
696 DEVICE_FRAME_LOOP (frmcons, d) | 962 DEVICE_FRAME_LOOP (frmcons, d) |
697 { | 963 { |
698 struct frame *f = XFRAME (XCAR (frmcons)); | 964 struct frame *f = XFRAME (XCAR (frmcons)); |
699 | 965 |
700 if (FRAME_REPAINT_P (f)) | 966 /* Sequence is quite important here. We not only want to |
967 redisplay the gutter area but we also want to flush any | |
968 frame size changes out so that the gutter redisplay happens | |
969 in a kosha environment. | |
970 | |
971 This is not only so that things look right but so that | |
972 glyph redisplay optimization kicks in, by default display | |
973 lines will be completely re-output if | |
974 f->windows_structure_changed is 1, and this is true if | |
975 frame size changes haven't been flushed out. Once frame | |
976 size changes have been flushed out we then need to | |
977 redisplay the frame in order to flush out pending window | |
978 size changes. */ | |
979 update_frame_gutter_geometry (f); | |
980 | |
981 if (f->windows_structure_changed) | |
982 redisplay_frame (f, 1); | |
983 else if (FRAME_REPAINT_P (f)) | |
701 { | 984 { |
985 /* We have to be "in display" when we output the gutter | |
986 - make it so. */ | |
987 hold_frame_size_changes (); | |
702 update_frame_gutters (f); | 988 update_frame_gutters (f); |
989 unhold_one_frame_size_changes (f); | |
703 } | 990 } |
704 } | 991 } |
705 | |
706 /* We now call the output_end routine for tty frames. We delay | 992 /* We now call the output_end routine for tty frames. We delay |
707 doing so in order to avoid cursor flicker. So much for 100% | 993 doing so in order to avoid cursor flicker. So much for 100% |
708 encapsulation. */ | 994 encapsulation. */ |
709 if (DEVICE_TTY_P (d)) | 995 if (DEVICE_TTY_P (d)) |
710 DEVMETH (d, output_end, (d)); | 996 DEVMETH (d, output_end, (d)); |
711 } | 997 |
998 d->gutter_changed = 0; | |
999 } | |
1000 | |
1001 /* This is so that further changes to the gutters will trigger redisplay. */ | |
1002 gutter_changed_set = 0; | |
1003 gutter_changed = 0; | |
712 | 1004 |
713 return Qnil; | 1005 return Qnil; |
714 } | 1006 } |
715 | 1007 |
716 void | 1008 void |
721 /* We are here as far in frame creation so cached specifiers are | 1013 /* We are here as far in frame creation so cached specifiers are |
722 already recomputed, and possibly modified by resource | 1014 already recomputed, and possibly modified by resource |
723 initialization. We need to recalculate autodetected gutters. */ | 1015 initialization. We need to recalculate autodetected gutters. */ |
724 GUTTER_POS_LOOP (pos) | 1016 GUTTER_POS_LOOP (pos) |
725 { | 1017 { |
1018 w->real_gutter[pos] = construct_window_gutter_spec (w, pos); | |
726 w->real_gutter_size[pos] = w->gutter_size[pos]; | 1019 w->real_gutter_size[pos] = w->gutter_size[pos]; |
727 if (EQ (w->gutter_size[pos], Qautodetect) | 1020 if (EQ (w->gutter_size[pos], Qautodetect) |
728 && !NILP (w->gutter_visible_p[pos])) | 1021 && !NILP (w->gutter_visible_p[pos])) |
729 { | 1022 { |
730 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); | 1023 w->real_gutter_size [pos] = calculate_gutter_size (w, pos); |
731 MARK_GUTTER_CHANGED; | 1024 MARK_GUTTER_CHANGED; |
732 MARK_WINDOWS_CHANGED (w); | 1025 MARK_WINDOWS_CHANGED (w); |
733 } | 1026 } |
734 } | 1027 } |
1028 | |
1029 /* Keep a record of the current sizes of things. */ | |
1030 GUTTER_POS_LOOP (pos) | |
1031 { | |
1032 f->current_gutter_bounds[pos] = FRAME_GUTTER_BOUNDS (f, pos); | |
1033 } | |
735 } | 1034 } |
736 | 1035 |
737 void | 1036 void |
738 syms_of_gutter (void) | 1037 syms_of_gutter (void) |
739 { | 1038 { |
740 DEFSUBR (Fgutter_specifier_p); | 1039 DEFSUBR (Fgutter_specifier_p); |
741 DEFSUBR (Fgutter_size_specifier_p); | 1040 DEFSUBR (Fgutter_size_specifier_p); |
1041 DEFSUBR (Fgutter_visible_specifier_p); | |
742 DEFSUBR (Fset_default_gutter_position); | 1042 DEFSUBR (Fset_default_gutter_position); |
743 DEFSUBR (Fdefault_gutter_position); | 1043 DEFSUBR (Fdefault_gutter_position); |
744 DEFSUBR (Fgutter_pixel_height); | 1044 DEFSUBR (Fgutter_pixel_height); |
745 DEFSUBR (Fgutter_pixel_width); | 1045 DEFSUBR (Fgutter_pixel_width); |
746 DEFSUBR (Fredisplay_gutter_area); | 1046 DEFSUBR (Fredisplay_gutter_area); |
747 | 1047 |
748 defsymbol (&Qgutter_size, "gutter-size"); | 1048 defsymbol (&Qgutter_size, "gutter-size"); |
1049 defsymbol (&Qgutter_visible, "gutter-visible"); | |
1050 defsymbol (&Qdefault_gutter_position_changed_hook, | |
1051 "default-gutter-position-changed"); | |
749 } | 1052 } |
750 | 1053 |
751 void | 1054 void |
752 vars_of_gutter (void) | 1055 vars_of_gutter (void) |
753 { | 1056 { |
759 | 1062 |
760 void | 1063 void |
761 specifier_type_create_gutter (void) | 1064 specifier_type_create_gutter (void) |
762 { | 1065 { |
763 INITIALIZE_SPECIFIER_TYPE (gutter, "gutter", "gutter-specifier-p"); | 1066 INITIALIZE_SPECIFIER_TYPE (gutter, "gutter", "gutter-specifier-p"); |
764 | |
765 SPECIFIER_HAS_METHOD (gutter, validate); | 1067 SPECIFIER_HAS_METHOD (gutter, validate); |
766 SPECIFIER_HAS_METHOD (gutter, after_change); | 1068 SPECIFIER_HAS_METHOD (gutter, after_change); |
767 | 1069 |
768 INITIALIZE_SPECIFIER_TYPE (gutter_size, "gutter-size", "gutter-size-specifier-p"); | 1070 INITIALIZE_SPECIFIER_TYPE (gutter_size, "gutter-size", "gutter-size-specifier-p"); |
769 | |
770 SPECIFIER_HAS_METHOD (gutter_size, validate); | 1071 SPECIFIER_HAS_METHOD (gutter_size, validate); |
1072 | |
1073 INITIALIZE_SPECIFIER_TYPE (gutter_visible, "gutter-visible", "gutter-visible-specifier-p"); | |
1074 SPECIFIER_HAS_METHOD (gutter_visible, validate); | |
771 } | 1075 } |
772 | 1076 |
773 void | 1077 void |
774 reinit_specifier_type_create_gutter (void) | 1078 reinit_specifier_type_create_gutter (void) |
775 { | 1079 { |
776 REINITIALIZE_SPECIFIER_TYPE (gutter); | 1080 REINITIALIZE_SPECIFIER_TYPE (gutter); |
777 REINITIALIZE_SPECIFIER_TYPE (gutter_size); | 1081 REINITIALIZE_SPECIFIER_TYPE (gutter_size); |
1082 REINITIALIZE_SPECIFIER_TYPE (gutter_visible); | |
778 } | 1083 } |
779 | 1084 |
780 void | 1085 void |
781 specifier_vars_of_gutter (void) | 1086 specifier_vars_of_gutter (void) |
782 { | 1087 { |
813 the visibility and thickness using `default-gutter-visible-p', | 1118 the visibility and thickness using `default-gutter-visible-p', |
814 `default-gutter-width', and `default-gutter-height', rather than | 1119 `default-gutter-width', and `default-gutter-height', rather than |
815 using position-specific specifiers. That way, you will get sane | 1120 using position-specific specifiers. That way, you will get sane |
816 behavior if the user changes the default gutter position. | 1121 behavior if the user changes the default gutter position. |
817 | 1122 |
818 The gutter value should be a string or nil. You can attach extents and | 1123 The gutter value should be a string, a property list of strings or |
819 glyphs to the string and hence display glyphs and text in other fonts | 1124 nil. You can attach extents and glyphs to the string and hence display |
820 in the gutter area. | 1125 glyphs and text in other fonts in the gutter area. If the gutter value |
821 | 1126 is a property list then the strings will be concatenated together |
822 */ ); | 1127 before being displayed. */ ); |
823 | 1128 |
824 Vdefault_gutter = Fmake_specifier (Qgutter); | 1129 Vdefault_gutter = Fmake_specifier (Qgutter); |
825 /* #### It would be even nicer if the specifier caching | 1130 /* #### It would be even nicer if the specifier caching |
826 automatically knew about specifier fallbacks, so we didn't | 1131 automatically knew about specifier fallbacks, so we didn't |
827 have to do it ourselves. */ | 1132 have to do it ourselves. */ |
837 See `default-gutter' for a description of a valid gutter instantiator. | 1142 See `default-gutter' for a description of a valid gutter instantiator. |
838 */ ); | 1143 */ ); |
839 Vgutter[TOP_GUTTER] = Fmake_specifier (Qgutter); | 1144 Vgutter[TOP_GUTTER] = Fmake_specifier (Qgutter); |
840 set_specifier_caching (Vgutter[TOP_GUTTER], | 1145 set_specifier_caching (Vgutter[TOP_GUTTER], |
841 offsetof (struct window, gutter[TOP_GUTTER]), | 1146 offsetof (struct window, gutter[TOP_GUTTER]), |
842 gutter_specs_changed, | 1147 top_gutter_specs_changed, |
843 0, 0); | 1148 0, 0); |
844 | 1149 |
845 DEFVAR_SPECIFIER ("bottom-gutter", | 1150 DEFVAR_SPECIFIER ("bottom-gutter", |
846 &Vgutter[BOTTOM_GUTTER] /* | 1151 &Vgutter[BOTTOM_GUTTER] /* |
847 Specifier for the gutter at the bottom of the frame. | 1152 Specifier for the gutter at the bottom of the frame. |
854 displayed even if you provide a value for `bottom-gutter'. | 1159 displayed even if you provide a value for `bottom-gutter'. |
855 */ ); | 1160 */ ); |
856 Vgutter[BOTTOM_GUTTER] = Fmake_specifier (Qgutter); | 1161 Vgutter[BOTTOM_GUTTER] = Fmake_specifier (Qgutter); |
857 set_specifier_caching (Vgutter[BOTTOM_GUTTER], | 1162 set_specifier_caching (Vgutter[BOTTOM_GUTTER], |
858 offsetof (struct window, gutter[BOTTOM_GUTTER]), | 1163 offsetof (struct window, gutter[BOTTOM_GUTTER]), |
859 gutter_specs_changed, | 1164 bottom_gutter_specs_changed, |
860 0, 0); | 1165 0, 0); |
861 | 1166 |
862 DEFVAR_SPECIFIER ("left-gutter", | 1167 DEFVAR_SPECIFIER ("left-gutter", |
863 &Vgutter[LEFT_GUTTER] /* | 1168 &Vgutter[LEFT_GUTTER] /* |
864 Specifier for the gutter at the left edge of the frame. | 1169 Specifier for the gutter at the left edge of the frame. |
871 displayed even if you provide a value for `left-gutter'. | 1176 displayed even if you provide a value for `left-gutter'. |
872 */ ); | 1177 */ ); |
873 Vgutter[LEFT_GUTTER] = Fmake_specifier (Qgutter); | 1178 Vgutter[LEFT_GUTTER] = Fmake_specifier (Qgutter); |
874 set_specifier_caching (Vgutter[LEFT_GUTTER], | 1179 set_specifier_caching (Vgutter[LEFT_GUTTER], |
875 offsetof (struct window, gutter[LEFT_GUTTER]), | 1180 offsetof (struct window, gutter[LEFT_GUTTER]), |
876 gutter_specs_changed, | 1181 left_gutter_specs_changed, |
877 0, 0); | 1182 0, 0); |
878 | 1183 |
879 DEFVAR_SPECIFIER ("right-gutter", | 1184 DEFVAR_SPECIFIER ("right-gutter", |
880 &Vgutter[RIGHT_GUTTER] /* | 1185 &Vgutter[RIGHT_GUTTER] /* |
881 Specifier for the gutter at the right edge of the frame. | 1186 Specifier for the gutter at the right edge of the frame. |
888 displayed even if you provide a value for `right-gutter'. | 1193 displayed even if you provide a value for `right-gutter'. |
889 */ ); | 1194 */ ); |
890 Vgutter[RIGHT_GUTTER] = Fmake_specifier (Qgutter); | 1195 Vgutter[RIGHT_GUTTER] = Fmake_specifier (Qgutter); |
891 set_specifier_caching (Vgutter[RIGHT_GUTTER], | 1196 set_specifier_caching (Vgutter[RIGHT_GUTTER], |
892 offsetof (struct window, gutter[RIGHT_GUTTER]), | 1197 offsetof (struct window, gutter[RIGHT_GUTTER]), |
893 gutter_specs_changed, | 1198 right_gutter_specs_changed, |
894 0, 0); | 1199 0, 0); |
895 | 1200 |
896 /* initially, top inherits from default; this can be | 1201 /* initially, top inherits from default; this can be |
897 changed with `set-default-gutter-position'. */ | 1202 changed with `set-default-gutter-position'. */ |
898 fb = list1 (Fcons (Qnil, Qnil)); | 1203 fb = list1 (Fcons (Qnil, Qnil)); |
953 See `default-gutter-height' for more information. | 1258 See `default-gutter-height' for more information. |
954 */ ); | 1259 */ ); |
955 Vgutter_size[TOP_GUTTER] = Fmake_specifier (Qgutter_size); | 1260 Vgutter_size[TOP_GUTTER] = Fmake_specifier (Qgutter_size); |
956 set_specifier_caching (Vgutter_size[TOP_GUTTER], | 1261 set_specifier_caching (Vgutter_size[TOP_GUTTER], |
957 offsetof (struct window, gutter_size[TOP_GUTTER]), | 1262 offsetof (struct window, gutter_size[TOP_GUTTER]), |
958 gutter_geometry_changed_in_window, | 1263 gutter_geometry_changed_in_window, 0, 0); |
959 0, 0); | |
960 | 1264 |
961 DEFVAR_SPECIFIER ("bottom-gutter-height", | 1265 DEFVAR_SPECIFIER ("bottom-gutter-height", |
962 &Vgutter_size[BOTTOM_GUTTER] /* | 1266 &Vgutter_size[BOTTOM_GUTTER] /* |
963 *Height of the bottom gutter. | 1267 *Height of the bottom gutter. |
964 This is a specifier; use `set-specifier' to change it. | 1268 This is a specifier; use `set-specifier' to change it. |
966 See `default-gutter-height' for more information. | 1270 See `default-gutter-height' for more information. |
967 */ ); | 1271 */ ); |
968 Vgutter_size[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_size); | 1272 Vgutter_size[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_size); |
969 set_specifier_caching (Vgutter_size[BOTTOM_GUTTER], | 1273 set_specifier_caching (Vgutter_size[BOTTOM_GUTTER], |
970 offsetof (struct window, gutter_size[BOTTOM_GUTTER]), | 1274 offsetof (struct window, gutter_size[BOTTOM_GUTTER]), |
971 gutter_geometry_changed_in_window, | 1275 gutter_geometry_changed_in_window, 0, 0); |
972 0, 0); | |
973 | 1276 |
974 DEFVAR_SPECIFIER ("left-gutter-width", | 1277 DEFVAR_SPECIFIER ("left-gutter-width", |
975 &Vgutter_size[LEFT_GUTTER] /* | 1278 &Vgutter_size[LEFT_GUTTER] /* |
976 *Width of left gutter. | 1279 *Width of left gutter. |
977 This is a specifier; use `set-specifier' to change it. | 1280 This is a specifier; use `set-specifier' to change it. |
979 See `default-gutter-height' for more information. | 1282 See `default-gutter-height' for more information. |
980 */ ); | 1283 */ ); |
981 Vgutter_size[LEFT_GUTTER] = Fmake_specifier (Qnatnum); | 1284 Vgutter_size[LEFT_GUTTER] = Fmake_specifier (Qnatnum); |
982 set_specifier_caching (Vgutter_size[LEFT_GUTTER], | 1285 set_specifier_caching (Vgutter_size[LEFT_GUTTER], |
983 offsetof (struct window, gutter_size[LEFT_GUTTER]), | 1286 offsetof (struct window, gutter_size[LEFT_GUTTER]), |
984 gutter_geometry_changed_in_window, | 1287 gutter_geometry_changed_in_window, 0, 0); |
985 0, 0); | |
986 | 1288 |
987 DEFVAR_SPECIFIER ("right-gutter-width", | 1289 DEFVAR_SPECIFIER ("right-gutter-width", |
988 &Vgutter_size[RIGHT_GUTTER] /* | 1290 &Vgutter_size[RIGHT_GUTTER] /* |
989 *Width of right gutter. | 1291 *Width of right gutter. |
990 This is a specifier; use `set-specifier' to change it. | 1292 This is a specifier; use `set-specifier' to change it. |
992 See `default-gutter-height' for more information. | 1294 See `default-gutter-height' for more information. |
993 */ ); | 1295 */ ); |
994 Vgutter_size[RIGHT_GUTTER] = Fmake_specifier (Qnatnum); | 1296 Vgutter_size[RIGHT_GUTTER] = Fmake_specifier (Qnatnum); |
995 set_specifier_caching (Vgutter_size[RIGHT_GUTTER], | 1297 set_specifier_caching (Vgutter_size[RIGHT_GUTTER], |
996 offsetof (struct window, gutter_size[RIGHT_GUTTER]), | 1298 offsetof (struct window, gutter_size[RIGHT_GUTTER]), |
997 gutter_geometry_changed_in_window, | 1299 gutter_geometry_changed_in_window, 0, 0); |
998 0, 0); | |
999 | 1300 |
1000 fb = Qnil; | 1301 fb = Qnil; |
1001 #ifdef HAVE_TTY | 1302 #ifdef HAVE_TTY |
1002 fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb); | 1303 fb = Fcons (Fcons (list1 (Qtty), Qautodetect), fb); |
1003 #endif | 1304 #endif |
1061 */ ); | 1362 */ ); |
1062 Vgutter_border_width[TOP_GUTTER] = Fmake_specifier (Qnatnum); | 1363 Vgutter_border_width[TOP_GUTTER] = Fmake_specifier (Qnatnum); |
1063 set_specifier_caching (Vgutter_border_width[TOP_GUTTER], | 1364 set_specifier_caching (Vgutter_border_width[TOP_GUTTER], |
1064 offsetof (struct window, | 1365 offsetof (struct window, |
1065 gutter_border_width[TOP_GUTTER]), | 1366 gutter_border_width[TOP_GUTTER]), |
1066 gutter_geometry_changed_in_window, | 1367 gutter_geometry_changed_in_window, 0, 0); |
1067 0, 0); | |
1068 | 1368 |
1069 DEFVAR_SPECIFIER ("bottom-gutter-border-width", | 1369 DEFVAR_SPECIFIER ("bottom-gutter-border-width", |
1070 &Vgutter_border_width[BOTTOM_GUTTER] /* | 1370 &Vgutter_border_width[BOTTOM_GUTTER] /* |
1071 *Border width of the bottom gutter. | 1371 *Border width of the bottom gutter. |
1072 This is a specifier; use `set-specifier' to change it. | 1372 This is a specifier; use `set-specifier' to change it. |
1075 */ ); | 1375 */ ); |
1076 Vgutter_border_width[BOTTOM_GUTTER] = Fmake_specifier (Qnatnum); | 1376 Vgutter_border_width[BOTTOM_GUTTER] = Fmake_specifier (Qnatnum); |
1077 set_specifier_caching (Vgutter_border_width[BOTTOM_GUTTER], | 1377 set_specifier_caching (Vgutter_border_width[BOTTOM_GUTTER], |
1078 offsetof (struct window, | 1378 offsetof (struct window, |
1079 gutter_border_width[BOTTOM_GUTTER]), | 1379 gutter_border_width[BOTTOM_GUTTER]), |
1080 gutter_geometry_changed_in_window, | 1380 gutter_geometry_changed_in_window, 0, 0); |
1081 0, 0); | |
1082 | 1381 |
1083 DEFVAR_SPECIFIER ("left-gutter-border-width", | 1382 DEFVAR_SPECIFIER ("left-gutter-border-width", |
1084 &Vgutter_border_width[LEFT_GUTTER] /* | 1383 &Vgutter_border_width[LEFT_GUTTER] /* |
1085 *Border width of left gutter. | 1384 *Border width of left gutter. |
1086 This is a specifier; use `set-specifier' to change it. | 1385 This is a specifier; use `set-specifier' to change it. |
1089 */ ); | 1388 */ ); |
1090 Vgutter_border_width[LEFT_GUTTER] = Fmake_specifier (Qnatnum); | 1389 Vgutter_border_width[LEFT_GUTTER] = Fmake_specifier (Qnatnum); |
1091 set_specifier_caching (Vgutter_border_width[LEFT_GUTTER], | 1390 set_specifier_caching (Vgutter_border_width[LEFT_GUTTER], |
1092 offsetof (struct window, | 1391 offsetof (struct window, |
1093 gutter_border_width[LEFT_GUTTER]), | 1392 gutter_border_width[LEFT_GUTTER]), |
1094 gutter_geometry_changed_in_window, | 1393 gutter_geometry_changed_in_window, 0, 0); |
1095 0, 0); | |
1096 | 1394 |
1097 DEFVAR_SPECIFIER ("right-gutter-border-width", | 1395 DEFVAR_SPECIFIER ("right-gutter-border-width", |
1098 &Vgutter_border_width[RIGHT_GUTTER] /* | 1396 &Vgutter_border_width[RIGHT_GUTTER] /* |
1099 *Border width of right gutter. | 1397 *Border width of right gutter. |
1100 This is a specifier; use `set-specifier' to change it. | 1398 This is a specifier; use `set-specifier' to change it. |
1103 */ ); | 1401 */ ); |
1104 Vgutter_border_width[RIGHT_GUTTER] = Fmake_specifier (Qnatnum); | 1402 Vgutter_border_width[RIGHT_GUTTER] = Fmake_specifier (Qnatnum); |
1105 set_specifier_caching (Vgutter_border_width[RIGHT_GUTTER], | 1403 set_specifier_caching (Vgutter_border_width[RIGHT_GUTTER], |
1106 offsetof (struct window, | 1404 offsetof (struct window, |
1107 gutter_border_width[RIGHT_GUTTER]), | 1405 gutter_border_width[RIGHT_GUTTER]), |
1108 gutter_geometry_changed_in_window, | 1406 gutter_geometry_changed_in_window, 0, 0); |
1109 0, 0); | |
1110 | 1407 |
1111 fb = Qnil; | 1408 fb = Qnil; |
1112 #ifdef HAVE_TTY | 1409 #ifdef HAVE_TTY |
1113 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb); | 1410 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb); |
1114 #endif | 1411 #endif |
1141 instead. | 1438 instead. |
1142 | 1439 |
1143 `default-gutter-visible-p' and all of the position-specific gutter | 1440 `default-gutter-visible-p' and all of the position-specific gutter |
1144 visibility specifiers have a fallback value of true. | 1441 visibility specifiers have a fallback value of true. |
1145 */ ); | 1442 */ ); |
1146 Vdefault_gutter_visible_p = Fmake_specifier (Qboolean); | 1443 Vdefault_gutter_visible_p = Fmake_specifier (Qgutter_visible); |
1147 set_specifier_caching (Vdefault_gutter_visible_p, | 1444 set_specifier_caching (Vdefault_gutter_visible_p, |
1148 offsetof (struct window, | 1445 offsetof (struct window, |
1149 default_gutter_visible_p), | 1446 default_gutter_visible_p), |
1150 default_gutter_visible_p_changed_in_window, | 1447 default_gutter_visible_p_changed_in_window, |
1151 0, 0); | 1448 0, 0); |
1155 *Whether the top gutter is visible. | 1452 *Whether the top gutter is visible. |
1156 This is a specifier; use `set-specifier' to change it. | 1453 This is a specifier; use `set-specifier' to change it. |
1157 | 1454 |
1158 See `default-gutter-visible-p' for more information. | 1455 See `default-gutter-visible-p' for more information. |
1159 */ ); | 1456 */ ); |
1160 Vgutter_visible_p[TOP_GUTTER] = Fmake_specifier (Qboolean); | 1457 Vgutter_visible_p[TOP_GUTTER] = Fmake_specifier (Qgutter_visible); |
1161 set_specifier_caching (Vgutter_visible_p[TOP_GUTTER], | 1458 set_specifier_caching (Vgutter_visible_p[TOP_GUTTER], |
1162 offsetof (struct window, | 1459 offsetof (struct window, |
1163 gutter_visible_p[TOP_GUTTER]), | 1460 gutter_visible_p[TOP_GUTTER]), |
1164 gutter_geometry_changed_in_window, | 1461 top_gutter_specs_changed, 0, 0); |
1165 0, 0); | |
1166 | 1462 |
1167 DEFVAR_SPECIFIER ("bottom-gutter-visible-p", | 1463 DEFVAR_SPECIFIER ("bottom-gutter-visible-p", |
1168 &Vgutter_visible_p[BOTTOM_GUTTER] /* | 1464 &Vgutter_visible_p[BOTTOM_GUTTER] /* |
1169 *Whether the bottom gutter is visible. | 1465 *Whether the bottom gutter is visible. |
1170 This is a specifier; use `set-specifier' to change it. | 1466 This is a specifier; use `set-specifier' to change it. |
1171 | 1467 |
1172 See `default-gutter-visible-p' for more information. | 1468 See `default-gutter-visible-p' for more information. |
1173 */ ); | 1469 */ ); |
1174 Vgutter_visible_p[BOTTOM_GUTTER] = Fmake_specifier (Qboolean); | 1470 Vgutter_visible_p[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_visible); |
1175 set_specifier_caching (Vgutter_visible_p[BOTTOM_GUTTER], | 1471 set_specifier_caching (Vgutter_visible_p[BOTTOM_GUTTER], |
1176 offsetof (struct window, | 1472 offsetof (struct window, |
1177 gutter_visible_p[BOTTOM_GUTTER]), | 1473 gutter_visible_p[BOTTOM_GUTTER]), |
1178 gutter_geometry_changed_in_window, | 1474 bottom_gutter_specs_changed, 0, 0); |
1179 0, 0); | |
1180 | 1475 |
1181 DEFVAR_SPECIFIER ("left-gutter-visible-p", | 1476 DEFVAR_SPECIFIER ("left-gutter-visible-p", |
1182 &Vgutter_visible_p[LEFT_GUTTER] /* | 1477 &Vgutter_visible_p[LEFT_GUTTER] /* |
1183 *Whether the left gutter is visible. | 1478 *Whether the left gutter is visible. |
1184 This is a specifier; use `set-specifier' to change it. | 1479 This is a specifier; use `set-specifier' to change it. |
1185 | 1480 |
1186 See `default-gutter-visible-p' for more information. | 1481 See `default-gutter-visible-p' for more information. |
1187 */ ); | 1482 */ ); |
1188 Vgutter_visible_p[LEFT_GUTTER] = Fmake_specifier (Qboolean); | 1483 Vgutter_visible_p[LEFT_GUTTER] = Fmake_specifier (Qgutter_visible); |
1189 set_specifier_caching (Vgutter_visible_p[LEFT_GUTTER], | 1484 set_specifier_caching (Vgutter_visible_p[LEFT_GUTTER], |
1190 offsetof (struct window, | 1485 offsetof (struct window, |
1191 gutter_visible_p[LEFT_GUTTER]), | 1486 gutter_visible_p[LEFT_GUTTER]), |
1192 gutter_geometry_changed_in_window, | 1487 left_gutter_specs_changed, 0, 0); |
1193 0, 0); | |
1194 | 1488 |
1195 DEFVAR_SPECIFIER ("right-gutter-visible-p", | 1489 DEFVAR_SPECIFIER ("right-gutter-visible-p", |
1196 &Vgutter_visible_p[RIGHT_GUTTER] /* | 1490 &Vgutter_visible_p[RIGHT_GUTTER] /* |
1197 *Whether the right gutter is visible. | 1491 *Whether the right gutter is visible. |
1198 This is a specifier; use `set-specifier' to change it. | 1492 This is a specifier; use `set-specifier' to change it. |
1199 | 1493 |
1200 See `default-gutter-visible-p' for more information. | 1494 See `default-gutter-visible-p' for more information. |
1201 */ ); | 1495 */ ); |
1202 Vgutter_visible_p[RIGHT_GUTTER] = Fmake_specifier (Qboolean); | 1496 Vgutter_visible_p[RIGHT_GUTTER] = Fmake_specifier (Qgutter_visible); |
1203 set_specifier_caching (Vgutter_visible_p[RIGHT_GUTTER], | 1497 set_specifier_caching (Vgutter_visible_p[RIGHT_GUTTER], |
1204 offsetof (struct window, | 1498 offsetof (struct window, |
1205 gutter_visible_p[RIGHT_GUTTER]), | 1499 gutter_visible_p[RIGHT_GUTTER]), |
1206 gutter_geometry_changed_in_window, | 1500 right_gutter_specs_changed, 0, 0); |
1207 0, 0); | |
1208 | 1501 |
1209 /* initially, top inherits from default; this can be | 1502 /* initially, top inherits from default; this can be |
1210 changed with `set-default-gutter-position'. */ | 1503 changed with `set-default-gutter-position'. */ |
1211 fb = list1 (Fcons (Qnil, Qt)); | 1504 fb = list1 (Fcons (Qnil, Qt)); |
1212 set_specifier_fallback (Vdefault_gutter_visible_p, fb); | 1505 set_specifier_fallback (Vdefault_gutter_visible_p, fb); |