* customize.texi (Composite Types): Move alist/plist from Simple Types (Bug#7545).
[emacs.git] / src / fringe.c
blobbd178846c6267addef5ac38d104d5ff431ac4031
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/>. */
21 #include <config.h>
22 #include <stdio.h>
23 #include <setjmp.h>
25 #include "lisp.h"
26 #include "frame.h"
27 #include "window.h"
28 #include "dispextern.h"
29 #include "buffer.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
47 loading fringe.el.
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,
95 ALIGN_BITMAP_TOP,
96 ALIGN_BITMAP_BOTTOM
99 struct fringe_bitmap
101 unsigned short *bits;
102 unsigned height : 8;
103 unsigned width : 8;
104 unsigned period : 8;
105 unsigned align : 2;
106 unsigned dynamic : 1;
110 /***********************************************************************
111 Fringe bitmaps
112 ***********************************************************************/
114 /* Undefined bitmap. A question mark. */
116 ..xxxx..
117 .xxxxxx.
118 xx....xx
119 xx....xx
120 ....xx..
121 ...xx...
122 ...xx...
123 ........
124 ...xx...
125 ...xx...
127 static unsigned short question_mark_bits[] = {
128 0x3c, 0x7e, 0x7e, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18};
130 /* An arrow like this: `<-'. */
132 ...xx...
133 ..xx....
134 .xx.....
135 xxxxxx..
136 xxxxxx..
137 .xx.....
138 ..xx....
139 ...xx...
141 static unsigned short left_arrow_bits[] = {
142 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
145 /* Right truncation arrow bitmap `->'. */
147 ...xx...
148 ....xx..
149 .....xx.
150 ..xxxxxx
151 ..xxxxxx
152 .....xx.
153 ....xx..
154 ...xx...
156 static unsigned short right_arrow_bits[] = {
157 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
160 /* Up arrow bitmap. */
162 ...xx...
163 ..xxxx..
164 .xxxxxx.
165 xxxxxxxx
166 ...xx...
167 ...xx...
168 ...xx...
169 ...xx...
171 static unsigned short up_arrow_bits[] = {
172 0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0x18};
175 /* Down arrow bitmap. */
177 ...xx...
178 ...xx...
179 ...xx...
180 ...xx...
181 xxxxxxxx
182 .xxxxxx.
183 ..xxxx..
184 ...xx...
186 static unsigned short down_arrow_bits[] = {
187 0x18, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18};
189 /* Marker for continuation lines. */
191 ..xxxx..
192 .xxxxx..
193 xx......
194 xxx..x..
195 xxxxxx..
196 .xxxxx..
197 ..xxxx..
198 .xxxxx..
200 static unsigned short left_curly_arrow_bits[] = {
201 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
203 /* Marker for continued lines. */
205 ..xxxx..
206 ..xxxxx.
207 ......xx
208 ..x..xxx
209 ..xxxxxx
210 ..xxxxx.
211 ..xxxx..
212 ..xxxxx.
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. */
219 ......xx
220 ....xxxx
221 ...xxxxx
222 ..xxxxxx
223 ..xxxxxx
224 ...xxxxx
225 ....xxxx
226 ......xx
228 static unsigned short left_triangle_bits[] = {
229 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
231 /* Overlay arrow bitmap. A triangular arrow. */
233 xx......
234 xxxx....
235 xxxxx...
236 xxxxxx..
237 xxxxxx..
238 xxxxx...
239 xxxx....
240 xx......
242 static unsigned short right_triangle_bits[] = {
243 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
245 /* First line bitmap. An top-left angle. */
247 xxxxxx..
248 xxxxxx..
249 xx......
250 xx......
251 xx......
252 xx......
253 xx......
254 ........
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. */
261 ..xxxxxx
262 ..xxxxxx
263 ......xx
264 ......xx
265 ......xx
266 ......xx
267 ......xx
268 ........
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. */
275 ........
276 xx......
277 xx......
278 xx......
279 xx......
280 xx......
281 xxxxxx..
282 xxxxxx..
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. */
289 ........
290 ......xx
291 ......xx
292 ......xx
293 ......xx
294 ......xx
295 ..xxxxxx
296 ..xxxxxx
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. */
303 xxxxxx..
304 xxxxxx..
305 xx......
306 xx......
307 xx......
308 xx......
309 xx......
310 xx......
311 xxxxxx..
312 xxxxxx..
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. */
319 ..xxxxxx
320 ..xxxxxx
321 ......xx
322 ......xx
323 ......xx
324 ......xx
325 ......xx
326 ......xx
327 ..xxxxxx
328 ..xxxxxx
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. */
335 xxxxxxx.
336 xxxxxxx.
337 xxxxxxx.
338 xxxxxxx.
339 xxxxxxx.
340 xxxxxxx.
341 xxxxxxx.
342 xxxxxxx.
343 xxxxxxx.
344 xxxxxxx.
345 xxxxxxx.
346 xxxxxxx.
347 xxxxxxx.
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. */
354 xxxxxxx.
355 x.....x.
356 x.....x.
357 x.....x.
358 x.....x.
359 x.....x.
360 x.....x.
361 x.....x.
362 x.....x.
363 x.....x.
364 x.....x.
365 x.....x.
366 xxxxxxx.
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. */
373 .xxxxxx.
374 .x....x.
375 .x....x.
376 .x....x.
377 .x....x.
378 .xxxxxx.
380 static unsigned short hollow_square_bits[] = {
381 0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e};
383 /* Filled square bitmap. */
385 .xxxxxx.
386 .xxxxxx.
387 .xxxxxx.
388 .xxxxxx.
389 .xxxxxx.
390 .xxxxxx.
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. */
397 xx......
398 xx......
399 xx......
400 xx......
401 xx......
402 xx......
403 xx......
404 xx......
405 xx......
406 xx......
407 xx......
408 xx......
409 xx......
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. */
416 xxxxxxx.
417 xxxxxxx.
419 static unsigned short horizontal_bar_bits[] = {
420 0xfe, 0xfe};
423 /* Bitmap drawn to indicate lines not displaying text if
424 `indicate-empty-lines' is non-nil. */
426 ........
427 ..xxxx..
428 ........
429 ........
430 ..xxxx..
431 ........
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)
494 Lisp_Object bitmap;
496 int bn;
498 bitmap = Fget (bitmap, Qfringe);
499 if (!INTEGERP (bitmap))
500 return 0;
502 bn = XINT (bitmap);
503 if (bn > NO_FRINGE_BITMAP
504 && bn < max_used_fringe_bitmap
505 && (bn < MAX_STANDARD_FRINGE_BITMAPS
506 || fringe_bitmaps[bn] != NULL))
507 return bn;
509 return 0;
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. */
519 static Lisp_Object
520 get_fringe_bitmap_name (bn)
521 int bn;
523 Lisp_Object bitmaps;
524 Lisp_Object num;
526 /* Zero means no bitmap -- return nil. */
527 if (bn <= 0)
528 return Qnil;
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)))
537 return bitmap;
538 bitmaps = XCDR (bitmaps);
541 return num;
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];
552 if (fb == NULL)
553 fb = &standard_bitmaps[bn < MAX_STANDARD_FRINGE_BITMAPS
554 ? bn : UNDEF_FRINGE_BITMAP];
556 return fb;
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
562 drawn.
563 LEFT_P is 1 for left fringe, 0 for right fringe.
566 static void
567 draw_fringe_bitmap_1 (w, row, left_p, overlay, which)
568 struct window *w;
569 struct glyph_row *row;
570 int left_p, overlay;
571 int which;
573 struct frame *f = XFRAME (WINDOW_FRAME (w));
574 struct draw_fringe_bitmap_params p;
575 struct fringe_bitmap *fb;
576 int period;
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)
585 offset = 0;
587 else if (left_p)
589 which = row->left_fringe_bitmap;
590 face_id = row->left_fringe_face_id;
591 offset = row->left_fringe_offset;
593 else
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)
602 Lisp_Object face;
604 if ((face = fringe_faces[which], NILP (face))
605 || (face_id = lookup_derived_face (f, face, FRINGE_FACE_ID, 0),
606 face_id < 0))
607 face_id = FRINGE_FACE_ID;
610 fb = get_fringe_bitmap_data (which);
612 period = fb->period;
614 /* Convert row to frame coordinates. */
615 p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y) + offset;
617 p.which = which;
618 p.bits = fb->bits;
619 p.wd = fb->width;
621 p.h = fb->height;
622 p.dh = (period > 0 ? (p.y % period) : 0);
623 p.h -= p.dh;
625 /* Adjust y to the offset in the row to start drawing the bitmap. */
626 switch (fb->align)
628 case ALIGN_BITMAP_CENTER:
629 p.y += (row->height - p.h) / 2;
630 break;
631 case ALIGN_BITMAP_BOTTOM:
632 p.y += (row->visible_height - p.h);
633 break;
634 case ALIGN_BITMAP_TOP:
635 break;
638 p.face = FACE_FROM_ID (f, face_id);
640 if (p.face == NULL)
642 /* This could happen after clearing face cache.
643 But it shouldn't happen anymore. ++kfs */
644 return;
647 PREPARE_FACE_FOR_DISPLAY (f, p.face);
649 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
650 the fringe. */
651 p.bx = -1;
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;
655 if (left_p)
657 int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
658 int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
659 ? LEFT_MARGIN_AREA
660 : TEXT_AREA));
661 if (p.wd > wd)
662 p.wd = wd;
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))
670 ? 1 : 0);
671 p.bx = x - wd;
672 p.nx = wd;
675 else
677 int x = window_box_right (w,
678 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
679 ? RIGHT_MARGIN_AREA
680 : TEXT_AREA));
681 int wd = WINDOW_RIGHT_FRINGE_WIDTH (w);
682 if (p.wd > wd)
683 p.wd = wd;
684 p.x = x + (wd - p.wd) / 2;
685 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
686 the fringe. */
687 if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny)
689 p.bx = x;
690 p.nx = wd;
694 FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p);
697 static int
698 get_logical_cursor_bitmap (w, cursor)
699 struct window *w;
700 Lisp_Object cursor;
702 Lisp_Object cmap, bm = Qnil;
704 if ((cmap = XBUFFER (w->buffer)->fringe_cursor_alist), !NILP (cmap))
706 bm = Fassq (cursor, cmap);
707 if (CONSP (bm))
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);
722 static int
723 get_logical_fringe_bitmap (w, bitmap, right_p, partial_p)
724 struct window *w;
725 Lisp_Object bitmap;
726 int right_p, partial_p;
728 Lisp_Object cmap, bm1 = Qnil, bm2 = Qnil, bm;
729 int ln1 = 0, ln2 = 0;
730 int ix1 = right_p;
731 int ix2 = ix1 + (partial_p ? 2 : 0);
733 /* Lookup in buffer-local fringe-indicator-alist before global alist.
735 Elements are:
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);
747 if (CONSP (bm1))
749 if ((bm1 = XCDR (bm1)), NILP (bm1))
750 return NO_FRINGE_BITMAP;
751 if (CONSP (bm1))
753 ln1 = XINT (Flength (bm1));
754 if (partial_p)
756 if (ln1 > ix2)
758 bm = Fnth (make_number (ix2), bm1);
759 if (!EQ (bm, Qt))
760 goto found;
763 else
765 if (ln1 > ix1)
767 bm = Fnth (make_number (ix1), bm1);
768 if (!EQ (bm, Qt))
769 goto found;
773 else if ((bm = bm1, !EQ (bm, Qt)))
774 goto found;
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);
782 if (CONSP (bm2))
784 if ((bm2 = XCDR (bm2)), !NILP (bm2))
786 if (CONSP (bm2))
788 ln2 = XINT (Flength (bm2));
789 if (partial_p)
791 if (ln2 > ix2)
793 bm = Fnth (make_number (ix2), bm2);
794 if (!EQ (bm, Qt))
795 goto found;
803 if (ln1 > ix1)
805 bm = Fnth (make_number (ix1), bm1);
806 if (!EQ (bm, Qt))
807 goto found;
810 if (ln2 > ix1)
812 bm = Fnth (make_number (ix1), bm2);
813 if (!EQ (bm, Qt))
814 goto found;
815 return NO_FRINGE_BITMAP;
817 else if ((bm = bm2, NILP (bm)))
818 return NO_FRINGE_BITMAP;
820 found:
821 return lookup_fringe_bitmap (bm);
825 void
826 draw_fringe_bitmap (w, row, left_p)
827 struct window *w;
828 struct glyph_row *row;
829 int left_p;
831 int overlay = 0;
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))
841 cursor = Qhollow;
842 else
843 cursor = Qhollow_small;
844 break;
845 case FILLED_BOX_CURSOR:
846 cursor = Qbox;
847 break;
848 case BAR_CURSOR:
849 cursor = Qbar;
850 break;
851 case HBAR_CURSOR:
852 cursor = Qhbar;
853 break;
854 case NO_CURSOR:
855 default:
856 w->phys_cursor_on_p = 0;
857 row->cursor_in_fringe_p = 0;
858 break;
860 if (!NILP (cursor))
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. */
881 void
882 draw_row_fringe_bitmaps (w, row)
883 struct window *w;
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)
891 return;
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)
913 struct window *w;
914 int no_fringe;
916 struct glyph_row *row;
917 int yb = window_text_bottom_y (w);
918 int nrows = w->current_matrix->nrows;
919 int y, rn;
920 int updated = 0;
922 if (w->pseudo_window_p)
923 return 0;
925 /* Must draw line if no fringe */
926 if (no_fringe
927 && (WINDOW_LEFT_FRINGE_WIDTH (w) == 0
928 || WINDOW_RIGHT_FRINGE_WIDTH (w) == 0))
929 updated++;
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)
936 continue;
937 draw_row_fringe_bitmaps (w, row);
938 row->redraw_fringe_bitmaps_p = 0;
939 updated++;
942 return updated;
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)
953 struct window *w;
954 int 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;
959 int y;
960 int redraw_p = 0;
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)
972 return 0;
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)))
981 Lisp_Object pos;
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);
993 else
994 /* Anything else means boundary on left and no arrows. */
995 boundary_top = boundary_bot = Qleft;
998 top_ind_rn = bot_ind_rn = -1;
999 if (!NILP (ind))
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);
1019 else
1020 row->indicate_top_line_p = !NILP (arrow_top);
1021 top_ind_rn = rn;
1024 if (bot_ind_rn < 0)
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));
1074 else
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);
1083 else
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;
1094 int top_ind_max_y;
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)
1099 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)
1106 break;
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);
1131 else
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);
1138 else
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;
1149 int bot_ind_min_y;
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)
1161 break;
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++)
1178 int left, right;
1179 unsigned left_face_id, right_face_id;
1180 int left_offset, right_offset;
1181 int periodic_p;
1183 row = w->desired_matrix->rows + rn;
1184 cur = w->current_matrix->rows + rn;
1185 if (!row->enabled_p)
1186 row = cur;
1188 left_face_id = right_face_id = DEFAULT_FACE_ID;
1189 left_offset = right_offset = 0;
1190 periodic_p = 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);
1232 else
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);
1275 else
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.
1346 void
1347 compute_fringe_widths (f, redraw)
1348 struct frame *f;
1349 int 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;
1391 else
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;
1406 else
1408 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
1409 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid;
1411 FRAME_FRINGE_COLS (f) = cols;
1413 else
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))
1424 redraw_frame (f);
1428 /* Free resources used by a user-defined bitmap. */
1430 void
1431 destroy_fringe_bitmap (n)
1432 int 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);
1445 xfree (*fbp);
1446 *fbp = NULL;
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,
1456 1, 1, 0,
1457 doc: /* Destroy fringe bitmap BITMAP.
1458 If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. */)
1459 (bitmap)
1460 Lisp_Object bitmap;
1462 int n;
1464 CHECK_SYMBOL (bitmap);
1465 n = lookup_fringe_bitmap (bitmap);
1466 if (!n)
1467 return Qnil;
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);
1478 return 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 */
1500 void
1501 init_fringe_bitmap (which, fb, once_p)
1502 int which;
1503 struct fringe_bitmap *fb;
1504 int once_p;
1506 if (once_p || fb->dynamic)
1508 #if defined (HAVE_X_WINDOWS)
1509 unsigned short *bits = fb->bits;
1510 int j;
1512 if (fb->width <= 8)
1514 unsigned char *cbits = (unsigned char *)fb->bits;
1515 for (j = 0; j < fb->height; j++)
1517 unsigned short b = *bits++;
1518 unsigned char c;
1519 c = (unsigned char)((swap_nibble[b & 0xf] << 4)
1520 | (swap_nibble[(b>>4) & 0xf]));
1521 *cbits++ = (c >> (8 - fb->width));
1524 else
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));
1536 #endif
1537 *bits++ = b;
1540 #endif /* HAVE_X_WINDOWS */
1544 if (!once_p)
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,
1562 2, 5, 0,
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
1572 should be repeated.
1573 If BITMAP already exists, the existing definition is replaced. */)
1574 (bitmap, bits, height, width, align)
1575 Lisp_Object bitmap, bits, height, width, align;
1577 int n, h, i, j;
1578 unsigned short *b;
1579 struct fringe_bitmap fb, *xfb;
1580 int fill1 = 0, fill2 = 0;
1582 CHECK_SYMBOL (bitmap);
1584 if (STRINGP (bits))
1585 h = SCHARS (bits);
1586 else if (VECTORP (bits))
1587 h = XVECTOR_SIZE (bits);
1588 else
1589 wrong_type_argument (Qsequencep, bits);
1591 if (NILP (height))
1592 fb.height = h;
1593 else
1595 CHECK_NUMBER (height);
1596 fb.height = min (XINT (height), 255);
1597 if (fb.height > h)
1599 fill1 = (fb.height - h) / 2;
1600 fill2 = fb.height - h - fill1;
1604 if (NILP (width))
1605 fb.width = 8;
1606 else
1608 CHECK_NUMBER (width);
1609 fb.width = min (XINT (width), 255);
1612 fb.period = 0;
1613 fb.align = ALIGN_BITMAP_CENTER;
1615 if (CONSP (align))
1617 Lisp_Object period = XCDR (align);
1618 if (CONSP (period))
1620 period = XCAR (period);
1621 if (!NILP (period))
1623 fb.period = fb.height;
1624 fb.height = 255;
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);
1637 if (!n)
1639 if (max_used_fringe_bitmap < max_fringe_bitmaps)
1640 n = max_used_fringe_bitmap++;
1641 else
1643 for (n = MAX_STANDARD_FRINGE_BITMAPS;
1644 n < max_fringe_bitmaps;
1645 n++)
1646 if (fringe_bitmaps[n] == NULL)
1647 break;
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;
1656 fringe_bitmaps
1657 = ((struct fringe_bitmap **)
1658 xrealloc (fringe_bitmaps, max_fringe_bitmaps * sizeof (struct fringe_bitmap *)));
1659 fringe_faces
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));
1674 fb.dynamic = 1;
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);
1681 j = 0;
1682 while (j < fb.height)
1684 for (i = 0; i < fill1 && j < fb.height; i++)
1685 b[j++] = 0;
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++)
1692 b[j++] = 0;
1695 *xfb = fb;
1697 init_fringe_bitmap (n, xfb, 0);
1699 return bitmap;
1702 DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face, Sset_fringe_bitmap_face,
1703 1, 2, 0,
1704 doc: /* Set face for fringe bitmap BITMAP to FACE.
1705 If FACE is nil, reset face to default fringe face. */)
1706 (bitmap, face)
1707 Lisp_Object bitmap, face;
1709 int n;
1710 int face_id;
1712 CHECK_SYMBOL (bitmap);
1713 n = lookup_fringe_bitmap (bitmap);
1714 if (!n)
1715 error ("Undefined fringe bitmap");
1717 if (!NILP (face))
1719 face_id = lookup_derived_face (SELECTED_FRAME (), face,
1720 FRINGE_FACE_ID, 1);
1721 if (face_id < 0)
1722 error ("No such face");
1725 fringe_faces[n] = face;
1727 return Qnil;
1730 DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos, Sfringe_bitmaps_at_pos,
1731 0, 2, 0,
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. */)
1739 (pos, window)
1740 Lisp_Object pos, window;
1742 struct window *w;
1743 struct glyph_row *row;
1744 int textpos;
1746 if (NILP (window))
1747 window = selected_window;
1748 CHECK_WINDOW (window);
1749 w = XWINDOW (window);
1751 if (!NILP (pos))
1753 CHECK_NUMBER_COERCE_MARKER (pos);
1754 textpos = XINT (pos);
1756 else if (w == XWINDOW (selected_window))
1757 textpos = PT;
1758 else
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);
1763 if (row)
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)));
1769 else
1770 return Qnil;
1774 /***********************************************************************
1775 Initialization
1776 ***********************************************************************/
1778 void
1779 syms_of_fringe ()
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 */
1815 void
1816 mark_fringe_data ()
1818 int i;
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. */
1827 void
1828 init_fringe_once ()
1830 int bt;
1832 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1833 init_fringe_bitmap(bt, &standard_bitmaps[bt], 1);
1836 void
1837 init_fringe ()
1839 int i;
1841 max_fringe_bitmaps = MAX_STANDARD_FRINGE_BITMAPS + 20;
1843 fringe_bitmaps
1844 = (struct fringe_bitmap **) xmalloc (max_fringe_bitmaps * sizeof (struct fringe_bitmap *));
1845 fringe_faces
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;
1855 #ifdef HAVE_NTGUI
1857 void
1858 w32_init_fringe (struct redisplay_interface *rif)
1860 int bt;
1862 if (!rif)
1863 return;
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);
1872 void
1873 w32_reset_fringes ()
1875 /* Destroy row bitmaps. */
1876 int bt;
1877 struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
1879 if (!rif)
1880 return;
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) */