cl-lib.el: Partial revert of "2015-04-05 Rationalize c[ad]+r"
[emacs.git] / src / fringe.c
blob5e5ec60a48f63147fb45d974a91b35f17e4139f9
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 if (fb->width <= 8)
1410 unsigned char *cbits = (unsigned char *)fb->bits;
1411 for (j = 0; j < fb->height; j++)
1413 unsigned short b = *bits++;
1414 unsigned char c;
1415 c = (unsigned char)((swap_nibble[b & 0xf] << 4)
1416 | (swap_nibble[(b>>4) & 0xf]));
1417 *cbits++ = (c >> (8 - fb->width));
1420 else
1422 for (j = 0; j < fb->height; j++)
1424 unsigned short b = *bits;
1425 b = (unsigned short)((swap_nibble[b & 0xf] << 12)
1426 | (swap_nibble[(b>>4) & 0xf] << 8)
1427 | (swap_nibble[(b>>8) & 0xf] << 4)
1428 | (swap_nibble[(b>>12) & 0xf]));
1429 b >>= (16 - fb->width);
1430 #ifdef WORDS_BIGENDIAN
1431 b = bswap_16 (b);
1432 #endif
1433 *bits++ = b;
1436 #endif /* HAVE_X_WINDOWS */
1440 if (!once_p)
1442 /* XXX Is SELECTED_FRAME OK here? */
1443 struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
1445 destroy_fringe_bitmap (which);
1447 if (rif && rif->define_fringe_bitmap)
1448 rif->define_fringe_bitmap (which, fb->bits, fb->height, fb->width);
1450 fringe_bitmaps[which] = fb;
1451 if (which >= max_used_fringe_bitmap)
1452 max_used_fringe_bitmap = which + 1;
1457 DEFUN ("define-fringe-bitmap", Fdefine_fringe_bitmap, Sdefine_fringe_bitmap,
1458 2, 5, 0,
1459 doc: /* Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.
1460 BITMAP is a symbol identifying the new fringe bitmap.
1461 BITS is either a string or a vector of integers.
1462 HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.
1463 WIDTH must be an integer between 1 and 16, or nil which defaults to 8.
1464 Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
1465 indicating the positioning of the bitmap relative to the rows where it
1466 is used; the default is to center the bitmap. Fifth arg may also be a
1467 list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap
1468 should be repeated.
1469 If BITMAP already exists, the existing definition is replaced. */)
1470 (Lisp_Object bitmap, Lisp_Object bits, Lisp_Object height, Lisp_Object width, Lisp_Object align)
1472 int n, h, i, j;
1473 unsigned short *b;
1474 struct fringe_bitmap fb, *xfb;
1475 int fill1 = 0, fill2 = 0;
1477 CHECK_SYMBOL (bitmap);
1478 h = CHECK_VECTOR_OR_STRING (bits);
1480 if (NILP (height))
1481 fb.height = h;
1482 else
1484 CHECK_NUMBER (height);
1485 fb.height = max (0, min (XINT (height), 255));
1486 if (fb.height > h)
1488 fill1 = (fb.height - h) / 2;
1489 fill2 = fb.height - h - fill1;
1493 if (NILP (width))
1494 fb.width = 8;
1495 else
1497 CHECK_NUMBER (width);
1498 fb.width = max (0, min (XINT (width), 255));
1501 fb.period = 0;
1502 fb.align = ALIGN_BITMAP_CENTER;
1504 if (CONSP (align))
1506 Lisp_Object period = XCDR (align);
1507 if (CONSP (period))
1509 period = XCAR (period);
1510 if (!NILP (period))
1512 fb.period = fb.height;
1513 fb.height = 255;
1516 align = XCAR (align);
1518 if (EQ (align, Qtop))
1519 fb.align = ALIGN_BITMAP_TOP;
1520 else if (EQ (align, Qbottom))
1521 fb.align = ALIGN_BITMAP_BOTTOM;
1522 else if (!NILP (align) && !EQ (align, Qcenter))
1523 error ("Bad align argument");
1525 n = lookup_fringe_bitmap (bitmap);
1526 if (!n)
1528 if (max_used_fringe_bitmap < max_fringe_bitmaps)
1529 n = max_used_fringe_bitmap++;
1530 else
1532 for (n = MAX_STANDARD_FRINGE_BITMAPS;
1533 n < max_fringe_bitmaps;
1534 n++)
1535 if (fringe_bitmaps[n] == NULL)
1536 break;
1538 if (n == max_fringe_bitmaps)
1540 int bitmaps = max_fringe_bitmaps + 20;
1541 if (MAX_FRINGE_BITMAPS < bitmaps)
1542 error ("No free fringe bitmap slots");
1544 i = max_fringe_bitmaps;
1545 fringe_bitmaps = xrealloc (fringe_bitmaps,
1546 bitmaps * sizeof *fringe_bitmaps);
1547 fringe_faces = xrealloc (fringe_faces,
1548 bitmaps * sizeof *fringe_faces);
1550 for (i = max_fringe_bitmaps; i < bitmaps; i++)
1552 fringe_bitmaps[i] = NULL;
1553 fringe_faces[i] = Qnil;
1556 max_fringe_bitmaps = bitmaps;
1560 Vfringe_bitmaps = Fcons (bitmap, Vfringe_bitmaps);
1561 Fput (bitmap, Qfringe, make_number (n));
1564 fb.dynamic = true;
1566 xfb = xmalloc (sizeof fb + fb.height * BYTES_PER_BITMAP_ROW);
1567 fb.bits = b = (unsigned short *) (xfb + 1);
1568 memset (b, 0, fb.height);
1570 j = 0;
1571 while (j < fb.height)
1573 for (i = 0; i < fill1 && j < fb.height; i++)
1574 b[j++] = 0;
1575 for (i = 0; i < h && j < fb.height; i++)
1577 Lisp_Object elt = Faref (bits, make_number (i));
1578 b[j++] = NUMBERP (elt) ? XINT (elt) : 0;
1580 for (i = 0; i < fill2 && j < fb.height; i++)
1581 b[j++] = 0;
1584 *xfb = fb;
1586 init_fringe_bitmap (n, xfb, 0);
1588 return bitmap;
1591 DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face, Sset_fringe_bitmap_face,
1592 1, 2, 0,
1593 doc: /* Set face for fringe bitmap BITMAP to FACE.
1594 FACE is merged with the `fringe' face, so normally FACE should specify
1595 only the foreground color.
1596 If FACE is nil, reset face to default fringe face. */)
1597 (Lisp_Object bitmap, Lisp_Object face)
1599 int n;
1601 CHECK_SYMBOL (bitmap);
1602 n = lookup_fringe_bitmap (bitmap);
1603 if (!n)
1604 error ("Undefined fringe bitmap");
1606 /* The purpose of the following code is to signal an error if FACE
1607 is not a face. This is for the caller's convenience only; the
1608 redisplay code should be able to fail gracefully. Skip the check
1609 if FRINGE_FACE_ID is unrealized (as in batch mode and during
1610 daemon startup). */
1611 if (!NILP (face))
1613 struct frame *f = SELECTED_FRAME ();
1615 if (FACE_FROM_ID (f, FRINGE_FACE_ID)
1616 && lookup_derived_face (f, face, FRINGE_FACE_ID, 1) < 0)
1617 error ("No such face");
1620 fringe_faces[n] = face;
1621 return Qnil;
1624 DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos, Sfringe_bitmaps_at_pos,
1625 0, 2, 0,
1626 doc: /* Return fringe bitmaps of row containing position POS in window WINDOW.
1627 If WINDOW is nil, use selected window. If POS is nil, use value of point
1628 in that window. Return value is a list (LEFT RIGHT OV), where LEFT
1629 is the symbol for the bitmap in the left fringe (or nil if no bitmap),
1630 RIGHT is similar for the right fringe, and OV is non-nil if there is an
1631 overlay arrow in the left fringe.
1632 Return nil if POS is not visible in WINDOW. */)
1633 (Lisp_Object pos, Lisp_Object window)
1635 struct window *w;
1636 struct glyph_row *row;
1637 ptrdiff_t textpos;
1639 w = decode_any_window (window);
1640 XSETWINDOW (window, w);
1642 if (!NILP (pos))
1644 CHECK_NUMBER_COERCE_MARKER (pos);
1645 if (! (BEGV <= XINT (pos) && XINT (pos) <= ZV))
1646 args_out_of_range (window, pos);
1647 textpos = XINT (pos);
1649 else if (w == XWINDOW (selected_window))
1650 textpos = PT;
1651 else
1652 textpos = marker_position (w->pointm);
1654 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1655 row = row_containing_pos (w, textpos, row, NULL, 0);
1656 if (row)
1657 return list3 (get_fringe_bitmap_name (row->left_fringe_bitmap),
1658 get_fringe_bitmap_name (row->right_fringe_bitmap),
1659 (row->overlay_arrow_bitmap == 0 ? Qnil
1660 : row->overlay_arrow_bitmap < 0 ? Qt
1661 : get_fringe_bitmap_name (row->overlay_arrow_bitmap)));
1662 else
1663 return Qnil;
1667 /***********************************************************************
1668 Initialization
1669 ***********************************************************************/
1671 void
1672 syms_of_fringe (void)
1674 DEFSYM (Qtruncation, "truncation");
1675 DEFSYM (Qcontinuation, "continuation");
1676 DEFSYM (Qoverlay_arrow, "overlay-arrow");
1677 DEFSYM (Qempty_line, "empty-line");
1678 DEFSYM (Qtop_bottom, "top-bottom");
1679 DEFSYM (Qhollow_small, "hollow-small");
1681 defsubr (&Sdestroy_fringe_bitmap);
1682 defsubr (&Sdefine_fringe_bitmap);
1683 defsubr (&Sfringe_bitmaps_at_pos);
1684 defsubr (&Sset_fringe_bitmap_face);
1686 DEFVAR_LISP ("overflow-newline-into-fringe", Voverflow_newline_into_fringe,
1687 doc: /* Non-nil means that newline may flow into the right fringe.
1688 This means that display lines which are exactly as wide as the window
1689 (not counting the final newline) will only occupy one screen line, by
1690 showing (or hiding) the final newline in the right fringe; when point
1691 is at the final newline, the cursor is shown in the right fringe.
1692 If nil, also continue lines which are exactly as wide as the window. */);
1693 Voverflow_newline_into_fringe = Qt;
1695 DEFVAR_LISP ("fringe-bitmaps", Vfringe_bitmaps,
1696 doc: /* List of fringe bitmap symbols. */);
1697 Vfringe_bitmaps = Qnil;
1700 /* Garbage collection hook */
1702 void
1703 mark_fringe_data (void)
1705 int i;
1707 for (i = 0; i < max_fringe_bitmaps; i++)
1708 if (!NILP (fringe_faces[i]))
1709 mark_object (fringe_faces[i]);
1712 /* Initialize this module when Emacs starts. */
1714 void
1715 init_fringe_once (void)
1717 int bt;
1719 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1720 init_fringe_bitmap (bt, &standard_bitmaps[bt], 1);
1723 void
1724 init_fringe (void)
1726 max_fringe_bitmaps = MAX_STANDARD_FRINGE_BITMAPS + 20;
1728 fringe_bitmaps = xzalloc (max_fringe_bitmaps * sizeof *fringe_bitmaps);
1730 verify (NIL_IS_ZERO);
1731 fringe_faces = xzalloc (max_fringe_bitmaps * sizeof *fringe_faces);
1734 #ifdef HAVE_NTGUI
1736 void
1737 w32_init_fringe (struct redisplay_interface *rif)
1739 int bt;
1741 if (!rif)
1742 return;
1744 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1746 struct fringe_bitmap *fb = &standard_bitmaps[bt];
1747 rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
1751 void
1752 w32_reset_fringes (void)
1754 /* Destroy row bitmaps. */
1755 int bt;
1756 struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
1758 if (!rif)
1759 return;
1761 for (bt = NO_FRINGE_BITMAP + 1; bt < max_used_fringe_bitmap; bt++)
1762 rif->destroy_fringe_bitmap (bt);
1765 #endif /* HAVE_NTGUI */