1 /* Fringe handling (split from xdisp.c).
2 Copyright (C) 1985-1988, 1993-1995, 1997-2011 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 appearence 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 whenver
932 row->indicate_bob_p is set, so it's OK that top_row_ends_at_zv_p
933 is not initialized here. Similarly for bot_ind_rn,
934 row->indicate_eob_p and bot_row_ends_at_zv_p. */
935 int top_row_ends_at_zv_p
IF_LINT (= 0), bot_row_ends_at_zv_p
IF_LINT (= 0);
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
= cur
->redraw_fringe_bitmaps_p
= 1;
1283 cur
->overlay_arrow_bitmap
= row
->overlay_arrow_bitmap
;
1286 row
->left_fringe_bitmap
= left
;
1287 row
->right_fringe_bitmap
= right
;
1288 row
->left_fringe_face_id
= left_face_id
;
1289 row
->right_fringe_face_id
= right_face_id
;
1290 row
->left_fringe_offset
= left_offset
;
1291 row
->right_fringe_offset
= right_offset
;
1292 row
->fringe_bitmap_periodic_p
= periodic_p
;
1295 return redraw_p
&& !keep_current_p
;
1299 /* Compute actual fringe widths for frame F.
1301 If REDRAW is 1, redraw F if the fringe settings was actually
1302 modified and F is visible.
1304 Since the combined left and right fringe must occupy an integral
1305 number of columns, we may need to add some pixels to each fringe.
1306 Typically, we add an equal amount (+/- 1 pixel) to each fringe,
1307 but a negative width value is taken literally (after negating it).
1309 We never make the fringes narrower than specified.
1313 compute_fringe_widths (struct frame
*f
, int redraw
)
1315 int o_left
= FRAME_LEFT_FRINGE_WIDTH (f
);
1316 int o_right
= FRAME_RIGHT_FRINGE_WIDTH (f
);
1317 int o_cols
= FRAME_FRINGE_COLS (f
);
1319 Lisp_Object left_fringe
= Fassq (Qleft_fringe
, f
->param_alist
);
1320 Lisp_Object right_fringe
= Fassq (Qright_fringe
, f
->param_alist
);
1321 int left_fringe_width
, right_fringe_width
;
1323 if (!NILP (left_fringe
))
1324 left_fringe
= Fcdr (left_fringe
);
1325 if (!NILP (right_fringe
))
1326 right_fringe
= Fcdr (right_fringe
);
1328 left_fringe_width
= ((NILP (left_fringe
) || !INTEGERP (left_fringe
)) ? 8 :
1329 XINT (left_fringe
));
1330 right_fringe_width
= ((NILP (right_fringe
) || !INTEGERP (right_fringe
)) ? 8 :
1331 XINT (right_fringe
));
1333 if (left_fringe_width
|| right_fringe_width
)
1335 int left_wid
= left_fringe_width
>= 0 ? left_fringe_width
: -left_fringe_width
;
1336 int right_wid
= right_fringe_width
>= 0 ? right_fringe_width
: -right_fringe_width
;
1337 int conf_wid
= left_wid
+ right_wid
;
1338 int font_wid
= FRAME_COLUMN_WIDTH (f
);
1339 int cols
= (left_wid
+ right_wid
+ font_wid
-1) / font_wid
;
1340 int real_wid
= cols
* font_wid
;
1341 if (left_wid
&& right_wid
)
1343 if (left_fringe_width
< 0)
1345 /* Left fringe width is fixed, adjust right fringe if necessary */
1346 FRAME_LEFT_FRINGE_WIDTH (f
) = left_wid
;
1347 FRAME_RIGHT_FRINGE_WIDTH (f
) = real_wid
- left_wid
;
1349 else if (right_fringe_width
< 0)
1351 /* Right fringe width is fixed, adjust left fringe if necessary */
1352 FRAME_LEFT_FRINGE_WIDTH (f
) = real_wid
- right_wid
;
1353 FRAME_RIGHT_FRINGE_WIDTH (f
) = right_wid
;
1357 /* Adjust both fringes with an equal amount.
1358 Note that we are doing integer arithmetic here, so don't
1359 lose a pixel if the total width is an odd number. */
1360 int fill
= real_wid
- conf_wid
;
1361 FRAME_LEFT_FRINGE_WIDTH (f
) = left_wid
+ fill
/2;
1362 FRAME_RIGHT_FRINGE_WIDTH (f
) = right_wid
+ fill
- fill
/2;
1365 else if (left_fringe_width
)
1367 FRAME_LEFT_FRINGE_WIDTH (f
) = real_wid
;
1368 FRAME_RIGHT_FRINGE_WIDTH (f
) = 0;
1372 FRAME_LEFT_FRINGE_WIDTH (f
) = 0;
1373 FRAME_RIGHT_FRINGE_WIDTH (f
) = real_wid
;
1375 FRAME_FRINGE_COLS (f
) = cols
;
1379 FRAME_LEFT_FRINGE_WIDTH (f
) = 0;
1380 FRAME_RIGHT_FRINGE_WIDTH (f
) = 0;
1381 FRAME_FRINGE_COLS (f
) = 0;
1384 if (redraw
&& FRAME_VISIBLE_P (f
))
1385 if (o_left
!= FRAME_LEFT_FRINGE_WIDTH (f
) ||
1386 o_right
!= FRAME_RIGHT_FRINGE_WIDTH (f
) ||
1387 o_cols
!= FRAME_FRINGE_COLS (f
))
1392 /* Free resources used by a user-defined bitmap. */
1395 destroy_fringe_bitmap (int n
)
1397 struct fringe_bitmap
**fbp
;
1399 fringe_faces
[n
] = Qnil
;
1401 fbp
= &fringe_bitmaps
[n
];
1402 if (*fbp
&& (*fbp
)->dynamic
)
1404 /* XXX Is SELECTED_FRAME OK here? */
1405 struct redisplay_interface
*rif
= FRAME_RIF (SELECTED_FRAME ());
1406 if (rif
&& rif
->destroy_fringe_bitmap
)
1407 rif
->destroy_fringe_bitmap (n
);
1412 while (max_used_fringe_bitmap
> MAX_STANDARD_FRINGE_BITMAPS
1413 && fringe_bitmaps
[max_used_fringe_bitmap
- 1] == NULL
)
1414 max_used_fringe_bitmap
--;
1418 DEFUN ("destroy-fringe-bitmap", Fdestroy_fringe_bitmap
, Sdestroy_fringe_bitmap
,
1420 doc
: /* Destroy fringe bitmap BITMAP.
1421 If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. */)
1422 (Lisp_Object bitmap
)
1426 CHECK_SYMBOL (bitmap
);
1427 n
= lookup_fringe_bitmap (bitmap
);
1431 destroy_fringe_bitmap (n
);
1433 if (n
>= MAX_STANDARD_FRINGE_BITMAPS
)
1435 Vfringe_bitmaps
= Fdelq (bitmap
, Vfringe_bitmaps
);
1436 /* It would be better to remove the fringe property. */
1437 Fput (bitmap
, Qfringe
, Qnil
);
1444 /* Initialize bitmap bit.
1446 On X, we bit-swap the built-in bitmaps and reduce bitmap
1447 from short to char array if width is <= 8 bits.
1449 On MAC with big-endian CPU, we need to byte-swap each short.
1451 On W32 and MAC (little endian), there's no need to do this.
1454 #if defined (HAVE_X_WINDOWS)
1455 static const unsigned char swap_nibble
[16] = {
1456 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
1457 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
1458 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
1459 0x3, 0xb, 0x7, 0xf}; /* 0011 1011 0111 1111 */
1460 #endif /* HAVE_X_WINDOWS */
1463 init_fringe_bitmap (int which
, struct fringe_bitmap
*fb
, int once_p
)
1465 if (once_p
|| fb
->dynamic
)
1467 #if defined (HAVE_X_WINDOWS)
1468 unsigned short *bits
= fb
->bits
;
1473 unsigned char *cbits
= (unsigned char *)fb
->bits
;
1474 for (j
= 0; j
< fb
->height
; j
++)
1476 unsigned short b
= *bits
++;
1478 c
= (unsigned char)((swap_nibble
[b
& 0xf] << 4)
1479 | (swap_nibble
[(b
>>4) & 0xf]));
1480 *cbits
++ = (c
>> (8 - fb
->width
));
1485 for (j
= 0; j
< fb
->height
; j
++)
1487 unsigned short b
= *bits
;
1488 b
= (unsigned short)((swap_nibble
[b
& 0xf] << 12)
1489 | (swap_nibble
[(b
>>4) & 0xf] << 8)
1490 | (swap_nibble
[(b
>>8) & 0xf] << 4)
1491 | (swap_nibble
[(b
>>12) & 0xf]));
1492 b
>>= (16 - fb
->width
);
1493 #ifdef WORDS_BIGENDIAN
1494 b
= ((b
>> 8) | (b
<< 8));
1499 #endif /* HAVE_X_WINDOWS */
1505 /* XXX Is SELECTED_FRAME OK here? */
1506 struct redisplay_interface
*rif
= FRAME_RIF (SELECTED_FRAME ());
1508 destroy_fringe_bitmap (which
);
1510 if (rif
&& rif
->define_fringe_bitmap
)
1511 rif
->define_fringe_bitmap (which
, fb
->bits
, fb
->height
, fb
->width
);
1513 fringe_bitmaps
[which
] = fb
;
1514 if (which
>= max_used_fringe_bitmap
)
1515 max_used_fringe_bitmap
= which
+ 1;
1520 DEFUN ("define-fringe-bitmap", Fdefine_fringe_bitmap
, Sdefine_fringe_bitmap
,
1522 doc
: /* Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.
1523 BITMAP is a symbol identifying the new fringe bitmap.
1524 BITS is either a string or a vector of integers.
1525 HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.
1526 WIDTH must be an integer between 1 and 16, or nil which defaults to 8.
1527 Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
1528 indicating the positioning of the bitmap relative to the rows where it
1529 is used; the default is to center the bitmap. Fifth arg may also be a
1530 list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap
1532 If BITMAP already exists, the existing definition is replaced. */)
1533 (Lisp_Object bitmap
, Lisp_Object bits
, Lisp_Object height
, Lisp_Object width
, Lisp_Object align
)
1537 struct fringe_bitmap fb
, *xfb
;
1538 int fill1
= 0, fill2
= 0;
1540 CHECK_SYMBOL (bitmap
);
1544 else if (VECTORP (bits
))
1547 wrong_type_argument (Qsequencep
, bits
);
1553 CHECK_NUMBER (height
);
1554 fb
.height
= min (XINT (height
), 255);
1557 fill1
= (fb
.height
- h
) / 2;
1558 fill2
= fb
.height
- h
- fill1
;
1566 CHECK_NUMBER (width
);
1567 fb
.width
= min (XINT (width
), 255);
1571 fb
.align
= ALIGN_BITMAP_CENTER
;
1575 Lisp_Object period
= XCDR (align
);
1578 period
= XCAR (period
);
1581 fb
.period
= fb
.height
;
1585 align
= XCAR (align
);
1587 if (EQ (align
, Qtop
))
1588 fb
.align
= ALIGN_BITMAP_TOP
;
1589 else if (EQ (align
, Qbottom
))
1590 fb
.align
= ALIGN_BITMAP_BOTTOM
;
1591 else if (!NILP (align
) && !EQ (align
, Qcenter
))
1592 error ("Bad align argument");
1594 n
= lookup_fringe_bitmap (bitmap
);
1597 if (max_used_fringe_bitmap
< max_fringe_bitmaps
)
1598 n
= max_used_fringe_bitmap
++;
1601 for (n
= MAX_STANDARD_FRINGE_BITMAPS
;
1602 n
< max_fringe_bitmaps
;
1604 if (fringe_bitmaps
[n
] == NULL
)
1607 if (n
== max_fringe_bitmaps
)
1609 if ((max_fringe_bitmaps
+ 20) > MAX_FRINGE_BITMAPS
)
1610 error ("No free fringe bitmap slots");
1612 i
= max_fringe_bitmaps
;
1613 max_fringe_bitmaps
+= 20;
1615 = ((struct fringe_bitmap
**)
1616 xrealloc (fringe_bitmaps
, max_fringe_bitmaps
* sizeof (struct fringe_bitmap
*)));
1618 = (Lisp_Object
*) xrealloc (fringe_faces
, max_fringe_bitmaps
* sizeof (Lisp_Object
));
1620 for (; i
< max_fringe_bitmaps
; i
++)
1622 fringe_bitmaps
[i
] = NULL
;
1623 fringe_faces
[i
] = Qnil
;
1628 Vfringe_bitmaps
= Fcons (bitmap
, Vfringe_bitmaps
);
1629 Fput (bitmap
, Qfringe
, make_number (n
));
1634 xfb
= (struct fringe_bitmap
*) xmalloc (sizeof fb
1635 + fb
.height
* BYTES_PER_BITMAP_ROW
);
1636 fb
.bits
= b
= (unsigned short *) (xfb
+ 1);
1637 memset (b
, 0, fb
.height
);
1640 while (j
< fb
.height
)
1642 for (i
= 0; i
< fill1
&& j
< fb
.height
; i
++)
1644 for (i
= 0; i
< h
&& j
< fb
.height
; i
++)
1646 Lisp_Object elt
= Faref (bits
, make_number (i
));
1647 b
[j
++] = NUMBERP (elt
) ? XINT (elt
) : 0;
1649 for (i
= 0; i
< fill2
&& j
< fb
.height
; i
++)
1655 init_fringe_bitmap (n
, xfb
, 0);
1660 DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face
, Sset_fringe_bitmap_face
,
1662 doc
: /* Set face for fringe bitmap BITMAP to FACE.
1663 If FACE is nil, reset face to default fringe face. */)
1664 (Lisp_Object bitmap
, Lisp_Object face
)
1669 CHECK_SYMBOL (bitmap
);
1670 n
= lookup_fringe_bitmap (bitmap
);
1672 error ("Undefined fringe bitmap");
1676 face_id
= lookup_derived_face (SELECTED_FRAME (), face
,
1679 error ("No such face");
1682 fringe_faces
[n
] = face
;
1687 DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos
, Sfringe_bitmaps_at_pos
,
1689 doc
: /* Return fringe bitmaps of row containing position POS in window WINDOW.
1690 If WINDOW is nil, use selected window. If POS is nil, use value of point
1691 in that window. Return value is a list (LEFT RIGHT OV), where LEFT
1692 is the symbol for the bitmap in the left fringe (or nil if no bitmap),
1693 RIGHT is similar for the right fringe, and OV is non-nil if there is an
1694 overlay arrow in the left fringe.
1695 Return nil if POS is not visible in WINDOW. */)
1696 (Lisp_Object pos
, Lisp_Object window
)
1699 struct glyph_row
*row
;
1703 window
= selected_window
;
1704 CHECK_WINDOW (window
);
1705 w
= XWINDOW (window
);
1709 CHECK_NUMBER_COERCE_MARKER (pos
);
1710 textpos
= XINT (pos
);
1712 else if (w
== XWINDOW (selected_window
))
1715 textpos
= XMARKER (w
->pointm
)->charpos
;
1717 row
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
1718 row
= row_containing_pos (w
, textpos
, row
, NULL
, 0);
1720 return list3 (get_fringe_bitmap_name (row
->left_fringe_bitmap
),
1721 get_fringe_bitmap_name (row
->right_fringe_bitmap
),
1722 (row
->overlay_arrow_bitmap
== 0 ? Qnil
1723 : row
->overlay_arrow_bitmap
< 0 ? Qt
1724 : get_fringe_bitmap_name (row
->overlay_arrow_bitmap
)));
1730 /***********************************************************************
1732 ***********************************************************************/
1735 syms_of_fringe (void)
1737 Qtruncation
= intern_c_string ("truncation");
1738 staticpro (&Qtruncation
);
1739 Qcontinuation
= intern_c_string ("continuation");
1740 staticpro (&Qcontinuation
);
1741 Qoverlay_arrow
= intern_c_string ("overlay-arrow");
1742 staticpro (&Qoverlay_arrow
);
1743 Qempty_line
= intern_c_string ("empty-line");
1744 staticpro (&Qempty_line
);
1745 Qtop_bottom
= intern_c_string ("top-bottom");
1746 staticpro (&Qtop_bottom
);
1747 Qhollow_small
= intern_c_string ("hollow-small");
1748 staticpro (&Qhollow_small
);
1750 defsubr (&Sdestroy_fringe_bitmap
);
1751 defsubr (&Sdefine_fringe_bitmap
);
1752 defsubr (&Sfringe_bitmaps_at_pos
);
1753 defsubr (&Sset_fringe_bitmap_face
);
1755 DEFVAR_LISP ("overflow-newline-into-fringe", Voverflow_newline_into_fringe
,
1756 doc
: /* *Non-nil means that newline may flow into the right fringe.
1757 This means that display lines which are exactly as wide as the window
1758 (not counting the final newline) will only occupy one screen line, by
1759 showing (or hiding) the final newline in the right fringe; when point
1760 is at the final newline, the cursor is shown in the right fringe.
1761 If nil, also continue lines which are exactly as wide as the window. */);
1762 Voverflow_newline_into_fringe
= Qt
;
1764 DEFVAR_LISP ("fringe-bitmaps", Vfringe_bitmaps
,
1765 doc
: /* List of fringe bitmap symbols. */);
1766 Vfringe_bitmaps
= Qnil
;
1769 /* Garbage collection hook */
1772 mark_fringe_data (void)
1776 for (i
= 0; i
< max_fringe_bitmaps
; i
++)
1777 if (!NILP (fringe_faces
[i
]))
1778 mark_object (fringe_faces
[i
]);
1781 /* Initialize this module when Emacs starts. */
1784 init_fringe_once (void)
1788 for (bt
= NO_FRINGE_BITMAP
+ 1; bt
< MAX_STANDARD_FRINGE_BITMAPS
; bt
++)
1789 init_fringe_bitmap(bt
, &standard_bitmaps
[bt
], 1);
1797 max_fringe_bitmaps
= MAX_STANDARD_FRINGE_BITMAPS
+ 20;
1800 = (struct fringe_bitmap
**) xmalloc (max_fringe_bitmaps
* sizeof (struct fringe_bitmap
*));
1802 = (Lisp_Object
*) xmalloc (max_fringe_bitmaps
* sizeof (Lisp_Object
));
1804 for (i
= 0; i
< max_fringe_bitmaps
; i
++)
1806 fringe_bitmaps
[i
] = NULL
;
1807 fringe_faces
[i
] = Qnil
;
1814 w32_init_fringe (struct redisplay_interface
*rif
)
1821 for (bt
= NO_FRINGE_BITMAP
+ 1; bt
< MAX_STANDARD_FRINGE_BITMAPS
; bt
++)
1823 struct fringe_bitmap
*fb
= &standard_bitmaps
[bt
];
1824 rif
->define_fringe_bitmap (bt
, fb
->bits
, fb
->height
, fb
->width
);
1829 w32_reset_fringes (void)
1831 /* Destroy row bitmaps. */
1833 struct redisplay_interface
*rif
= FRAME_RIF (SELECTED_FRAME ());
1838 for (bt
= NO_FRINGE_BITMAP
+ 1; bt
< max_used_fringe_bitmap
; bt
++)
1839 rif
->destroy_fringe_bitmap (bt
);
1842 #endif /* HAVE_NTGUI */
1844 #endif /* HAVE_WINDOW_SYSTEM */