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/>. */
26 #include "dispextern.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,
89 /***********************************************************************
91 ***********************************************************************/
93 /* Undefined bitmap. A question mark. */
106 static unsigned short question_mark_bits
[] = {
107 0x3c, 0x7e, 0x7e, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18};
109 /* An arrow like this: `<-'. */
120 static unsigned short left_arrow_bits
[] = {
121 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
124 /* Right truncation arrow bitmap `->'. */
135 static unsigned short right_arrow_bits
[] = {
136 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
139 /* Up arrow bitmap. */
150 static unsigned short up_arrow_bits
[] = {
151 0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0x18};
154 /* Down arrow bitmap. */
165 static unsigned short down_arrow_bits
[] = {
166 0x18, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18};
168 /* Marker for continuation lines. */
179 static unsigned short left_curly_arrow_bits
[] = {
180 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
182 /* Marker for continued lines. */
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. */
207 static unsigned short left_triangle_bits
[] = {
208 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
210 /* Overlay arrow bitmap. A triangular arrow. */
221 static unsigned short right_triangle_bits
[] = {
222 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
224 /* First line bitmap. An top-left angle. */
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. */
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. */
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. */
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. */
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. */
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. */
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. */
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. */
359 static unsigned short hollow_square_bits
[] = {
360 0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e};
362 /* Filled square bitmap. */
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. */
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. */
398 static unsigned short horizontal_bar_bits
[] = {
402 /* Bitmap drawn to indicate lines not displaying text if
403 `indicate-empty-lines' is non-nil. */
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
;
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
)
479 bitmap
= Fget (bitmap
, Qfringe
);
480 if (!INTEGERP (bitmap
))
484 if (bn
> NO_FRINGE_BITMAP
485 && bn
< max_used_fringe_bitmap
486 && (bn
< MAX_STANDARD_FRINGE_BITMAPS
487 || fringe_bitmaps
[bn
] != NULL
))
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. */
501 get_fringe_bitmap_name (int bn
)
506 /* Zero means no bitmap -- return nil. */
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
)))
518 bitmaps
= XCDR (bitmaps
);
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
];
533 fb
= &standard_bitmaps
[bn
< MAX_STANDARD_FRINGE_BITMAPS
534 ? bn
: UNDEF_FRINGE_BITMAP
];
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
543 LEFT_P is 1 for left fringe, 0 for right fringe.
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
;
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
)
565 which
= row
->left_fringe_bitmap
;
566 face_id
= row
->left_fringe_face_id
;
567 offset
= row
->left_fringe_offset
;
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);
582 face_id
= FRINGE_FACE_ID
;
585 fb
= get_fringe_bitmap_data (which
);
589 /* Convert row to frame coordinates. */
590 p
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
) + offset
;
597 p
.dh
= (period
> 0 ? (p
.y
% period
) : 0);
600 /* Adjust y to the offset in the row to start drawing the bitmap. */
603 case ALIGN_BITMAP_CENTER
:
604 p
.y
+= (row
->height
- p
.h
) / 2;
606 case ALIGN_BITMAP_BOTTOM
:
607 p
.y
+= (row
->visible_height
- p
.h
);
609 case ALIGN_BITMAP_TOP
:
613 p
.face
= FACE_FROM_ID (f
, face_id
);
617 /* This could happen after clearing face cache.
618 But it shouldn't happen anymore. ++kfs */
622 PREPARE_FACE_FOR_DISPLAY (f
, p
.face
);
624 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
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
;
632 int wd
= WINDOW_LEFT_FRINGE_WIDTH (w
);
633 int x
= window_box_left (w
, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
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
))
652 int x
= window_box_right (w
,
653 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
656 int wd
= WINDOW_RIGHT_FRINGE_WIDTH (w
);
659 p
.x
= x
+ (wd
- p
.wd
) / 2;
660 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
662 if (p
.wd
< wd
|| p
.y
> p
.by
|| p
.y
+ p
.h
< p
.by
+ p
.ny
)
669 FRAME_RIF (f
)->draw_fringe_bitmap (w
, row
, &p
);
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
);
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
);
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;
701 int ix2
= ix1
+ (partial_p
? 2 : 0);
703 /* Lookup in buffer-local fringe-indicator-alist before global alist.
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
);
719 if ((bm1
= XCDR (bm1
)), NILP (bm1
))
720 return NO_FRINGE_BITMAP
;
723 ln1
= XINT (Flength (bm1
));
728 bm
= Fnth (make_number (ix2
), bm1
);
737 bm
= Fnth (make_number (ix1
), bm1
);
743 else if ((bm
= bm1
, !EQ (bm
, Qt
)))
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
));
754 if ((bm2
= XCDR (bm2
)), !NILP (bm2
))
758 ln2
= XINT (Flength (bm2
));
763 bm
= Fnth (make_number (ix2
), bm2
);
775 bm
= Fnth (make_number (ix1
), bm1
);
782 bm
= Fnth (make_number (ix1
), bm2
);
785 return NO_FRINGE_BITMAP
;
787 else if ((bm
= bm2
, NILP (bm
)))
788 return NO_FRINGE_BITMAP
;
791 return lookup_fringe_bitmap (bm
);
796 draw_fringe_bitmap (struct window
*w
, struct glyph_row
*row
, int left_p
)
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
))
810 cursor
= Qhollow_small
;
812 case FILLED_BOX_CURSOR
:
823 w
->phys_cursor_on_p
= 0;
824 row
->cursor_in_fringe_p
= 0;
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. */
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)
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
;
885 if (w
->pseudo_window_p
)
888 /* Must draw line if no fringe */
890 && (WINDOW_LEFT_FRINGE_WIDTH (w
) == 0
891 || WINDOW_RIGHT_FRINGE_WIDTH (w
) == 0))
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
)
900 draw_row_fringe_bitmaps (w
, row
);
901 row
->redraw_fringe_bitmaps_p
= 0;
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
;
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
)
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
)))
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
);
960 /* Anything else means boundary on left and no arrows. */
961 boundary_top
= boundary_bot
= Qleft
;
964 top_ind_rn
= bot_ind_rn
= -1;
967 for (y
= w
->vscroll
, rn
= 0;
968 y
< yb
&& rn
< nrows
;
969 y
+= row
->height
, ++rn
)
971 row
= w
->desired_matrix
->rows
+ rn
;
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
);
986 row
->indicate_top_line_p
= !NILP (arrow_top
);
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));
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);
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
;
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
)
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
)
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
);
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);
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
;
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
)
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
++)
1145 unsigned left_face_id
, right_face_id
;
1146 int left_offset
, right_offset
;
1149 row
= w
->desired_matrix
->rows
+ rn
;
1150 cur
= w
->current_matrix
->rows
+ rn
;
1151 if (!row
->enabled_p
)
1154 left_face_id
= right_face_id
= DEFAULT_FACE_ID
;
1155 left_offset
= right_offset
= 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
);
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);
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.
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
;
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;
1376 FRAME_LEFT_FRINGE_WIDTH (f
) = 0;
1377 FRAME_RIGHT_FRINGE_WIDTH (f
) = real_wid
;
1379 FRAME_FRINGE_COLS (f
) = cols
;
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
))
1396 /* Free resources used by a user-defined bitmap. */
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
);
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
,
1424 doc
: /* Destroy fringe bitmap BITMAP.
1425 If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. */)
1426 (Lisp_Object bitmap
)
1430 CHECK_SYMBOL (bitmap
);
1431 n
= lookup_fringe_bitmap (bitmap
);
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
);
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 */
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
;
1477 unsigned char *cbits
= (unsigned char *)fb
->bits
;
1478 for (j
= 0; j
< fb
->height
; j
++)
1480 unsigned short b
= *bits
++;
1482 c
= (unsigned char)((swap_nibble
[b
& 0xf] << 4)
1483 | (swap_nibble
[(b
>>4) & 0xf]));
1484 *cbits
++ = (c
>> (8 - fb
->width
));
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));
1503 #endif /* HAVE_X_WINDOWS */
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
,
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
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
)
1541 struct fringe_bitmap fb
, *xfb
;
1542 int fill1
= 0, fill2
= 0;
1544 CHECK_SYMBOL (bitmap
);
1548 else if (VECTORP (bits
))
1551 wrong_type_argument (Qsequencep
, bits
);
1557 CHECK_NUMBER (height
);
1558 fb
.height
= min (XINT (height
), 255);
1561 fill1
= (fb
.height
- h
) / 2;
1562 fill2
= fb
.height
- h
- fill1
;
1570 CHECK_NUMBER (width
);
1571 fb
.width
= min (XINT (width
), 255);
1575 fb
.align
= ALIGN_BITMAP_CENTER
;
1579 Lisp_Object period
= XCDR (align
);
1582 period
= XCAR (period
);
1585 fb
.period
= fb
.height
;
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
);
1601 if (max_used_fringe_bitmap
< max_fringe_bitmaps
)
1602 n
= max_used_fringe_bitmap
++;
1605 for (n
= MAX_STANDARD_FRINGE_BITMAPS
;
1606 n
< max_fringe_bitmaps
;
1608 if (fringe_bitmaps
[n
] == NULL
)
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
;
1619 = ((struct fringe_bitmap
**)
1620 xrealloc (fringe_bitmaps
, bitmaps
* sizeof *fringe_bitmaps
));
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
));
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
);
1647 while (j
< fb
.height
)
1649 for (i
= 0; i
< fill1
&& j
< fb
.height
; i
++)
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
++)
1662 init_fringe_bitmap (n
, xfb
, 0);
1667 DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face
, Sset_fringe_bitmap_face
,
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
)
1676 CHECK_SYMBOL (bitmap
);
1677 n
= lookup_fringe_bitmap (bitmap
);
1679 error ("Undefined fringe bitmap");
1683 face_id
= lookup_derived_face (SELECTED_FRAME (), face
,
1686 error ("No such face");
1689 fringe_faces
[n
] = face
;
1694 DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos
, Sfringe_bitmaps_at_pos
,
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
)
1706 struct glyph_row
*row
;
1710 window
= selected_window
;
1711 CHECK_WINDOW (window
);
1712 w
= XWINDOW (window
);
1716 CHECK_NUMBER_COERCE_MARKER (pos
);
1717 textpos
= XINT (pos
);
1719 else if (w
== XWINDOW (selected_window
))
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);
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
)));
1737 /***********************************************************************
1739 ***********************************************************************/
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 */
1773 mark_fringe_data (void)
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. */
1785 init_fringe_once (void)
1789 for (bt
= NO_FRINGE_BITMAP
+ 1; bt
< MAX_STANDARD_FRINGE_BITMAPS
; bt
++)
1790 init_fringe_bitmap (bt
, &standard_bitmaps
[bt
], 1);
1798 max_fringe_bitmaps
= MAX_STANDARD_FRINGE_BITMAPS
+ 20;
1801 = (struct fringe_bitmap
**) xmalloc (max_fringe_bitmaps
* sizeof (struct fringe_bitmap
*));
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
;
1815 w32_init_fringe (struct redisplay_interface
*rif
)
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
);
1830 w32_reset_fringes (void)
1832 /* Destroy row bitmaps. */
1834 struct redisplay_interface
*rif
= FRAME_RIF (SELECTED_FRAME ());
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 */