]> code.delx.au - gnu-emacs/blob - src/fringe.c
Add 2012 to FSF copyright years for Emacs files (do not merge to trunk)
[gnu-emacs] / src / fringe.c
1 /* Fringe handling (split from xdisp.c).
2 Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1997,
3 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
5
6 This file is part of GNU Emacs.
7
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <setjmp.h>
24
25 #include "lisp.h"
26 #include "frame.h"
27 #include "window.h"
28 #include "dispextern.h"
29 #include "buffer.h"
30 #include "blockinput.h"
31 #include "termhooks.h"
32
33 #ifdef HAVE_WINDOW_SYSTEM
34
35 extern Lisp_Object Qfringe;
36 extern Lisp_Object Qtop, Qbottom, Qcenter;
37 extern Lisp_Object Qup, Qdown, Qleft, Qright;
38
39 /* Non-nil means that newline may flow into the right fringe. */
40
41 Lisp_Object Voverflow_newline_into_fringe;
42
43 /* List of known fringe bitmap symbols.
44
45 The fringe bitmap number is stored in the `fringe' property on
46 those symbols. Names for the built-in bitmaps are installed by
47 loading fringe.el.
48 */
49
50 Lisp_Object Vfringe_bitmaps;
51
52 /* Fringe bitmaps are represented in three different ways:
53
54 Logical bitmaps are used internally to denote things like
55 'end-of-buffer', 'left-truncation', 'overlay-arrow', etc.
56
57 Physical bitmaps specify the visual appearence of the bitmap,
58 e.g. 'bottom-left-angle', 'left-arrow', 'left-triangle', etc.
59 User defined bitmaps are physical bitmaps.
60
61 Internally, fringe bitmaps for a specific display row are
62 represented as a simple integer that is used as an index
63 into the table of all defined bitmaps. This index is stored
64 in the `fringe' property of the physical bitmap symbol.
65
66 Logical bitmaps are mapped to physical bitmaps through the
67 buffer-local `fringe-indicator-alist' variable.
68
69 Each element of this alist is a cons (LOGICAL . PHYSICAL)
70 mapping a logical bitmap to a physical bitmap.
71 PHYSICAL is either a symbol to use in both left and right fringe,
72 or a cons of two symbols (LEFT . RIGHT) denoting different
73 bitmaps to use in left and right fringe.
74
75 LOGICAL is first looked up in the window's buffer's buffer-local
76 value of the fringe-indicator-alist variable, and if not present,
77 in the global value of fringe-indicator-alist.
78
79 If LOGICAL is not present in either alist, or the PHYSICAL value
80 found is nil, no bitmap is shown for the logical bitmap.
81
82 The `left-fringe' and `right-fringe' display properties
83 must specify physical bitmap symbols.
84 */
85
86 extern Lisp_Object Qunknown;
87 Lisp_Object Qtruncation, Qcontinuation, Qoverlay_arrow;
88 Lisp_Object Qempty_line, Qtop_bottom;
89 extern Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
90 Lisp_Object Qhollow_small;
91
92 enum fringe_bitmap_align
93 {
94 ALIGN_BITMAP_CENTER = 0,
95 ALIGN_BITMAP_TOP,
96 ALIGN_BITMAP_BOTTOM
97 };
98
99 struct fringe_bitmap
100 {
101 unsigned short *bits;
102 unsigned height : 8;
103 unsigned width : 8;
104 unsigned period : 8;
105 unsigned align : 2;
106 unsigned dynamic : 1;
107 };
108
109 \f
110 /***********************************************************************
111 Fringe bitmaps
112 ***********************************************************************/
113
114 /* Undefined bitmap. A question mark. */
115 /*
116 ..xxxx..
117 .xxxxxx.
118 xx....xx
119 xx....xx
120 ....xx..
121 ...xx...
122 ...xx...
123 ........
124 ...xx...
125 ...xx...
126 */
127 static unsigned short question_mark_bits[] = {
128 0x3c, 0x7e, 0x7e, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18};
129
130 /* An arrow like this: `<-'. */
131 /*
132 ...xx...
133 ..xx....
134 .xx.....
135 xxxxxx..
136 xxxxxx..
137 .xx.....
138 ..xx....
139 ...xx...
140 */
141 static unsigned short left_arrow_bits[] = {
142 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
143
144
145 /* Right truncation arrow bitmap `->'. */
146 /*
147 ...xx...
148 ....xx..
149 .....xx.
150 ..xxxxxx
151 ..xxxxxx
152 .....xx.
153 ....xx..
154 ...xx...
155 */
156 static unsigned short right_arrow_bits[] = {
157 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
158
159
160 /* Up arrow bitmap. */
161 /*
162 ...xx...
163 ..xxxx..
164 .xxxxxx.
165 xxxxxxxx
166 ...xx...
167 ...xx...
168 ...xx...
169 ...xx...
170 */
171 static unsigned short up_arrow_bits[] = {
172 0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0x18};
173
174
175 /* Down arrow bitmap. */
176 /*
177 ...xx...
178 ...xx...
179 ...xx...
180 ...xx...
181 xxxxxxxx
182 .xxxxxx.
183 ..xxxx..
184 ...xx...
185 */
186 static unsigned short down_arrow_bits[] = {
187 0x18, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18};
188
189 /* Marker for continuation lines. */
190 /*
191 ..xxxx..
192 .xxxxx..
193 xx......
194 xxx..x..
195 xxxxxx..
196 .xxxxx..
197 ..xxxx..
198 .xxxxx..
199 */
200 static unsigned short left_curly_arrow_bits[] = {
201 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
202
203 /* Marker for continued lines. */
204 /*
205 ..xxxx..
206 ..xxxxx.
207 ......xx
208 ..x..xxx
209 ..xxxxxx
210 ..xxxxx.
211 ..xxxx..
212 ..xxxxx.
213 */
214 static unsigned short right_curly_arrow_bits[] = {
215 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
216
217 /* Reverse Overlay arrow bitmap. A triangular arrow. */
218 /*
219 ......xx
220 ....xxxx
221 ...xxxxx
222 ..xxxxxx
223 ..xxxxxx
224 ...xxxxx
225 ....xxxx
226 ......xx
227 */
228 static unsigned short left_triangle_bits[] = {
229 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
230
231 /* Overlay arrow bitmap. A triangular arrow. */
232 /*
233 xx......
234 xxxx....
235 xxxxx...
236 xxxxxx..
237 xxxxxx..
238 xxxxx...
239 xxxx....
240 xx......
241 */
242 static unsigned short right_triangle_bits[] = {
243 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
244
245 /* First line bitmap. An top-left angle. */
246 /*
247 xxxxxx..
248 xxxxxx..
249 xx......
250 xx......
251 xx......
252 xx......
253 xx......
254 ........
255 */
256 static unsigned short top_left_angle_bits[] = {
257 0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00};
258
259 /* First line bitmap. An right-up angle. */
260 /*
261 ..xxxxxx
262 ..xxxxxx
263 ......xx
264 ......xx
265 ......xx
266 ......xx
267 ......xx
268 ........
269 */
270 static unsigned short top_right_angle_bits[] = {
271 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00};
272
273 /* Last line bitmap. An left-down angle. */
274 /*
275 ........
276 xx......
277 xx......
278 xx......
279 xx......
280 xx......
281 xxxxxx..
282 xxxxxx..
283 */
284 static unsigned short bottom_left_angle_bits[] = {
285 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
286
287 /* Last line bitmap. An right-down angle. */
288 /*
289 ........
290 ......xx
291 ......xx
292 ......xx
293 ......xx
294 ......xx
295 ..xxxxxx
296 ..xxxxxx
297 */
298 static unsigned short bottom_right_angle_bits[] = {
299 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
300
301 /* First/last line bitmap. An left bracket. */
302 /*
303 xxxxxx..
304 xxxxxx..
305 xx......
306 xx......
307 xx......
308 xx......
309 xx......
310 xx......
311 xxxxxx..
312 xxxxxx..
313 */
314 static unsigned short left_bracket_bits[] = {
315 0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
316
317 /* First/last line bitmap. An right bracket. */
318 /*
319 ..xxxxxx
320 ..xxxxxx
321 ......xx
322 ......xx
323 ......xx
324 ......xx
325 ......xx
326 ......xx
327 ..xxxxxx
328 ..xxxxxx
329 */
330 static unsigned short right_bracket_bits[] = {
331 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
332
333 /* Filled box cursor bitmap. A filled box; max 13 pixels high. */
334 /*
335 xxxxxxx.
336 xxxxxxx.
337 xxxxxxx.
338 xxxxxxx.
339 xxxxxxx.
340 xxxxxxx.
341 xxxxxxx.
342 xxxxxxx.
343 xxxxxxx.
344 xxxxxxx.
345 xxxxxxx.
346 xxxxxxx.
347 xxxxxxx.
348 */
349 static unsigned short filled_rectangle_bits[] = {
350 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
351
352 /* Hollow box cursor bitmap. A hollow box; max 13 pixels high. */
353 /*
354 xxxxxxx.
355 x.....x.
356 x.....x.
357 x.....x.
358 x.....x.
359 x.....x.
360 x.....x.
361 x.....x.
362 x.....x.
363 x.....x.
364 x.....x.
365 x.....x.
366 xxxxxxx.
367 */
368 static unsigned short hollow_rectangle_bits[] = {
369 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe};
370
371 /* Hollow square bitmap. */
372 /*
373 .xxxxxx.
374 .x....x.
375 .x....x.
376 .x....x.
377 .x....x.
378 .xxxxxx.
379 */
380 static unsigned short hollow_square_bits[] = {
381 0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e};
382
383 /* Filled square bitmap. */
384 /*
385 .xxxxxx.
386 .xxxxxx.
387 .xxxxxx.
388 .xxxxxx.
389 .xxxxxx.
390 .xxxxxx.
391 */
392 static unsigned short filled_square_bits[] = {
393 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e};
394
395 /* Bar cursor bitmap. A vertical bar; max 13 pixels high. */
396 /*
397 xx......
398 xx......
399 xx......
400 xx......
401 xx......
402 xx......
403 xx......
404 xx......
405 xx......
406 xx......
407 xx......
408 xx......
409 xx......
410 */
411 static unsigned short vertical_bar_bits[] = {
412 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0};
413
414 /* HBar cursor bitmap. A horizontal bar; 2 pixels high. */
415 /*
416 xxxxxxx.
417 xxxxxxx.
418 */
419 static unsigned short horizontal_bar_bits[] = {
420 0xfe, 0xfe};
421
422
423 /* Bitmap drawn to indicate lines not displaying text if
424 `indicate-empty-lines' is non-nil. */
425 /*
426 ........
427 ..xxxx..
428 ........
429 ........
430 ..xxxx..
431 ........
432 */
433 static unsigned short empty_line_bits[] = {
434 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
435 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
436 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
437 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
438 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
439 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
440 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
441 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
442
443
444 #define BYTES_PER_BITMAP_ROW (sizeof (unsigned short))
445 #define STANDARD_BITMAP_HEIGHT(bits) (sizeof (bits)/BYTES_PER_BITMAP_ROW)
446 #define FRBITS(bits) bits, STANDARD_BITMAP_HEIGHT (bits)
447
448 /* NOTE: The order of these bitmaps must match the sequence
449 used in fringe.el to define the corresponding symbols. */
450
451 struct fringe_bitmap standard_bitmaps[] =
452 {
453 { NULL, 0, 0, 0, 0, 0 }, /* NO_FRINGE_BITMAP */
454 { FRBITS (question_mark_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
455 { FRBITS (left_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
456 { FRBITS (right_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
457 { FRBITS (up_arrow_bits), 8, 0, ALIGN_BITMAP_TOP, 0 },
458 { FRBITS (down_arrow_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
459 { FRBITS (left_curly_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
460 { FRBITS (right_curly_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
461 { FRBITS (left_triangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
462 { FRBITS (right_triangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
463 { FRBITS (top_left_angle_bits), 8, 0, ALIGN_BITMAP_TOP, 0 },
464 { FRBITS (top_right_angle_bits), 8, 0, ALIGN_BITMAP_TOP, 0 },
465 { FRBITS (bottom_left_angle_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
466 { FRBITS (bottom_right_angle_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
467 { FRBITS (left_bracket_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
468 { FRBITS (right_bracket_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
469 { FRBITS (filled_rectangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
470 { FRBITS (hollow_rectangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
471 { FRBITS (filled_square_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
472 { FRBITS (hollow_square_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
473 { FRBITS (vertical_bar_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
474 { FRBITS (horizontal_bar_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
475 { FRBITS (empty_line_bits), 8, 3, ALIGN_BITMAP_TOP, 0 },
476 };
477
478 #define NO_FRINGE_BITMAP 0
479 #define UNDEF_FRINGE_BITMAP 1
480 #define MAX_STANDARD_FRINGE_BITMAPS (sizeof(standard_bitmaps)/sizeof(standard_bitmaps[0]))
481
482 static struct fringe_bitmap **fringe_bitmaps;
483 static Lisp_Object *fringe_faces;
484 static int max_fringe_bitmaps;
485
486 int max_used_fringe_bitmap = MAX_STANDARD_FRINGE_BITMAPS;
487
488
489 /* Lookup bitmap number for symbol BITMAP.
490 Return 0 if not a bitmap. */
491
492 int
493 lookup_fringe_bitmap (bitmap)
494 Lisp_Object bitmap;
495 {
496 int bn;
497
498 bitmap = Fget (bitmap, Qfringe);
499 if (!INTEGERP (bitmap))
500 return 0;
501
502 bn = XINT (bitmap);
503 if (bn > NO_FRINGE_BITMAP
504 && bn < max_used_fringe_bitmap
505 && (bn < MAX_STANDARD_FRINGE_BITMAPS
506 || fringe_bitmaps[bn] != NULL))
507 return bn;
508
509 return 0;
510 }
511
512 /* Get fringe bitmap name for bitmap number BN.
513
514 Found by traversing Vfringe_bitmaps comparing BN to the
515 fringe property for each symbol.
516
517 Return BN if not found in Vfringe_bitmaps. */
518
519 static Lisp_Object
520 get_fringe_bitmap_name (bn)
521 int bn;
522 {
523 Lisp_Object bitmaps;
524 Lisp_Object num;
525
526 /* Zero means no bitmap -- return nil. */
527 if (bn <= 0)
528 return Qnil;
529
530 bitmaps = Vfringe_bitmaps;
531 num = make_number (bn);
532
533 while (CONSP (bitmaps))
534 {
535 Lisp_Object bitmap = XCAR (bitmaps);
536 if (EQ (num, Fget (bitmap, Qfringe)))
537 return bitmap;
538 bitmaps = XCDR (bitmaps);
539 }
540
541 return num;
542 }
543
544 /* Get fringe bitmap data for bitmap number BN. */
545
546 static struct fringe_bitmap *
547 get_fringe_bitmap_data (int bn)
548 {
549 struct fringe_bitmap *fb;
550
551 fb = fringe_bitmaps[bn];
552 if (fb == NULL)
553 fb = &standard_bitmaps[bn < MAX_STANDARD_FRINGE_BITMAPS
554 ? bn : UNDEF_FRINGE_BITMAP];
555
556 return fb;
557 }
558
559 /* Draw the bitmap WHICH in one of the left or right fringes of
560 window W. ROW is the glyph row for which to display the bitmap; it
561 determines the vertical position at which the bitmap has to be
562 drawn.
563 LEFT_P is 1 for left fringe, 0 for right fringe.
564 */
565
566 static void
567 draw_fringe_bitmap_1 (w, row, left_p, overlay, which)
568 struct window *w;
569 struct glyph_row *row;
570 int left_p, overlay;
571 int which;
572 {
573 struct frame *f = XFRAME (WINDOW_FRAME (w));
574 struct draw_fringe_bitmap_params p;
575 struct fringe_bitmap *fb;
576 int period;
577 int face_id = DEFAULT_FACE_ID;
578 int offset, header_line_height;
579
580 p.overlay_p = (overlay & 1) == 1;
581 p.cursor_p = (overlay & 2) == 2;
582
583 if (which != NO_FRINGE_BITMAP)
584 {
585 offset = 0;
586 }
587 else if (left_p)
588 {
589 which = row->left_fringe_bitmap;
590 face_id = row->left_fringe_face_id;
591 offset = row->left_fringe_offset;
592 }
593 else
594 {
595 which = row->right_fringe_bitmap;
596 face_id = row->right_fringe_face_id;
597 offset = row->right_fringe_offset;
598 }
599
600 if (face_id == DEFAULT_FACE_ID)
601 {
602 Lisp_Object face;
603
604 if ((face = fringe_faces[which], NILP (face))
605 || (face_id = lookup_derived_face (f, face, FRINGE_FACE_ID, 0),
606 face_id < 0))
607 face_id = FRINGE_FACE_ID;
608 }
609
610 fb = get_fringe_bitmap_data (which);
611
612 period = fb->period;
613
614 /* Convert row to frame coordinates. */
615 p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y) + offset;
616
617 p.which = which;
618 p.bits = fb->bits;
619 p.wd = fb->width;
620
621 p.h = fb->height;
622 p.dh = (period > 0 ? (p.y % period) : 0);
623 p.h -= p.dh;
624
625 /* Adjust y to the offset in the row to start drawing the bitmap. */
626 switch (fb->align)
627 {
628 case ALIGN_BITMAP_CENTER:
629 p.y += (row->height - p.h) / 2;
630 break;
631 case ALIGN_BITMAP_BOTTOM:
632 p.y += (row->visible_height - p.h);
633 break;
634 case ALIGN_BITMAP_TOP:
635 break;
636 }
637
638 p.face = FACE_FROM_ID (f, face_id);
639
640 if (p.face == NULL)
641 {
642 /* This could happen after clearing face cache.
643 But it shouldn't happen anymore. ++kfs */
644 return;
645 }
646
647 PREPARE_FACE_FOR_DISPLAY (f, p.face);
648
649 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
650 the fringe. */
651 p.bx = -1;
652 header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
653 p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
654 p.ny = row->visible_height;
655 if (left_p)
656 {
657 int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
658 int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
659 ? LEFT_MARGIN_AREA
660 : TEXT_AREA));
661 if (p.wd > wd)
662 p.wd = wd;
663 p.x = x - p.wd - (wd - p.wd) / 2;
664
665 if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny)
666 {
667 /* If W has a vertical border to its left, don't draw over it. */
668 wd -= ((!WINDOW_LEFTMOST_P (w)
669 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
670 ? 1 : 0);
671 p.bx = x - wd;
672 p.nx = wd;
673 }
674 }
675 else
676 {
677 int x = window_box_right (w,
678 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
679 ? RIGHT_MARGIN_AREA
680 : TEXT_AREA));
681 int wd = WINDOW_RIGHT_FRINGE_WIDTH (w);
682 if (p.wd > wd)
683 p.wd = wd;
684 p.x = x + (wd - p.wd) / 2;
685 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
686 the fringe. */
687 if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny)
688 {
689 p.bx = x;
690 p.nx = wd;
691 }
692 }
693
694 FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p);
695 }
696
697 static int
698 get_logical_cursor_bitmap (w, cursor)
699 struct window *w;
700 Lisp_Object cursor;
701 {
702 Lisp_Object cmap, bm = Qnil;
703
704 if ((cmap = XBUFFER (w->buffer)->fringe_cursor_alist), !NILP (cmap))
705 {
706 bm = Fassq (cursor, cmap);
707 if (CONSP (bm))
708 {
709 if ((bm = XCDR (bm)), NILP (bm))
710 return NO_FRINGE_BITMAP;
711 return lookup_fringe_bitmap (bm);
712 }
713 }
714 if (EQ (cmap, buffer_defaults.fringe_cursor_alist))
715 return NO_FRINGE_BITMAP;
716 bm = Fassq (cursor, buffer_defaults.fringe_cursor_alist);
717 if (!CONSP (bm) || ((bm = XCDR (bm)), NILP (bm)))
718 return NO_FRINGE_BITMAP;
719 return lookup_fringe_bitmap (bm);
720 }
721
722 static int
723 get_logical_fringe_bitmap (w, bitmap, right_p, partial_p)
724 struct window *w;
725 Lisp_Object bitmap;
726 int right_p, partial_p;
727 {
728 Lisp_Object cmap, bm1 = Qnil, bm2 = Qnil, bm;
729 int ln1 = 0, ln2 = 0;
730 int ix1 = right_p;
731 int ix2 = ix1 + (partial_p ? 2 : 0);
732
733 /* Lookup in buffer-local fringe-indicator-alist before global alist.
734
735 Elements are:
736 BITMAP -- use for all
737 (L R) -- use for left right (whether partial or not)
738 (L R PL PR) -- use for left right partial-left partial-right
739 If any value in local binding is not present or t, use global value.
740
741 If partial, lookup partial bitmap in default value if not found here.
742 If not partial, or no partial spec is present, use non-partial bitmap. */
743
744 if ((cmap = XBUFFER (w->buffer)->fringe_indicator_alist), !NILP (cmap))
745 {
746 bm1 = Fassq (bitmap, cmap);
747 if (CONSP (bm1))
748 {
749 if ((bm1 = XCDR (bm1)), NILP (bm1))
750 return NO_FRINGE_BITMAP;
751 if (CONSP (bm1))
752 {
753 ln1 = XINT (Flength (bm1));
754 if (partial_p)
755 {
756 if (ln1 > ix2)
757 {
758 bm = Fnth (make_number (ix2), bm1);
759 if (!EQ (bm, Qt))
760 goto found;
761 }
762 }
763 else
764 {
765 if (ln1 > ix1)
766 {
767 bm = Fnth (make_number (ix1), bm1);
768 if (!EQ (bm, Qt))
769 goto found;
770 }
771 }
772 }
773 else if ((bm = bm1, !EQ (bm, Qt)))
774 goto found;
775 }
776 }
777
778 if (!EQ (cmap, buffer_defaults.fringe_indicator_alist)
779 && !NILP (buffer_defaults.fringe_indicator_alist))
780 {
781 bm2 = Fassq (bitmap, buffer_defaults.fringe_indicator_alist);
782 if (CONSP (bm2))
783 {
784 if ((bm2 = XCDR (bm2)), !NILP (bm2))
785 {
786 if (CONSP (bm2))
787 {
788 ln2 = XINT (Flength (bm2));
789 if (partial_p)
790 {
791 if (ln2 > ix2)
792 {
793 bm = Fnth (make_number (ix2), bm2);
794 if (!EQ (bm, Qt))
795 goto found;
796 }
797 }
798 }
799 }
800 }
801 }
802
803 if (ln1 > ix1)
804 {
805 bm = Fnth (make_number (ix1), bm1);
806 if (!EQ (bm, Qt))
807 goto found;
808 }
809
810 if (ln2 > ix1)
811 {
812 bm = Fnth (make_number (ix1), bm2);
813 if (!EQ (bm, Qt))
814 goto found;
815 return NO_FRINGE_BITMAP;
816 }
817 else if ((bm = bm2, NILP (bm)))
818 return NO_FRINGE_BITMAP;
819
820 found:
821 return lookup_fringe_bitmap (bm);
822 }
823
824
825 void
826 draw_fringe_bitmap (w, row, left_p)
827 struct window *w;
828 struct glyph_row *row;
829 int left_p;
830 {
831 int overlay = 0;
832
833 if (!left_p && row->cursor_in_fringe_p)
834 {
835 Lisp_Object cursor = Qnil;
836
837 switch (w->phys_cursor_type)
838 {
839 case HOLLOW_BOX_CURSOR:
840 if (row->visible_height >= STANDARD_BITMAP_HEIGHT (hollow_rectangle_bits))
841 cursor = Qhollow;
842 else
843 cursor = Qhollow_small;
844 break;
845 case FILLED_BOX_CURSOR:
846 cursor = Qbox;
847 break;
848 case BAR_CURSOR:
849 cursor = Qbar;
850 break;
851 case HBAR_CURSOR:
852 cursor = Qhbar;
853 break;
854 case NO_CURSOR:
855 default:
856 w->phys_cursor_on_p = 0;
857 row->cursor_in_fringe_p = 0;
858 break;
859 }
860 if (!NILP (cursor))
861 {
862 int bm = get_logical_cursor_bitmap (w, cursor);
863 if (bm != NO_FRINGE_BITMAP)
864 {
865 draw_fringe_bitmap_1 (w, row, 0, 2, bm);
866 overlay = EQ (cursor, Qbox) ? 3 : 1;
867 }
868 }
869 }
870
871 draw_fringe_bitmap_1 (w, row, left_p, overlay, NO_FRINGE_BITMAP);
872
873 if (left_p && row->overlay_arrow_bitmap != NO_FRINGE_BITMAP)
874 draw_fringe_bitmap_1 (w, row, 1, 1, row->overlay_arrow_bitmap);
875 }
876
877
878 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
879 function with input blocked. */
880
881 void
882 draw_row_fringe_bitmaps (w, row)
883 struct window *w;
884 struct glyph_row *row;
885 {
886 xassert (interrupt_input_blocked);
887
888 /* If row is completely invisible, because of vscrolling, we
889 don't have to draw anything. */
890 if (row->visible_height <= 0)
891 return;
892
893 if (WINDOW_LEFT_FRINGE_WIDTH (w) != 0)
894 draw_fringe_bitmap (w, row, 1);
895
896 if (WINDOW_RIGHT_FRINGE_WIDTH (w) != 0)
897 draw_fringe_bitmap (w, row, 0);
898 }
899
900 /* Draw the fringes of window W. Only fringes for rows marked for
901 update in redraw_fringe_bitmaps_p are drawn.
902
903 Return >0 if left or right fringe was redrawn in any way.
904
905 If NO_FRINGE is non-zero, also return >0 if either fringe has zero width.
906
907 A return value >0 indicates that the vertical line between windows
908 needs update (as it may be drawn in the fringe).
909 */
910
911 int
912 draw_window_fringes (w, no_fringe)
913 struct window *w;
914 int no_fringe;
915 {
916 struct glyph_row *row;
917 int yb = window_text_bottom_y (w);
918 int nrows = w->current_matrix->nrows;
919 int y, rn;
920 int updated = 0;
921
922 if (w->pseudo_window_p)
923 return 0;
924
925 /* Must draw line if no fringe */
926 if (no_fringe
927 && (WINDOW_LEFT_FRINGE_WIDTH (w) == 0
928 || WINDOW_RIGHT_FRINGE_WIDTH (w) == 0))
929 updated++;
930
931 for (y = w->vscroll, rn = 0, row = w->current_matrix->rows;
932 y < yb && rn < nrows;
933 y += row->height, ++row, ++rn)
934 {
935 if (!row->redraw_fringe_bitmaps_p)
936 continue;
937 draw_row_fringe_bitmaps (w, row);
938 row->redraw_fringe_bitmaps_p = 0;
939 updated++;
940 }
941
942 return updated;
943 }
944
945
946 /* Recalculate the bitmaps to show in the fringes of window W.
947 Only mark rows with modified bitmaps for update in redraw_fringe_bitmaps_p.
948
949 If KEEP_CURRENT_P is 0, update current_matrix too. */
950
951 int
952 update_window_fringes (w, keep_current_p)
953 struct window *w;
954 int keep_current_p;
955 {
956 struct glyph_row *row, *cur = 0;
957 int yb = window_text_bottom_y (w);
958 int rn, nrows = w->current_matrix->nrows;
959 int y;
960 int redraw_p = 0;
961 Lisp_Object boundary_top = Qnil, boundary_bot = Qnil;
962 Lisp_Object arrow_top = Qnil, arrow_bot = Qnil;
963 Lisp_Object empty_pos;
964 Lisp_Object ind = Qnil;
965 #define MAX_BITMAP_CACHE (8*4)
966 int bitmap_cache[MAX_BITMAP_CACHE];
967 int top_ind_rn, bot_ind_rn;
968 int top_ind_min_y, bot_ind_max_y;
969 int top_row_ends_at_zv_p, bot_row_ends_at_zv_p;
970
971 if (w->pseudo_window_p)
972 return 0;
973
974 if (!MINI_WINDOW_P (w)
975 && (ind = XBUFFER (w->buffer)->indicate_buffer_boundaries, !NILP (ind)))
976 {
977 if (EQ (ind, Qleft) || EQ (ind, Qright))
978 boundary_top = boundary_bot = arrow_top = arrow_bot = ind;
979 else if (CONSP (ind) && CONSP (XCAR (ind)))
980 {
981 Lisp_Object pos;
982 if (pos = Fassq (Qt, ind), !NILP (pos))
983 boundary_top = boundary_bot = arrow_top = arrow_bot = XCDR (pos);
984 if (pos = Fassq (Qtop, ind), !NILP (pos))
985 boundary_top = XCDR (pos);
986 if (pos = Fassq (Qbottom, ind), !NILP (pos))
987 boundary_bot = XCDR (pos);
988 if (pos = Fassq (Qup, ind), !NILP (pos))
989 arrow_top = XCDR (pos);
990 if (pos = Fassq (Qdown, ind), !NILP (pos))
991 arrow_bot = XCDR (pos);
992 }
993 else
994 /* Anything else means boundary on left and no arrows. */
995 boundary_top = boundary_bot = Qleft;
996 }
997
998 top_ind_rn = bot_ind_rn = -1;
999 if (!NILP (ind))
1000 {
1001 for (y = w->vscroll, rn = 0;
1002 y < yb && rn < nrows;
1003 y += row->height, ++rn)
1004 {
1005 row = w->desired_matrix->rows + rn;
1006 if (!row->enabled_p)
1007 row = w->current_matrix->rows + rn;
1008
1009 row->indicate_bob_p = row->indicate_top_line_p = 0;
1010 row->indicate_eob_p = row->indicate_bottom_line_p = 0;
1011
1012 if (!row->mode_line_p)
1013 {
1014 if (top_ind_rn < 0 && row->visible_height > 0)
1015 {
1016 if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer))
1017 && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
1018 row->indicate_bob_p = !NILP (boundary_top);
1019 else
1020 row->indicate_top_line_p = !NILP (arrow_top);
1021 top_ind_rn = rn;
1022 }
1023
1024 if (bot_ind_rn < 0)
1025 {
1026 if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer))
1027 && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
1028 row->indicate_eob_p = !NILP (boundary_bot), bot_ind_rn = rn;
1029 else if (y + row->height >= yb)
1030 row->indicate_bottom_line_p = !NILP (arrow_bot), bot_ind_rn = rn;
1031 }
1032 }
1033 }
1034 }
1035
1036 empty_pos = XBUFFER (w->buffer)->indicate_empty_lines;
1037 if (!NILP (empty_pos) && !EQ (empty_pos, Qright))
1038 empty_pos = WINDOW_LEFT_FRINGE_WIDTH (w) == 0 ? Qright : Qleft;
1039
1040 for (y = 0; y < MAX_BITMAP_CACHE; y++)
1041 bitmap_cache[y] = -1;
1042
1043 #define LEFT_FRINGE(cache, which, partial_p) \
1044 (bitmap_cache[cache*4+partial_p] >= 0 \
1045 ? bitmap_cache[cache*4+partial_p] \
1046 : (bitmap_cache[cache*4+partial_p] = \
1047 get_logical_fringe_bitmap (w, which, 0, partial_p)))
1048
1049 #define RIGHT_FRINGE(cache, which, partial_p) \
1050 (bitmap_cache[cache*4+2+partial_p] >= 0 \
1051 ? bitmap_cache[cache*4+2+partial_p] \
1052 : (bitmap_cache[cache*4+2+partial_p] = \
1053 get_logical_fringe_bitmap (w, which, 1, partial_p)))
1054
1055
1056 /* Extend top-aligned top indicator (or bottom-aligned bottom
1057 indicator) to adjacent rows if it doesn't fit in one row. */
1058 top_ind_min_y = bot_ind_max_y = -1;
1059 if (top_ind_rn >= 0)
1060 {
1061 int bn = NO_FRINGE_BITMAP;
1062
1063 row = w->desired_matrix->rows + top_ind_rn;
1064 if (!row->enabled_p)
1065 row = w->current_matrix->rows + top_ind_rn;
1066
1067 top_row_ends_at_zv_p = row->ends_at_zv_p;
1068 if (row->indicate_bob_p)
1069 {
1070 if (EQ (boundary_top, Qleft))
1071 bn = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
1072 ? LEFT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p)
1073 : LEFT_FRINGE (2, Qtop, 0));
1074 else
1075 bn = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
1076 ? RIGHT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p)
1077 : RIGHT_FRINGE (2, Qtop, 0));
1078 }
1079 else if (row->indicate_top_line_p)
1080 {
1081 if (EQ (arrow_top, Qleft))
1082 bn = LEFT_FRINGE (6, Qup, 0);
1083 else
1084 bn = RIGHT_FRINGE (6, Qup, 0);
1085 }
1086
1087 if (bn != NO_FRINGE_BITMAP)
1088 {
1089 struct fringe_bitmap *fb = get_fringe_bitmap_data (bn);
1090
1091 if (fb->align == ALIGN_BITMAP_TOP && fb->period == 0)
1092 {
1093 struct glyph_row *row1;
1094 int top_ind_max_y;
1095
1096 top_ind_min_y = WINDOW_HEADER_LINE_HEIGHT (w);
1097 top_ind_max_y = top_ind_min_y + fb->height;
1098 if (top_ind_max_y > yb)
1099 top_ind_max_y = yb;
1100
1101 for (y = row->y + row->height, rn = top_ind_rn + 1;
1102 y < top_ind_max_y && rn < nrows;
1103 y += row1->height, rn++)
1104 {
1105 if (bot_ind_rn >= 0 && rn >= bot_ind_rn)
1106 break;
1107
1108 row1 = w->desired_matrix->rows + rn;
1109 if (!row1->enabled_p)
1110 row1 = w->current_matrix->rows + rn;
1111
1112 row1->indicate_bob_p = row->indicate_bob_p;
1113 row1->indicate_top_line_p = row->indicate_top_line_p;
1114 }
1115 }
1116 }
1117 }
1118 if (bot_ind_rn >= 0)
1119 {
1120 int bn = NO_FRINGE_BITMAP;
1121
1122 row = w->desired_matrix->rows + bot_ind_rn;
1123 if (!row->enabled_p)
1124 row = w->current_matrix->rows + bot_ind_rn;
1125
1126 bot_row_ends_at_zv_p = row->ends_at_zv_p;
1127 if (row->indicate_eob_p)
1128 {
1129 if (EQ (boundary_bot, Qleft))
1130 bn = LEFT_FRINGE (3, Qbottom, row->ends_at_zv_p);
1131 else
1132 bn = RIGHT_FRINGE (3, Qbottom, row->ends_at_zv_p);
1133 }
1134 else if (row->indicate_bottom_line_p)
1135 {
1136 if (EQ (arrow_bot, Qleft))
1137 bn = LEFT_FRINGE (7, Qdown, 0);
1138 else
1139 bn = RIGHT_FRINGE (7, Qdown, 0);
1140 }
1141
1142 if (bn != NO_FRINGE_BITMAP)
1143 {
1144 struct fringe_bitmap *fb = get_fringe_bitmap_data (bn);
1145
1146 if (fb->align == ALIGN_BITMAP_BOTTOM && fb->period == 0)
1147 {
1148 struct glyph_row *row1;
1149 int bot_ind_min_y;
1150
1151 bot_ind_max_y = row->y + row->visible_height;
1152 bot_ind_min_y = bot_ind_max_y - fb->height;
1153 if (bot_ind_min_y < WINDOW_HEADER_LINE_HEIGHT (w))
1154 bot_ind_min_y = WINDOW_HEADER_LINE_HEIGHT (w);
1155
1156 for (y = row->y, rn = bot_ind_rn - 1;
1157 y >= bot_ind_min_y && rn >= 0;
1158 y -= row1->height, rn--)
1159 {
1160 if (top_ind_rn >= 0 && rn <= top_ind_rn)
1161 break;
1162
1163 row1 = w->desired_matrix->rows + rn;
1164 if (!row1->enabled_p)
1165 row1 = w->current_matrix->rows + rn;
1166
1167 row1->indicate_eob_p = row->indicate_eob_p;
1168 row1->indicate_bottom_line_p = row->indicate_bottom_line_p;
1169 }
1170 }
1171 }
1172 }
1173
1174 for (y = w->vscroll, rn = 0;
1175 y < yb && rn < nrows;
1176 y += row->height, rn++)
1177 {
1178 int left, right;
1179 unsigned left_face_id, right_face_id;
1180 int left_offset, right_offset;
1181 int periodic_p;
1182
1183 row = w->desired_matrix->rows + rn;
1184 cur = w->current_matrix->rows + rn;
1185 if (!row->enabled_p)
1186 row = cur;
1187
1188 left_face_id = right_face_id = DEFAULT_FACE_ID;
1189 left_offset = right_offset = 0;
1190 periodic_p = 0;
1191
1192 /* Decide which bitmap to draw in the left fringe. */
1193 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
1194 left = NO_FRINGE_BITMAP;
1195 else if (row->left_user_fringe_bitmap != NO_FRINGE_BITMAP)
1196 {
1197 left = row->left_user_fringe_bitmap;
1198 left_face_id = row->left_user_fringe_face_id;
1199 }
1200 else if (row->truncated_on_left_p)
1201 left = LEFT_FRINGE(0, Qtruncation, 0);
1202 else if (row->indicate_bob_p && EQ (boundary_top, Qleft))
1203 {
1204 left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
1205 ? LEFT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p)
1206 : LEFT_FRINGE (2, Qtop, 0));
1207 if (top_ind_min_y >= 0)
1208 left_offset = top_ind_min_y - row->y;
1209 }
1210 else if (row->indicate_eob_p && EQ (boundary_bot, Qleft))
1211 {
1212 left = LEFT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p);
1213 if (bot_ind_max_y >= 0)
1214 left_offset = bot_ind_max_y - (row->y + row->visible_height);
1215 }
1216 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1217 left = LEFT_FRINGE (4, Qcontinuation, 0);
1218 else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft))
1219 left = LEFT_FRINGE (5, Qempty_line, 0);
1220 else if (row->indicate_top_line_p && EQ (arrow_top, Qleft))
1221 {
1222 left = LEFT_FRINGE (6, Qup, 0);
1223 if (top_ind_min_y >= 0)
1224 left_offset = top_ind_min_y - row->y;
1225 }
1226 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qleft))
1227 {
1228 left = LEFT_FRINGE (7, Qdown, 0);
1229 if (bot_ind_max_y >= 0)
1230 left_offset = bot_ind_max_y - (row->y + row->visible_height);
1231 }
1232 else
1233 left = NO_FRINGE_BITMAP;
1234
1235 /* Decide which bitmap to draw in the right fringe. */
1236 if (WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)
1237 right = NO_FRINGE_BITMAP;
1238 else if (row->right_user_fringe_bitmap != NO_FRINGE_BITMAP)
1239 {
1240 right = row->right_user_fringe_bitmap;
1241 right_face_id = row->right_user_fringe_face_id;
1242 }
1243 else if (row->truncated_on_right_p)
1244 right = RIGHT_FRINGE (0, Qtruncation, 0);
1245 else if (row->indicate_bob_p && EQ (boundary_top, Qright))
1246 {
1247 right = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
1248 ? RIGHT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p)
1249 : RIGHT_FRINGE (2, Qtop, 0));
1250 if (top_ind_min_y >= 0)
1251 right_offset = top_ind_min_y - row->y;
1252 }
1253 else if (row->indicate_eob_p && EQ (boundary_bot, Qright))
1254 {
1255 right = RIGHT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p);
1256 if (bot_ind_max_y >= 0)
1257 right_offset = bot_ind_max_y - (row->y + row->visible_height);
1258 }
1259 else if (row->continued_p)
1260 right = RIGHT_FRINGE (4, Qcontinuation, 0);
1261 else if (row->indicate_top_line_p && EQ (arrow_top, Qright))
1262 {
1263 right = RIGHT_FRINGE (6, Qup, 0);
1264 if (top_ind_min_y >= 0)
1265 right_offset = top_ind_min_y - row->y;
1266 }
1267 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright))
1268 {
1269 right = RIGHT_FRINGE (7, Qdown, 0);
1270 if (bot_ind_max_y >= 0)
1271 right_offset = bot_ind_max_y - (row->y + row->visible_height);
1272 }
1273 else if (row->indicate_empty_line_p && EQ (empty_pos, Qright))
1274 right = RIGHT_FRINGE (5, Qempty_line, 0);
1275 else
1276 right = NO_FRINGE_BITMAP;
1277
1278 periodic_p = (get_fringe_bitmap_data (left)->period != 0
1279 || get_fringe_bitmap_data (right)->period != 0);
1280
1281 if (row->y != cur->y
1282 || row->visible_height != cur->visible_height
1283 || row->ends_at_zv_p != cur->ends_at_zv_p
1284 || left != cur->left_fringe_bitmap
1285 || right != cur->right_fringe_bitmap
1286 || left_face_id != cur->left_fringe_face_id
1287 || right_face_id != cur->right_fringe_face_id
1288 || left_offset != cur->left_fringe_offset
1289 || right_offset != cur->right_fringe_offset
1290 || periodic_p != cur->fringe_bitmap_periodic_p
1291 || cur->redraw_fringe_bitmaps_p)
1292 {
1293 redraw_p = row->redraw_fringe_bitmaps_p = 1;
1294 if (!keep_current_p)
1295 {
1296 cur->redraw_fringe_bitmaps_p = 1;
1297 cur->left_fringe_bitmap = left;
1298 cur->right_fringe_bitmap = right;
1299 cur->left_fringe_face_id = left_face_id;
1300 cur->right_fringe_face_id = right_face_id;
1301 cur->left_fringe_offset = left_offset;
1302 cur->right_fringe_offset = right_offset;
1303 cur->fringe_bitmap_periodic_p = periodic_p;
1304 }
1305 }
1306
1307 if (row->overlay_arrow_bitmap < 0)
1308 row->overlay_arrow_bitmap = get_logical_fringe_bitmap (w, Qoverlay_arrow, 0, 0);
1309
1310 if (row->overlay_arrow_bitmap != cur->overlay_arrow_bitmap)
1311 {
1312 redraw_p = row->redraw_fringe_bitmaps_p = 1;
1313 if (!keep_current_p)
1314 {
1315 cur->redraw_fringe_bitmaps_p = 1;
1316 cur->overlay_arrow_bitmap = row->overlay_arrow_bitmap;
1317 }
1318 }
1319
1320 row->left_fringe_bitmap = left;
1321 row->right_fringe_bitmap = right;
1322 row->left_fringe_face_id = left_face_id;
1323 row->right_fringe_face_id = right_face_id;
1324 row->left_fringe_offset = left_offset;
1325 row->right_fringe_offset = right_offset;
1326 row->fringe_bitmap_periodic_p = periodic_p;
1327 }
1328
1329 return redraw_p && !keep_current_p;
1330 }
1331
1332
1333 /* Compute actual fringe widths for frame F.
1334
1335 If REDRAW is 1, redraw F if the fringe settings was actually
1336 modified and F is visible.
1337
1338 Since the combined left and right fringe must occupy an integral
1339 number of columns, we may need to add some pixels to each fringe.
1340 Typically, we add an equal amount (+/- 1 pixel) to each fringe,
1341 but a negative width value is taken literally (after negating it).
1342
1343 We never make the fringes narrower than specified.
1344 */
1345
1346 void
1347 compute_fringe_widths (f, redraw)
1348 struct frame *f;
1349 int redraw;
1350 {
1351 int o_left = FRAME_LEFT_FRINGE_WIDTH (f);
1352 int o_right = FRAME_RIGHT_FRINGE_WIDTH (f);
1353 int o_cols = FRAME_FRINGE_COLS (f);
1354
1355 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
1356 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
1357 int left_fringe_width, right_fringe_width;
1358
1359 if (!NILP (left_fringe))
1360 left_fringe = Fcdr (left_fringe);
1361 if (!NILP (right_fringe))
1362 right_fringe = Fcdr (right_fringe);
1363
1364 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
1365 XINT (left_fringe));
1366 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
1367 XINT (right_fringe));
1368
1369 if (left_fringe_width || right_fringe_width)
1370 {
1371 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
1372 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
1373 int conf_wid = left_wid + right_wid;
1374 int font_wid = FRAME_COLUMN_WIDTH (f);
1375 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
1376 int real_wid = cols * font_wid;
1377 if (left_wid && right_wid)
1378 {
1379 if (left_fringe_width < 0)
1380 {
1381 /* Left fringe width is fixed, adjust right fringe if necessary */
1382 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid;
1383 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid;
1384 }
1385 else if (right_fringe_width < 0)
1386 {
1387 /* Right fringe width is fixed, adjust left fringe if necessary */
1388 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
1389 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid;
1390 }
1391 else
1392 {
1393 /* Adjust both fringes with an equal amount.
1394 Note that we are doing integer arithmetic here, so don't
1395 lose a pixel if the total width is an odd number. */
1396 int fill = real_wid - conf_wid;
1397 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2;
1398 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2;
1399 }
1400 }
1401 else if (left_fringe_width)
1402 {
1403 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid;
1404 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
1405 }
1406 else
1407 {
1408 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
1409 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid;
1410 }
1411 FRAME_FRINGE_COLS (f) = cols;
1412 }
1413 else
1414 {
1415 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
1416 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
1417 FRAME_FRINGE_COLS (f) = 0;
1418 }
1419
1420 if (redraw && FRAME_VISIBLE_P (f))
1421 if (o_left != FRAME_LEFT_FRINGE_WIDTH (f) ||
1422 o_right != FRAME_RIGHT_FRINGE_WIDTH (f) ||
1423 o_cols != FRAME_FRINGE_COLS (f))
1424 redraw_frame (f);
1425 }
1426
1427
1428 /* Free resources used by a user-defined bitmap. */
1429
1430 void
1431 destroy_fringe_bitmap (n)
1432 int n;
1433 {
1434 struct fringe_bitmap **fbp;
1435
1436 fringe_faces[n] = Qnil;
1437
1438 fbp = &fringe_bitmaps[n];
1439 if (*fbp && (*fbp)->dynamic)
1440 {
1441 /* XXX Is SELECTED_FRAME OK here? */
1442 struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
1443 if (rif && rif->destroy_fringe_bitmap)
1444 rif->destroy_fringe_bitmap (n);
1445 xfree (*fbp);
1446 *fbp = NULL;
1447 }
1448
1449 while (max_used_fringe_bitmap > MAX_STANDARD_FRINGE_BITMAPS
1450 && fringe_bitmaps[max_used_fringe_bitmap - 1] == NULL)
1451 max_used_fringe_bitmap--;
1452 }
1453
1454
1455 DEFUN ("destroy-fringe-bitmap", Fdestroy_fringe_bitmap, Sdestroy_fringe_bitmap,
1456 1, 1, 0,
1457 doc: /* Destroy fringe bitmap BITMAP.
1458 If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. */)
1459 (bitmap)
1460 Lisp_Object bitmap;
1461 {
1462 int n;
1463
1464 CHECK_SYMBOL (bitmap);
1465 n = lookup_fringe_bitmap (bitmap);
1466 if (!n)
1467 return Qnil;
1468
1469 destroy_fringe_bitmap (n);
1470
1471 if (n >= MAX_STANDARD_FRINGE_BITMAPS)
1472 {
1473 Vfringe_bitmaps = Fdelq (bitmap, Vfringe_bitmaps);
1474 /* It would be better to remove the fringe property. */
1475 Fput (bitmap, Qfringe, Qnil);
1476 }
1477
1478 return Qnil;
1479 }
1480
1481
1482 /* Initialize bitmap bit.
1483
1484 On X, we bit-swap the built-in bitmaps and reduce bitmap
1485 from short to char array if width is <= 8 bits.
1486
1487 On MAC with big-endian CPU, we need to byte-swap each short.
1488
1489 On W32 and MAC (little endian), there's no need to do this.
1490 */
1491
1492 #if defined (HAVE_X_WINDOWS)
1493 static const unsigned char swap_nibble[16] = {
1494 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
1495 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
1496 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
1497 0x3, 0xb, 0x7, 0xf}; /* 0011 1011 0111 1111 */
1498 #endif /* HAVE_X_WINDOWS */
1499
1500 void
1501 init_fringe_bitmap (which, fb, once_p)
1502 int which;
1503 struct fringe_bitmap *fb;
1504 int once_p;
1505 {
1506 if (once_p || fb->dynamic)
1507 {
1508 #if defined (HAVE_X_WINDOWS)
1509 unsigned short *bits = fb->bits;
1510 int j;
1511
1512 if (fb->width <= 8)
1513 {
1514 unsigned char *cbits = (unsigned char *)fb->bits;
1515 for (j = 0; j < fb->height; j++)
1516 {
1517 unsigned short b = *bits++;
1518 unsigned char c;
1519 c = (unsigned char)((swap_nibble[b & 0xf] << 4)
1520 | (swap_nibble[(b>>4) & 0xf]));
1521 *cbits++ = (c >> (8 - fb->width));
1522 }
1523 }
1524 else
1525 {
1526 for (j = 0; j < fb->height; j++)
1527 {
1528 unsigned short b = *bits;
1529 b = (unsigned short)((swap_nibble[b & 0xf] << 12)
1530 | (swap_nibble[(b>>4) & 0xf] << 8)
1531 | (swap_nibble[(b>>8) & 0xf] << 4)
1532 | (swap_nibble[(b>>12) & 0xf]));
1533 b >>= (16 - fb->width);
1534 #ifdef WORDS_BIG_ENDIAN
1535 b = ((b >> 8) | (b << 8));
1536 #endif
1537 *bits++ = b;
1538 }
1539 }
1540 #endif /* HAVE_X_WINDOWS */
1541
1542 }
1543
1544 if (!once_p)
1545 {
1546 /* XXX Is SELECTED_FRAME OK here? */
1547 struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
1548
1549 destroy_fringe_bitmap (which);
1550
1551 if (rif && rif->define_fringe_bitmap)
1552 rif->define_fringe_bitmap (which, fb->bits, fb->height, fb->width);
1553
1554 fringe_bitmaps[which] = fb;
1555 if (which >= max_used_fringe_bitmap)
1556 max_used_fringe_bitmap = which + 1;
1557 }
1558 }
1559
1560
1561 DEFUN ("define-fringe-bitmap", Fdefine_fringe_bitmap, Sdefine_fringe_bitmap,
1562 2, 5, 0,
1563 doc: /* Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.
1564 BITMAP is a symbol identifying the new fringe bitmap.
1565 BITS is either a string or a vector of integers.
1566 HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.
1567 WIDTH must be an integer between 1 and 16, or nil which defaults to 8.
1568 Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
1569 indicating the positioning of the bitmap relative to the rows where it
1570 is used; the default is to center the bitmap. Fifth arg may also be a
1571 list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap
1572 should be repeated.
1573 If BITMAP already exists, the existing definition is replaced. */)
1574 (bitmap, bits, height, width, align)
1575 Lisp_Object bitmap, bits, height, width, align;
1576 {
1577 int n, h, i, j;
1578 unsigned short *b;
1579 struct fringe_bitmap fb, *xfb;
1580 int fill1 = 0, fill2 = 0;
1581
1582 CHECK_SYMBOL (bitmap);
1583
1584 if (STRINGP (bits))
1585 h = SCHARS (bits);
1586 else if (VECTORP (bits))
1587 h = XVECTOR_SIZE (bits);
1588 else
1589 wrong_type_argument (Qsequencep, bits);
1590
1591 if (NILP (height))
1592 fb.height = h;
1593 else
1594 {
1595 CHECK_NUMBER (height);
1596 fb.height = min (XINT (height), 255);
1597 if (fb.height > h)
1598 {
1599 fill1 = (fb.height - h) / 2;
1600 fill2 = fb.height - h - fill1;
1601 }
1602 }
1603
1604 if (NILP (width))
1605 fb.width = 8;
1606 else
1607 {
1608 CHECK_NUMBER (width);
1609 fb.width = min (XINT (width), 255);
1610 }
1611
1612 fb.period = 0;
1613 fb.align = ALIGN_BITMAP_CENTER;
1614
1615 if (CONSP (align))
1616 {
1617 Lisp_Object period = XCDR (align);
1618 if (CONSP (period))
1619 {
1620 period = XCAR (period);
1621 if (!NILP (period))
1622 {
1623 fb.period = fb.height;
1624 fb.height = 255;
1625 }
1626 }
1627 align = XCAR (align);
1628 }
1629 if (EQ (align, Qtop))
1630 fb.align = ALIGN_BITMAP_TOP;
1631 else if (EQ (align, Qbottom))
1632 fb.align = ALIGN_BITMAP_BOTTOM;
1633 else if (!NILP (align) && !EQ (align, Qcenter))
1634 error ("Bad align argument");
1635
1636 n = lookup_fringe_bitmap (bitmap);
1637 if (!n)
1638 {
1639 if (max_used_fringe_bitmap < max_fringe_bitmaps)
1640 n = max_used_fringe_bitmap++;
1641 else
1642 {
1643 for (n = MAX_STANDARD_FRINGE_BITMAPS;
1644 n < max_fringe_bitmaps;
1645 n++)
1646 if (fringe_bitmaps[n] == NULL)
1647 break;
1648
1649 if (n == max_fringe_bitmaps)
1650 {
1651 if ((max_fringe_bitmaps + 20) > MAX_FRINGE_BITMAPS)
1652 error ("No free fringe bitmap slots");
1653
1654 i = max_fringe_bitmaps;
1655 max_fringe_bitmaps += 20;
1656 fringe_bitmaps
1657 = ((struct fringe_bitmap **)
1658 xrealloc (fringe_bitmaps, max_fringe_bitmaps * sizeof (struct fringe_bitmap *)));
1659 fringe_faces
1660 = (Lisp_Object *) xrealloc (fringe_faces, max_fringe_bitmaps * sizeof (Lisp_Object));
1661
1662 for (; i < max_fringe_bitmaps; i++)
1663 {
1664 fringe_bitmaps[i] = NULL;
1665 fringe_faces[i] = Qnil;
1666 }
1667 }
1668 }
1669
1670 Vfringe_bitmaps = Fcons (bitmap, Vfringe_bitmaps);
1671 Fput (bitmap, Qfringe, make_number (n));
1672 }
1673
1674 fb.dynamic = 1;
1675
1676 xfb = (struct fringe_bitmap *) xmalloc (sizeof fb
1677 + fb.height * BYTES_PER_BITMAP_ROW);
1678 fb.bits = b = (unsigned short *) (xfb + 1);
1679 bzero (b, fb.height);
1680
1681 j = 0;
1682 while (j < fb.height)
1683 {
1684 for (i = 0; i < fill1 && j < fb.height; i++)
1685 b[j++] = 0;
1686 for (i = 0; i < h && j < fb.height; i++)
1687 {
1688 Lisp_Object elt = Faref (bits, make_number (i));
1689 b[j++] = NUMBERP (elt) ? XINT (elt) : 0;
1690 }
1691 for (i = 0; i < fill2 && j < fb.height; i++)
1692 b[j++] = 0;
1693 }
1694
1695 *xfb = fb;
1696
1697 init_fringe_bitmap (n, xfb, 0);
1698
1699 return bitmap;
1700 }
1701
1702 DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face, Sset_fringe_bitmap_face,
1703 1, 2, 0,
1704 doc: /* Set face for fringe bitmap BITMAP to FACE.
1705 If FACE is nil, reset face to default fringe face. */)
1706 (bitmap, face)
1707 Lisp_Object bitmap, face;
1708 {
1709 int n;
1710 int face_id;
1711
1712 CHECK_SYMBOL (bitmap);
1713 n = lookup_fringe_bitmap (bitmap);
1714 if (!n)
1715 error ("Undefined fringe bitmap");
1716
1717 if (!NILP (face))
1718 {
1719 face_id = lookup_derived_face (SELECTED_FRAME (), face,
1720 FRINGE_FACE_ID, 1);
1721 if (face_id < 0)
1722 error ("No such face");
1723 }
1724
1725 fringe_faces[n] = face;
1726
1727 return Qnil;
1728 }
1729
1730 DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos, Sfringe_bitmaps_at_pos,
1731 0, 2, 0,
1732 doc: /* Return fringe bitmaps of row containing position POS in window WINDOW.
1733 If WINDOW is nil, use selected window. If POS is nil, use value of point
1734 in that window. Return value is a list (LEFT RIGHT OV), where LEFT
1735 is the symbol for the bitmap in the left fringe (or nil if no bitmap),
1736 RIGHT is similar for the right fringe, and OV is non-nil if there is an
1737 overlay arrow in the left fringe.
1738 Return nil if POS is not visible in WINDOW. */)
1739 (pos, window)
1740 Lisp_Object pos, window;
1741 {
1742 struct window *w;
1743 struct glyph_row *row;
1744 int textpos;
1745
1746 if (NILP (window))
1747 window = selected_window;
1748 CHECK_WINDOW (window);
1749 w = XWINDOW (window);
1750
1751 if (!NILP (pos))
1752 {
1753 CHECK_NUMBER_COERCE_MARKER (pos);
1754 textpos = XINT (pos);
1755 }
1756 else if (w == XWINDOW (selected_window))
1757 textpos = PT;
1758 else
1759 textpos = XMARKER (w->pointm)->charpos;
1760
1761 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1762 row = row_containing_pos (w, textpos, row, NULL, 0);
1763 if (row)
1764 return list3 (get_fringe_bitmap_name (row->left_fringe_bitmap),
1765 get_fringe_bitmap_name (row->right_fringe_bitmap),
1766 (row->overlay_arrow_bitmap == 0 ? Qnil
1767 : row->overlay_arrow_bitmap < 0 ? Qt
1768 : get_fringe_bitmap_name (row->overlay_arrow_bitmap)));
1769 else
1770 return Qnil;
1771 }
1772
1773
1774 /***********************************************************************
1775 Initialization
1776 ***********************************************************************/
1777
1778 void
1779 syms_of_fringe ()
1780 {
1781 Qtruncation = intern_c_string ("truncation");
1782 staticpro (&Qtruncation);
1783 Qcontinuation = intern_c_string ("continuation");
1784 staticpro (&Qcontinuation);
1785 Qoverlay_arrow = intern_c_string ("overlay-arrow");
1786 staticpro (&Qoverlay_arrow);
1787 Qempty_line = intern_c_string ("empty-line");
1788 staticpro (&Qempty_line);
1789 Qtop_bottom = intern_c_string ("top-bottom");
1790 staticpro (&Qtop_bottom);
1791 Qhollow_small = intern_c_string ("hollow-small");
1792 staticpro (&Qhollow_small);
1793
1794 defsubr (&Sdestroy_fringe_bitmap);
1795 defsubr (&Sdefine_fringe_bitmap);
1796 defsubr (&Sfringe_bitmaps_at_pos);
1797 defsubr (&Sset_fringe_bitmap_face);
1798
1799 DEFVAR_LISP ("overflow-newline-into-fringe", &Voverflow_newline_into_fringe,
1800 doc: /* *Non-nil means that newline may flow into the right fringe.
1801 This means that display lines which are exactly as wide as the window
1802 (not counting the final newline) will only occupy one screen line, by
1803 showing (or hiding) the final newline in the right fringe; when point
1804 is at the final newline, the cursor is shown in the right fringe.
1805 If nil, also continue lines which are exactly as wide as the window. */);
1806 Voverflow_newline_into_fringe = Qt;
1807
1808 DEFVAR_LISP ("fringe-bitmaps", &Vfringe_bitmaps,
1809 doc: /* List of fringe bitmap symbols. */);
1810 Vfringe_bitmaps = Qnil;
1811 }
1812
1813 /* Garbage collection hook */
1814
1815 void
1816 mark_fringe_data ()
1817 {
1818 int i;
1819
1820 for (i = 0; i < max_fringe_bitmaps; i++)
1821 if (!NILP (fringe_faces[i]))
1822 mark_object (fringe_faces[i]);
1823 }
1824
1825 /* Initialize this module when Emacs starts. */
1826
1827 void
1828 init_fringe_once ()
1829 {
1830 int bt;
1831
1832 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1833 init_fringe_bitmap(bt, &standard_bitmaps[bt], 1);
1834 }
1835
1836 void
1837 init_fringe ()
1838 {
1839 int i;
1840
1841 max_fringe_bitmaps = MAX_STANDARD_FRINGE_BITMAPS + 20;
1842
1843 fringe_bitmaps
1844 = (struct fringe_bitmap **) xmalloc (max_fringe_bitmaps * sizeof (struct fringe_bitmap *));
1845 fringe_faces
1846 = (Lisp_Object *) xmalloc (max_fringe_bitmaps * sizeof (Lisp_Object));
1847
1848 for (i = 0; i < max_fringe_bitmaps; i++)
1849 {
1850 fringe_bitmaps[i] = NULL;
1851 fringe_faces[i] = Qnil;
1852 }
1853 }
1854
1855 #ifdef HAVE_NTGUI
1856
1857 void
1858 w32_init_fringe (struct redisplay_interface *rif)
1859 {
1860 int bt;
1861
1862 if (!rif)
1863 return;
1864
1865 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1866 {
1867 struct fringe_bitmap *fb = &standard_bitmaps[bt];
1868 rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
1869 }
1870 }
1871
1872 void
1873 w32_reset_fringes ()
1874 {
1875 /* Destroy row bitmaps. */
1876 int bt;
1877 struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
1878
1879 if (!rif)
1880 return;
1881
1882 for (bt = NO_FRINGE_BITMAP + 1; bt < max_used_fringe_bitmap; bt++)
1883 rif->destroy_fringe_bitmap (bt);
1884 }
1885
1886 #endif /* HAVE_NTGUI */
1887
1888 #endif /* HAVE_WINDOW_SYSTEM */
1889
1890 /* arch-tag: 04596920-43eb-473d-b319-82712338162d
1891 (do not change this comment) */