Add separator.pbm tool-bar image
[emacs.git] / src / fringe.c
blobfcc5207b0629d93b8ba6ede747a8d1f1dfad78f9
1 /* Fringe handling (split from xdisp.c).
2 Copyright (C) 1985-1988, 1993-1995, 1997-2015 Free Software
3 Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 #include <config.h>
21 #include <stdio.h>
23 #include <byteswap.h>
25 #include "lisp.h"
26 #include "frame.h"
27 #include "window.h"
28 #include "dispextern.h"
29 #include "character.h"
30 #include "buffer.h"
31 #include "blockinput.h"
32 #include "termhooks.h"
34 /* Fringe bitmaps are represented in three different ways:
36 Logical bitmaps are used internally to denote things like
37 'end-of-buffer', 'left-truncation', 'overlay-arrow', etc.
39 Physical bitmaps specify the visual appearance of the bitmap,
40 e.g. 'bottom-left-angle', 'left-arrow', 'left-triangle', etc.
41 User defined bitmaps are physical bitmaps.
43 Internally, fringe bitmaps for a specific display row are
44 represented as a simple integer that is used as an index
45 into the table of all defined bitmaps. This index is stored
46 in the `fringe' property of the physical bitmap symbol.
48 Logical bitmaps are mapped to physical bitmaps through the
49 buffer-local `fringe-indicator-alist' variable.
51 Each element of this alist is a cons (LOGICAL . PHYSICAL)
52 mapping a logical bitmap to a physical bitmap.
53 PHYSICAL is either a symbol to use in both left and right fringe,
54 or a cons of two symbols (LEFT . RIGHT) denoting different
55 bitmaps to use in left and right fringe.
57 LOGICAL is first looked up in the window's buffer's buffer-local
58 value of the fringe-indicator-alist variable, and if not present,
59 in the global value of fringe-indicator-alist.
61 If LOGICAL is not present in either alist, or the PHYSICAL value
62 found is nil, no bitmap is shown for the logical bitmap.
64 The `left-fringe' and `right-fringe' display properties
65 must specify physical bitmap symbols.
68 enum fringe_bitmap_align
70 ALIGN_BITMAP_CENTER = 0,
71 ALIGN_BITMAP_TOP,
72 ALIGN_BITMAP_BOTTOM
75 struct fringe_bitmap
77 unsigned short *bits;
78 unsigned height : 8;
79 unsigned width : 8;
80 unsigned period : 8;
81 unsigned align : 2;
82 bool_bf dynamic : 1;
86 /***********************************************************************
87 Fringe bitmaps
88 ***********************************************************************/
90 /* Undefined bitmap. A question mark. */
92 ..xxxx..
93 .xxxxxx.
94 xx....xx
95 xx....xx
96 ....xx..
97 ...xx...
98 ...xx...
99 ........
100 ...xx...
101 ...xx...
103 static unsigned short question_mark_bits[] = {
104 0x3c, 0x7e, 0x7e, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18};
106 /* An exclamation mark. */
108 ...XX...
109 ...XX...
110 ...XX...
111 ...XX...
112 ...XX...
113 ...XX...
114 ...XX...
115 ........
116 ...XX...
117 ...XX...
119 static unsigned short exclamation_mark_bits[] = {
120 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18};
122 /* An arrow like this: `<-'. */
124 ...xx...
125 ..xx....
126 .xx.....
127 xxxxxx..
128 xxxxxx..
129 .xx.....
130 ..xx....
131 ...xx...
133 static unsigned short left_arrow_bits[] = {
134 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
137 /* Right truncation arrow bitmap `->'. */
139 ...xx...
140 ....xx..
141 .....xx.
142 ..xxxxxx
143 ..xxxxxx
144 .....xx.
145 ....xx..
146 ...xx...
148 static unsigned short right_arrow_bits[] = {
149 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
152 /* Up arrow bitmap. */
154 ...xx...
155 ..xxxx..
156 .xxxxxx.
157 xxxxxxxx
158 ...xx...
159 ...xx...
160 ...xx...
161 ...xx...
163 static unsigned short up_arrow_bits[] = {
164 0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0x18};
167 /* Down arrow bitmap. */
169 ...xx...
170 ...xx...
171 ...xx...
172 ...xx...
173 xxxxxxxx
174 .xxxxxx.
175 ..xxxx..
176 ...xx...
178 static unsigned short down_arrow_bits[] = {
179 0x18, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18};
181 /* Marker for continuation lines. */
183 ..xxxx..
184 .xxxxx..
185 xx......
186 xxx..x..
187 xxxxxx..
188 .xxxxx..
189 ..xxxx..
190 .xxxxx..
192 static unsigned short left_curly_arrow_bits[] = {
193 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
195 /* Marker for continued lines. */
197 ..xxxx..
198 ..xxxxx.
199 ......xx
200 ..x..xxx
201 ..xxxxxx
202 ..xxxxx.
203 ..xxxx..
204 ..xxxxx.
206 static unsigned short right_curly_arrow_bits[] = {
207 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
209 /* Reverse Overlay arrow bitmap. A triangular arrow. */
211 ......xx
212 ....xxxx
213 ...xxxxx
214 ..xxxxxx
215 ..xxxxxx
216 ...xxxxx
217 ....xxxx
218 ......xx
220 static unsigned short left_triangle_bits[] = {
221 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
223 /* Overlay arrow bitmap. A triangular arrow. */
225 xx......
226 xxxx....
227 xxxxx...
228 xxxxxx..
229 xxxxxx..
230 xxxxx...
231 xxxx....
232 xx......
234 static unsigned short right_triangle_bits[] = {
235 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
237 /* First line bitmap. An top-left angle. */
239 xxxxxx..
240 xxxxxx..
241 xx......
242 xx......
243 xx......
244 xx......
245 xx......
246 ........
248 static unsigned short top_left_angle_bits[] = {
249 0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00};
251 /* First line bitmap. An right-up angle. */
253 ..xxxxxx
254 ..xxxxxx
255 ......xx
256 ......xx
257 ......xx
258 ......xx
259 ......xx
260 ........
262 static unsigned short top_right_angle_bits[] = {
263 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00};
265 /* Last line bitmap. An left-down angle. */
267 ........
268 xx......
269 xx......
270 xx......
271 xx......
272 xx......
273 xxxxxx..
274 xxxxxx..
276 static unsigned short bottom_left_angle_bits[] = {
277 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
279 /* Last line bitmap. An right-down angle. */
281 ........
282 ......xx
283 ......xx
284 ......xx
285 ......xx
286 ......xx
287 ..xxxxxx
288 ..xxxxxx
290 static unsigned short bottom_right_angle_bits[] = {
291 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
293 /* First/last line bitmap. An left bracket. */
295 xxxxxx..
296 xxxxxx..
297 xx......
298 xx......
299 xx......
300 xx......
301 xx......
302 xx......
303 xxxxxx..
304 xxxxxx..
306 static unsigned short left_bracket_bits[] = {
307 0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
309 /* First/last line bitmap. An right bracket. */
311 ..xxxxxx
312 ..xxxxxx
313 ......xx
314 ......xx
315 ......xx
316 ......xx
317 ......xx
318 ......xx
319 ..xxxxxx
320 ..xxxxxx
322 static unsigned short right_bracket_bits[] = {
323 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
325 /* Filled box cursor bitmap. A filled box; max 13 pixels high. */
327 xxxxxxx.
328 xxxxxxx.
329 xxxxxxx.
330 xxxxxxx.
331 xxxxxxx.
332 xxxxxxx.
333 xxxxxxx.
334 xxxxxxx.
335 xxxxxxx.
336 xxxxxxx.
337 xxxxxxx.
338 xxxxxxx.
339 xxxxxxx.
341 static unsigned short filled_rectangle_bits[] = {
342 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
344 /* Hollow box cursor bitmap. A hollow box; max 13 pixels high. */
346 xxxxxxx.
347 x.....x.
348 x.....x.
349 x.....x.
350 x.....x.
351 x.....x.
352 x.....x.
353 x.....x.
354 x.....x.
355 x.....x.
356 x.....x.
357 x.....x.
358 xxxxxxx.
360 static unsigned short hollow_rectangle_bits[] = {
361 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe};
363 /* Hollow square bitmap. */
365 .xxxxxx.
366 .x....x.
367 .x....x.
368 .x....x.
369 .x....x.
370 .xxxxxx.
372 static unsigned short hollow_square_bits[] = {
373 0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e};
375 /* Filled square bitmap. */
377 .xxxxxx.
378 .xxxxxx.
379 .xxxxxx.
380 .xxxxxx.
381 .xxxxxx.
382 .xxxxxx.
384 static unsigned short filled_square_bits[] = {
385 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e};
387 /* Bar cursor bitmap. A vertical bar; max 13 pixels high. */
389 xx......
390 xx......
391 xx......
392 xx......
393 xx......
394 xx......
395 xx......
396 xx......
397 xx......
398 xx......
399 xx......
400 xx......
401 xx......
403 static unsigned short vertical_bar_bits[] = {
404 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0};
406 /* HBar cursor bitmap. A horizontal bar; 2 pixels high. */
408 xxxxxxx.
409 xxxxxxx.
411 static unsigned short horizontal_bar_bits[] = {
412 0xfe, 0xfe};
415 /* Bitmap drawn to indicate lines not displaying text if
416 `indicate-empty-lines' is non-nil. */
418 ........
419 ..xxxx..
420 ........
421 ........
422 ..xxxx..
423 ........
425 static unsigned short empty_line_bits[] = {
426 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
427 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
428 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
429 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
430 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
431 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
432 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
433 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
436 #define BYTES_PER_BITMAP_ROW (sizeof (unsigned short))
437 #define STANDARD_BITMAP_HEIGHT(bits) (sizeof (bits)/BYTES_PER_BITMAP_ROW)
438 #define FRBITS(bits) bits, STANDARD_BITMAP_HEIGHT (bits)
440 /* NOTE: The order of these bitmaps must match the sequence
441 used in fringe.el to define the corresponding symbols. */
443 static struct fringe_bitmap standard_bitmaps[] =
445 { NULL, 0, 0, 0, 0, 0 }, /* NO_FRINGE_BITMAP */
446 { FRBITS (question_mark_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
447 { FRBITS (exclamation_mark_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
448 { FRBITS (left_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
449 { FRBITS (right_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
450 { FRBITS (up_arrow_bits), 8, 0, ALIGN_BITMAP_TOP, 0 },
451 { FRBITS (down_arrow_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
452 { FRBITS (left_curly_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
453 { FRBITS (right_curly_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
454 { FRBITS (left_triangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
455 { FRBITS (right_triangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
456 { FRBITS (top_left_angle_bits), 8, 0, ALIGN_BITMAP_TOP, 0 },
457 { FRBITS (top_right_angle_bits), 8, 0, ALIGN_BITMAP_TOP, 0 },
458 { FRBITS (bottom_left_angle_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
459 { FRBITS (bottom_right_angle_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
460 { FRBITS (left_bracket_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
461 { FRBITS (right_bracket_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
462 { FRBITS (filled_rectangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
463 { FRBITS (hollow_rectangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
464 { FRBITS (filled_square_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
465 { FRBITS (hollow_square_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
466 { FRBITS (vertical_bar_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
467 { FRBITS (horizontal_bar_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
468 { FRBITS (empty_line_bits), 8, 3, ALIGN_BITMAP_TOP, 0 },
471 #define NO_FRINGE_BITMAP 0
472 #define UNDEF_FRINGE_BITMAP 1
473 #define MAX_STANDARD_FRINGE_BITMAPS ARRAYELTS (standard_bitmaps)
475 static struct fringe_bitmap **fringe_bitmaps;
476 static Lisp_Object *fringe_faces;
477 static int max_fringe_bitmaps;
479 int max_used_fringe_bitmap = MAX_STANDARD_FRINGE_BITMAPS;
482 /* Lookup bitmap number for symbol BITMAP.
483 Return 0 if not a bitmap. */
486 lookup_fringe_bitmap (Lisp_Object bitmap)
488 EMACS_INT bn;
490 bitmap = Fget (bitmap, Qfringe);
491 if (!INTEGERP (bitmap))
492 return 0;
494 bn = XINT (bitmap);
495 if (bn > NO_FRINGE_BITMAP
496 && bn < max_used_fringe_bitmap
497 && (bn < MAX_STANDARD_FRINGE_BITMAPS
498 || fringe_bitmaps[bn] != NULL))
499 return bn;
501 return 0;
504 /* Get fringe bitmap name for bitmap number BN.
506 Found by traversing Vfringe_bitmaps comparing BN to the
507 fringe property for each symbol.
509 Return BN if not found in Vfringe_bitmaps. */
511 static Lisp_Object
512 get_fringe_bitmap_name (int bn)
514 Lisp_Object bitmaps;
515 Lisp_Object num;
517 /* Zero means no bitmap -- return nil. */
518 if (bn <= 0)
519 return Qnil;
521 bitmaps = Vfringe_bitmaps;
522 num = make_number (bn);
524 while (CONSP (bitmaps))
526 Lisp_Object bitmap = XCAR (bitmaps);
527 if (EQ (num, Fget (bitmap, Qfringe)))
528 return bitmap;
529 bitmaps = XCDR (bitmaps);
532 return num;
535 /* Get fringe bitmap data for bitmap number BN. */
537 static struct fringe_bitmap *
538 get_fringe_bitmap_data (int bn)
540 struct fringe_bitmap *fb;
542 fb = fringe_bitmaps[bn];
543 if (fb == NULL)
544 fb = &standard_bitmaps[bn < MAX_STANDARD_FRINGE_BITMAPS
545 ? bn : UNDEF_FRINGE_BITMAP];
547 return fb;
550 /* Draw the bitmap WHICH in one of the left or right fringes of
551 window W. ROW is the glyph row for which to display the bitmap; it
552 determines the vertical position at which the bitmap has to be
553 drawn.
554 LEFT_P is 1 for left fringe, 0 for right fringe.
557 static void
558 draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int overlay, int which)
560 struct frame *f = XFRAME (WINDOW_FRAME (w));
561 struct draw_fringe_bitmap_params p;
562 struct fringe_bitmap *fb;
563 int period;
564 int face_id = DEFAULT_FACE_ID;
565 int offset, header_line_height;
567 p.overlay_p = (overlay & 1) == 1;
568 p.cursor_p = (overlay & 2) == 2;
570 if (which != NO_FRINGE_BITMAP)
572 offset = 0;
574 else if (left_p)
576 which = row->left_fringe_bitmap;
577 face_id = row->left_fringe_face_id;
578 offset = row->left_fringe_offset;
580 else
582 which = row->right_fringe_bitmap;
583 face_id = row->right_fringe_face_id;
584 offset = row->right_fringe_offset;
587 if (face_id == DEFAULT_FACE_ID)
589 Lisp_Object face = fringe_faces[which];
590 face_id = NILP (face) ? lookup_named_face (f, Qfringe, false)
591 : lookup_derived_face (f, face, FRINGE_FACE_ID, 0);
592 if (face_id < 0)
593 face_id = FRINGE_FACE_ID;
596 fb = get_fringe_bitmap_data (which);
598 period = fb->period;
600 /* Convert row to frame coordinates. */
601 p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y) + offset;
603 p.which = which;
604 p.bits = fb->bits;
605 p.wd = fb->width;
607 p.h = fb->height;
608 p.dh = (period > 0 ? (p.y % period) : 0);
609 p.h -= p.dh;
611 /* Adjust y to the offset in the row to start drawing the bitmap. */
612 switch (fb->align)
614 case ALIGN_BITMAP_CENTER:
615 p.y += (row->height - p.h) / 2;
616 break;
617 case ALIGN_BITMAP_BOTTOM:
618 p.y += (row->visible_height - p.h);
619 break;
620 case ALIGN_BITMAP_TOP:
621 break;
624 p.face = FACE_FROM_ID (f, face_id);
626 if (p.face == NULL)
628 /* This could happen after clearing face cache.
629 But it shouldn't happen anymore. ++kfs */
630 return;
633 prepare_face_for_display (f, p.face);
635 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
636 the fringe. */
637 p.bx = -1;
638 header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
639 p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
640 p.ny = row->visible_height;
641 if (left_p)
643 int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
644 int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
645 ? LEFT_MARGIN_AREA
646 : TEXT_AREA));
647 if (p.wd > wd)
648 p.wd = wd;
649 p.x = x - p.wd - (wd - p.wd) / 2;
651 if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny)
653 /* If W has a vertical border to its left, don't draw over it. */
654 wd -= ((!WINDOW_LEFTMOST_P (w)
655 /* This could be wrong when we allow window local
656 right dividers - but the window on the left is hard
657 to get. */
658 && !FRAME_RIGHT_DIVIDER_WIDTH (f)
659 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
660 /* But don't reduce the fringe width if the window
661 has a left margin, because that means we are not
662 in danger of drawing over the vertical border,
663 and OTOH leaving out that one pixel leaves behind
664 traces of the cursor, if it was in column zero
665 before drawing non-empty margin area. */
666 && w->left_margin_cols == 0)
667 ? 1 : 0);
668 p.bx = x - wd;
669 p.nx = wd;
672 else
674 int x = window_box_right (w,
675 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
676 ? RIGHT_MARGIN_AREA
677 : TEXT_AREA));
678 int wd = WINDOW_RIGHT_FRINGE_WIDTH (w);
679 if (p.wd > wd)
680 p.wd = wd;
681 p.x = x + (wd - p.wd) / 2;
682 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
683 the fringe. */
684 if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny)
686 p.bx = x;
687 p.nx = wd;
691 if (p.x >= WINDOW_BOX_LEFT_EDGE_X (w)
692 && (p.x + p.wd) <= WINDOW_BOX_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w))
693 FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p);
696 static int
697 get_logical_cursor_bitmap (struct window *w, Lisp_Object cursor)
699 Lisp_Object cmap, bm = Qnil;
701 if ((cmap = BVAR (XBUFFER (w->contents), fringe_cursor_alist)), !NILP (cmap))
703 bm = Fassq (cursor, cmap);
704 if (CONSP (bm))
706 if ((bm = XCDR (bm)), NILP (bm))
707 return NO_FRINGE_BITMAP;
708 return lookup_fringe_bitmap (bm);
711 if (EQ (cmap, BVAR (&buffer_defaults, fringe_cursor_alist)))
712 return NO_FRINGE_BITMAP;
713 bm = Fassq (cursor, BVAR (&buffer_defaults, fringe_cursor_alist));
714 if (!CONSP (bm) || ((bm = XCDR (bm)), NILP (bm)))
715 return NO_FRINGE_BITMAP;
716 return lookup_fringe_bitmap (bm);
719 static int
720 get_logical_fringe_bitmap (struct window *w, Lisp_Object bitmap, int right_p, int partial_p)
722 Lisp_Object cmap, bm1 = Qnil, bm2 = Qnil, bm;
723 EMACS_INT ln1 = 0, ln2 = 0;
724 int ix1 = right_p;
725 int ix2 = ix1 + (partial_p ? 2 : 0);
727 /* Lookup in buffer-local fringe-indicator-alist before global alist.
729 Elements are:
730 BITMAP -- use for all
731 (L R) -- use for left right (whether partial or not)
732 (L R PL PR) -- use for left right partial-left partial-right
733 If any value in local binding is not present or t, use global value.
735 If partial, lookup partial bitmap in default value if not found here.
736 If not partial, or no partial spec is present, use non-partial bitmap. */
738 if ((cmap = BVAR (XBUFFER (w->contents), fringe_indicator_alist)), !NILP (cmap))
740 bm1 = Fassq (bitmap, cmap);
741 if (CONSP (bm1))
743 if ((bm1 = XCDR (bm1)), NILP (bm1))
744 return NO_FRINGE_BITMAP;
745 if (CONSP (bm1))
747 ln1 = XINT (Flength (bm1));
748 if (partial_p)
750 if (ln1 > ix2)
752 bm = Fnth (make_number (ix2), bm1);
753 if (!EQ (bm, Qt))
754 goto found;
757 else
759 if (ln1 > ix1)
761 bm = Fnth (make_number (ix1), bm1);
762 if (!EQ (bm, Qt))
763 goto found;
767 else if ((bm = bm1, !EQ (bm, Qt)))
768 goto found;
772 if (!EQ (cmap, BVAR (&buffer_defaults, fringe_indicator_alist))
773 && !NILP (BVAR (&buffer_defaults, fringe_indicator_alist)))
775 bm2 = Fassq (bitmap, BVAR (&buffer_defaults, fringe_indicator_alist));
776 if (CONSP (bm2))
778 if ((bm2 = XCDR (bm2)), !NILP (bm2))
780 if (CONSP (bm2))
782 ln2 = XINT (Flength (bm2));
783 if (partial_p)
785 if (ln2 > ix2)
787 bm = Fnth (make_number (ix2), bm2);
788 if (!EQ (bm, Qt))
789 goto found;
797 if (ln1 > ix1)
799 bm = Fnth (make_number (ix1), bm1);
800 if (!EQ (bm, Qt))
801 goto found;
804 if (ln2 > ix1)
806 bm = Fnth (make_number (ix1), bm2);
807 if (!EQ (bm, Qt))
808 goto found;
809 return NO_FRINGE_BITMAP;
811 else if ((bm = bm2, NILP (bm)))
812 return NO_FRINGE_BITMAP;
814 found:
815 return lookup_fringe_bitmap (bm);
819 void
820 draw_fringe_bitmap (struct window *w, struct glyph_row *row, int left_p)
822 int overlay = 0;
824 if (left_p == row->reversed_p && row->cursor_in_fringe_p)
826 Lisp_Object cursor = Qnil;
828 switch (w->phys_cursor_type)
830 case HOLLOW_BOX_CURSOR:
831 if (row->visible_height >= STANDARD_BITMAP_HEIGHT (hollow_rectangle_bits))
832 cursor = Qhollow;
833 else
834 cursor = Qhollow_small;
835 break;
836 case FILLED_BOX_CURSOR:
837 cursor = Qbox;
838 break;
839 case BAR_CURSOR:
840 cursor = Qbar;
841 break;
842 case HBAR_CURSOR:
843 cursor = Qhbar;
844 break;
845 case NO_CURSOR:
846 default:
847 w->phys_cursor_on_p = 0;
848 row->cursor_in_fringe_p = 0;
849 break;
851 if (!NILP (cursor))
853 int bm = get_logical_cursor_bitmap (w, cursor);
854 if (bm != NO_FRINGE_BITMAP)
856 draw_fringe_bitmap_1 (w, row, left_p, 2, bm);
857 overlay = EQ (cursor, Qbox) ? 3 : 1;
862 draw_fringe_bitmap_1 (w, row, left_p, overlay, NO_FRINGE_BITMAP);
864 if (left_p && row->overlay_arrow_bitmap != NO_FRINGE_BITMAP)
865 draw_fringe_bitmap_1 (w, row, 1, 1, row->overlay_arrow_bitmap);
869 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
870 function with input blocked. */
872 void
873 draw_row_fringe_bitmaps (struct window *w, struct glyph_row *row)
875 eassert (input_blocked_p ());
877 /* If row is completely invisible, because of vscrolling, we
878 don't have to draw anything. */
879 if (row->visible_height <= 0)
880 return;
882 if (WINDOW_LEFT_FRINGE_WIDTH (w) != 0)
883 draw_fringe_bitmap (w, row, 1);
885 if (WINDOW_RIGHT_FRINGE_WIDTH (w) != 0)
886 draw_fringe_bitmap (w, row, 0);
889 /* Draw the fringes of window W. Only fringes for rows marked for
890 update in redraw_fringe_bitmaps_p are drawn.
892 Return nonzero if left or right fringe was redrawn in any way.
894 If NO_FRINGE_P is non-zero, also return nonzero if either fringe
895 has zero width.
897 A return nonzero value indicates that the vertical line between
898 windows needs update (as it may be drawn in the fringe).
901 bool
902 draw_window_fringes (struct window *w, bool no_fringe_p)
904 struct glyph_row *row;
905 int yb = window_text_bottom_y (w);
906 int nrows = w->current_matrix->nrows;
907 int y, rn;
908 bool updated_p = 0;
910 if (w->pseudo_window_p)
911 return updated_p;
913 /* Must draw line if no fringe */
914 if (no_fringe_p
915 && (WINDOW_LEFT_FRINGE_WIDTH (w) == 0
916 || WINDOW_RIGHT_FRINGE_WIDTH (w) == 0))
917 updated_p = 1;
919 for (y = w->vscroll, rn = 0, row = w->current_matrix->rows;
920 y < yb && rn < nrows;
921 y += row->height, ++row, ++rn)
923 if (!row->redraw_fringe_bitmaps_p)
924 continue;
925 draw_row_fringe_bitmaps (w, row);
926 row->redraw_fringe_bitmaps_p = 0;
927 updated_p = 1;
930 return updated_p;
934 /* Recalculate the bitmaps to show in the fringes of window W.
935 Only mark rows with modified bitmaps for update in redraw_fringe_bitmaps_p.
937 If KEEP_CURRENT_P is 0, update current_matrix too. */
939 bool
940 update_window_fringes (struct window *w, bool keep_current_p)
942 struct glyph_row *row, *cur = 0;
943 int yb = window_text_bottom_y (w);
944 int rn, nrows = w->current_matrix->nrows;
945 int y;
946 bool redraw_p = 0;
947 Lisp_Object boundary_top = Qnil, boundary_bot = Qnil;
948 Lisp_Object arrow_top = Qnil, arrow_bot = Qnil;
949 Lisp_Object empty_pos;
950 Lisp_Object ind = Qnil;
951 #define MAX_BITMAP_CACHE (8*4)
952 int bitmap_cache[MAX_BITMAP_CACHE];
953 int top_ind_rn, bot_ind_rn;
954 int top_ind_min_y, bot_ind_max_y;
956 /* top_ind_rn is set to a nonnegative value whenever
957 row->indicate_bob_p is set, so it's OK that top_row_ends_at_zv_p
958 is not initialized here. Similarly for bot_ind_rn,
959 row->indicate_eob_p and bot_row_ends_at_zv_p. */
960 int top_row_ends_at_zv_p IF_LINT (= 0), bot_row_ends_at_zv_p IF_LINT (= 0);
962 if (w->pseudo_window_p)
963 return 0;
965 if (!MINI_WINDOW_P (w)
966 && (ind = BVAR (XBUFFER (w->contents), indicate_buffer_boundaries), !NILP (ind)))
968 if (EQ (ind, Qleft) || EQ (ind, Qright))
969 boundary_top = boundary_bot = arrow_top = arrow_bot = ind;
970 else if (CONSP (ind) && CONSP (XCAR (ind)))
972 Lisp_Object pos;
973 if (pos = Fassq (Qt, ind), !NILP (pos))
974 boundary_top = boundary_bot = arrow_top = arrow_bot = XCDR (pos);
975 if (pos = Fassq (Qtop, ind), !NILP (pos))
976 boundary_top = XCDR (pos);
977 if (pos = Fassq (Qbottom, ind), !NILP (pos))
978 boundary_bot = XCDR (pos);
979 if (pos = Fassq (Qup, ind), !NILP (pos))
980 arrow_top = XCDR (pos);
981 if (pos = Fassq (Qdown, ind), !NILP (pos))
982 arrow_bot = XCDR (pos);
984 else
985 /* Anything else means boundary on left and no arrows. */
986 boundary_top = boundary_bot = Qleft;
989 top_ind_rn = bot_ind_rn = -1;
990 if (!NILP (ind))
992 for (y = w->vscroll, rn = 0;
993 y < yb && rn < nrows;
994 y += row->height, ++rn)
996 row = w->desired_matrix->rows + rn;
997 if (!row->enabled_p)
998 row = w->current_matrix->rows + rn;
1000 row->indicate_bob_p = row->indicate_top_line_p = 0;
1001 row->indicate_eob_p = row->indicate_bottom_line_p = 0;
1003 if (!row->mode_line_p)
1005 if (top_ind_rn < 0 && row->visible_height > 0)
1007 if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->contents))
1008 && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
1009 row->indicate_bob_p = !NILP (boundary_top);
1010 else
1011 row->indicate_top_line_p = !NILP (arrow_top);
1012 top_ind_rn = rn;
1015 if (bot_ind_rn < 0)
1017 if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->contents))
1018 && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
1019 row->indicate_eob_p = !NILP (boundary_bot), bot_ind_rn = rn;
1020 else if (y + row->height >= yb)
1021 row->indicate_bottom_line_p = !NILP (arrow_bot), bot_ind_rn = rn;
1027 empty_pos = BVAR (XBUFFER (w->contents), indicate_empty_lines);
1028 if (!NILP (empty_pos) && !EQ (empty_pos, Qright))
1029 empty_pos = WINDOW_LEFT_FRINGE_WIDTH (w) == 0 ? Qright : Qleft;
1031 for (y = 0; y < MAX_BITMAP_CACHE; y++)
1032 bitmap_cache[y] = -1;
1034 #define LEFT_FRINGE(cache, which, partial_p) \
1035 (bitmap_cache[cache*4+partial_p] >= 0 \
1036 ? bitmap_cache[cache*4+partial_p] \
1037 : (bitmap_cache[cache*4+partial_p] = \
1038 get_logical_fringe_bitmap (w, which, 0, partial_p)))
1040 #define RIGHT_FRINGE(cache, which, partial_p) \
1041 (bitmap_cache[cache*4+2+partial_p] >= 0 \
1042 ? bitmap_cache[cache*4+2+partial_p] \
1043 : (bitmap_cache[cache*4+2+partial_p] = \
1044 get_logical_fringe_bitmap (w, which, 1, partial_p)))
1047 /* Extend top-aligned top indicator (or bottom-aligned bottom
1048 indicator) to adjacent rows if it doesn't fit in one row. */
1049 top_ind_min_y = bot_ind_max_y = -1;
1050 if (top_ind_rn >= 0)
1052 int bn = NO_FRINGE_BITMAP;
1054 row = w->desired_matrix->rows + top_ind_rn;
1055 if (!row->enabled_p)
1056 row = w->current_matrix->rows + top_ind_rn;
1058 top_row_ends_at_zv_p = row->ends_at_zv_p;
1059 if (row->indicate_bob_p)
1061 if (EQ (boundary_top, Qleft))
1062 bn = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
1063 ? LEFT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p)
1064 : LEFT_FRINGE (2, Qtop, 0));
1065 else
1066 bn = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
1067 ? RIGHT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p)
1068 : RIGHT_FRINGE (2, Qtop, 0));
1070 else if (row->indicate_top_line_p)
1072 if (EQ (arrow_top, Qleft))
1073 bn = LEFT_FRINGE (6, Qup, 0);
1074 else
1075 bn = RIGHT_FRINGE (6, Qup, 0);
1078 if (bn != NO_FRINGE_BITMAP)
1080 struct fringe_bitmap *fb = get_fringe_bitmap_data (bn);
1082 if (fb->align == ALIGN_BITMAP_TOP && fb->period == 0)
1084 struct glyph_row *row1;
1085 int top_ind_max_y;
1087 top_ind_min_y = WINDOW_HEADER_LINE_HEIGHT (w);
1088 top_ind_max_y = top_ind_min_y + fb->height;
1089 if (top_ind_max_y > yb)
1090 top_ind_max_y = yb;
1092 for (y = row->y + row->height, rn = top_ind_rn + 1;
1093 y < top_ind_max_y && rn < nrows;
1094 y += row1->height, rn++)
1096 if (bot_ind_rn >= 0 && rn >= bot_ind_rn)
1097 break;
1099 row1 = w->desired_matrix->rows + rn;
1100 if (!row1->enabled_p)
1101 row1 = w->current_matrix->rows + rn;
1103 row1->indicate_bob_p = row->indicate_bob_p;
1104 row1->indicate_top_line_p = row->indicate_top_line_p;
1109 if (bot_ind_rn >= 0)
1111 int bn = NO_FRINGE_BITMAP;
1113 row = w->desired_matrix->rows + bot_ind_rn;
1114 if (!row->enabled_p)
1115 row = w->current_matrix->rows + bot_ind_rn;
1117 bot_row_ends_at_zv_p = row->ends_at_zv_p;
1118 if (row->indicate_eob_p)
1120 if (EQ (boundary_bot, Qleft))
1121 bn = LEFT_FRINGE (3, Qbottom, row->ends_at_zv_p);
1122 else
1123 bn = RIGHT_FRINGE (3, Qbottom, row->ends_at_zv_p);
1125 else if (row->indicate_bottom_line_p)
1127 if (EQ (arrow_bot, Qleft))
1128 bn = LEFT_FRINGE (7, Qdown, 0);
1129 else
1130 bn = RIGHT_FRINGE (7, Qdown, 0);
1133 if (bn != NO_FRINGE_BITMAP)
1135 struct fringe_bitmap *fb = get_fringe_bitmap_data (bn);
1137 if (fb->align == ALIGN_BITMAP_BOTTOM && fb->period == 0)
1139 struct glyph_row *row1;
1140 int bot_ind_min_y;
1142 bot_ind_max_y = row->y + row->visible_height;
1143 bot_ind_min_y = bot_ind_max_y - fb->height;
1144 if (bot_ind_min_y < WINDOW_HEADER_LINE_HEIGHT (w))
1145 bot_ind_min_y = WINDOW_HEADER_LINE_HEIGHT (w);
1147 for (y = row->y, rn = bot_ind_rn - 1;
1148 y >= bot_ind_min_y && rn >= 0;
1149 y -= row1->height, rn--)
1151 if (top_ind_rn >= 0 && rn <= top_ind_rn)
1152 break;
1154 row1 = w->desired_matrix->rows + rn;
1155 if (!row1->enabled_p)
1156 row1 = w->current_matrix->rows + rn;
1158 row1->indicate_eob_p = row->indicate_eob_p;
1159 row1->indicate_bottom_line_p = row->indicate_bottom_line_p;
1165 for (y = w->vscroll, rn = 0;
1166 y < yb && rn < nrows;
1167 y += row->height, rn++)
1169 int left, right;
1170 unsigned left_face_id, right_face_id;
1171 int left_offset, right_offset;
1172 bool periodic_p;
1174 row = w->desired_matrix->rows + rn;
1175 cur = w->current_matrix->rows + rn;
1176 if (!row->enabled_p)
1177 row = cur;
1179 left_face_id = right_face_id = DEFAULT_FACE_ID;
1180 left_offset = right_offset = 0;
1181 periodic_p = 0;
1183 /* Decide which bitmap to draw in the left fringe. */
1184 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
1185 left = NO_FRINGE_BITMAP;
1186 else if (row->left_user_fringe_bitmap != NO_FRINGE_BITMAP)
1188 left = row->left_user_fringe_bitmap;
1189 left_face_id = row->left_user_fringe_face_id;
1191 else if ((!row->reversed_p && row->truncated_on_left_p)
1192 || (row->reversed_p && row->truncated_on_right_p))
1193 left = LEFT_FRINGE (0, Qtruncation, 0);
1194 else if (row->indicate_bob_p && EQ (boundary_top, Qleft))
1196 left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
1197 ? LEFT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p)
1198 : LEFT_FRINGE (2, Qtop, 0));
1199 if (top_ind_min_y >= 0)
1200 left_offset = top_ind_min_y - row->y;
1202 else if (row->indicate_eob_p && EQ (boundary_bot, Qleft))
1204 left = LEFT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p);
1205 if (bot_ind_max_y >= 0)
1206 left_offset = bot_ind_max_y - (row->y + row->visible_height);
1208 else if ((!row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row))
1209 || (row->reversed_p && row->continued_p))
1210 left = LEFT_FRINGE (4, Qcontinuation, 0);
1211 else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft))
1212 left = LEFT_FRINGE (5, Qempty_line, 0);
1213 else if (row->indicate_top_line_p && EQ (arrow_top, Qleft))
1215 left = LEFT_FRINGE (6, Qup, 0);
1216 if (top_ind_min_y >= 0)
1217 left_offset = top_ind_min_y - row->y;
1219 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qleft))
1221 left = LEFT_FRINGE (7, Qdown, 0);
1222 if (bot_ind_max_y >= 0)
1223 left_offset = bot_ind_max_y - (row->y + row->visible_height);
1225 else
1226 left = NO_FRINGE_BITMAP;
1228 /* Decide which bitmap to draw in the right fringe. */
1229 if (WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)
1230 right = NO_FRINGE_BITMAP;
1231 else if (row->right_user_fringe_bitmap != NO_FRINGE_BITMAP)
1233 right = row->right_user_fringe_bitmap;
1234 right_face_id = row->right_user_fringe_face_id;
1236 else if ((!row->reversed_p && row->truncated_on_right_p)
1237 || (row->reversed_p && row->truncated_on_left_p))
1238 right = RIGHT_FRINGE (0, Qtruncation, 0);
1239 else if (row->indicate_bob_p && EQ (boundary_top, Qright))
1241 right = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
1242 ? RIGHT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p)
1243 : RIGHT_FRINGE (2, Qtop, 0));
1244 if (top_ind_min_y >= 0)
1245 right_offset = top_ind_min_y - row->y;
1247 else if (row->indicate_eob_p && EQ (boundary_bot, Qright))
1249 right = RIGHT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p);
1250 if (bot_ind_max_y >= 0)
1251 right_offset = bot_ind_max_y - (row->y + row->visible_height);
1253 else if ((!row->reversed_p && row->continued_p)
1254 || (row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row)))
1255 right = RIGHT_FRINGE (4, Qcontinuation, 0);
1256 else if (row->indicate_top_line_p && EQ (arrow_top, Qright))
1258 right = RIGHT_FRINGE (6, Qup, 0);
1259 if (top_ind_min_y >= 0)
1260 right_offset = top_ind_min_y - row->y;
1262 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright))
1264 right = RIGHT_FRINGE (7, Qdown, 0);
1265 if (bot_ind_max_y >= 0)
1266 right_offset = bot_ind_max_y - (row->y + row->visible_height);
1268 else if (row->indicate_empty_line_p && EQ (empty_pos, Qright))
1269 right = RIGHT_FRINGE (5, Qempty_line, 0);
1270 else
1271 right = NO_FRINGE_BITMAP;
1273 periodic_p = (get_fringe_bitmap_data (left)->period != 0
1274 || get_fringe_bitmap_data (right)->period != 0);
1276 if (row->y != cur->y
1277 || row->visible_height != cur->visible_height
1278 || row->ends_at_zv_p != cur->ends_at_zv_p
1279 || left != cur->left_fringe_bitmap
1280 || right != cur->right_fringe_bitmap
1281 || left_face_id != cur->left_fringe_face_id
1282 || right_face_id != cur->right_fringe_face_id
1283 || left_offset != cur->left_fringe_offset
1284 || right_offset != cur->right_fringe_offset
1285 || periodic_p != cur->fringe_bitmap_periodic_p
1286 || cur->redraw_fringe_bitmaps_p)
1288 redraw_p = 1, row->redraw_fringe_bitmaps_p = 1;
1289 if (!keep_current_p)
1291 cur->redraw_fringe_bitmaps_p = 1;
1292 cur->left_fringe_bitmap = left;
1293 cur->right_fringe_bitmap = right;
1294 cur->left_fringe_face_id = left_face_id;
1295 cur->right_fringe_face_id = right_face_id;
1296 cur->left_fringe_offset = left_offset;
1297 cur->right_fringe_offset = right_offset;
1298 cur->fringe_bitmap_periodic_p = periodic_p;
1302 if (row->overlay_arrow_bitmap < 0)
1303 row->overlay_arrow_bitmap = get_logical_fringe_bitmap (w, Qoverlay_arrow, 0, 0);
1305 if (row->overlay_arrow_bitmap != cur->overlay_arrow_bitmap)
1307 redraw_p = 1, row->redraw_fringe_bitmaps_p = 1;
1308 if (!keep_current_p)
1310 cur->redraw_fringe_bitmaps_p = 1;
1311 cur->overlay_arrow_bitmap = row->overlay_arrow_bitmap;
1315 row->left_fringe_bitmap = left;
1316 row->right_fringe_bitmap = right;
1317 row->left_fringe_face_id = left_face_id;
1318 row->right_fringe_face_id = right_face_id;
1319 row->left_fringe_offset = left_offset;
1320 row->right_fringe_offset = right_offset;
1321 row->fringe_bitmap_periodic_p = periodic_p;
1324 return redraw_p && !keep_current_p;
1329 /* Free resources used by a user-defined bitmap. */
1331 static void
1332 destroy_fringe_bitmap (int n)
1334 struct fringe_bitmap **fbp;
1336 fringe_faces[n] = Qnil;
1338 fbp = &fringe_bitmaps[n];
1339 if (*fbp && (*fbp)->dynamic)
1341 /* XXX Is SELECTED_FRAME OK here? */
1342 struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
1343 if (rif && rif->destroy_fringe_bitmap)
1344 rif->destroy_fringe_bitmap (n);
1345 xfree (*fbp);
1346 *fbp = NULL;
1349 while (max_used_fringe_bitmap > MAX_STANDARD_FRINGE_BITMAPS
1350 && fringe_bitmaps[max_used_fringe_bitmap - 1] == NULL)
1351 max_used_fringe_bitmap--;
1355 DEFUN ("destroy-fringe-bitmap", Fdestroy_fringe_bitmap, Sdestroy_fringe_bitmap,
1356 1, 1, 0,
1357 doc: /* Destroy fringe bitmap BITMAP.
1358 If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. */)
1359 (Lisp_Object bitmap)
1361 int n;
1363 CHECK_SYMBOL (bitmap);
1364 n = lookup_fringe_bitmap (bitmap);
1365 if (!n)
1366 return Qnil;
1368 destroy_fringe_bitmap (n);
1370 if (n >= MAX_STANDARD_FRINGE_BITMAPS)
1372 Vfringe_bitmaps = Fdelq (bitmap, Vfringe_bitmaps);
1373 /* It would be better to remove the fringe property. */
1374 Fput (bitmap, Qfringe, Qnil);
1377 return Qnil;
1381 /* Initialize bitmap bit.
1383 On X, we bit-swap the built-in bitmaps and reduce bitmap
1384 from short to char array if width is <= 8 bits.
1386 On MAC with big-endian CPU, we need to byte-swap each short.
1388 On W32 and MAC (little endian), there's no need to do this.
1391 #if defined (HAVE_X_WINDOWS)
1392 static const unsigned char swap_nibble[16] = {
1393 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
1394 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
1395 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
1396 0x3, 0xb, 0x7, 0xf}; /* 0011 1011 0111 1111 */
1397 #endif /* HAVE_X_WINDOWS */
1399 static void
1400 init_fringe_bitmap (int which, struct fringe_bitmap *fb, int once_p)
1402 if (once_p || fb->dynamic)
1404 #if defined (HAVE_X_WINDOWS)
1405 unsigned short *bits = fb->bits;
1406 int j;
1408 #ifdef USE_CAIRO
1409 for (j = 0; j < fb->height; j++)
1411 unsigned short b = *bits;
1412 #ifdef WORDS_BIGENDIAN
1413 *bits++ = (b << (16 - fb->width));
1414 #else
1415 b = (unsigned short)((swap_nibble[b & 0xf] << 12)
1416 | (swap_nibble[(b>>4) & 0xf] << 8)
1417 | (swap_nibble[(b>>8) & 0xf] << 4)
1418 | (swap_nibble[(b>>12) & 0xf]));
1419 *bits++ = (b >> (16 - fb->width));
1420 #endif
1422 #else /* not USE_CAIRO */
1423 if (fb->width <= 8)
1425 unsigned char *cbits = (unsigned char *)fb->bits;
1426 for (j = 0; j < fb->height; j++)
1428 unsigned short b = *bits++;
1429 unsigned char c;
1430 c = (unsigned char)((swap_nibble[b & 0xf] << 4)
1431 | (swap_nibble[(b>>4) & 0xf]));
1432 *cbits++ = (c >> (8 - fb->width));
1435 else
1437 for (j = 0; j < fb->height; j++)
1439 unsigned short b = *bits;
1440 b = (unsigned short)((swap_nibble[b & 0xf] << 12)
1441 | (swap_nibble[(b>>4) & 0xf] << 8)
1442 | (swap_nibble[(b>>8) & 0xf] << 4)
1443 | (swap_nibble[(b>>12) & 0xf]));
1444 b >>= (16 - fb->width);
1445 #ifdef WORDS_BIGENDIAN
1446 b = bswap_16 (b);
1447 #endif
1448 *bits++ = b;
1451 #endif /* not USE_CAIRO */
1452 #endif /* HAVE_X_WINDOWS */
1456 if (!once_p)
1458 /* XXX Is SELECTED_FRAME OK here? */
1459 struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
1461 destroy_fringe_bitmap (which);
1463 if (rif && rif->define_fringe_bitmap)
1464 rif->define_fringe_bitmap (which, fb->bits, fb->height, fb->width);
1466 fringe_bitmaps[which] = fb;
1467 if (which >= max_used_fringe_bitmap)
1468 max_used_fringe_bitmap = which + 1;
1473 DEFUN ("define-fringe-bitmap", Fdefine_fringe_bitmap, Sdefine_fringe_bitmap,
1474 2, 5, 0,
1475 doc: /* Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.
1476 BITMAP is a symbol identifying the new fringe bitmap.
1477 BITS is either a string or a vector of integers.
1478 HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.
1479 WIDTH must be an integer between 1 and 16, or nil which defaults to 8.
1480 Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
1481 indicating the positioning of the bitmap relative to the rows where it
1482 is used; the default is to center the bitmap. Fifth arg may also be a
1483 list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap
1484 should be repeated.
1485 If BITMAP already exists, the existing definition is replaced. */)
1486 (Lisp_Object bitmap, Lisp_Object bits, Lisp_Object height, Lisp_Object width, Lisp_Object align)
1488 int n, h, i, j;
1489 unsigned short *b;
1490 struct fringe_bitmap fb, *xfb;
1491 int fill1 = 0, fill2 = 0;
1493 CHECK_SYMBOL (bitmap);
1494 h = CHECK_VECTOR_OR_STRING (bits);
1496 if (NILP (height))
1497 fb.height = h;
1498 else
1500 CHECK_NUMBER (height);
1501 fb.height = max (0, min (XINT (height), 255));
1502 if (fb.height > h)
1504 fill1 = (fb.height - h) / 2;
1505 fill2 = fb.height - h - fill1;
1509 if (NILP (width))
1510 fb.width = 8;
1511 else
1513 CHECK_NUMBER (width);
1514 fb.width = max (0, min (XINT (width), 255));
1517 fb.period = 0;
1518 fb.align = ALIGN_BITMAP_CENTER;
1520 if (CONSP (align))
1522 Lisp_Object period = XCDR (align);
1523 if (CONSP (period))
1525 period = XCAR (period);
1526 if (!NILP (period))
1528 fb.period = fb.height;
1529 fb.height = 255;
1532 align = XCAR (align);
1534 if (EQ (align, Qtop))
1535 fb.align = ALIGN_BITMAP_TOP;
1536 else if (EQ (align, Qbottom))
1537 fb.align = ALIGN_BITMAP_BOTTOM;
1538 else if (!NILP (align) && !EQ (align, Qcenter))
1539 error ("Bad align argument");
1541 n = lookup_fringe_bitmap (bitmap);
1542 if (!n)
1544 if (max_used_fringe_bitmap < max_fringe_bitmaps)
1545 n = max_used_fringe_bitmap++;
1546 else
1548 for (n = MAX_STANDARD_FRINGE_BITMAPS;
1549 n < max_fringe_bitmaps;
1550 n++)
1551 if (fringe_bitmaps[n] == NULL)
1552 break;
1554 if (n == max_fringe_bitmaps)
1556 int bitmaps = max_fringe_bitmaps + 20;
1557 if (MAX_FRINGE_BITMAPS < bitmaps)
1558 error ("No free fringe bitmap slots");
1560 i = max_fringe_bitmaps;
1561 fringe_bitmaps = xrealloc (fringe_bitmaps,
1562 bitmaps * sizeof *fringe_bitmaps);
1563 fringe_faces = xrealloc (fringe_faces,
1564 bitmaps * sizeof *fringe_faces);
1566 for (i = max_fringe_bitmaps; i < bitmaps; i++)
1568 fringe_bitmaps[i] = NULL;
1569 fringe_faces[i] = Qnil;
1572 max_fringe_bitmaps = bitmaps;
1576 Vfringe_bitmaps = Fcons (bitmap, Vfringe_bitmaps);
1577 Fput (bitmap, Qfringe, make_number (n));
1580 fb.dynamic = true;
1582 xfb = xmalloc (sizeof fb + fb.height * BYTES_PER_BITMAP_ROW);
1583 fb.bits = b = (unsigned short *) (xfb + 1);
1584 memset (b, 0, fb.height);
1586 j = 0;
1587 while (j < fb.height)
1589 for (i = 0; i < fill1 && j < fb.height; i++)
1590 b[j++] = 0;
1591 for (i = 0; i < h && j < fb.height; i++)
1593 Lisp_Object elt = Faref (bits, make_number (i));
1594 b[j++] = NUMBERP (elt) ? XINT (elt) : 0;
1596 for (i = 0; i < fill2 && j < fb.height; i++)
1597 b[j++] = 0;
1600 *xfb = fb;
1602 init_fringe_bitmap (n, xfb, 0);
1604 return bitmap;
1607 DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face, Sset_fringe_bitmap_face,
1608 1, 2, 0,
1609 doc: /* Set face for fringe bitmap BITMAP to FACE.
1610 FACE is merged with the `fringe' face, so normally FACE should specify
1611 only the foreground color.
1612 If FACE is nil, reset face to default fringe face. */)
1613 (Lisp_Object bitmap, Lisp_Object face)
1615 int n;
1617 CHECK_SYMBOL (bitmap);
1618 n = lookup_fringe_bitmap (bitmap);
1619 if (!n)
1620 error ("Undefined fringe bitmap");
1622 /* The purpose of the following code is to signal an error if FACE
1623 is not a face. This is for the caller's convenience only; the
1624 redisplay code should be able to fail gracefully. Skip the check
1625 if FRINGE_FACE_ID is unrealized (as in batch mode and during
1626 daemon startup). */
1627 if (!NILP (face))
1629 struct frame *f = SELECTED_FRAME ();
1631 if (FACE_FROM_ID (f, FRINGE_FACE_ID)
1632 && lookup_derived_face (f, face, FRINGE_FACE_ID, 1) < 0)
1633 error ("No such face");
1636 fringe_faces[n] = face;
1637 return Qnil;
1640 DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos, Sfringe_bitmaps_at_pos,
1641 0, 2, 0,
1642 doc: /* Return fringe bitmaps of row containing position POS in window WINDOW.
1643 If WINDOW is nil, use selected window. If POS is nil, use value of point
1644 in that window. Return value is a list (LEFT RIGHT OV), where LEFT
1645 is the symbol for the bitmap in the left fringe (or nil if no bitmap),
1646 RIGHT is similar for the right fringe, and OV is non-nil if there is an
1647 overlay arrow in the left fringe.
1648 Return nil if POS is not visible in WINDOW. */)
1649 (Lisp_Object pos, Lisp_Object window)
1651 struct window *w;
1652 struct glyph_row *row;
1653 ptrdiff_t textpos;
1655 w = decode_any_window (window);
1656 XSETWINDOW (window, w);
1658 if (!NILP (pos))
1660 CHECK_NUMBER_COERCE_MARKER (pos);
1661 if (! (BEGV <= XINT (pos) && XINT (pos) <= ZV))
1662 args_out_of_range (window, pos);
1663 textpos = XINT (pos);
1665 else if (w == XWINDOW (selected_window))
1666 textpos = PT;
1667 else
1668 textpos = marker_position (w->pointm);
1670 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1671 row = row_containing_pos (w, textpos, row, NULL, 0);
1672 if (row)
1673 return list3 (get_fringe_bitmap_name (row->left_fringe_bitmap),
1674 get_fringe_bitmap_name (row->right_fringe_bitmap),
1675 (row->overlay_arrow_bitmap == 0 ? Qnil
1676 : row->overlay_arrow_bitmap < 0 ? Qt
1677 : get_fringe_bitmap_name (row->overlay_arrow_bitmap)));
1678 else
1679 return Qnil;
1683 /***********************************************************************
1684 Initialization
1685 ***********************************************************************/
1687 void
1688 syms_of_fringe (void)
1690 DEFSYM (Qtruncation, "truncation");
1691 DEFSYM (Qcontinuation, "continuation");
1692 DEFSYM (Qoverlay_arrow, "overlay-arrow");
1693 DEFSYM (Qempty_line, "empty-line");
1694 DEFSYM (Qtop_bottom, "top-bottom");
1695 DEFSYM (Qhollow_small, "hollow-small");
1697 defsubr (&Sdestroy_fringe_bitmap);
1698 defsubr (&Sdefine_fringe_bitmap);
1699 defsubr (&Sfringe_bitmaps_at_pos);
1700 defsubr (&Sset_fringe_bitmap_face);
1702 DEFVAR_LISP ("overflow-newline-into-fringe", Voverflow_newline_into_fringe,
1703 doc: /* Non-nil means that newline may flow into the right fringe.
1704 This means that display lines which are exactly as wide as the window
1705 (not counting the final newline) will only occupy one screen line, by
1706 showing (or hiding) the final newline in the right fringe; when point
1707 is at the final newline, the cursor is shown in the right fringe.
1708 If nil, also continue lines which are exactly as wide as the window. */);
1709 Voverflow_newline_into_fringe = Qt;
1711 DEFVAR_LISP ("fringe-bitmaps", Vfringe_bitmaps,
1712 doc: /* List of fringe bitmap symbols. */);
1713 Vfringe_bitmaps = Qnil;
1716 /* Garbage collection hook */
1718 void
1719 mark_fringe_data (void)
1721 int i;
1723 for (i = 0; i < max_fringe_bitmaps; i++)
1724 if (!NILP (fringe_faces[i]))
1725 mark_object (fringe_faces[i]);
1728 /* Initialize this module when Emacs starts. */
1730 void
1731 init_fringe_once (void)
1733 int bt;
1735 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1736 init_fringe_bitmap (bt, &standard_bitmaps[bt], 1);
1739 void
1740 init_fringe (void)
1742 max_fringe_bitmaps = MAX_STANDARD_FRINGE_BITMAPS + 20;
1744 fringe_bitmaps = xzalloc (max_fringe_bitmaps * sizeof *fringe_bitmaps);
1746 verify (NIL_IS_ZERO);
1747 fringe_faces = xzalloc (max_fringe_bitmaps * sizeof *fringe_faces);
1750 #if defined (HAVE_NTGUI) || defined (USE_CAIRO)
1752 void
1753 #ifdef HAVE_NTGUI
1754 w32_init_fringe (struct redisplay_interface *rif)
1755 #else
1756 x_cr_init_fringe (struct redisplay_interface *rif)
1757 #endif
1759 int bt;
1761 if (!rif)
1762 return;
1764 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1766 struct fringe_bitmap *fb = &standard_bitmaps[bt];
1767 rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
1770 #endif
1772 #ifdef HAVE_NTGUI
1773 void
1774 w32_reset_fringes (void)
1776 /* Destroy row bitmaps. */
1777 int bt;
1778 struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
1780 if (!rif)
1781 return;
1783 for (bt = NO_FRINGE_BITMAP + 1; bt < max_used_fringe_bitmap; bt++)
1784 rif->destroy_fringe_bitmap (bt);
1787 #endif /* HAVE_NTGUI */