Merge changes made in Gnus trunk
[emacs.git] / src / fringe.c
blob5285d09dfb0957f16f1722633f5bbc7c1df0084d
1 /* Fringe handling (split from xdisp.c).
2 Copyright (C) 1985-1988, 1993-1995, 1997-2012 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19 #include <config.h>
20 #include <stdio.h>
21 #include <setjmp.h>
23 #include "lisp.h"
24 #include "frame.h"
25 #include "window.h"
26 #include "dispextern.h"
27 #include "buffer.h"
28 #include "blockinput.h"
29 #include "termhooks.h"
31 #ifdef HAVE_WINDOW_SYSTEM
33 /* Fringe bitmaps are represented in three different ways:
35 Logical bitmaps are used internally to denote things like
36 'end-of-buffer', 'left-truncation', 'overlay-arrow', etc.
38 Physical bitmaps specify the visual appearance of the bitmap,
39 e.g. 'bottom-left-angle', 'left-arrow', 'left-triangle', etc.
40 User defined bitmaps are physical bitmaps.
42 Internally, fringe bitmaps for a specific display row are
43 represented as a simple integer that is used as an index
44 into the table of all defined bitmaps. This index is stored
45 in the `fringe' property of the physical bitmap symbol.
47 Logical bitmaps are mapped to physical bitmaps through the
48 buffer-local `fringe-indicator-alist' variable.
50 Each element of this alist is a cons (LOGICAL . PHYSICAL)
51 mapping a logical bitmap to a physical bitmap.
52 PHYSICAL is either a symbol to use in both left and right fringe,
53 or a cons of two symbols (LEFT . RIGHT) denoting different
54 bitmaps to use in left and right fringe.
56 LOGICAL is first looked up in the window's buffer's buffer-local
57 value of the fringe-indicator-alist variable, and if not present,
58 in the global value of fringe-indicator-alist.
60 If LOGICAL is not present in either alist, or the PHYSICAL value
61 found is nil, no bitmap is shown for the logical bitmap.
63 The `left-fringe' and `right-fringe' display properties
64 must specify physical bitmap symbols.
67 static Lisp_Object Qtruncation, Qcontinuation, Qoverlay_arrow;
68 static Lisp_Object Qempty_line, Qtop_bottom;
69 static Lisp_Object Qhollow_small;
71 enum fringe_bitmap_align
73 ALIGN_BITMAP_CENTER = 0,
74 ALIGN_BITMAP_TOP,
75 ALIGN_BITMAP_BOTTOM
78 struct fringe_bitmap
80 unsigned short *bits;
81 unsigned height : 8;
82 unsigned width : 8;
83 unsigned period : 8;
84 unsigned align : 2;
85 unsigned dynamic : 1;
89 /***********************************************************************
90 Fringe bitmaps
91 ***********************************************************************/
93 /* Undefined bitmap. A question mark. */
95 ..xxxx..
96 .xxxxxx.
97 xx....xx
98 xx....xx
99 ....xx..
100 ...xx...
101 ...xx...
102 ........
103 ...xx...
104 ...xx...
106 static unsigned short question_mark_bits[] = {
107 0x3c, 0x7e, 0x7e, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18};
109 /* An arrow like this: `<-'. */
111 ...xx...
112 ..xx....
113 .xx.....
114 xxxxxx..
115 xxxxxx..
116 .xx.....
117 ..xx....
118 ...xx...
120 static unsigned short left_arrow_bits[] = {
121 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
124 /* Right truncation arrow bitmap `->'. */
126 ...xx...
127 ....xx..
128 .....xx.
129 ..xxxxxx
130 ..xxxxxx
131 .....xx.
132 ....xx..
133 ...xx...
135 static unsigned short right_arrow_bits[] = {
136 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
139 /* Up arrow bitmap. */
141 ...xx...
142 ..xxxx..
143 .xxxxxx.
144 xxxxxxxx
145 ...xx...
146 ...xx...
147 ...xx...
148 ...xx...
150 static unsigned short up_arrow_bits[] = {
151 0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0x18};
154 /* Down arrow bitmap. */
156 ...xx...
157 ...xx...
158 ...xx...
159 ...xx...
160 xxxxxxxx
161 .xxxxxx.
162 ..xxxx..
163 ...xx...
165 static unsigned short down_arrow_bits[] = {
166 0x18, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18};
168 /* Marker for continuation lines. */
170 ..xxxx..
171 .xxxxx..
172 xx......
173 xxx..x..
174 xxxxxx..
175 .xxxxx..
176 ..xxxx..
177 .xxxxx..
179 static unsigned short left_curly_arrow_bits[] = {
180 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
182 /* Marker for continued lines. */
184 ..xxxx..
185 ..xxxxx.
186 ......xx
187 ..x..xxx
188 ..xxxxxx
189 ..xxxxx.
190 ..xxxx..
191 ..xxxxx.
193 static unsigned short right_curly_arrow_bits[] = {
194 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
196 /* Reverse Overlay arrow bitmap. A triangular arrow. */
198 ......xx
199 ....xxxx
200 ...xxxxx
201 ..xxxxxx
202 ..xxxxxx
203 ...xxxxx
204 ....xxxx
205 ......xx
207 static unsigned short left_triangle_bits[] = {
208 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
210 /* Overlay arrow bitmap. A triangular arrow. */
212 xx......
213 xxxx....
214 xxxxx...
215 xxxxxx..
216 xxxxxx..
217 xxxxx...
218 xxxx....
219 xx......
221 static unsigned short right_triangle_bits[] = {
222 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
224 /* First line bitmap. An top-left angle. */
226 xxxxxx..
227 xxxxxx..
228 xx......
229 xx......
230 xx......
231 xx......
232 xx......
233 ........
235 static unsigned short top_left_angle_bits[] = {
236 0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00};
238 /* First line bitmap. An right-up angle. */
240 ..xxxxxx
241 ..xxxxxx
242 ......xx
243 ......xx
244 ......xx
245 ......xx
246 ......xx
247 ........
249 static unsigned short top_right_angle_bits[] = {
250 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00};
252 /* Last line bitmap. An left-down angle. */
254 ........
255 xx......
256 xx......
257 xx......
258 xx......
259 xx......
260 xxxxxx..
261 xxxxxx..
263 static unsigned short bottom_left_angle_bits[] = {
264 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
266 /* Last line bitmap. An right-down angle. */
268 ........
269 ......xx
270 ......xx
271 ......xx
272 ......xx
273 ......xx
274 ..xxxxxx
275 ..xxxxxx
277 static unsigned short bottom_right_angle_bits[] = {
278 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
280 /* First/last line bitmap. An left bracket. */
282 xxxxxx..
283 xxxxxx..
284 xx......
285 xx......
286 xx......
287 xx......
288 xx......
289 xx......
290 xxxxxx..
291 xxxxxx..
293 static unsigned short left_bracket_bits[] = {
294 0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
296 /* First/last line bitmap. An right bracket. */
298 ..xxxxxx
299 ..xxxxxx
300 ......xx
301 ......xx
302 ......xx
303 ......xx
304 ......xx
305 ......xx
306 ..xxxxxx
307 ..xxxxxx
309 static unsigned short right_bracket_bits[] = {
310 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
312 /* Filled box cursor bitmap. A filled box; max 13 pixels high. */
314 xxxxxxx.
315 xxxxxxx.
316 xxxxxxx.
317 xxxxxxx.
318 xxxxxxx.
319 xxxxxxx.
320 xxxxxxx.
321 xxxxxxx.
322 xxxxxxx.
323 xxxxxxx.
324 xxxxxxx.
325 xxxxxxx.
326 xxxxxxx.
328 static unsigned short filled_rectangle_bits[] = {
329 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
331 /* Hollow box cursor bitmap. A hollow box; max 13 pixels high. */
333 xxxxxxx.
334 x.....x.
335 x.....x.
336 x.....x.
337 x.....x.
338 x.....x.
339 x.....x.
340 x.....x.
341 x.....x.
342 x.....x.
343 x.....x.
344 x.....x.
345 xxxxxxx.
347 static unsigned short hollow_rectangle_bits[] = {
348 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe};
350 /* Hollow square bitmap. */
352 .xxxxxx.
353 .x....x.
354 .x....x.
355 .x....x.
356 .x....x.
357 .xxxxxx.
359 static unsigned short hollow_square_bits[] = {
360 0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e};
362 /* Filled square bitmap. */
364 .xxxxxx.
365 .xxxxxx.
366 .xxxxxx.
367 .xxxxxx.
368 .xxxxxx.
369 .xxxxxx.
371 static unsigned short filled_square_bits[] = {
372 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e};
374 /* Bar cursor bitmap. A vertical bar; max 13 pixels high. */
376 xx......
377 xx......
378 xx......
379 xx......
380 xx......
381 xx......
382 xx......
383 xx......
384 xx......
385 xx......
386 xx......
387 xx......
388 xx......
390 static unsigned short vertical_bar_bits[] = {
391 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0};
393 /* HBar cursor bitmap. A horizontal bar; 2 pixels high. */
395 xxxxxxx.
396 xxxxxxx.
398 static unsigned short horizontal_bar_bits[] = {
399 0xfe, 0xfe};
402 /* Bitmap drawn to indicate lines not displaying text if
403 `indicate-empty-lines' is non-nil. */
405 ........
406 ..xxxx..
407 ........
408 ........
409 ..xxxx..
410 ........
412 static unsigned short empty_line_bits[] = {
413 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
414 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
415 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
416 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
417 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
418 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
419 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
420 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
423 #define BYTES_PER_BITMAP_ROW (sizeof (unsigned short))
424 #define STANDARD_BITMAP_HEIGHT(bits) (sizeof (bits)/BYTES_PER_BITMAP_ROW)
425 #define FRBITS(bits) bits, STANDARD_BITMAP_HEIGHT (bits)
427 /* NOTE: The order of these bitmaps must match the sequence
428 used in fringe.el to define the corresponding symbols. */
430 static struct fringe_bitmap standard_bitmaps[] =
432 { NULL, 0, 0, 0, 0, 0 }, /* NO_FRINGE_BITMAP */
433 { FRBITS (question_mark_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
434 { FRBITS (left_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
435 { FRBITS (right_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
436 { FRBITS (up_arrow_bits), 8, 0, ALIGN_BITMAP_TOP, 0 },
437 { FRBITS (down_arrow_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
438 { FRBITS (left_curly_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
439 { FRBITS (right_curly_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
440 { FRBITS (left_triangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
441 { FRBITS (right_triangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
442 { FRBITS (top_left_angle_bits), 8, 0, ALIGN_BITMAP_TOP, 0 },
443 { FRBITS (top_right_angle_bits), 8, 0, ALIGN_BITMAP_TOP, 0 },
444 { FRBITS (bottom_left_angle_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
445 { FRBITS (bottom_right_angle_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
446 { FRBITS (left_bracket_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
447 { FRBITS (right_bracket_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
448 { FRBITS (filled_rectangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
449 { FRBITS (hollow_rectangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
450 { FRBITS (filled_square_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
451 { FRBITS (hollow_square_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
452 { FRBITS (vertical_bar_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
453 { FRBITS (horizontal_bar_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
454 { FRBITS (empty_line_bits), 8, 3, ALIGN_BITMAP_TOP, 0 },
457 #define NO_FRINGE_BITMAP 0
458 #define UNDEF_FRINGE_BITMAP 1
459 #define MAX_STANDARD_FRINGE_BITMAPS (sizeof (standard_bitmaps)/sizeof (standard_bitmaps[0]))
461 static struct fringe_bitmap **fringe_bitmaps;
462 static Lisp_Object *fringe_faces;
463 static int max_fringe_bitmaps;
465 #ifndef HAVE_NS
466 static
467 #endif
468 int max_used_fringe_bitmap = MAX_STANDARD_FRINGE_BITMAPS;
471 /* Lookup bitmap number for symbol BITMAP.
472 Return 0 if not a bitmap. */
475 lookup_fringe_bitmap (Lisp_Object bitmap)
477 int bn;
479 bitmap = Fget (bitmap, Qfringe);
480 if (!INTEGERP (bitmap))
481 return 0;
483 bn = XINT (bitmap);
484 if (bn > NO_FRINGE_BITMAP
485 && bn < max_used_fringe_bitmap
486 && (bn < MAX_STANDARD_FRINGE_BITMAPS
487 || fringe_bitmaps[bn] != NULL))
488 return bn;
490 return 0;
493 /* Get fringe bitmap name for bitmap number BN.
495 Found by traversing Vfringe_bitmaps comparing BN to the
496 fringe property for each symbol.
498 Return BN if not found in Vfringe_bitmaps. */
500 static Lisp_Object
501 get_fringe_bitmap_name (int bn)
503 Lisp_Object bitmaps;
504 Lisp_Object num;
506 /* Zero means no bitmap -- return nil. */
507 if (bn <= 0)
508 return Qnil;
510 bitmaps = Vfringe_bitmaps;
511 num = make_number (bn);
513 while (CONSP (bitmaps))
515 Lisp_Object bitmap = XCAR (bitmaps);
516 if (EQ (num, Fget (bitmap, Qfringe)))
517 return bitmap;
518 bitmaps = XCDR (bitmaps);
521 return num;
524 /* Get fringe bitmap data for bitmap number BN. */
526 static struct fringe_bitmap *
527 get_fringe_bitmap_data (int bn)
529 struct fringe_bitmap *fb;
531 fb = fringe_bitmaps[bn];
532 if (fb == NULL)
533 fb = &standard_bitmaps[bn < MAX_STANDARD_FRINGE_BITMAPS
534 ? bn : UNDEF_FRINGE_BITMAP];
536 return fb;
539 /* Draw the bitmap WHICH in one of the left or right fringes of
540 window W. ROW is the glyph row for which to display the bitmap; it
541 determines the vertical position at which the bitmap has to be
542 drawn.
543 LEFT_P is 1 for left fringe, 0 for right fringe.
546 static void
547 draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int overlay, int which)
549 struct frame *f = XFRAME (WINDOW_FRAME (w));
550 struct draw_fringe_bitmap_params p;
551 struct fringe_bitmap *fb;
552 int period;
553 int face_id = DEFAULT_FACE_ID;
554 int offset, header_line_height;
556 p.overlay_p = (overlay & 1) == 1;
557 p.cursor_p = (overlay & 2) == 2;
559 if (which != NO_FRINGE_BITMAP)
561 offset = 0;
563 else if (left_p)
565 which = row->left_fringe_bitmap;
566 face_id = row->left_fringe_face_id;
567 offset = row->left_fringe_offset;
569 else
571 which = row->right_fringe_bitmap;
572 face_id = row->right_fringe_face_id;
573 offset = row->right_fringe_offset;
576 if (face_id == DEFAULT_FACE_ID)
578 Lisp_Object face = fringe_faces[which];
579 face_id = NILP (face) ? lookup_named_face (f, Qfringe, 0)
580 : lookup_derived_face (f, face, FRINGE_FACE_ID, 0);
581 if (face_id < 0)
582 face_id = FRINGE_FACE_ID;
585 fb = get_fringe_bitmap_data (which);
587 period = fb->period;
589 /* Convert row to frame coordinates. */
590 p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y) + offset;
592 p.which = which;
593 p.bits = fb->bits;
594 p.wd = fb->width;
596 p.h = fb->height;
597 p.dh = (period > 0 ? (p.y % period) : 0);
598 p.h -= p.dh;
600 /* Adjust y to the offset in the row to start drawing the bitmap. */
601 switch (fb->align)
603 case ALIGN_BITMAP_CENTER:
604 p.y += (row->height - p.h) / 2;
605 break;
606 case ALIGN_BITMAP_BOTTOM:
607 p.y += (row->visible_height - p.h);
608 break;
609 case ALIGN_BITMAP_TOP:
610 break;
613 p.face = FACE_FROM_ID (f, face_id);
615 if (p.face == NULL)
617 /* This could happen after clearing face cache.
618 But it shouldn't happen anymore. ++kfs */
619 return;
622 PREPARE_FACE_FOR_DISPLAY (f, p.face);
624 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
625 the fringe. */
626 p.bx = -1;
627 header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
628 p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
629 p.ny = row->visible_height;
630 if (left_p)
632 int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
633 int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
634 ? LEFT_MARGIN_AREA
635 : TEXT_AREA));
636 if (p.wd > wd)
637 p.wd = wd;
638 p.x = x - p.wd - (wd - p.wd) / 2;
640 if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny)
642 /* If W has a vertical border to its left, don't draw over it. */
643 wd -= ((!WINDOW_LEFTMOST_P (w)
644 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
645 ? 1 : 0);
646 p.bx = x - wd;
647 p.nx = wd;
650 else
652 int x = window_box_right (w,
653 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
654 ? RIGHT_MARGIN_AREA
655 : TEXT_AREA));
656 int wd = WINDOW_RIGHT_FRINGE_WIDTH (w);
657 if (p.wd > wd)
658 p.wd = wd;
659 p.x = x + (wd - p.wd) / 2;
660 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
661 the fringe. */
662 if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny)
664 p.bx = x;
665 p.nx = wd;
669 FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p);
672 static int
673 get_logical_cursor_bitmap (struct window *w, Lisp_Object cursor)
675 Lisp_Object cmap, bm = Qnil;
677 if ((cmap = BVAR (XBUFFER (w->buffer), fringe_cursor_alist)), !NILP (cmap))
679 bm = Fassq (cursor, cmap);
680 if (CONSP (bm))
682 if ((bm = XCDR (bm)), NILP (bm))
683 return NO_FRINGE_BITMAP;
684 return lookup_fringe_bitmap (bm);
687 if (EQ (cmap, BVAR (&buffer_defaults, fringe_cursor_alist)))
688 return NO_FRINGE_BITMAP;
689 bm = Fassq (cursor, BVAR (&buffer_defaults, fringe_cursor_alist));
690 if (!CONSP (bm) || ((bm = XCDR (bm)), NILP (bm)))
691 return NO_FRINGE_BITMAP;
692 return lookup_fringe_bitmap (bm);
695 static int
696 get_logical_fringe_bitmap (struct window *w, Lisp_Object bitmap, int right_p, int partial_p)
698 Lisp_Object cmap, bm1 = Qnil, bm2 = Qnil, bm;
699 int ln1 = 0, ln2 = 0;
700 int ix1 = right_p;
701 int ix2 = ix1 + (partial_p ? 2 : 0);
703 /* Lookup in buffer-local fringe-indicator-alist before global alist.
705 Elements are:
706 BITMAP -- use for all
707 (L R) -- use for left right (whether partial or not)
708 (L R PL PR) -- use for left right partial-left partial-right
709 If any value in local binding is not present or t, use global value.
711 If partial, lookup partial bitmap in default value if not found here.
712 If not partial, or no partial spec is present, use non-partial bitmap. */
714 if ((cmap = BVAR (XBUFFER (w->buffer), fringe_indicator_alist)), !NILP (cmap))
716 bm1 = Fassq (bitmap, cmap);
717 if (CONSP (bm1))
719 if ((bm1 = XCDR (bm1)), NILP (bm1))
720 return NO_FRINGE_BITMAP;
721 if (CONSP (bm1))
723 ln1 = XINT (Flength (bm1));
724 if (partial_p)
726 if (ln1 > ix2)
728 bm = Fnth (make_number (ix2), bm1);
729 if (!EQ (bm, Qt))
730 goto found;
733 else
735 if (ln1 > ix1)
737 bm = Fnth (make_number (ix1), bm1);
738 if (!EQ (bm, Qt))
739 goto found;
743 else if ((bm = bm1, !EQ (bm, Qt)))
744 goto found;
748 if (!EQ (cmap, BVAR (&buffer_defaults, fringe_indicator_alist))
749 && !NILP (BVAR (&buffer_defaults, fringe_indicator_alist)))
751 bm2 = Fassq (bitmap, BVAR (&buffer_defaults, fringe_indicator_alist));
752 if (CONSP (bm2))
754 if ((bm2 = XCDR (bm2)), !NILP (bm2))
756 if (CONSP (bm2))
758 ln2 = XINT (Flength (bm2));
759 if (partial_p)
761 if (ln2 > ix2)
763 bm = Fnth (make_number (ix2), bm2);
764 if (!EQ (bm, Qt))
765 goto found;
773 if (ln1 > ix1)
775 bm = Fnth (make_number (ix1), bm1);
776 if (!EQ (bm, Qt))
777 goto found;
780 if (ln2 > ix1)
782 bm = Fnth (make_number (ix1), bm2);
783 if (!EQ (bm, Qt))
784 goto found;
785 return NO_FRINGE_BITMAP;
787 else if ((bm = bm2, NILP (bm)))
788 return NO_FRINGE_BITMAP;
790 found:
791 return lookup_fringe_bitmap (bm);
795 void
796 draw_fringe_bitmap (struct window *w, struct glyph_row *row, int left_p)
798 int overlay = 0;
800 if (left_p == row->reversed_p && row->cursor_in_fringe_p)
802 Lisp_Object cursor = Qnil;
804 switch (w->phys_cursor_type)
806 case HOLLOW_BOX_CURSOR:
807 if (row->visible_height >= STANDARD_BITMAP_HEIGHT (hollow_rectangle_bits))
808 cursor = Qhollow;
809 else
810 cursor = Qhollow_small;
811 break;
812 case FILLED_BOX_CURSOR:
813 cursor = Qbox;
814 break;
815 case BAR_CURSOR:
816 cursor = Qbar;
817 break;
818 case HBAR_CURSOR:
819 cursor = Qhbar;
820 break;
821 case NO_CURSOR:
822 default:
823 w->phys_cursor_on_p = 0;
824 row->cursor_in_fringe_p = 0;
825 break;
827 if (!NILP (cursor))
829 int bm = get_logical_cursor_bitmap (w, cursor);
830 if (bm != NO_FRINGE_BITMAP)
832 draw_fringe_bitmap_1 (w, row, left_p, 2, bm);
833 overlay = EQ (cursor, Qbox) ? 3 : 1;
838 draw_fringe_bitmap_1 (w, row, left_p, overlay, NO_FRINGE_BITMAP);
840 if (left_p && row->overlay_arrow_bitmap != NO_FRINGE_BITMAP)
841 draw_fringe_bitmap_1 (w, row, 1, 1, row->overlay_arrow_bitmap);
845 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
846 function with input blocked. */
848 void
849 draw_row_fringe_bitmaps (struct window *w, struct glyph_row *row)
851 xassert (interrupt_input_blocked);
853 /* If row is completely invisible, because of vscrolling, we
854 don't have to draw anything. */
855 if (row->visible_height <= 0)
856 return;
858 if (WINDOW_LEFT_FRINGE_WIDTH (w) != 0)
859 draw_fringe_bitmap (w, row, 1);
861 if (WINDOW_RIGHT_FRINGE_WIDTH (w) != 0)
862 draw_fringe_bitmap (w, row, 0);
865 /* Draw the fringes of window W. Only fringes for rows marked for
866 update in redraw_fringe_bitmaps_p are drawn.
868 Return >0 if left or right fringe was redrawn in any way.
870 If NO_FRINGE is non-zero, also return >0 if either fringe has zero width.
872 A return value >0 indicates that the vertical line between windows
873 needs update (as it may be drawn in the fringe).
877 draw_window_fringes (struct window *w, int no_fringe)
879 struct glyph_row *row;
880 int yb = window_text_bottom_y (w);
881 int nrows = w->current_matrix->nrows;
882 int y, rn;
883 int updated = 0;
885 if (w->pseudo_window_p)
886 return 0;
888 /* Must draw line if no fringe */
889 if (no_fringe
890 && (WINDOW_LEFT_FRINGE_WIDTH (w) == 0
891 || WINDOW_RIGHT_FRINGE_WIDTH (w) == 0))
892 updated++;
894 for (y = w->vscroll, rn = 0, row = w->current_matrix->rows;
895 y < yb && rn < nrows;
896 y += row->height, ++row, ++rn)
898 if (!row->redraw_fringe_bitmaps_p)
899 continue;
900 draw_row_fringe_bitmaps (w, row);
901 row->redraw_fringe_bitmaps_p = 0;
902 updated++;
905 return updated;
909 /* Recalculate the bitmaps to show in the fringes of window W.
910 Only mark rows with modified bitmaps for update in redraw_fringe_bitmaps_p.
912 If KEEP_CURRENT_P is 0, update current_matrix too. */
915 update_window_fringes (struct window *w, int keep_current_p)
917 struct glyph_row *row, *cur = 0;
918 int yb = window_text_bottom_y (w);
919 int rn, nrows = w->current_matrix->nrows;
920 int y;
921 int redraw_p = 0;
922 Lisp_Object boundary_top = Qnil, boundary_bot = Qnil;
923 Lisp_Object arrow_top = Qnil, arrow_bot = Qnil;
924 Lisp_Object empty_pos;
925 Lisp_Object ind = Qnil;
926 #define MAX_BITMAP_CACHE (8*4)
927 int bitmap_cache[MAX_BITMAP_CACHE];
928 int top_ind_rn, bot_ind_rn;
929 int top_ind_min_y, bot_ind_max_y;
931 /* top_ind_rn is set to a nonnegative value whenever
932 row->indicate_bob_p is set, so it's OK that top_row_ends_at_zv_p
933 is not initialized here. Similarly for bot_ind_rn,
934 row->indicate_eob_p and bot_row_ends_at_zv_p. */
935 int top_row_ends_at_zv_p IF_LINT (= 0), bot_row_ends_at_zv_p IF_LINT (= 0);
937 if (w->pseudo_window_p)
938 return 0;
940 if (!MINI_WINDOW_P (w)
941 && (ind = BVAR (XBUFFER (w->buffer), indicate_buffer_boundaries), !NILP (ind)))
943 if (EQ (ind, Qleft) || EQ (ind, Qright))
944 boundary_top = boundary_bot = arrow_top = arrow_bot = ind;
945 else if (CONSP (ind) && CONSP (XCAR (ind)))
947 Lisp_Object pos;
948 if (pos = Fassq (Qt, ind), !NILP (pos))
949 boundary_top = boundary_bot = arrow_top = arrow_bot = XCDR (pos);
950 if (pos = Fassq (Qtop, ind), !NILP (pos))
951 boundary_top = XCDR (pos);
952 if (pos = Fassq (Qbottom, ind), !NILP (pos))
953 boundary_bot = XCDR (pos);
954 if (pos = Fassq (Qup, ind), !NILP (pos))
955 arrow_top = XCDR (pos);
956 if (pos = Fassq (Qdown, ind), !NILP (pos))
957 arrow_bot = XCDR (pos);
959 else
960 /* Anything else means boundary on left and no arrows. */
961 boundary_top = boundary_bot = Qleft;
964 top_ind_rn = bot_ind_rn = -1;
965 if (!NILP (ind))
967 for (y = w->vscroll, rn = 0;
968 y < yb && rn < nrows;
969 y += row->height, ++rn)
971 row = w->desired_matrix->rows + rn;
972 if (!row->enabled_p)
973 row = w->current_matrix->rows + rn;
975 row->indicate_bob_p = row->indicate_top_line_p = 0;
976 row->indicate_eob_p = row->indicate_bottom_line_p = 0;
978 if (!row->mode_line_p)
980 if (top_ind_rn < 0 && row->visible_height > 0)
982 if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer))
983 && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
984 row->indicate_bob_p = !NILP (boundary_top);
985 else
986 row->indicate_top_line_p = !NILP (arrow_top);
987 top_ind_rn = rn;
990 if (bot_ind_rn < 0)
992 if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer))
993 && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
994 row->indicate_eob_p = !NILP (boundary_bot), bot_ind_rn = rn;
995 else if (y + row->height >= yb)
996 row->indicate_bottom_line_p = !NILP (arrow_bot), bot_ind_rn = rn;
1002 empty_pos = BVAR (XBUFFER (w->buffer), indicate_empty_lines);
1003 if (!NILP (empty_pos) && !EQ (empty_pos, Qright))
1004 empty_pos = WINDOW_LEFT_FRINGE_WIDTH (w) == 0 ? Qright : Qleft;
1006 for (y = 0; y < MAX_BITMAP_CACHE; y++)
1007 bitmap_cache[y] = -1;
1009 #define LEFT_FRINGE(cache, which, partial_p) \
1010 (bitmap_cache[cache*4+partial_p] >= 0 \
1011 ? bitmap_cache[cache*4+partial_p] \
1012 : (bitmap_cache[cache*4+partial_p] = \
1013 get_logical_fringe_bitmap (w, which, 0, partial_p)))
1015 #define RIGHT_FRINGE(cache, which, partial_p) \
1016 (bitmap_cache[cache*4+2+partial_p] >= 0 \
1017 ? bitmap_cache[cache*4+2+partial_p] \
1018 : (bitmap_cache[cache*4+2+partial_p] = \
1019 get_logical_fringe_bitmap (w, which, 1, partial_p)))
1022 /* Extend top-aligned top indicator (or bottom-aligned bottom
1023 indicator) to adjacent rows if it doesn't fit in one row. */
1024 top_ind_min_y = bot_ind_max_y = -1;
1025 if (top_ind_rn >= 0)
1027 int bn = NO_FRINGE_BITMAP;
1029 row = w->desired_matrix->rows + top_ind_rn;
1030 if (!row->enabled_p)
1031 row = w->current_matrix->rows + top_ind_rn;
1033 top_row_ends_at_zv_p = row->ends_at_zv_p;
1034 if (row->indicate_bob_p)
1036 if (EQ (boundary_top, Qleft))
1037 bn = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
1038 ? LEFT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p)
1039 : LEFT_FRINGE (2, Qtop, 0));
1040 else
1041 bn = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
1042 ? RIGHT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p)
1043 : RIGHT_FRINGE (2, Qtop, 0));
1045 else if (row->indicate_top_line_p)
1047 if (EQ (arrow_top, Qleft))
1048 bn = LEFT_FRINGE (6, Qup, 0);
1049 else
1050 bn = RIGHT_FRINGE (6, Qup, 0);
1053 if (bn != NO_FRINGE_BITMAP)
1055 struct fringe_bitmap *fb = get_fringe_bitmap_data (bn);
1057 if (fb->align == ALIGN_BITMAP_TOP && fb->period == 0)
1059 struct glyph_row *row1;
1060 int top_ind_max_y;
1062 top_ind_min_y = WINDOW_HEADER_LINE_HEIGHT (w);
1063 top_ind_max_y = top_ind_min_y + fb->height;
1064 if (top_ind_max_y > yb)
1065 top_ind_max_y = yb;
1067 for (y = row->y + row->height, rn = top_ind_rn + 1;
1068 y < top_ind_max_y && rn < nrows;
1069 y += row1->height, rn++)
1071 if (bot_ind_rn >= 0 && rn >= bot_ind_rn)
1072 break;
1074 row1 = w->desired_matrix->rows + rn;
1075 if (!row1->enabled_p)
1076 row1 = w->current_matrix->rows + rn;
1078 row1->indicate_bob_p = row->indicate_bob_p;
1079 row1->indicate_top_line_p = row->indicate_top_line_p;
1084 if (bot_ind_rn >= 0)
1086 int bn = NO_FRINGE_BITMAP;
1088 row = w->desired_matrix->rows + bot_ind_rn;
1089 if (!row->enabled_p)
1090 row = w->current_matrix->rows + bot_ind_rn;
1092 bot_row_ends_at_zv_p = row->ends_at_zv_p;
1093 if (row->indicate_eob_p)
1095 if (EQ (boundary_bot, Qleft))
1096 bn = LEFT_FRINGE (3, Qbottom, row->ends_at_zv_p);
1097 else
1098 bn = RIGHT_FRINGE (3, Qbottom, row->ends_at_zv_p);
1100 else if (row->indicate_bottom_line_p)
1102 if (EQ (arrow_bot, Qleft))
1103 bn = LEFT_FRINGE (7, Qdown, 0);
1104 else
1105 bn = RIGHT_FRINGE (7, Qdown, 0);
1108 if (bn != NO_FRINGE_BITMAP)
1110 struct fringe_bitmap *fb = get_fringe_bitmap_data (bn);
1112 if (fb->align == ALIGN_BITMAP_BOTTOM && fb->period == 0)
1114 struct glyph_row *row1;
1115 int bot_ind_min_y;
1117 bot_ind_max_y = row->y + row->visible_height;
1118 bot_ind_min_y = bot_ind_max_y - fb->height;
1119 if (bot_ind_min_y < WINDOW_HEADER_LINE_HEIGHT (w))
1120 bot_ind_min_y = WINDOW_HEADER_LINE_HEIGHT (w);
1122 for (y = row->y, rn = bot_ind_rn - 1;
1123 y >= bot_ind_min_y && rn >= 0;
1124 y -= row1->height, rn--)
1126 if (top_ind_rn >= 0 && rn <= top_ind_rn)
1127 break;
1129 row1 = w->desired_matrix->rows + rn;
1130 if (!row1->enabled_p)
1131 row1 = w->current_matrix->rows + rn;
1133 row1->indicate_eob_p = row->indicate_eob_p;
1134 row1->indicate_bottom_line_p = row->indicate_bottom_line_p;
1140 for (y = w->vscroll, rn = 0;
1141 y < yb && rn < nrows;
1142 y += row->height, rn++)
1144 int left, right;
1145 unsigned left_face_id, right_face_id;
1146 int left_offset, right_offset;
1147 int periodic_p;
1149 row = w->desired_matrix->rows + rn;
1150 cur = w->current_matrix->rows + rn;
1151 if (!row->enabled_p)
1152 row = cur;
1154 left_face_id = right_face_id = DEFAULT_FACE_ID;
1155 left_offset = right_offset = 0;
1156 periodic_p = 0;
1158 /* Decide which bitmap to draw in the left fringe. */
1159 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
1160 left = NO_FRINGE_BITMAP;
1161 else if (row->left_user_fringe_bitmap != NO_FRINGE_BITMAP)
1163 left = row->left_user_fringe_bitmap;
1164 left_face_id = row->left_user_fringe_face_id;
1166 else if ((!row->reversed_p && row->truncated_on_left_p)
1167 || (row->reversed_p && row->truncated_on_right_p))
1168 left = LEFT_FRINGE (0, Qtruncation, 0);
1169 else if (row->indicate_bob_p && EQ (boundary_top, Qleft))
1171 left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
1172 ? LEFT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p)
1173 : LEFT_FRINGE (2, Qtop, 0));
1174 if (top_ind_min_y >= 0)
1175 left_offset = top_ind_min_y - row->y;
1177 else if (row->indicate_eob_p && EQ (boundary_bot, Qleft))
1179 left = LEFT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p);
1180 if (bot_ind_max_y >= 0)
1181 left_offset = bot_ind_max_y - (row->y + row->visible_height);
1183 else if ((!row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row))
1184 || (row->reversed_p && row->continued_p))
1185 left = LEFT_FRINGE (4, Qcontinuation, 0);
1186 else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft))
1187 left = LEFT_FRINGE (5, Qempty_line, 0);
1188 else if (row->indicate_top_line_p && EQ (arrow_top, Qleft))
1190 left = LEFT_FRINGE (6, Qup, 0);
1191 if (top_ind_min_y >= 0)
1192 left_offset = top_ind_min_y - row->y;
1194 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qleft))
1196 left = LEFT_FRINGE (7, Qdown, 0);
1197 if (bot_ind_max_y >= 0)
1198 left_offset = bot_ind_max_y - (row->y + row->visible_height);
1200 else
1201 left = NO_FRINGE_BITMAP;
1203 /* Decide which bitmap to draw in the right fringe. */
1204 if (WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)
1205 right = NO_FRINGE_BITMAP;
1206 else if (row->right_user_fringe_bitmap != NO_FRINGE_BITMAP)
1208 right = row->right_user_fringe_bitmap;
1209 right_face_id = row->right_user_fringe_face_id;
1211 else if ((!row->reversed_p && row->truncated_on_right_p)
1212 || (row->reversed_p && row->truncated_on_left_p))
1213 right = RIGHT_FRINGE (0, Qtruncation, 0);
1214 else if (row->indicate_bob_p && EQ (boundary_top, Qright))
1216 right = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
1217 ? RIGHT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p)
1218 : RIGHT_FRINGE (2, Qtop, 0));
1219 if (top_ind_min_y >= 0)
1220 right_offset = top_ind_min_y - row->y;
1222 else if (row->indicate_eob_p && EQ (boundary_bot, Qright))
1224 right = RIGHT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p);
1225 if (bot_ind_max_y >= 0)
1226 right_offset = bot_ind_max_y - (row->y + row->visible_height);
1228 else if ((!row->reversed_p && row->continued_p)
1229 || (row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row)))
1230 right = RIGHT_FRINGE (4, Qcontinuation, 0);
1231 else if (row->indicate_top_line_p && EQ (arrow_top, Qright))
1233 right = RIGHT_FRINGE (6, Qup, 0);
1234 if (top_ind_min_y >= 0)
1235 right_offset = top_ind_min_y - row->y;
1237 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright))
1239 right = RIGHT_FRINGE (7, Qdown, 0);
1240 if (bot_ind_max_y >= 0)
1241 right_offset = bot_ind_max_y - (row->y + row->visible_height);
1243 else if (row->indicate_empty_line_p && EQ (empty_pos, Qright))
1244 right = RIGHT_FRINGE (5, Qempty_line, 0);
1245 else
1246 right = NO_FRINGE_BITMAP;
1248 periodic_p = (get_fringe_bitmap_data (left)->period != 0
1249 || get_fringe_bitmap_data (right)->period != 0);
1251 if (row->y != cur->y
1252 || row->visible_height != cur->visible_height
1253 || row->ends_at_zv_p != cur->ends_at_zv_p
1254 || left != cur->left_fringe_bitmap
1255 || right != cur->right_fringe_bitmap
1256 || left_face_id != cur->left_fringe_face_id
1257 || right_face_id != cur->right_fringe_face_id
1258 || left_offset != cur->left_fringe_offset
1259 || right_offset != cur->right_fringe_offset
1260 || periodic_p != cur->fringe_bitmap_periodic_p
1261 || cur->redraw_fringe_bitmaps_p)
1263 redraw_p = row->redraw_fringe_bitmaps_p = 1;
1264 if (!keep_current_p)
1266 cur->redraw_fringe_bitmaps_p = 1;
1267 cur->left_fringe_bitmap = left;
1268 cur->right_fringe_bitmap = right;
1269 cur->left_fringe_face_id = left_face_id;
1270 cur->right_fringe_face_id = right_face_id;
1271 cur->left_fringe_offset = left_offset;
1272 cur->right_fringe_offset = right_offset;
1273 cur->fringe_bitmap_periodic_p = periodic_p;
1277 if (row->overlay_arrow_bitmap < 0)
1278 row->overlay_arrow_bitmap = get_logical_fringe_bitmap (w, Qoverlay_arrow, 0, 0);
1280 if (row->overlay_arrow_bitmap != cur->overlay_arrow_bitmap)
1282 redraw_p = row->redraw_fringe_bitmaps_p = 1;
1283 if (!keep_current_p)
1285 cur->redraw_fringe_bitmaps_p = 1;
1286 cur->overlay_arrow_bitmap = row->overlay_arrow_bitmap;
1290 row->left_fringe_bitmap = left;
1291 row->right_fringe_bitmap = right;
1292 row->left_fringe_face_id = left_face_id;
1293 row->right_fringe_face_id = right_face_id;
1294 row->left_fringe_offset = left_offset;
1295 row->right_fringe_offset = right_offset;
1296 row->fringe_bitmap_periodic_p = periodic_p;
1299 return redraw_p && !keep_current_p;
1303 /* Compute actual fringe widths for frame F.
1305 If REDRAW is 1, redraw F if the fringe settings was actually
1306 modified and F is visible.
1308 Since the combined left and right fringe must occupy an integral
1309 number of columns, we may need to add some pixels to each fringe.
1310 Typically, we add an equal amount (+/- 1 pixel) to each fringe,
1311 but a negative width value is taken literally (after negating it).
1313 We never make the fringes narrower than specified.
1316 void
1317 compute_fringe_widths (struct frame *f, int redraw)
1319 int o_left = FRAME_LEFT_FRINGE_WIDTH (f);
1320 int o_right = FRAME_RIGHT_FRINGE_WIDTH (f);
1321 int o_cols = FRAME_FRINGE_COLS (f);
1323 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
1324 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
1325 int left_fringe_width, right_fringe_width;
1327 if (!NILP (left_fringe))
1328 left_fringe = Fcdr (left_fringe);
1329 if (!NILP (right_fringe))
1330 right_fringe = Fcdr (right_fringe);
1332 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
1333 XINT (left_fringe));
1334 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
1335 XINT (right_fringe));
1337 if (left_fringe_width || right_fringe_width)
1339 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
1340 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
1341 int conf_wid = left_wid + right_wid;
1342 int font_wid = FRAME_COLUMN_WIDTH (f);
1343 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
1344 int real_wid = cols * font_wid;
1345 if (left_wid && right_wid)
1347 if (left_fringe_width < 0)
1349 /* Left fringe width is fixed, adjust right fringe if necessary */
1350 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid;
1351 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid;
1353 else if (right_fringe_width < 0)
1355 /* Right fringe width is fixed, adjust left fringe if necessary */
1356 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
1357 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid;
1359 else
1361 /* Adjust both fringes with an equal amount.
1362 Note that we are doing integer arithmetic here, so don't
1363 lose a pixel if the total width is an odd number. */
1364 int fill = real_wid - conf_wid;
1365 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2;
1366 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2;
1369 else if (left_fringe_width)
1371 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid;
1372 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
1374 else
1376 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
1377 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid;
1379 FRAME_FRINGE_COLS (f) = cols;
1381 else
1383 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
1384 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
1385 FRAME_FRINGE_COLS (f) = 0;
1388 if (redraw && FRAME_VISIBLE_P (f))
1389 if (o_left != FRAME_LEFT_FRINGE_WIDTH (f) ||
1390 o_right != FRAME_RIGHT_FRINGE_WIDTH (f) ||
1391 o_cols != FRAME_FRINGE_COLS (f))
1392 redraw_frame (f);
1396 /* Free resources used by a user-defined bitmap. */
1398 static void
1399 destroy_fringe_bitmap (int n)
1401 struct fringe_bitmap **fbp;
1403 fringe_faces[n] = Qnil;
1405 fbp = &fringe_bitmaps[n];
1406 if (*fbp && (*fbp)->dynamic)
1408 /* XXX Is SELECTED_FRAME OK here? */
1409 struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
1410 if (rif && rif->destroy_fringe_bitmap)
1411 rif->destroy_fringe_bitmap (n);
1412 xfree (*fbp);
1413 *fbp = NULL;
1416 while (max_used_fringe_bitmap > MAX_STANDARD_FRINGE_BITMAPS
1417 && fringe_bitmaps[max_used_fringe_bitmap - 1] == NULL)
1418 max_used_fringe_bitmap--;
1422 DEFUN ("destroy-fringe-bitmap", Fdestroy_fringe_bitmap, Sdestroy_fringe_bitmap,
1423 1, 1, 0,
1424 doc: /* Destroy fringe bitmap BITMAP.
1425 If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. */)
1426 (Lisp_Object bitmap)
1428 int n;
1430 CHECK_SYMBOL (bitmap);
1431 n = lookup_fringe_bitmap (bitmap);
1432 if (!n)
1433 return Qnil;
1435 destroy_fringe_bitmap (n);
1437 if (n >= MAX_STANDARD_FRINGE_BITMAPS)
1439 Vfringe_bitmaps = Fdelq (bitmap, Vfringe_bitmaps);
1440 /* It would be better to remove the fringe property. */
1441 Fput (bitmap, Qfringe, Qnil);
1444 return Qnil;
1448 /* Initialize bitmap bit.
1450 On X, we bit-swap the built-in bitmaps and reduce bitmap
1451 from short to char array if width is <= 8 bits.
1453 On MAC with big-endian CPU, we need to byte-swap each short.
1455 On W32 and MAC (little endian), there's no need to do this.
1458 #if defined (HAVE_X_WINDOWS)
1459 static const unsigned char swap_nibble[16] = {
1460 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
1461 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
1462 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
1463 0x3, 0xb, 0x7, 0xf}; /* 0011 1011 0111 1111 */
1464 #endif /* HAVE_X_WINDOWS */
1466 static void
1467 init_fringe_bitmap (int which, struct fringe_bitmap *fb, int once_p)
1469 if (once_p || fb->dynamic)
1471 #if defined (HAVE_X_WINDOWS)
1472 unsigned short *bits = fb->bits;
1473 int j;
1475 if (fb->width <= 8)
1477 unsigned char *cbits = (unsigned char *)fb->bits;
1478 for (j = 0; j < fb->height; j++)
1480 unsigned short b = *bits++;
1481 unsigned char c;
1482 c = (unsigned char)((swap_nibble[b & 0xf] << 4)
1483 | (swap_nibble[(b>>4) & 0xf]));
1484 *cbits++ = (c >> (8 - fb->width));
1487 else
1489 for (j = 0; j < fb->height; j++)
1491 unsigned short b = *bits;
1492 b = (unsigned short)((swap_nibble[b & 0xf] << 12)
1493 | (swap_nibble[(b>>4) & 0xf] << 8)
1494 | (swap_nibble[(b>>8) & 0xf] << 4)
1495 | (swap_nibble[(b>>12) & 0xf]));
1496 b >>= (16 - fb->width);
1497 #ifdef WORDS_BIGENDIAN
1498 b = ((b >> 8) | (b << 8));
1499 #endif
1500 *bits++ = b;
1503 #endif /* HAVE_X_WINDOWS */
1507 if (!once_p)
1509 /* XXX Is SELECTED_FRAME OK here? */
1510 struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
1512 destroy_fringe_bitmap (which);
1514 if (rif && rif->define_fringe_bitmap)
1515 rif->define_fringe_bitmap (which, fb->bits, fb->height, fb->width);
1517 fringe_bitmaps[which] = fb;
1518 if (which >= max_used_fringe_bitmap)
1519 max_used_fringe_bitmap = which + 1;
1524 DEFUN ("define-fringe-bitmap", Fdefine_fringe_bitmap, Sdefine_fringe_bitmap,
1525 2, 5, 0,
1526 doc: /* Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.
1527 BITMAP is a symbol identifying the new fringe bitmap.
1528 BITS is either a string or a vector of integers.
1529 HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.
1530 WIDTH must be an integer between 1 and 16, or nil which defaults to 8.
1531 Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
1532 indicating the positioning of the bitmap relative to the rows where it
1533 is used; the default is to center the bitmap. Fifth arg may also be a
1534 list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap
1535 should be repeated.
1536 If BITMAP already exists, the existing definition is replaced. */)
1537 (Lisp_Object bitmap, Lisp_Object bits, Lisp_Object height, Lisp_Object width, Lisp_Object align)
1539 int n, h, i, j;
1540 unsigned short *b;
1541 struct fringe_bitmap fb, *xfb;
1542 int fill1 = 0, fill2 = 0;
1544 CHECK_SYMBOL (bitmap);
1546 if (STRINGP (bits))
1547 h = SCHARS (bits);
1548 else if (VECTORP (bits))
1549 h = ASIZE (bits);
1550 else
1551 wrong_type_argument (Qsequencep, bits);
1553 if (NILP (height))
1554 fb.height = h;
1555 else
1557 CHECK_NUMBER (height);
1558 fb.height = min (XINT (height), 255);
1559 if (fb.height > h)
1561 fill1 = (fb.height - h) / 2;
1562 fill2 = fb.height - h - fill1;
1566 if (NILP (width))
1567 fb.width = 8;
1568 else
1570 CHECK_NUMBER (width);
1571 fb.width = min (XINT (width), 255);
1574 fb.period = 0;
1575 fb.align = ALIGN_BITMAP_CENTER;
1577 if (CONSP (align))
1579 Lisp_Object period = XCDR (align);
1580 if (CONSP (period))
1582 period = XCAR (period);
1583 if (!NILP (period))
1585 fb.period = fb.height;
1586 fb.height = 255;
1589 align = XCAR (align);
1591 if (EQ (align, Qtop))
1592 fb.align = ALIGN_BITMAP_TOP;
1593 else if (EQ (align, Qbottom))
1594 fb.align = ALIGN_BITMAP_BOTTOM;
1595 else if (!NILP (align) && !EQ (align, Qcenter))
1596 error ("Bad align argument");
1598 n = lookup_fringe_bitmap (bitmap);
1599 if (!n)
1601 if (max_used_fringe_bitmap < max_fringe_bitmaps)
1602 n = max_used_fringe_bitmap++;
1603 else
1605 for (n = MAX_STANDARD_FRINGE_BITMAPS;
1606 n < max_fringe_bitmaps;
1607 n++)
1608 if (fringe_bitmaps[n] == NULL)
1609 break;
1611 if (n == max_fringe_bitmaps)
1613 int bitmaps = max_fringe_bitmaps + 20;
1614 if (MAX_FRINGE_BITMAPS < bitmaps)
1615 error ("No free fringe bitmap slots");
1617 i = max_fringe_bitmaps;
1618 fringe_bitmaps
1619 = ((struct fringe_bitmap **)
1620 xrealloc (fringe_bitmaps, bitmaps * sizeof *fringe_bitmaps));
1621 fringe_faces
1622 = (Lisp_Object *) xrealloc (fringe_faces,
1623 bitmaps * sizeof *fringe_faces);
1625 for (i = max_fringe_bitmaps; i < bitmaps; i++)
1627 fringe_bitmaps[i] = NULL;
1628 fringe_faces[i] = Qnil;
1631 max_fringe_bitmaps = bitmaps;
1635 Vfringe_bitmaps = Fcons (bitmap, Vfringe_bitmaps);
1636 Fput (bitmap, Qfringe, make_number (n));
1639 fb.dynamic = 1;
1641 xfb = (struct fringe_bitmap *) xmalloc (sizeof fb
1642 + fb.height * BYTES_PER_BITMAP_ROW);
1643 fb.bits = b = (unsigned short *) (xfb + 1);
1644 memset (b, 0, fb.height);
1646 j = 0;
1647 while (j < fb.height)
1649 for (i = 0; i < fill1 && j < fb.height; i++)
1650 b[j++] = 0;
1651 for (i = 0; i < h && j < fb.height; i++)
1653 Lisp_Object elt = Faref (bits, make_number (i));
1654 b[j++] = NUMBERP (elt) ? XINT (elt) : 0;
1656 for (i = 0; i < fill2 && j < fb.height; i++)
1657 b[j++] = 0;
1660 *xfb = fb;
1662 init_fringe_bitmap (n, xfb, 0);
1664 return bitmap;
1667 DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face, Sset_fringe_bitmap_face,
1668 1, 2, 0,
1669 doc: /* Set face for fringe bitmap BITMAP to FACE.
1670 If FACE is nil, reset face to default fringe face. */)
1671 (Lisp_Object bitmap, Lisp_Object face)
1673 int n;
1674 int face_id;
1676 CHECK_SYMBOL (bitmap);
1677 n = lookup_fringe_bitmap (bitmap);
1678 if (!n)
1679 error ("Undefined fringe bitmap");
1681 if (!NILP (face))
1683 face_id = lookup_derived_face (SELECTED_FRAME (), face,
1684 FRINGE_FACE_ID, 1);
1685 if (face_id < 0)
1686 error ("No such face");
1689 fringe_faces[n] = face;
1691 return Qnil;
1694 DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos, Sfringe_bitmaps_at_pos,
1695 0, 2, 0,
1696 doc: /* Return fringe bitmaps of row containing position POS in window WINDOW.
1697 If WINDOW is nil, use selected window. If POS is nil, use value of point
1698 in that window. Return value is a list (LEFT RIGHT OV), where LEFT
1699 is the symbol for the bitmap in the left fringe (or nil if no bitmap),
1700 RIGHT is similar for the right fringe, and OV is non-nil if there is an
1701 overlay arrow in the left fringe.
1702 Return nil if POS is not visible in WINDOW. */)
1703 (Lisp_Object pos, Lisp_Object window)
1705 struct window *w;
1706 struct glyph_row *row;
1707 int textpos;
1709 if (NILP (window))
1710 window = selected_window;
1711 CHECK_WINDOW (window);
1712 w = XWINDOW (window);
1714 if (!NILP (pos))
1716 CHECK_NUMBER_COERCE_MARKER (pos);
1717 textpos = XINT (pos);
1719 else if (w == XWINDOW (selected_window))
1720 textpos = PT;
1721 else
1722 textpos = XMARKER (w->pointm)->charpos;
1724 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1725 row = row_containing_pos (w, textpos, row, NULL, 0);
1726 if (row)
1727 return list3 (get_fringe_bitmap_name (row->left_fringe_bitmap),
1728 get_fringe_bitmap_name (row->right_fringe_bitmap),
1729 (row->overlay_arrow_bitmap == 0 ? Qnil
1730 : row->overlay_arrow_bitmap < 0 ? Qt
1731 : get_fringe_bitmap_name (row->overlay_arrow_bitmap)));
1732 else
1733 return Qnil;
1737 /***********************************************************************
1738 Initialization
1739 ***********************************************************************/
1741 void
1742 syms_of_fringe (void)
1744 DEFSYM (Qtruncation, "truncation");
1745 DEFSYM (Qcontinuation, "continuation");
1746 DEFSYM (Qoverlay_arrow, "overlay-arrow");
1747 DEFSYM (Qempty_line, "empty-line");
1748 DEFSYM (Qtop_bottom, "top-bottom");
1749 DEFSYM (Qhollow_small, "hollow-small");
1751 defsubr (&Sdestroy_fringe_bitmap);
1752 defsubr (&Sdefine_fringe_bitmap);
1753 defsubr (&Sfringe_bitmaps_at_pos);
1754 defsubr (&Sset_fringe_bitmap_face);
1756 DEFVAR_LISP ("overflow-newline-into-fringe", Voverflow_newline_into_fringe,
1757 doc: /* *Non-nil means that newline may flow into the right fringe.
1758 This means that display lines which are exactly as wide as the window
1759 (not counting the final newline) will only occupy one screen line, by
1760 showing (or hiding) the final newline in the right fringe; when point
1761 is at the final newline, the cursor is shown in the right fringe.
1762 If nil, also continue lines which are exactly as wide as the window. */);
1763 Voverflow_newline_into_fringe = Qt;
1765 DEFVAR_LISP ("fringe-bitmaps", Vfringe_bitmaps,
1766 doc: /* List of fringe bitmap symbols. */);
1767 Vfringe_bitmaps = Qnil;
1770 /* Garbage collection hook */
1772 void
1773 mark_fringe_data (void)
1775 int i;
1777 for (i = 0; i < max_fringe_bitmaps; i++)
1778 if (!NILP (fringe_faces[i]))
1779 mark_object (fringe_faces[i]);
1782 /* Initialize this module when Emacs starts. */
1784 void
1785 init_fringe_once (void)
1787 int bt;
1789 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1790 init_fringe_bitmap (bt, &standard_bitmaps[bt], 1);
1793 void
1794 init_fringe (void)
1796 int i;
1798 max_fringe_bitmaps = MAX_STANDARD_FRINGE_BITMAPS + 20;
1800 fringe_bitmaps
1801 = (struct fringe_bitmap **) xmalloc (max_fringe_bitmaps * sizeof (struct fringe_bitmap *));
1802 fringe_faces
1803 = (Lisp_Object *) xmalloc (max_fringe_bitmaps * sizeof (Lisp_Object));
1805 for (i = 0; i < max_fringe_bitmaps; i++)
1807 fringe_bitmaps[i] = NULL;
1808 fringe_faces[i] = Qnil;
1812 #ifdef HAVE_NTGUI
1814 void
1815 w32_init_fringe (struct redisplay_interface *rif)
1817 int bt;
1819 if (!rif)
1820 return;
1822 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1824 struct fringe_bitmap *fb = &standard_bitmaps[bt];
1825 rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
1829 void
1830 w32_reset_fringes (void)
1832 /* Destroy row bitmaps. */
1833 int bt;
1834 struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
1836 if (!rif)
1837 return;
1839 for (bt = NO_FRINGE_BITMAP + 1; bt < max_used_fringe_bitmap; bt++)
1840 rif->destroy_fringe_bitmap (bt);
1843 #endif /* HAVE_NTGUI */
1845 #endif /* HAVE_WINDOW_SYSTEM */