1 /* Fringe handling (split from xdisp.c).
2 Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1997,
3 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
28 #include "dispextern.h"
30 #include "blockinput.h"
31 #include "termhooks.h"
33 #ifdef HAVE_WINDOW_SYSTEM
35 extern Lisp_Object Qfringe
;
36 extern Lisp_Object Qtop
, Qbottom
, Qcenter
;
37 extern Lisp_Object Qup
, Qdown
, Qleft
, Qright
;
39 /* Non-nil means that newline may flow into the right fringe. */
41 Lisp_Object Voverflow_newline_into_fringe
;
43 /* List of known fringe bitmap symbols.
45 The fringe bitmap number is stored in the `fringe' property on
46 those symbols. Names for the built-in bitmaps are installed by
50 Lisp_Object Vfringe_bitmaps
;
52 /* Fringe bitmaps are represented in three different ways:
54 Logical bitmaps are used internally to denote things like
55 'end-of-buffer', 'left-truncation', 'overlay-arrow', etc.
57 Physical bitmaps specify the visual appearence of the bitmap,
58 e.g. 'bottom-left-angle', 'left-arrow', 'left-triangle', etc.
59 User defined bitmaps are physical bitmaps.
61 Internally, fringe bitmaps for a specific display row are
62 represented as a simple integer that is used as an index
63 into the table of all defined bitmaps. This index is stored
64 in the `fringe' property of the physical bitmap symbol.
66 Logical bitmaps are mapped to physical bitmaps through the
67 buffer-local `fringe-indicator-alist' variable.
69 Each element of this alist is a cons (LOGICAL . PHYSICAL)
70 mapping a logical bitmap to a physical bitmap.
71 PHYSICAL is either a symbol to use in both left and right fringe,
72 or a cons of two symbols (LEFT . RIGHT) denoting different
73 bitmaps to use in left and right fringe.
75 LOGICAL is first looked up in the window's buffer's buffer-local
76 value of the fringe-indicator-alist variable, and if not present,
77 in the global value of fringe-indicator-alist.
79 If LOGICAL is not present in either alist, or the PHYSICAL value
80 found is nil, no bitmap is shown for the logical bitmap.
82 The `left-fringe' and `right-fringe' display properties
83 must specify physical bitmap symbols.
86 extern Lisp_Object Qunknown
;
87 Lisp_Object Qtruncation
, Qcontinuation
, Qoverlay_arrow
;
88 Lisp_Object Qempty_line
, Qtop_bottom
;
89 extern Lisp_Object Qbar
, Qhbar
, Qbox
, Qhollow
;
90 Lisp_Object Qhollow_small
;
92 enum fringe_bitmap_align
94 ALIGN_BITMAP_CENTER
= 0,
101 unsigned short *bits
;
106 unsigned dynamic
: 1;
110 /***********************************************************************
112 ***********************************************************************/
114 /* Undefined bitmap. A question mark. */
127 static unsigned short question_mark_bits
[] = {
128 0x3c, 0x7e, 0x7e, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18};
130 /* An arrow like this: `<-'. */
141 static unsigned short left_arrow_bits
[] = {
142 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
145 /* Right truncation arrow bitmap `->'. */
156 static unsigned short right_arrow_bits
[] = {
157 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
160 /* Up arrow bitmap. */
171 static unsigned short up_arrow_bits
[] = {
172 0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0x18};
175 /* Down arrow bitmap. */
186 static unsigned short down_arrow_bits
[] = {
187 0x18, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18};
189 /* Marker for continuation lines. */
200 static unsigned short left_curly_arrow_bits
[] = {
201 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
203 /* Marker for continued lines. */
214 static unsigned short right_curly_arrow_bits
[] = {
215 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
217 /* Reverse Overlay arrow bitmap. A triangular arrow. */
228 static unsigned short left_triangle_bits
[] = {
229 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
231 /* Overlay arrow bitmap. A triangular arrow. */
242 static unsigned short right_triangle_bits
[] = {
243 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
245 /* First line bitmap. An top-left angle. */
256 static unsigned short top_left_angle_bits
[] = {
257 0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00};
259 /* First line bitmap. An right-up angle. */
270 static unsigned short top_right_angle_bits
[] = {
271 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00};
273 /* Last line bitmap. An left-down angle. */
284 static unsigned short bottom_left_angle_bits
[] = {
285 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
287 /* Last line bitmap. An right-down angle. */
298 static unsigned short bottom_right_angle_bits
[] = {
299 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
301 /* First/last line bitmap. An left bracket. */
314 static unsigned short left_bracket_bits
[] = {
315 0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
317 /* First/last line bitmap. An right bracket. */
330 static unsigned short right_bracket_bits
[] = {
331 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
333 /* Filled box cursor bitmap. A filled box; max 13 pixels high. */
349 static unsigned short filled_rectangle_bits
[] = {
350 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
352 /* Hollow box cursor bitmap. A hollow box; max 13 pixels high. */
368 static unsigned short hollow_rectangle_bits
[] = {
369 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe};
371 /* Hollow square bitmap. */
380 static unsigned short hollow_square_bits
[] = {
381 0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e};
383 /* Filled square bitmap. */
392 static unsigned short filled_square_bits
[] = {
393 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e};
395 /* Bar cursor bitmap. A vertical bar; max 13 pixels high. */
411 static unsigned short vertical_bar_bits
[] = {
412 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0};
414 /* HBar cursor bitmap. A horizontal bar; 2 pixels high. */
419 static unsigned short horizontal_bar_bits
[] = {
423 /* Bitmap drawn to indicate lines not displaying text if
424 `indicate-empty-lines' is non-nil. */
433 static unsigned short empty_line_bits
[] = {
434 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
435 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
436 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
437 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
438 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
439 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
440 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
441 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
444 #define BYTES_PER_BITMAP_ROW (sizeof (unsigned short))
445 #define STANDARD_BITMAP_HEIGHT(bits) (sizeof (bits)/BYTES_PER_BITMAP_ROW)
446 #define FRBITS(bits) bits, STANDARD_BITMAP_HEIGHT (bits)
448 /* NOTE: The order of these bitmaps must match the sequence
449 used in fringe.el to define the corresponding symbols. */
451 struct fringe_bitmap standard_bitmaps
[] =
453 { NULL
, 0, 0, 0, 0, 0 }, /* NO_FRINGE_BITMAP */
454 { FRBITS (question_mark_bits
), 8, 0, ALIGN_BITMAP_CENTER
, 0 },
455 { FRBITS (left_arrow_bits
), 8, 0, ALIGN_BITMAP_CENTER
, 0 },
456 { FRBITS (right_arrow_bits
), 8, 0, ALIGN_BITMAP_CENTER
, 0 },
457 { FRBITS (up_arrow_bits
), 8, 0, ALIGN_BITMAP_TOP
, 0 },
458 { FRBITS (down_arrow_bits
), 8, 0, ALIGN_BITMAP_BOTTOM
, 0 },
459 { FRBITS (left_curly_arrow_bits
), 8, 0, ALIGN_BITMAP_CENTER
, 0 },
460 { FRBITS (right_curly_arrow_bits
), 8, 0, ALIGN_BITMAP_CENTER
, 0 },
461 { FRBITS (left_triangle_bits
), 8, 0, ALIGN_BITMAP_CENTER
, 0 },
462 { FRBITS (right_triangle_bits
), 8, 0, ALIGN_BITMAP_CENTER
, 0 },
463 { FRBITS (top_left_angle_bits
), 8, 0, ALIGN_BITMAP_TOP
, 0 },
464 { FRBITS (top_right_angle_bits
), 8, 0, ALIGN_BITMAP_TOP
, 0 },
465 { FRBITS (bottom_left_angle_bits
), 8, 0, ALIGN_BITMAP_BOTTOM
, 0 },
466 { FRBITS (bottom_right_angle_bits
), 8, 0, ALIGN_BITMAP_BOTTOM
, 0 },
467 { FRBITS (left_bracket_bits
), 8, 0, ALIGN_BITMAP_CENTER
, 0 },
468 { FRBITS (right_bracket_bits
), 8, 0, ALIGN_BITMAP_CENTER
, 0 },
469 { FRBITS (filled_rectangle_bits
), 8, 0, ALIGN_BITMAP_CENTER
, 0 },
470 { FRBITS (hollow_rectangle_bits
), 8, 0, ALIGN_BITMAP_CENTER
, 0 },
471 { FRBITS (filled_square_bits
), 8, 0, ALIGN_BITMAP_CENTER
, 0 },
472 { FRBITS (hollow_square_bits
), 8, 0, ALIGN_BITMAP_CENTER
, 0 },
473 { FRBITS (vertical_bar_bits
), 8, 0, ALIGN_BITMAP_CENTER
, 0 },
474 { FRBITS (horizontal_bar_bits
), 8, 0, ALIGN_BITMAP_BOTTOM
, 0 },
475 { FRBITS (empty_line_bits
), 8, 3, ALIGN_BITMAP_TOP
, 0 },
478 #define NO_FRINGE_BITMAP 0
479 #define UNDEF_FRINGE_BITMAP 1
480 #define MAX_STANDARD_FRINGE_BITMAPS (sizeof(standard_bitmaps)/sizeof(standard_bitmaps[0]))
482 static struct fringe_bitmap
**fringe_bitmaps
;
483 static Lisp_Object
*fringe_faces
;
484 static int max_fringe_bitmaps
;
486 int max_used_fringe_bitmap
= MAX_STANDARD_FRINGE_BITMAPS
;
489 /* Lookup bitmap number for symbol BITMAP.
490 Return 0 if not a bitmap. */
493 lookup_fringe_bitmap (bitmap
)
498 bitmap
= Fget (bitmap
, Qfringe
);
499 if (!INTEGERP (bitmap
))
503 if (bn
> NO_FRINGE_BITMAP
504 && bn
< max_used_fringe_bitmap
505 && (bn
< MAX_STANDARD_FRINGE_BITMAPS
506 || fringe_bitmaps
[bn
] != NULL
))
512 /* Get fringe bitmap name for bitmap number BN.
514 Found by traversing Vfringe_bitmaps comparing BN to the
515 fringe property for each symbol.
517 Return BN if not found in Vfringe_bitmaps. */
520 get_fringe_bitmap_name (bn
)
526 /* Zero means no bitmap -- return nil. */
530 bitmaps
= Vfringe_bitmaps
;
531 num
= make_number (bn
);
533 while (CONSP (bitmaps
))
535 Lisp_Object bitmap
= XCAR (bitmaps
);
536 if (EQ (num
, Fget (bitmap
, Qfringe
)))
538 bitmaps
= XCDR (bitmaps
);
544 /* Get fringe bitmap data for bitmap number BN. */
546 static struct fringe_bitmap
*
547 get_fringe_bitmap_data (int bn
)
549 struct fringe_bitmap
*fb
;
551 fb
= fringe_bitmaps
[bn
];
553 fb
= &standard_bitmaps
[bn
< MAX_STANDARD_FRINGE_BITMAPS
554 ? bn
: UNDEF_FRINGE_BITMAP
];
559 /* Draw the bitmap WHICH in one of the left or right fringes of
560 window W. ROW is the glyph row for which to display the bitmap; it
561 determines the vertical position at which the bitmap has to be
563 LEFT_P is 1 for left fringe, 0 for right fringe.
567 draw_fringe_bitmap_1 (w
, row
, left_p
, overlay
, which
)
569 struct glyph_row
*row
;
573 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
574 struct draw_fringe_bitmap_params p
;
575 struct fringe_bitmap
*fb
;
577 int face_id
= DEFAULT_FACE_ID
;
578 int offset
, header_line_height
;
580 p
.overlay_p
= (overlay
& 1) == 1;
581 p
.cursor_p
= (overlay
& 2) == 2;
583 if (which
!= NO_FRINGE_BITMAP
)
589 which
= row
->left_fringe_bitmap
;
590 face_id
= row
->left_fringe_face_id
;
591 offset
= row
->left_fringe_offset
;
595 which
= row
->right_fringe_bitmap
;
596 face_id
= row
->right_fringe_face_id
;
597 offset
= row
->right_fringe_offset
;
600 if (face_id
== DEFAULT_FACE_ID
)
604 if ((face
= fringe_faces
[which
], NILP (face
))
605 || (face_id
= lookup_derived_face (f
, face
, FRINGE_FACE_ID
, 0),
607 face_id
= FRINGE_FACE_ID
;
610 fb
= get_fringe_bitmap_data (which
);
614 /* Convert row to frame coordinates. */
615 p
.y
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
) + offset
;
622 p
.dh
= (period
> 0 ? (p
.y
% period
) : 0);
625 /* Adjust y to the offset in the row to start drawing the bitmap. */
628 case ALIGN_BITMAP_CENTER
:
629 p
.y
+= (row
->height
- p
.h
) / 2;
631 case ALIGN_BITMAP_BOTTOM
:
632 p
.y
+= (row
->visible_height
- p
.h
);
634 case ALIGN_BITMAP_TOP
:
638 p
.face
= FACE_FROM_ID (f
, face_id
);
642 /* This could happen after clearing face cache.
643 But it shouldn't happen anymore. ++kfs */
647 PREPARE_FACE_FOR_DISPLAY (f
, p
.face
);
649 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
652 header_line_height
= WINDOW_HEADER_LINE_HEIGHT (w
);
653 p
.by
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (header_line_height
, row
->y
));
654 p
.ny
= row
->visible_height
;
657 int wd
= WINDOW_LEFT_FRINGE_WIDTH (w
);
658 int x
= window_box_left (w
, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
663 p
.x
= x
- p
.wd
- (wd
- p
.wd
) / 2;
665 if (p
.wd
< wd
|| p
.y
> p
.by
|| p
.y
+ p
.h
< p
.by
+ p
.ny
)
667 /* If W has a vertical border to its left, don't draw over it. */
668 wd
-= ((!WINDOW_LEFTMOST_P (w
)
669 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w
))
677 int x
= window_box_right (w
,
678 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
681 int wd
= WINDOW_RIGHT_FRINGE_WIDTH (w
);
684 p
.x
= x
+ (wd
- p
.wd
) / 2;
685 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
687 if (p
.wd
< wd
|| p
.y
> p
.by
|| p
.y
+ p
.h
< p
.by
+ p
.ny
)
694 FRAME_RIF (f
)->draw_fringe_bitmap (w
, row
, &p
);
698 get_logical_cursor_bitmap (w
, cursor
)
702 Lisp_Object cmap
, bm
= Qnil
;
704 if ((cmap
= XBUFFER (w
->buffer
)->fringe_cursor_alist
), !NILP (cmap
))
706 bm
= Fassq (cursor
, cmap
);
709 if ((bm
= XCDR (bm
)), NILP (bm
))
710 return NO_FRINGE_BITMAP
;
711 return lookup_fringe_bitmap (bm
);
714 if (EQ (cmap
, buffer_defaults
.fringe_cursor_alist
))
715 return NO_FRINGE_BITMAP
;
716 bm
= Fassq (cursor
, buffer_defaults
.fringe_cursor_alist
);
717 if (!CONSP (bm
) || ((bm
= XCDR (bm
)), NILP (bm
)))
718 return NO_FRINGE_BITMAP
;
719 return lookup_fringe_bitmap (bm
);
723 get_logical_fringe_bitmap (w
, bitmap
, right_p
, partial_p
)
726 int right_p
, partial_p
;
728 Lisp_Object cmap
, bm1
= Qnil
, bm2
= Qnil
, bm
;
729 int ln1
= 0, ln2
= 0;
731 int ix2
= ix1
+ (partial_p
? 2 : 0);
733 /* Lookup in buffer-local fringe-indicator-alist before global alist.
736 BITMAP -- use for all
737 (L R) -- use for left right (whether partial or not)
738 (L R PL PR) -- use for left right partial-left partial-right
739 If any value in local binding is not present or t, use global value.
741 If partial, lookup partial bitmap in default value if not found here.
742 If not partial, or no partial spec is present, use non-partial bitmap. */
744 if ((cmap
= XBUFFER (w
->buffer
)->fringe_indicator_alist
), !NILP (cmap
))
746 bm1
= Fassq (bitmap
, cmap
);
749 if ((bm1
= XCDR (bm1
)), NILP (bm1
))
750 return NO_FRINGE_BITMAP
;
753 ln1
= XINT (Flength (bm1
));
758 bm
= Fnth (make_number (ix2
), bm1
);
767 bm
= Fnth (make_number (ix1
), bm1
);
773 else if ((bm
= bm1
, !EQ (bm
, Qt
)))
778 if (!EQ (cmap
, buffer_defaults
.fringe_indicator_alist
)
779 && !NILP (buffer_defaults
.fringe_indicator_alist
))
781 bm2
= Fassq (bitmap
, buffer_defaults
.fringe_indicator_alist
);
784 if ((bm2
= XCDR (bm2
)), !NILP (bm2
))
788 ln2
= XINT (Flength (bm2
));
793 bm
= Fnth (make_number (ix2
), bm2
);
805 bm
= Fnth (make_number (ix1
), bm1
);
812 bm
= Fnth (make_number (ix1
), bm2
);
815 return NO_FRINGE_BITMAP
;
817 else if ((bm
= bm2
, NILP (bm
)))
818 return NO_FRINGE_BITMAP
;
821 return lookup_fringe_bitmap (bm
);
826 draw_fringe_bitmap (w
, row
, left_p
)
828 struct glyph_row
*row
;
833 if (!left_p
&& row
->cursor_in_fringe_p
)
835 Lisp_Object cursor
= Qnil
;
837 switch (w
->phys_cursor_type
)
839 case HOLLOW_BOX_CURSOR
:
840 if (row
->visible_height
>= STANDARD_BITMAP_HEIGHT (hollow_rectangle_bits
))
843 cursor
= Qhollow_small
;
845 case FILLED_BOX_CURSOR
:
856 w
->phys_cursor_on_p
= 0;
857 row
->cursor_in_fringe_p
= 0;
862 int bm
= get_logical_cursor_bitmap (w
, cursor
);
863 if (bm
!= NO_FRINGE_BITMAP
)
865 draw_fringe_bitmap_1 (w
, row
, 0, 2, bm
);
866 overlay
= EQ (cursor
, Qbox
) ? 3 : 1;
871 draw_fringe_bitmap_1 (w
, row
, left_p
, overlay
, NO_FRINGE_BITMAP
);
873 if (left_p
&& row
->overlay_arrow_bitmap
!= NO_FRINGE_BITMAP
)
874 draw_fringe_bitmap_1 (w
, row
, 1, 1, row
->overlay_arrow_bitmap
);
878 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
879 function with input blocked. */
882 draw_row_fringe_bitmaps (w
, row
)
884 struct glyph_row
*row
;
886 xassert (interrupt_input_blocked
);
888 /* If row is completely invisible, because of vscrolling, we
889 don't have to draw anything. */
890 if (row
->visible_height
<= 0)
893 if (WINDOW_LEFT_FRINGE_WIDTH (w
) != 0)
894 draw_fringe_bitmap (w
, row
, 1);
896 if (WINDOW_RIGHT_FRINGE_WIDTH (w
) != 0)
897 draw_fringe_bitmap (w
, row
, 0);
900 /* Draw the fringes of window W. Only fringes for rows marked for
901 update in redraw_fringe_bitmaps_p are drawn.
903 Return >0 if left or right fringe was redrawn in any way.
905 If NO_FRINGE is non-zero, also return >0 if either fringe has zero width.
907 A return value >0 indicates that the vertical line between windows
908 needs update (as it may be drawn in the fringe).
912 draw_window_fringes (w
, no_fringe
)
916 struct glyph_row
*row
;
917 int yb
= window_text_bottom_y (w
);
918 int nrows
= w
->current_matrix
->nrows
;
922 if (w
->pseudo_window_p
)
925 /* Must draw line if no fringe */
927 && (WINDOW_LEFT_FRINGE_WIDTH (w
) == 0
928 || WINDOW_RIGHT_FRINGE_WIDTH (w
) == 0))
931 for (y
= w
->vscroll
, rn
= 0, row
= w
->current_matrix
->rows
;
932 y
< yb
&& rn
< nrows
;
933 y
+= row
->height
, ++row
, ++rn
)
935 if (!row
->redraw_fringe_bitmaps_p
)
937 draw_row_fringe_bitmaps (w
, row
);
938 row
->redraw_fringe_bitmaps_p
= 0;
946 /* Recalculate the bitmaps to show in the fringes of window W.
947 Only mark rows with modified bitmaps for update in redraw_fringe_bitmaps_p.
949 If KEEP_CURRENT_P is 0, update current_matrix too. */
952 update_window_fringes (w
, keep_current_p
)
956 struct glyph_row
*row
, *cur
= 0;
957 int yb
= window_text_bottom_y (w
);
958 int rn
, nrows
= w
->current_matrix
->nrows
;
961 Lisp_Object boundary_top
= Qnil
, boundary_bot
= Qnil
;
962 Lisp_Object arrow_top
= Qnil
, arrow_bot
= Qnil
;
963 Lisp_Object empty_pos
;
964 Lisp_Object ind
= Qnil
;
965 #define MAX_BITMAP_CACHE (8*4)
966 int bitmap_cache
[MAX_BITMAP_CACHE
];
967 int top_ind_rn
, bot_ind_rn
;
968 int top_ind_min_y
, bot_ind_max_y
;
969 int top_row_ends_at_zv_p
, bot_row_ends_at_zv_p
;
971 if (w
->pseudo_window_p
)
974 if (!MINI_WINDOW_P (w
)
975 && (ind
= XBUFFER (w
->buffer
)->indicate_buffer_boundaries
, !NILP (ind
)))
977 if (EQ (ind
, Qleft
) || EQ (ind
, Qright
))
978 boundary_top
= boundary_bot
= arrow_top
= arrow_bot
= ind
;
979 else if (CONSP (ind
) && CONSP (XCAR (ind
)))
982 if (pos
= Fassq (Qt
, ind
), !NILP (pos
))
983 boundary_top
= boundary_bot
= arrow_top
= arrow_bot
= XCDR (pos
);
984 if (pos
= Fassq (Qtop
, ind
), !NILP (pos
))
985 boundary_top
= XCDR (pos
);
986 if (pos
= Fassq (Qbottom
, ind
), !NILP (pos
))
987 boundary_bot
= XCDR (pos
);
988 if (pos
= Fassq (Qup
, ind
), !NILP (pos
))
989 arrow_top
= XCDR (pos
);
990 if (pos
= Fassq (Qdown
, ind
), !NILP (pos
))
991 arrow_bot
= XCDR (pos
);
994 /* Anything else means boundary on left and no arrows. */
995 boundary_top
= boundary_bot
= Qleft
;
998 top_ind_rn
= bot_ind_rn
= -1;
1001 for (y
= w
->vscroll
, rn
= 0;
1002 y
< yb
&& rn
< nrows
;
1003 y
+= row
->height
, ++rn
)
1005 row
= w
->desired_matrix
->rows
+ rn
;
1006 if (!row
->enabled_p
)
1007 row
= w
->current_matrix
->rows
+ rn
;
1009 row
->indicate_bob_p
= row
->indicate_top_line_p
= 0;
1010 row
->indicate_eob_p
= row
->indicate_bottom_line_p
= 0;
1012 if (!row
->mode_line_p
)
1014 if (top_ind_rn
< 0 && row
->visible_height
> 0)
1016 if (MATRIX_ROW_START_CHARPOS (row
) <= BUF_BEGV (XBUFFER (w
->buffer
))
1017 && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w
, row
))
1018 row
->indicate_bob_p
= !NILP (boundary_top
);
1020 row
->indicate_top_line_p
= !NILP (arrow_top
);
1026 if (MATRIX_ROW_END_CHARPOS (row
) >= BUF_ZV (XBUFFER (w
->buffer
))
1027 && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w
, row
))
1028 row
->indicate_eob_p
= !NILP (boundary_bot
), bot_ind_rn
= rn
;
1029 else if (y
+ row
->height
>= yb
)
1030 row
->indicate_bottom_line_p
= !NILP (arrow_bot
), bot_ind_rn
= rn
;
1036 empty_pos
= XBUFFER (w
->buffer
)->indicate_empty_lines
;
1037 if (!NILP (empty_pos
) && !EQ (empty_pos
, Qright
))
1038 empty_pos
= WINDOW_LEFT_FRINGE_WIDTH (w
) == 0 ? Qright
: Qleft
;
1040 for (y
= 0; y
< MAX_BITMAP_CACHE
; y
++)
1041 bitmap_cache
[y
] = -1;
1043 #define LEFT_FRINGE(cache, which, partial_p) \
1044 (bitmap_cache[cache*4+partial_p] >= 0 \
1045 ? bitmap_cache[cache*4+partial_p] \
1046 : (bitmap_cache[cache*4+partial_p] = \
1047 get_logical_fringe_bitmap (w, which, 0, partial_p)))
1049 #define RIGHT_FRINGE(cache, which, partial_p) \
1050 (bitmap_cache[cache*4+2+partial_p] >= 0 \
1051 ? bitmap_cache[cache*4+2+partial_p] \
1052 : (bitmap_cache[cache*4+2+partial_p] = \
1053 get_logical_fringe_bitmap (w, which, 1, partial_p)))
1056 /* Extend top-aligned top indicator (or bottom-aligned bottom
1057 indicator) to adjacent rows if it doesn't fit in one row. */
1058 top_ind_min_y
= bot_ind_max_y
= -1;
1059 if (top_ind_rn
>= 0)
1061 int bn
= NO_FRINGE_BITMAP
;
1063 row
= w
->desired_matrix
->rows
+ top_ind_rn
;
1064 if (!row
->enabled_p
)
1065 row
= w
->current_matrix
->rows
+ top_ind_rn
;
1067 top_row_ends_at_zv_p
= row
->ends_at_zv_p
;
1068 if (row
->indicate_bob_p
)
1070 if (EQ (boundary_top
, Qleft
))
1071 bn
= ((row
->indicate_eob_p
&& EQ (boundary_bot
, Qleft
))
1072 ? LEFT_FRINGE (1, Qtop_bottom
, row
->ends_at_zv_p
)
1073 : LEFT_FRINGE (2, Qtop
, 0));
1075 bn
= ((row
->indicate_eob_p
&& EQ (boundary_bot
, Qright
))
1076 ? RIGHT_FRINGE (1, Qtop_bottom
, row
->ends_at_zv_p
)
1077 : RIGHT_FRINGE (2, Qtop
, 0));
1079 else if (row
->indicate_top_line_p
)
1081 if (EQ (arrow_top
, Qleft
))
1082 bn
= LEFT_FRINGE (6, Qup
, 0);
1084 bn
= RIGHT_FRINGE (6, Qup
, 0);
1087 if (bn
!= NO_FRINGE_BITMAP
)
1089 struct fringe_bitmap
*fb
= get_fringe_bitmap_data (bn
);
1091 if (fb
->align
== ALIGN_BITMAP_TOP
&& fb
->period
== 0)
1093 struct glyph_row
*row1
;
1096 top_ind_min_y
= WINDOW_HEADER_LINE_HEIGHT (w
);
1097 top_ind_max_y
= top_ind_min_y
+ fb
->height
;
1098 if (top_ind_max_y
> yb
)
1101 for (y
= row
->y
+ row
->height
, rn
= top_ind_rn
+ 1;
1102 y
< top_ind_max_y
&& rn
< nrows
;
1103 y
+= row1
->height
, rn
++)
1105 if (bot_ind_rn
>= 0 && rn
>= bot_ind_rn
)
1108 row1
= w
->desired_matrix
->rows
+ rn
;
1109 if (!row1
->enabled_p
)
1110 row1
= w
->current_matrix
->rows
+ rn
;
1112 row1
->indicate_bob_p
= row
->indicate_bob_p
;
1113 row1
->indicate_top_line_p
= row
->indicate_top_line_p
;
1118 if (bot_ind_rn
>= 0)
1120 int bn
= NO_FRINGE_BITMAP
;
1122 row
= w
->desired_matrix
->rows
+ bot_ind_rn
;
1123 if (!row
->enabled_p
)
1124 row
= w
->current_matrix
->rows
+ bot_ind_rn
;
1126 bot_row_ends_at_zv_p
= row
->ends_at_zv_p
;
1127 if (row
->indicate_eob_p
)
1129 if (EQ (boundary_bot
, Qleft
))
1130 bn
= LEFT_FRINGE (3, Qbottom
, row
->ends_at_zv_p
);
1132 bn
= RIGHT_FRINGE (3, Qbottom
, row
->ends_at_zv_p
);
1134 else if (row
->indicate_bottom_line_p
)
1136 if (EQ (arrow_bot
, Qleft
))
1137 bn
= LEFT_FRINGE (7, Qdown
, 0);
1139 bn
= RIGHT_FRINGE (7, Qdown
, 0);
1142 if (bn
!= NO_FRINGE_BITMAP
)
1144 struct fringe_bitmap
*fb
= get_fringe_bitmap_data (bn
);
1146 if (fb
->align
== ALIGN_BITMAP_BOTTOM
&& fb
->period
== 0)
1148 struct glyph_row
*row1
;
1151 bot_ind_max_y
= row
->y
+ row
->visible_height
;
1152 bot_ind_min_y
= bot_ind_max_y
- fb
->height
;
1153 if (bot_ind_min_y
< WINDOW_HEADER_LINE_HEIGHT (w
))
1154 bot_ind_min_y
= WINDOW_HEADER_LINE_HEIGHT (w
);
1156 for (y
= row
->y
, rn
= bot_ind_rn
- 1;
1157 y
>= bot_ind_min_y
&& rn
>= 0;
1158 y
-= row1
->height
, rn
--)
1160 if (top_ind_rn
>= 0 && rn
<= top_ind_rn
)
1163 row1
= w
->desired_matrix
->rows
+ rn
;
1164 if (!row1
->enabled_p
)
1165 row1
= w
->current_matrix
->rows
+ rn
;
1167 row1
->indicate_eob_p
= row
->indicate_eob_p
;
1168 row1
->indicate_bottom_line_p
= row
->indicate_bottom_line_p
;
1174 for (y
= w
->vscroll
, rn
= 0;
1175 y
< yb
&& rn
< nrows
;
1176 y
+= row
->height
, rn
++)
1179 unsigned left_face_id
, right_face_id
;
1180 int left_offset
, right_offset
;
1183 row
= w
->desired_matrix
->rows
+ rn
;
1184 cur
= w
->current_matrix
->rows
+ rn
;
1185 if (!row
->enabled_p
)
1188 left_face_id
= right_face_id
= DEFAULT_FACE_ID
;
1189 left_offset
= right_offset
= 0;
1192 /* Decide which bitmap to draw in the left fringe. */
1193 if (WINDOW_LEFT_FRINGE_WIDTH (w
) == 0)
1194 left
= NO_FRINGE_BITMAP
;
1195 else if (row
->left_user_fringe_bitmap
!= NO_FRINGE_BITMAP
)
1197 left
= row
->left_user_fringe_bitmap
;
1198 left_face_id
= row
->left_user_fringe_face_id
;
1200 else if (row
->truncated_on_left_p
)
1201 left
= LEFT_FRINGE(0, Qtruncation
, 0);
1202 else if (row
->indicate_bob_p
&& EQ (boundary_top
, Qleft
))
1204 left
= ((row
->indicate_eob_p
&& EQ (boundary_bot
, Qleft
))
1205 ? LEFT_FRINGE (1, Qtop_bottom
, top_row_ends_at_zv_p
)
1206 : LEFT_FRINGE (2, Qtop
, 0));
1207 if (top_ind_min_y
>= 0)
1208 left_offset
= top_ind_min_y
- row
->y
;
1210 else if (row
->indicate_eob_p
&& EQ (boundary_bot
, Qleft
))
1212 left
= LEFT_FRINGE (3, Qbottom
, bot_row_ends_at_zv_p
);
1213 if (bot_ind_max_y
>= 0)
1214 left_offset
= bot_ind_max_y
- (row
->y
+ row
->visible_height
);
1216 else if (MATRIX_ROW_CONTINUATION_LINE_P (row
))
1217 left
= LEFT_FRINGE (4, Qcontinuation
, 0);
1218 else if (row
->indicate_empty_line_p
&& EQ (empty_pos
, Qleft
))
1219 left
= LEFT_FRINGE (5, Qempty_line
, 0);
1220 else if (row
->indicate_top_line_p
&& EQ (arrow_top
, Qleft
))
1222 left
= LEFT_FRINGE (6, Qup
, 0);
1223 if (top_ind_min_y
>= 0)
1224 left_offset
= top_ind_min_y
- row
->y
;
1226 else if (row
->indicate_bottom_line_p
&& EQ (arrow_bot
, Qleft
))
1228 left
= LEFT_FRINGE (7, Qdown
, 0);
1229 if (bot_ind_max_y
>= 0)
1230 left_offset
= bot_ind_max_y
- (row
->y
+ row
->visible_height
);
1233 left
= NO_FRINGE_BITMAP
;
1235 /* Decide which bitmap to draw in the right fringe. */
1236 if (WINDOW_RIGHT_FRINGE_WIDTH (w
) == 0)
1237 right
= NO_FRINGE_BITMAP
;
1238 else if (row
->right_user_fringe_bitmap
!= NO_FRINGE_BITMAP
)
1240 right
= row
->right_user_fringe_bitmap
;
1241 right_face_id
= row
->right_user_fringe_face_id
;
1243 else if (row
->truncated_on_right_p
)
1244 right
= RIGHT_FRINGE (0, Qtruncation
, 0);
1245 else if (row
->indicate_bob_p
&& EQ (boundary_top
, Qright
))
1247 right
= ((row
->indicate_eob_p
&& EQ (boundary_bot
, Qright
))
1248 ? RIGHT_FRINGE (1, Qtop_bottom
, top_row_ends_at_zv_p
)
1249 : RIGHT_FRINGE (2, Qtop
, 0));
1250 if (top_ind_min_y
>= 0)
1251 right_offset
= top_ind_min_y
- row
->y
;
1253 else if (row
->indicate_eob_p
&& EQ (boundary_bot
, Qright
))
1255 right
= RIGHT_FRINGE (3, Qbottom
, bot_row_ends_at_zv_p
);
1256 if (bot_ind_max_y
>= 0)
1257 right_offset
= bot_ind_max_y
- (row
->y
+ row
->visible_height
);
1259 else if (row
->continued_p
)
1260 right
= RIGHT_FRINGE (4, Qcontinuation
, 0);
1261 else if (row
->indicate_top_line_p
&& EQ (arrow_top
, Qright
))
1263 right
= RIGHT_FRINGE (6, Qup
, 0);
1264 if (top_ind_min_y
>= 0)
1265 right_offset
= top_ind_min_y
- row
->y
;
1267 else if (row
->indicate_bottom_line_p
&& EQ (arrow_bot
, Qright
))
1269 right
= RIGHT_FRINGE (7, Qdown
, 0);
1270 if (bot_ind_max_y
>= 0)
1271 right_offset
= bot_ind_max_y
- (row
->y
+ row
->visible_height
);
1273 else if (row
->indicate_empty_line_p
&& EQ (empty_pos
, Qright
))
1274 right
= RIGHT_FRINGE (5, Qempty_line
, 0);
1276 right
= NO_FRINGE_BITMAP
;
1278 periodic_p
= (get_fringe_bitmap_data (left
)->period
!= 0
1279 || get_fringe_bitmap_data (right
)->period
!= 0);
1281 if (row
->y
!= cur
->y
1282 || row
->visible_height
!= cur
->visible_height
1283 || row
->ends_at_zv_p
!= cur
->ends_at_zv_p
1284 || left
!= cur
->left_fringe_bitmap
1285 || right
!= cur
->right_fringe_bitmap
1286 || left_face_id
!= cur
->left_fringe_face_id
1287 || right_face_id
!= cur
->right_fringe_face_id
1288 || left_offset
!= cur
->left_fringe_offset
1289 || right_offset
!= cur
->right_fringe_offset
1290 || periodic_p
!= cur
->fringe_bitmap_periodic_p
1291 || cur
->redraw_fringe_bitmaps_p
)
1293 redraw_p
= row
->redraw_fringe_bitmaps_p
= 1;
1294 if (!keep_current_p
)
1296 cur
->redraw_fringe_bitmaps_p
= 1;
1297 cur
->left_fringe_bitmap
= left
;
1298 cur
->right_fringe_bitmap
= right
;
1299 cur
->left_fringe_face_id
= left_face_id
;
1300 cur
->right_fringe_face_id
= right_face_id
;
1301 cur
->left_fringe_offset
= left_offset
;
1302 cur
->right_fringe_offset
= right_offset
;
1303 cur
->fringe_bitmap_periodic_p
= periodic_p
;
1307 if (row
->overlay_arrow_bitmap
< 0)
1308 row
->overlay_arrow_bitmap
= get_logical_fringe_bitmap (w
, Qoverlay_arrow
, 0, 0);
1310 if (row
->overlay_arrow_bitmap
!= cur
->overlay_arrow_bitmap
)
1312 redraw_p
= row
->redraw_fringe_bitmaps_p
= 1;
1313 if (!keep_current_p
)
1315 cur
->redraw_fringe_bitmaps_p
= 1;
1316 cur
->overlay_arrow_bitmap
= row
->overlay_arrow_bitmap
;
1320 row
->left_fringe_bitmap
= left
;
1321 row
->right_fringe_bitmap
= right
;
1322 row
->left_fringe_face_id
= left_face_id
;
1323 row
->right_fringe_face_id
= right_face_id
;
1324 row
->left_fringe_offset
= left_offset
;
1325 row
->right_fringe_offset
= right_offset
;
1326 row
->fringe_bitmap_periodic_p
= periodic_p
;
1329 return redraw_p
&& !keep_current_p
;
1333 /* Compute actual fringe widths for frame F.
1335 If REDRAW is 1, redraw F if the fringe settings was actually
1336 modified and F is visible.
1338 Since the combined left and right fringe must occupy an integral
1339 number of columns, we may need to add some pixels to each fringe.
1340 Typically, we add an equal amount (+/- 1 pixel) to each fringe,
1341 but a negative width value is taken literally (after negating it).
1343 We never make the fringes narrower than specified.
1347 compute_fringe_widths (f
, redraw
)
1351 int o_left
= FRAME_LEFT_FRINGE_WIDTH (f
);
1352 int o_right
= FRAME_RIGHT_FRINGE_WIDTH (f
);
1353 int o_cols
= FRAME_FRINGE_COLS (f
);
1355 Lisp_Object left_fringe
= Fassq (Qleft_fringe
, f
->param_alist
);
1356 Lisp_Object right_fringe
= Fassq (Qright_fringe
, f
->param_alist
);
1357 int left_fringe_width
, right_fringe_width
;
1359 if (!NILP (left_fringe
))
1360 left_fringe
= Fcdr (left_fringe
);
1361 if (!NILP (right_fringe
))
1362 right_fringe
= Fcdr (right_fringe
);
1364 left_fringe_width
= ((NILP (left_fringe
) || !INTEGERP (left_fringe
)) ? 8 :
1365 XINT (left_fringe
));
1366 right_fringe_width
= ((NILP (right_fringe
) || !INTEGERP (right_fringe
)) ? 8 :
1367 XINT (right_fringe
));
1369 if (left_fringe_width
|| right_fringe_width
)
1371 int left_wid
= left_fringe_width
>= 0 ? left_fringe_width
: -left_fringe_width
;
1372 int right_wid
= right_fringe_width
>= 0 ? right_fringe_width
: -right_fringe_width
;
1373 int conf_wid
= left_wid
+ right_wid
;
1374 int font_wid
= FRAME_COLUMN_WIDTH (f
);
1375 int cols
= (left_wid
+ right_wid
+ font_wid
-1) / font_wid
;
1376 int real_wid
= cols
* font_wid
;
1377 if (left_wid
&& right_wid
)
1379 if (left_fringe_width
< 0)
1381 /* Left fringe width is fixed, adjust right fringe if necessary */
1382 FRAME_LEFT_FRINGE_WIDTH (f
) = left_wid
;
1383 FRAME_RIGHT_FRINGE_WIDTH (f
) = real_wid
- left_wid
;
1385 else if (right_fringe_width
< 0)
1387 /* Right fringe width is fixed, adjust left fringe if necessary */
1388 FRAME_LEFT_FRINGE_WIDTH (f
) = real_wid
- right_wid
;
1389 FRAME_RIGHT_FRINGE_WIDTH (f
) = right_wid
;
1393 /* Adjust both fringes with an equal amount.
1394 Note that we are doing integer arithmetic here, so don't
1395 lose a pixel if the total width is an odd number. */
1396 int fill
= real_wid
- conf_wid
;
1397 FRAME_LEFT_FRINGE_WIDTH (f
) = left_wid
+ fill
/2;
1398 FRAME_RIGHT_FRINGE_WIDTH (f
) = right_wid
+ fill
- fill
/2;
1401 else if (left_fringe_width
)
1403 FRAME_LEFT_FRINGE_WIDTH (f
) = real_wid
;
1404 FRAME_RIGHT_FRINGE_WIDTH (f
) = 0;
1408 FRAME_LEFT_FRINGE_WIDTH (f
) = 0;
1409 FRAME_RIGHT_FRINGE_WIDTH (f
) = real_wid
;
1411 FRAME_FRINGE_COLS (f
) = cols
;
1415 FRAME_LEFT_FRINGE_WIDTH (f
) = 0;
1416 FRAME_RIGHT_FRINGE_WIDTH (f
) = 0;
1417 FRAME_FRINGE_COLS (f
) = 0;
1420 if (redraw
&& FRAME_VISIBLE_P (f
))
1421 if (o_left
!= FRAME_LEFT_FRINGE_WIDTH (f
) ||
1422 o_right
!= FRAME_RIGHT_FRINGE_WIDTH (f
) ||
1423 o_cols
!= FRAME_FRINGE_COLS (f
))
1428 /* Free resources used by a user-defined bitmap. */
1431 destroy_fringe_bitmap (n
)
1434 struct fringe_bitmap
**fbp
;
1436 fringe_faces
[n
] = Qnil
;
1438 fbp
= &fringe_bitmaps
[n
];
1439 if (*fbp
&& (*fbp
)->dynamic
)
1441 /* XXX Is SELECTED_FRAME OK here? */
1442 struct redisplay_interface
*rif
= FRAME_RIF (SELECTED_FRAME ());
1443 if (rif
&& rif
->destroy_fringe_bitmap
)
1444 rif
->destroy_fringe_bitmap (n
);
1449 while (max_used_fringe_bitmap
> MAX_STANDARD_FRINGE_BITMAPS
1450 && fringe_bitmaps
[max_used_fringe_bitmap
- 1] == NULL
)
1451 max_used_fringe_bitmap
--;
1455 DEFUN ("destroy-fringe-bitmap", Fdestroy_fringe_bitmap
, Sdestroy_fringe_bitmap
,
1457 doc
: /* Destroy fringe bitmap BITMAP.
1458 If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. */)
1464 CHECK_SYMBOL (bitmap
);
1465 n
= lookup_fringe_bitmap (bitmap
);
1469 destroy_fringe_bitmap (n
);
1471 if (n
>= MAX_STANDARD_FRINGE_BITMAPS
)
1473 Vfringe_bitmaps
= Fdelq (bitmap
, Vfringe_bitmaps
);
1474 /* It would be better to remove the fringe property. */
1475 Fput (bitmap
, Qfringe
, Qnil
);
1482 /* Initialize bitmap bit.
1484 On X, we bit-swap the built-in bitmaps and reduce bitmap
1485 from short to char array if width is <= 8 bits.
1487 On MAC with big-endian CPU, we need to byte-swap each short.
1489 On W32 and MAC (little endian), there's no need to do this.
1492 #if defined (HAVE_X_WINDOWS)
1493 static const unsigned char swap_nibble
[16] = {
1494 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
1495 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
1496 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
1497 0x3, 0xb, 0x7, 0xf}; /* 0011 1011 0111 1111 */
1498 #endif /* HAVE_X_WINDOWS */
1501 init_fringe_bitmap (which
, fb
, once_p
)
1503 struct fringe_bitmap
*fb
;
1506 if (once_p
|| fb
->dynamic
)
1508 #if defined (HAVE_X_WINDOWS)
1509 unsigned short *bits
= fb
->bits
;
1514 unsigned char *cbits
= (unsigned char *)fb
->bits
;
1515 for (j
= 0; j
< fb
->height
; j
++)
1517 unsigned short b
= *bits
++;
1519 c
= (unsigned char)((swap_nibble
[b
& 0xf] << 4)
1520 | (swap_nibble
[(b
>>4) & 0xf]));
1521 *cbits
++ = (c
>> (8 - fb
->width
));
1526 for (j
= 0; j
< fb
->height
; j
++)
1528 unsigned short b
= *bits
;
1529 b
= (unsigned short)((swap_nibble
[b
& 0xf] << 12)
1530 | (swap_nibble
[(b
>>4) & 0xf] << 8)
1531 | (swap_nibble
[(b
>>8) & 0xf] << 4)
1532 | (swap_nibble
[(b
>>12) & 0xf]));
1533 b
>>= (16 - fb
->width
);
1534 #ifdef WORDS_BIG_ENDIAN
1535 b
= ((b
>> 8) | (b
<< 8));
1540 #endif /* HAVE_X_WINDOWS */
1546 /* XXX Is SELECTED_FRAME OK here? */
1547 struct redisplay_interface
*rif
= FRAME_RIF (SELECTED_FRAME ());
1549 destroy_fringe_bitmap (which
);
1551 if (rif
&& rif
->define_fringe_bitmap
)
1552 rif
->define_fringe_bitmap (which
, fb
->bits
, fb
->height
, fb
->width
);
1554 fringe_bitmaps
[which
] = fb
;
1555 if (which
>= max_used_fringe_bitmap
)
1556 max_used_fringe_bitmap
= which
+ 1;
1561 DEFUN ("define-fringe-bitmap", Fdefine_fringe_bitmap
, Sdefine_fringe_bitmap
,
1563 doc
: /* Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.
1564 BITMAP is a symbol identifying the new fringe bitmap.
1565 BITS is either a string or a vector of integers.
1566 HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.
1567 WIDTH must be an integer between 1 and 16, or nil which defaults to 8.
1568 Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
1569 indicating the positioning of the bitmap relative to the rows where it
1570 is used; the default is to center the bitmap. Fifth arg may also be a
1571 list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap
1573 If BITMAP already exists, the existing definition is replaced. */)
1574 (bitmap
, bits
, height
, width
, align
)
1575 Lisp_Object bitmap
, bits
, height
, width
, align
;
1579 struct fringe_bitmap fb
, *xfb
;
1580 int fill1
= 0, fill2
= 0;
1582 CHECK_SYMBOL (bitmap
);
1586 else if (VECTORP (bits
))
1587 h
= XVECTOR_SIZE (bits
);
1589 wrong_type_argument (Qsequencep
, bits
);
1595 CHECK_NUMBER (height
);
1596 fb
.height
= min (XINT (height
), 255);
1599 fill1
= (fb
.height
- h
) / 2;
1600 fill2
= fb
.height
- h
- fill1
;
1608 CHECK_NUMBER (width
);
1609 fb
.width
= min (XINT (width
), 255);
1613 fb
.align
= ALIGN_BITMAP_CENTER
;
1617 Lisp_Object period
= XCDR (align
);
1620 period
= XCAR (period
);
1623 fb
.period
= fb
.height
;
1627 align
= XCAR (align
);
1629 if (EQ (align
, Qtop
))
1630 fb
.align
= ALIGN_BITMAP_TOP
;
1631 else if (EQ (align
, Qbottom
))
1632 fb
.align
= ALIGN_BITMAP_BOTTOM
;
1633 else if (!NILP (align
) && !EQ (align
, Qcenter
))
1634 error ("Bad align argument");
1636 n
= lookup_fringe_bitmap (bitmap
);
1639 if (max_used_fringe_bitmap
< max_fringe_bitmaps
)
1640 n
= max_used_fringe_bitmap
++;
1643 for (n
= MAX_STANDARD_FRINGE_BITMAPS
;
1644 n
< max_fringe_bitmaps
;
1646 if (fringe_bitmaps
[n
] == NULL
)
1649 if (n
== max_fringe_bitmaps
)
1651 if ((max_fringe_bitmaps
+ 20) > MAX_FRINGE_BITMAPS
)
1652 error ("No free fringe bitmap slots");
1654 i
= max_fringe_bitmaps
;
1655 max_fringe_bitmaps
+= 20;
1657 = ((struct fringe_bitmap
**)
1658 xrealloc (fringe_bitmaps
, max_fringe_bitmaps
* sizeof (struct fringe_bitmap
*)));
1660 = (Lisp_Object
*) xrealloc (fringe_faces
, max_fringe_bitmaps
* sizeof (Lisp_Object
));
1662 for (; i
< max_fringe_bitmaps
; i
++)
1664 fringe_bitmaps
[i
] = NULL
;
1665 fringe_faces
[i
] = Qnil
;
1670 Vfringe_bitmaps
= Fcons (bitmap
, Vfringe_bitmaps
);
1671 Fput (bitmap
, Qfringe
, make_number (n
));
1676 xfb
= (struct fringe_bitmap
*) xmalloc (sizeof fb
1677 + fb
.height
* BYTES_PER_BITMAP_ROW
);
1678 fb
.bits
= b
= (unsigned short *) (xfb
+ 1);
1679 bzero (b
, fb
.height
);
1682 while (j
< fb
.height
)
1684 for (i
= 0; i
< fill1
&& j
< fb
.height
; i
++)
1686 for (i
= 0; i
< h
&& j
< fb
.height
; i
++)
1688 Lisp_Object elt
= Faref (bits
, make_number (i
));
1689 b
[j
++] = NUMBERP (elt
) ? XINT (elt
) : 0;
1691 for (i
= 0; i
< fill2
&& j
< fb
.height
; i
++)
1697 init_fringe_bitmap (n
, xfb
, 0);
1702 DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face
, Sset_fringe_bitmap_face
,
1704 doc
: /* Set face for fringe bitmap BITMAP to FACE.
1705 If FACE is nil, reset face to default fringe face. */)
1707 Lisp_Object bitmap
, face
;
1712 CHECK_SYMBOL (bitmap
);
1713 n
= lookup_fringe_bitmap (bitmap
);
1715 error ("Undefined fringe bitmap");
1719 face_id
= lookup_derived_face (SELECTED_FRAME (), face
,
1722 error ("No such face");
1725 fringe_faces
[n
] = face
;
1730 DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos
, Sfringe_bitmaps_at_pos
,
1732 doc
: /* Return fringe bitmaps of row containing position POS in window WINDOW.
1733 If WINDOW is nil, use selected window. If POS is nil, use value of point
1734 in that window. Return value is a list (LEFT RIGHT OV), where LEFT
1735 is the symbol for the bitmap in the left fringe (or nil if no bitmap),
1736 RIGHT is similar for the right fringe, and OV is non-nil if there is an
1737 overlay arrow in the left fringe.
1738 Return nil if POS is not visible in WINDOW. */)
1740 Lisp_Object pos
, window
;
1743 struct glyph_row
*row
;
1747 window
= selected_window
;
1748 CHECK_WINDOW (window
);
1749 w
= XWINDOW (window
);
1753 CHECK_NUMBER_COERCE_MARKER (pos
);
1754 textpos
= XINT (pos
);
1756 else if (w
== XWINDOW (selected_window
))
1759 textpos
= XMARKER (w
->pointm
)->charpos
;
1761 row
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
1762 row
= row_containing_pos (w
, textpos
, row
, NULL
, 0);
1764 return list3 (get_fringe_bitmap_name (row
->left_fringe_bitmap
),
1765 get_fringe_bitmap_name (row
->right_fringe_bitmap
),
1766 (row
->overlay_arrow_bitmap
== 0 ? Qnil
1767 : row
->overlay_arrow_bitmap
< 0 ? Qt
1768 : get_fringe_bitmap_name (row
->overlay_arrow_bitmap
)));
1774 /***********************************************************************
1776 ***********************************************************************/
1781 Qtruncation
= intern_c_string ("truncation");
1782 staticpro (&Qtruncation
);
1783 Qcontinuation
= intern_c_string ("continuation");
1784 staticpro (&Qcontinuation
);
1785 Qoverlay_arrow
= intern_c_string ("overlay-arrow");
1786 staticpro (&Qoverlay_arrow
);
1787 Qempty_line
= intern_c_string ("empty-line");
1788 staticpro (&Qempty_line
);
1789 Qtop_bottom
= intern_c_string ("top-bottom");
1790 staticpro (&Qtop_bottom
);
1791 Qhollow_small
= intern_c_string ("hollow-small");
1792 staticpro (&Qhollow_small
);
1794 defsubr (&Sdestroy_fringe_bitmap
);
1795 defsubr (&Sdefine_fringe_bitmap
);
1796 defsubr (&Sfringe_bitmaps_at_pos
);
1797 defsubr (&Sset_fringe_bitmap_face
);
1799 DEFVAR_LISP ("overflow-newline-into-fringe", &Voverflow_newline_into_fringe
,
1800 doc
: /* *Non-nil means that newline may flow into the right fringe.
1801 This means that display lines which are exactly as wide as the window
1802 (not counting the final newline) will only occupy one screen line, by
1803 showing (or hiding) the final newline in the right fringe; when point
1804 is at the final newline, the cursor is shown in the right fringe.
1805 If nil, also continue lines which are exactly as wide as the window. */);
1806 Voverflow_newline_into_fringe
= Qt
;
1808 DEFVAR_LISP ("fringe-bitmaps", &Vfringe_bitmaps
,
1809 doc
: /* List of fringe bitmap symbols. */);
1810 Vfringe_bitmaps
= Qnil
;
1813 /* Garbage collection hook */
1820 for (i
= 0; i
< max_fringe_bitmaps
; i
++)
1821 if (!NILP (fringe_faces
[i
]))
1822 mark_object (fringe_faces
[i
]);
1825 /* Initialize this module when Emacs starts. */
1832 for (bt
= NO_FRINGE_BITMAP
+ 1; bt
< MAX_STANDARD_FRINGE_BITMAPS
; bt
++)
1833 init_fringe_bitmap(bt
, &standard_bitmaps
[bt
], 1);
1841 max_fringe_bitmaps
= MAX_STANDARD_FRINGE_BITMAPS
+ 20;
1844 = (struct fringe_bitmap
**) xmalloc (max_fringe_bitmaps
* sizeof (struct fringe_bitmap
*));
1846 = (Lisp_Object
*) xmalloc (max_fringe_bitmaps
* sizeof (Lisp_Object
));
1848 for (i
= 0; i
< max_fringe_bitmaps
; i
++)
1850 fringe_bitmaps
[i
] = NULL
;
1851 fringe_faces
[i
] = Qnil
;
1858 w32_init_fringe (struct redisplay_interface
*rif
)
1865 for (bt
= NO_FRINGE_BITMAP
+ 1; bt
< MAX_STANDARD_FRINGE_BITMAPS
; bt
++)
1867 struct fringe_bitmap
*fb
= &standard_bitmaps
[bt
];
1868 rif
->define_fringe_bitmap (bt
, fb
->bits
, fb
->height
, fb
->width
);
1873 w32_reset_fringes ()
1875 /* Destroy row bitmaps. */
1877 struct redisplay_interface
*rif
= FRAME_RIF (SELECTED_FRAME ());
1882 for (bt
= NO_FRINGE_BITMAP
+ 1; bt
< max_used_fringe_bitmap
; bt
++)
1883 rif
->destroy_fringe_bitmap (bt
);
1886 #endif /* HAVE_NTGUI */
1888 #endif /* HAVE_WINDOW_SYSTEM */
1890 /* arch-tag: 04596920-43eb-473d-b319-82712338162d
1891 (do not change this comment) */