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