Replace bcopy, bzero, bcmp by memcpy, memmove, memset, memcmp
[bpt/emacs.git] / src / fringe.c
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 Free Software Foundation, Inc.
5
6 This file is part of GNU Emacs.
7
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.
12
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.
17
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/>. */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <setjmp.h>
24
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"
32
33 #ifdef HAVE_WINDOW_SYSTEM
34
35 extern Lisp_Object Qfringe;
36 extern Lisp_Object Qtop, Qbottom, Qcenter;
37 extern Lisp_Object Qup, Qdown, Qleft, Qright;
38
39 /* Non-nil means that newline may flow into the right fringe. */
40
41 Lisp_Object Voverflow_newline_into_fringe;
42
43 /* List of known fringe bitmap symbols.
44
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.
48 */
49
50 Lisp_Object Vfringe_bitmaps;
51
52 /* Fringe bitmaps are represented in three different ways:
53
54 Logical bitmaps are used internally to denote things like
55 'end-of-buffer', 'left-truncation', 'overlay-arrow', etc.
56
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.
60
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.
65
66 Logical bitmaps are mapped to physical bitmaps through the
67 buffer-local `fringe-indicator-alist' variable.
68
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.
74
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.
78
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.
81
82 The `left-fringe' and `right-fringe' display properties
83 must specify physical bitmap symbols.
84 */
85
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;
91
92 enum fringe_bitmap_align
93 {
94 ALIGN_BITMAP_CENTER = 0,
95 ALIGN_BITMAP_TOP,
96 ALIGN_BITMAP_BOTTOM
97 };
98
99 struct fringe_bitmap
100 {
101 unsigned short *bits;
102 unsigned height : 8;
103 unsigned width : 8;
104 unsigned period : 8;
105 unsigned align : 2;
106 unsigned dynamic : 1;
107 };
108
109 \f
110 /***********************************************************************
111 Fringe bitmaps
112 ***********************************************************************/
113
114 /* Undefined bitmap. A question mark. */
115 /*
116 ..xxxx..
117 .xxxxxx.
118 xx....xx
119 xx....xx
120 ....xx..
121 ...xx...
122 ...xx...
123 ........
124 ...xx...
125 ...xx...
126 */
127 static unsigned short question_mark_bits[] = {
128 0x3c, 0x7e, 0x7e, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18};
129
130 /* An arrow like this: `<-'. */
131 /*
132 ...xx...
133 ..xx....
134 .xx.....
135 xxxxxx..
136 xxxxxx..
137 .xx.....
138 ..xx....
139 ...xx...
140 */
141 static unsigned short left_arrow_bits[] = {
142 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
143
144
145 /* Right truncation arrow bitmap `->'. */
146 /*
147 ...xx...
148 ....xx..
149 .....xx.
150 ..xxxxxx
151 ..xxxxxx
152 .....xx.
153 ....xx..
154 ...xx...
155 */
156 static unsigned short right_arrow_bits[] = {
157 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
158
159
160 /* Up arrow bitmap. */
161 /*
162 ...xx...
163 ..xxxx..
164 .xxxxxx.
165 xxxxxxxx
166 ...xx...
167 ...xx...
168 ...xx...
169 ...xx...
170 */
171 static unsigned short up_arrow_bits[] = {
172 0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0x18};
173
174
175 /* Down arrow bitmap. */
176 /*
177 ...xx...
178 ...xx...
179 ...xx...
180 ...xx...
181 xxxxxxxx
182 .xxxxxx.
183 ..xxxx..
184 ...xx...
185 */
186 static unsigned short down_arrow_bits[] = {
187 0x18, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18};
188
189 /* Marker for continuation lines. */
190 /*
191 ..xxxx..
192 .xxxxx..
193 xx......
194 xxx..x..
195 xxxxxx..
196 .xxxxx..
197 ..xxxx..
198 .xxxxx..
199 */
200 static unsigned short left_curly_arrow_bits[] = {
201 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
202
203 /* Marker for continued lines. */
204 /*
205 ..xxxx..
206 ..xxxxx.
207 ......xx
208 ..x..xxx
209 ..xxxxxx
210 ..xxxxx.
211 ..xxxx..
212 ..xxxxx.
213 */
214 static unsigned short right_curly_arrow_bits[] = {
215 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
216
217 /* Reverse Overlay arrow bitmap. A triangular arrow. */
218 /*
219 ......xx
220 ....xxxx
221 ...xxxxx
222 ..xxxxxx
223 ..xxxxxx
224 ...xxxxx
225 ....xxxx
226 ......xx
227 */
228 static unsigned short left_triangle_bits[] = {
229 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
230
231 /* Overlay arrow bitmap. A triangular arrow. */
232 /*
233 xx......
234 xxxx....
235 xxxxx...
236 xxxxxx..
237 xxxxxx..
238 xxxxx...
239 xxxx....
240 xx......
241 */
242 static unsigned short right_triangle_bits[] = {
243 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
244
245 /* First line bitmap. An top-left angle. */
246 /*
247 xxxxxx..
248 xxxxxx..
249 xx......
250 xx......
251 xx......
252 xx......
253 xx......
254 ........
255 */
256 static unsigned short top_left_angle_bits[] = {
257 0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00};
258
259 /* First line bitmap. An right-up angle. */
260 /*
261 ..xxxxxx
262 ..xxxxxx
263 ......xx
264 ......xx
265 ......xx
266 ......xx
267 ......xx
268 ........
269 */
270 static unsigned short top_right_angle_bits[] = {
271 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00};
272
273 /* Last line bitmap. An left-down angle. */
274 /*
275 ........
276 xx......
277 xx......
278 xx......
279 xx......
280 xx......
281 xxxxxx..
282 xxxxxx..
283 */
284 static unsigned short bottom_left_angle_bits[] = {
285 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
286
287 /* Last line bitmap. An right-down angle. */
288 /*
289 ........
290 ......xx
291 ......xx
292 ......xx
293 ......xx
294 ......xx
295 ..xxxxxx
296 ..xxxxxx
297 */
298 static unsigned short bottom_right_angle_bits[] = {
299 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
300
301 /* First/last line bitmap. An left bracket. */
302 /*
303 xxxxxx..
304 xxxxxx..
305 xx......
306 xx......
307 xx......
308 xx......
309 xx......
310 xx......
311 xxxxxx..
312 xxxxxx..
313 */
314 static unsigned short left_bracket_bits[] = {
315 0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
316
317 /* First/last line bitmap. An right bracket. */
318 /*
319 ..xxxxxx
320 ..xxxxxx
321 ......xx
322 ......xx
323 ......xx
324 ......xx
325 ......xx
326 ......xx
327 ..xxxxxx
328 ..xxxxxx
329 */
330 static unsigned short right_bracket_bits[] = {
331 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
332
333 /* Filled box cursor bitmap. A filled box; max 13 pixels high. */
334 /*
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.
348 */
349 static unsigned short filled_rectangle_bits[] = {
350 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
351
352 /* Hollow box cursor bitmap. A hollow box; max 13 pixels high. */
353 /*
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.
367 */
368 static unsigned short hollow_rectangle_bits[] = {
369 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe};
370
371 /* Hollow square bitmap. */
372 /*
373 .xxxxxx.
374 .x....x.
375 .x....x.
376 .x....x.
377 .x....x.
378 .xxxxxx.
379 */
380 static unsigned short hollow_square_bits[] = {
381 0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e};
382
383 /* Filled square bitmap. */
384 /*
385 .xxxxxx.
386 .xxxxxx.
387 .xxxxxx.
388 .xxxxxx.
389 .xxxxxx.
390 .xxxxxx.
391 */
392 static unsigned short filled_square_bits[] = {
393 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e};
394
395 /* Bar cursor bitmap. A vertical bar; max 13 pixels high. */
396 /*
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......
410 */
411 static unsigned short vertical_bar_bits[] = {
412 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0};
413
414 /* HBar cursor bitmap. A horizontal bar; 2 pixels high. */
415 /*
416 xxxxxxx.
417 xxxxxxx.
418 */
419 static unsigned short horizontal_bar_bits[] = {
420 0xfe, 0xfe};
421
422
423 /* Bitmap drawn to indicate lines not displaying text if
424 `indicate-empty-lines' is non-nil. */
425 /*
426 ........
427 ..xxxx..
428 ........
429 ........
430 ..xxxx..
431 ........
432 */
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};
442
443
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)
447
448 /* NOTE: The order of these bitmaps must match the sequence
449 used in fringe.el to define the corresponding symbols. */
450
451 struct fringe_bitmap standard_bitmaps[] =
452 {
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 },
476 };
477
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]))
481
482 static struct fringe_bitmap **fringe_bitmaps;
483 static Lisp_Object *fringe_faces;
484 static int max_fringe_bitmaps;
485
486 int max_used_fringe_bitmap = MAX_STANDARD_FRINGE_BITMAPS;
487
488
489 /* Lookup bitmap number for symbol BITMAP.
490 Return 0 if not a bitmap. */
491
492 int
493 lookup_fringe_bitmap (Lisp_Object bitmap)
494 {
495 int bn;
496
497 bitmap = Fget (bitmap, Qfringe);
498 if (!INTEGERP (bitmap))
499 return 0;
500
501 bn = XINT (bitmap);
502 if (bn > NO_FRINGE_BITMAP
503 && bn < max_used_fringe_bitmap
504 && (bn < MAX_STANDARD_FRINGE_BITMAPS
505 || fringe_bitmaps[bn] != NULL))
506 return bn;
507
508 return 0;
509 }
510
511 /* Get fringe bitmap name for bitmap number BN.
512
513 Found by traversing Vfringe_bitmaps comparing BN to the
514 fringe property for each symbol.
515
516 Return BN if not found in Vfringe_bitmaps. */
517
518 static Lisp_Object
519 get_fringe_bitmap_name (int bn)
520 {
521 Lisp_Object bitmaps;
522 Lisp_Object num;
523
524 /* Zero means no bitmap -- return nil. */
525 if (bn <= 0)
526 return Qnil;
527
528 bitmaps = Vfringe_bitmaps;
529 num = make_number (bn);
530
531 while (CONSP (bitmaps))
532 {
533 Lisp_Object bitmap = XCAR (bitmaps);
534 if (EQ (num, Fget (bitmap, Qfringe)))
535 return bitmap;
536 bitmaps = XCDR (bitmaps);
537 }
538
539 return num;
540 }
541
542
543 /* Draw the bitmap WHICH in one of the left or right fringes of
544 window W. ROW is the glyph row for which to display the bitmap; it
545 determines the vertical position at which the bitmap has to be
546 drawn.
547 LEFT_P is 1 for left fringe, 0 for right fringe.
548 */
549
550 static void
551 draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int overlay, int which)
552 {
553 struct frame *f = XFRAME (WINDOW_FRAME (w));
554 struct draw_fringe_bitmap_params p;
555 struct fringe_bitmap *fb;
556 int period;
557 int face_id = DEFAULT_FACE_ID;
558
559 p.cursor_p = 0;
560 p.overlay_p = (overlay & 1) == 1;
561 p.cursor_p = (overlay & 2) == 2;
562
563 if (which != NO_FRINGE_BITMAP)
564 {
565 }
566 else if (left_p)
567 {
568 which = row->left_fringe_bitmap;
569 face_id = row->left_fringe_face_id;
570 }
571 else
572 {
573 which = row->right_fringe_bitmap;
574 face_id = row->right_fringe_face_id;
575 }
576
577 if (face_id == DEFAULT_FACE_ID)
578 {
579 Lisp_Object face = fringe_faces[which];
580 face_id = NILP (face) ? lookup_named_face (f, Qfringe, 0)
581 : lookup_derived_face (f, face, FRINGE_FACE_ID, 0);
582 if (face_id < 0)
583 face_id = FRINGE_FACE_ID;
584 }
585
586 fb = fringe_bitmaps[which];
587 if (fb == NULL)
588 fb = &standard_bitmaps[which < MAX_STANDARD_FRINGE_BITMAPS
589 ? which : UNDEF_FRINGE_BITMAP];
590
591 period = fb->period;
592
593 /* Convert row to frame coordinates. */
594 p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
595
596 p.which = which;
597 p.bits = fb->bits;
598 p.wd = fb->width;
599
600 p.h = fb->height;
601 p.dh = (period > 0 ? (p.y % period) : 0);
602 p.h -= p.dh;
603 /* Clip bitmap if too high. */
604 if (p.h > row->height)
605 p.h = row->height;
606
607 p.face = FACE_FROM_ID (f, face_id);
608
609 if (p.face == NULL)
610 {
611 /* This could happen after clearing face cache.
612 But it shouldn't happen anymore. ++kfs */
613 return;
614 }
615
616 PREPARE_FACE_FOR_DISPLAY (f, p.face);
617
618 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
619 the fringe. */
620 p.bx = -1;
621 if (left_p)
622 {
623 int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
624 int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
625 ? LEFT_MARGIN_AREA
626 : TEXT_AREA));
627 if (p.wd > wd)
628 p.wd = wd;
629 p.x = x - p.wd - (wd - p.wd) / 2;
630
631 if (p.wd < wd || row->height > p.h)
632 {
633 /* If W has a vertical border to its left, don't draw over it. */
634 wd -= ((!WINDOW_LEFTMOST_P (w)
635 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
636 ? 1 : 0);
637 p.bx = x - wd;
638 p.nx = wd;
639 }
640 }
641 else
642 {
643 int x = window_box_right (w,
644 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
645 ? RIGHT_MARGIN_AREA
646 : TEXT_AREA));
647 int wd = WINDOW_RIGHT_FRINGE_WIDTH (w);
648 if (p.wd > wd)
649 p.wd = wd;
650 p.x = x + (wd - p.wd) / 2;
651 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
652 the fringe. */
653 if (p.wd < wd || row->height > p.h)
654 {
655 p.bx = x;
656 p.nx = wd;
657 }
658 }
659
660 if (p.bx >= 0)
661 {
662 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
663
664 p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
665 p.ny = row->visible_height;
666 }
667
668 /* Adjust y to the offset in the row to start drawing the bitmap. */
669 switch (fb->align)
670 {
671 case ALIGN_BITMAP_CENTER:
672 p.y += (row->height - p.h) / 2;
673 break;
674 case ALIGN_BITMAP_BOTTOM:
675 p.h = fb->height;
676 p.y += (row->visible_height - p.h);
677 break;
678 case ALIGN_BITMAP_TOP:
679 break;
680 }
681
682 FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p);
683 }
684
685 static int
686 get_logical_cursor_bitmap (struct window *w, Lisp_Object cursor)
687 {
688 Lisp_Object cmap, bm = Qnil;
689
690 if ((cmap = XBUFFER (w->buffer)->fringe_cursor_alist), !NILP (cmap))
691 {
692 bm = Fassq (cursor, cmap);
693 if (CONSP (bm))
694 {
695 if ((bm = XCDR (bm)), NILP (bm))
696 return NO_FRINGE_BITMAP;
697 return lookup_fringe_bitmap (bm);
698 }
699 }
700 if (EQ (cmap, buffer_defaults.fringe_cursor_alist))
701 return NO_FRINGE_BITMAP;
702 bm = Fassq (cursor, buffer_defaults.fringe_cursor_alist);
703 if (!CONSP (bm) || ((bm = XCDR (bm)), NILP (bm)))
704 return NO_FRINGE_BITMAP;
705 return lookup_fringe_bitmap (bm);
706 }
707
708 static int
709 get_logical_fringe_bitmap (struct window *w, Lisp_Object bitmap, int right_p, int partial_p)
710 {
711 Lisp_Object cmap, bm1 = Qnil, bm2 = Qnil, bm;
712 int ln1 = 0, ln2 = 0;
713 int ix1 = right_p;
714 int ix2 = ix1 + (partial_p ? 2 : 0);
715
716 /* Lookup in buffer-local fringe-indicator-alist before global alist.
717
718 Elements are:
719 BITMAP -- use for all
720 (L R) -- use for left right (whether partial or not)
721 (L R PL PR) -- use for left right partial-left partial-right
722 If any value in local binding is not present or t, use global value.
723
724 If partial, lookup partial bitmap in default value if not found here.
725 If not partial, or no partial spec is present, use non-partial bitmap. */
726
727 if ((cmap = XBUFFER (w->buffer)->fringe_indicator_alist), !NILP (cmap))
728 {
729 bm1 = Fassq (bitmap, cmap);
730 if (CONSP (bm1))
731 {
732 if ((bm1 = XCDR (bm1)), NILP (bm1))
733 return NO_FRINGE_BITMAP;
734 if (CONSP (bm1))
735 {
736 ln1 = XINT (Flength (bm1));
737 if (partial_p)
738 {
739 if (ln1 > ix2)
740 {
741 bm = Fnth (make_number (ix2), bm1);
742 if (!EQ (bm, Qt))
743 goto found;
744 }
745 }
746 else
747 {
748 if (ln1 > ix1)
749 {
750 bm = Fnth (make_number (ix1), bm1);
751 if (!EQ (bm, Qt))
752 goto found;
753 }
754 }
755 }
756 else if ((bm = bm1, !EQ (bm, Qt)))
757 goto found;
758 }
759 }
760
761 if (!EQ (cmap, buffer_defaults.fringe_indicator_alist)
762 && !NILP (buffer_defaults.fringe_indicator_alist))
763 {
764 bm2 = Fassq (bitmap, buffer_defaults.fringe_indicator_alist);
765 if (CONSP (bm2))
766 {
767 if ((bm2 = XCDR (bm2)), !NILP (bm2))
768 {
769 if (CONSP (bm2))
770 {
771 ln2 = XINT (Flength (bm2));
772 if (partial_p)
773 {
774 if (ln2 > ix2)
775 {
776 bm = Fnth (make_number (ix2), bm2);
777 if (!EQ (bm, Qt))
778 goto found;
779 }
780 }
781 }
782 }
783 }
784 }
785
786 if (ln1 > ix1)
787 {
788 bm = Fnth (make_number (ix1), bm1);
789 if (!EQ (bm, Qt))
790 goto found;
791 }
792
793 if (ln2 > ix1)
794 {
795 bm = Fnth (make_number (ix1), bm2);
796 if (!EQ (bm, Qt))
797 goto found;
798 return NO_FRINGE_BITMAP;
799 }
800 else if ((bm = bm2, NILP (bm)))
801 return NO_FRINGE_BITMAP;
802
803 found:
804 return lookup_fringe_bitmap (bm);
805 }
806
807
808 void
809 draw_fringe_bitmap (struct window *w, struct glyph_row *row, int left_p)
810 {
811 int overlay = 0;
812
813 if (left_p == row->reversed_p && row->cursor_in_fringe_p)
814 {
815 Lisp_Object cursor = Qnil;
816
817 switch (w->phys_cursor_type)
818 {
819 case HOLLOW_BOX_CURSOR:
820 if (row->visible_height >= STANDARD_BITMAP_HEIGHT (hollow_rectangle_bits))
821 cursor = Qhollow;
822 else
823 cursor = Qhollow_small;
824 break;
825 case FILLED_BOX_CURSOR:
826 cursor = Qbox;
827 break;
828 case BAR_CURSOR:
829 cursor = Qbar;
830 break;
831 case HBAR_CURSOR:
832 cursor = Qhbar;
833 break;
834 case NO_CURSOR:
835 default:
836 w->phys_cursor_on_p = 0;
837 row->cursor_in_fringe_p = 0;
838 break;
839 }
840 if (!NILP (cursor))
841 {
842 int bm = get_logical_cursor_bitmap (w, cursor);
843 if (bm != NO_FRINGE_BITMAP)
844 {
845 draw_fringe_bitmap_1 (w, row, left_p, 2, bm);
846 overlay = EQ (cursor, Qbox) ? 3 : 1;
847 }
848 }
849 }
850
851 draw_fringe_bitmap_1 (w, row, left_p, overlay, NO_FRINGE_BITMAP);
852
853 if (left_p && row->overlay_arrow_bitmap != NO_FRINGE_BITMAP)
854 draw_fringe_bitmap_1 (w, row, 1, 1, row->overlay_arrow_bitmap);
855 }
856
857
858 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
859 function with input blocked. */
860
861 void
862 draw_row_fringe_bitmaps (struct window *w, struct glyph_row *row)
863 {
864 xassert (interrupt_input_blocked);
865
866 /* If row is completely invisible, because of vscrolling, we
867 don't have to draw anything. */
868 if (row->visible_height <= 0)
869 return;
870
871 if (WINDOW_LEFT_FRINGE_WIDTH (w) != 0)
872 draw_fringe_bitmap (w, row, 1);
873
874 if (WINDOW_RIGHT_FRINGE_WIDTH (w) != 0)
875 draw_fringe_bitmap (w, row, 0);
876 }
877
878 /* Draw the fringes of window W. Only fringes for rows marked for
879 update in redraw_fringe_bitmaps_p are drawn.
880
881 Return >0 if left or right fringe was redrawn in any way.
882
883 If NO_FRINGE is non-zero, also return >0 if either fringe has zero width.
884
885 A return value >0 indicates that the vertical line between windows
886 needs update (as it may be drawn in the fringe).
887 */
888
889 int
890 draw_window_fringes (struct window *w, int no_fringe)
891 {
892 struct glyph_row *row;
893 int yb = window_text_bottom_y (w);
894 int nrows = w->current_matrix->nrows;
895 int y = 0, rn;
896 int updated = 0;
897
898 if (w->pseudo_window_p)
899 return 0;
900
901 /* Must draw line if no fringe */
902 if (no_fringe
903 && (WINDOW_LEFT_FRINGE_WIDTH (w) == 0
904 || WINDOW_RIGHT_FRINGE_WIDTH (w) == 0))
905 updated++;
906
907 for (y = 0, rn = 0, row = w->current_matrix->rows;
908 y < yb && rn < nrows;
909 y += row->height, ++row, ++rn)
910 {
911 if (!row->redraw_fringe_bitmaps_p)
912 continue;
913 draw_row_fringe_bitmaps (w, row);
914 row->redraw_fringe_bitmaps_p = 0;
915 updated++;
916 }
917
918 return updated;
919 }
920
921
922 /* Recalculate the bitmaps to show in the fringes of window W.
923 Only mark rows with modified bitmaps for update in redraw_fringe_bitmaps_p.
924
925 If KEEP_CURRENT_P is 0, update current_matrix too. */
926
927 int
928 update_window_fringes (struct window *w, int keep_current_p)
929 {
930 struct glyph_row *row, *cur = 0;
931 int yb = window_text_bottom_y (w);
932 int rn, nrows = w->current_matrix->nrows;
933 int y;
934 int redraw_p = 0;
935 Lisp_Object boundary_top = Qnil, boundary_bot = Qnil;
936 Lisp_Object arrow_top = Qnil, arrow_bot = Qnil;
937 Lisp_Object empty_pos;
938 Lisp_Object ind = Qnil;
939 #define MAX_BITMAP_CACHE (8*4)
940 int bitmap_cache[MAX_BITMAP_CACHE];
941
942 if (w->pseudo_window_p)
943 return 0;
944
945 if (!MINI_WINDOW_P (w)
946 && (ind = XBUFFER (w->buffer)->indicate_buffer_boundaries, !NILP (ind)))
947 {
948 if (EQ (ind, Qleft) || EQ (ind, Qright))
949 boundary_top = boundary_bot = arrow_top = arrow_bot = ind;
950 else if (CONSP (ind) && CONSP (XCAR (ind)))
951 {
952 Lisp_Object pos;
953 if (pos = Fassq (Qt, ind), !NILP (pos))
954 boundary_top = boundary_bot = arrow_top = arrow_bot = XCDR (pos);
955 if (pos = Fassq (Qtop, ind), !NILP (pos))
956 boundary_top = XCDR (pos);
957 if (pos = Fassq (Qbottom, ind), !NILP (pos))
958 boundary_bot = XCDR (pos);
959 if (pos = Fassq (Qup, ind), !NILP (pos))
960 arrow_top = XCDR (pos);
961 if (pos = Fassq (Qdown, ind), !NILP (pos))
962 arrow_bot = XCDR (pos);
963 }
964 else
965 /* Anything else means boundary on left and no arrows. */
966 boundary_top = boundary_bot = Qleft;
967 }
968
969 if (!NILP (ind))
970 {
971 int done_top = 0, done_bot = 0;
972
973 for (y = 0, rn = 0;
974 y < yb && rn < nrows;
975 y += row->height, ++rn)
976 {
977 unsigned indicate_bob_p, indicate_top_line_p;
978 unsigned indicate_eob_p, indicate_bottom_line_p;
979
980 row = w->desired_matrix->rows + rn;
981 if (!row->enabled_p)
982 row = w->current_matrix->rows + rn;
983
984 indicate_bob_p = row->indicate_bob_p;
985 indicate_top_line_p = row->indicate_top_line_p;
986 indicate_eob_p = row->indicate_eob_p;
987 indicate_bottom_line_p = row->indicate_bottom_line_p;
988
989 row->indicate_bob_p = row->indicate_top_line_p = 0;
990 row->indicate_eob_p = row->indicate_bottom_line_p = 0;
991
992 if (!row->mode_line_p)
993 {
994 if (!done_top)
995 {
996 if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer))
997 && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
998 row->indicate_bob_p = !NILP (boundary_top);
999 else
1000 row->indicate_top_line_p = !NILP (arrow_top);
1001 done_top = 1;
1002 }
1003
1004 if (!done_bot)
1005 {
1006 if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer))
1007 && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
1008 row->indicate_eob_p = !NILP (boundary_bot), done_bot = 1;
1009 else if (y + row->height >= yb)
1010 row->indicate_bottom_line_p = !NILP (arrow_bot), done_bot = 1;
1011 }
1012 }
1013
1014 if (indicate_bob_p != row->indicate_bob_p
1015 || indicate_top_line_p != row->indicate_top_line_p
1016 || indicate_eob_p != row->indicate_eob_p
1017 || indicate_bottom_line_p != row->indicate_bottom_line_p)
1018 row->redraw_fringe_bitmaps_p = 1;
1019 }
1020 }
1021
1022 empty_pos = XBUFFER (w->buffer)->indicate_empty_lines;
1023 if (!NILP (empty_pos) && !EQ (empty_pos, Qright))
1024 empty_pos = WINDOW_LEFT_FRINGE_WIDTH (w) == 0 ? Qright : Qleft;
1025
1026 for (y = 0; y < MAX_BITMAP_CACHE; y++)
1027 bitmap_cache[y] = -1;
1028
1029 #define LEFT_FRINGE(cache, which, partial_p) \
1030 (bitmap_cache[cache*4+partial_p] >= 0 \
1031 ? bitmap_cache[cache*4+partial_p] \
1032 : (bitmap_cache[cache*4+partial_p] = \
1033 get_logical_fringe_bitmap (w, which, 0, partial_p)))
1034
1035 #define RIGHT_FRINGE(cache, which, partial_p) \
1036 (bitmap_cache[cache*4+2+partial_p] >= 0 \
1037 ? bitmap_cache[cache*4+2+partial_p] \
1038 : (bitmap_cache[cache*4+2+partial_p] = \
1039 get_logical_fringe_bitmap (w, which, 1, partial_p)))
1040
1041
1042 for (y = 0, rn = 0;
1043 y < yb && rn < nrows;
1044 y += row->height, rn++)
1045 {
1046 int left, right;
1047 unsigned left_face_id, right_face_id;
1048
1049 row = w->desired_matrix->rows + rn;
1050 cur = w->current_matrix->rows + rn;
1051 if (!row->enabled_p)
1052 row = cur;
1053
1054 left_face_id = right_face_id = DEFAULT_FACE_ID;
1055
1056 /* Decide which bitmap to draw in the left fringe. */
1057 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
1058 left = NO_FRINGE_BITMAP;
1059 else if (row->left_user_fringe_bitmap != NO_FRINGE_BITMAP)
1060 {
1061 left = row->left_user_fringe_bitmap;
1062 left_face_id = row->left_user_fringe_face_id;
1063 }
1064 else if ((!row->reversed_p && row->truncated_on_left_p)
1065 || (row->reversed_p && row->truncated_on_right_p))
1066 left = LEFT_FRINGE(0, Qtruncation, 0);
1067 else if (row->indicate_bob_p && EQ (boundary_top, Qleft))
1068 left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
1069 ? LEFT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p)
1070 : LEFT_FRINGE (2, Qtop, 0));
1071 else if (row->indicate_eob_p && EQ (boundary_bot, Qleft))
1072 left = LEFT_FRINGE (3, Qbottom, row->ends_at_zv_p);
1073 else if ((!row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row))
1074 || (row->reversed_p && row->continued_p))
1075 left = LEFT_FRINGE (4, Qcontinuation, 0);
1076 else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft))
1077 left = LEFT_FRINGE (5, Qempty_line, 0);
1078 else if (row->indicate_top_line_p && EQ (arrow_top, Qleft))
1079 left = LEFT_FRINGE (6, Qup, 0);
1080 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qleft))
1081 left = LEFT_FRINGE (7, Qdown, 0);
1082 else
1083 left = NO_FRINGE_BITMAP;
1084
1085 /* Decide which bitmap to draw in the right fringe. */
1086 if (WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)
1087 right = NO_FRINGE_BITMAP;
1088 else if (row->right_user_fringe_bitmap != NO_FRINGE_BITMAP)
1089 {
1090 right = row->right_user_fringe_bitmap;
1091 right_face_id = row->right_user_fringe_face_id;
1092 }
1093 else if ((!row->reversed_p && row->truncated_on_right_p)
1094 || (row->reversed_p && row->truncated_on_left_p))
1095 right = RIGHT_FRINGE (0, Qtruncation, 0);
1096 else if (row->indicate_bob_p && EQ (boundary_top, Qright))
1097 right = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
1098 ? RIGHT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p)
1099 : RIGHT_FRINGE (2, Qtop, 0));
1100 else if (row->indicate_eob_p && EQ (boundary_bot, Qright))
1101 right = RIGHT_FRINGE (3, Qbottom, row->ends_at_zv_p);
1102 else if ((!row->reversed_p && row->continued_p)
1103 || (row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row)))
1104 right = RIGHT_FRINGE (4, Qcontinuation, 0);
1105 else if (row->indicate_top_line_p && EQ (arrow_top, Qright))
1106 right = RIGHT_FRINGE (6, Qup, 0);
1107 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright))
1108 right = RIGHT_FRINGE (7, Qdown, 0);
1109 else if (row->indicate_empty_line_p && EQ (empty_pos, Qright))
1110 right = RIGHT_FRINGE (5, Qempty_line, 0);
1111 else
1112 right = NO_FRINGE_BITMAP;
1113
1114 if (row->y != cur->y
1115 || row->visible_height != cur->visible_height
1116 || row->ends_at_zv_p != cur->ends_at_zv_p
1117 || left != cur->left_fringe_bitmap
1118 || right != cur->right_fringe_bitmap
1119 || left_face_id != cur->left_fringe_face_id
1120 || right_face_id != cur->right_fringe_face_id
1121 || cur->redraw_fringe_bitmaps_p)
1122 {
1123 redraw_p = row->redraw_fringe_bitmaps_p = 1;
1124 if (!keep_current_p)
1125 {
1126 cur->redraw_fringe_bitmaps_p = 1;
1127 cur->left_fringe_bitmap = left;
1128 cur->right_fringe_bitmap = right;
1129 cur->left_fringe_face_id = left_face_id;
1130 cur->right_fringe_face_id = right_face_id;
1131 }
1132 }
1133
1134 if (row->overlay_arrow_bitmap < 0)
1135 row->overlay_arrow_bitmap = get_logical_fringe_bitmap (w, Qoverlay_arrow, 0, 0);
1136
1137 if (row->overlay_arrow_bitmap != cur->overlay_arrow_bitmap)
1138 {
1139 redraw_p = row->redraw_fringe_bitmaps_p = cur->redraw_fringe_bitmaps_p = 1;
1140 cur->overlay_arrow_bitmap = row->overlay_arrow_bitmap;
1141 }
1142
1143 row->left_fringe_bitmap = left;
1144 row->right_fringe_bitmap = right;
1145 row->left_fringe_face_id = left_face_id;
1146 row->right_fringe_face_id = right_face_id;
1147
1148 if (rn > 0 && row->redraw_fringe_bitmaps_p)
1149 row[-1].redraw_fringe_bitmaps_p = cur[-1].redraw_fringe_bitmaps_p = 1;
1150 }
1151
1152 return redraw_p && !keep_current_p;
1153 }
1154
1155
1156 /* Compute actual fringe widths for frame F.
1157
1158 If REDRAW is 1, redraw F if the fringe settings was actually
1159 modified and F is visible.
1160
1161 Since the combined left and right fringe must occupy an integral
1162 number of columns, we may need to add some pixels to each fringe.
1163 Typically, we add an equal amount (+/- 1 pixel) to each fringe,
1164 but a negative width value is taken literally (after negating it).
1165
1166 We never make the fringes narrower than specified.
1167 */
1168
1169 void
1170 compute_fringe_widths (struct frame *f, int redraw)
1171 {
1172 int o_left = FRAME_LEFT_FRINGE_WIDTH (f);
1173 int o_right = FRAME_RIGHT_FRINGE_WIDTH (f);
1174 int o_cols = FRAME_FRINGE_COLS (f);
1175
1176 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
1177 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
1178 int left_fringe_width, right_fringe_width;
1179
1180 if (!NILP (left_fringe))
1181 left_fringe = Fcdr (left_fringe);
1182 if (!NILP (right_fringe))
1183 right_fringe = Fcdr (right_fringe);
1184
1185 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
1186 XINT (left_fringe));
1187 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
1188 XINT (right_fringe));
1189
1190 if (left_fringe_width || right_fringe_width)
1191 {
1192 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
1193 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
1194 int conf_wid = left_wid + right_wid;
1195 int font_wid = FRAME_COLUMN_WIDTH (f);
1196 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
1197 int real_wid = cols * font_wid;
1198 if (left_wid && right_wid)
1199 {
1200 if (left_fringe_width < 0)
1201 {
1202 /* Left fringe width is fixed, adjust right fringe if necessary */
1203 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid;
1204 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid;
1205 }
1206 else if (right_fringe_width < 0)
1207 {
1208 /* Right fringe width is fixed, adjust left fringe if necessary */
1209 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
1210 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid;
1211 }
1212 else
1213 {
1214 /* Adjust both fringes with an equal amount.
1215 Note that we are doing integer arithmetic here, so don't
1216 lose a pixel if the total width is an odd number. */
1217 int fill = real_wid - conf_wid;
1218 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2;
1219 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2;
1220 }
1221 }
1222 else if (left_fringe_width)
1223 {
1224 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid;
1225 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
1226 }
1227 else
1228 {
1229 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
1230 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid;
1231 }
1232 FRAME_FRINGE_COLS (f) = cols;
1233 }
1234 else
1235 {
1236 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
1237 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
1238 FRAME_FRINGE_COLS (f) = 0;
1239 }
1240
1241 if (redraw && FRAME_VISIBLE_P (f))
1242 if (o_left != FRAME_LEFT_FRINGE_WIDTH (f) ||
1243 o_right != FRAME_RIGHT_FRINGE_WIDTH (f) ||
1244 o_cols != FRAME_FRINGE_COLS (f))
1245 redraw_frame (f);
1246 }
1247
1248
1249 /* Free resources used by a user-defined bitmap. */
1250
1251 void
1252 destroy_fringe_bitmap (int n)
1253 {
1254 struct fringe_bitmap **fbp;
1255
1256 fringe_faces[n] = Qnil;
1257
1258 fbp = &fringe_bitmaps[n];
1259 if (*fbp && (*fbp)->dynamic)
1260 {
1261 /* XXX Is SELECTED_FRAME OK here? */
1262 struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
1263 if (rif && rif->destroy_fringe_bitmap)
1264 rif->destroy_fringe_bitmap (n);
1265 xfree (*fbp);
1266 *fbp = NULL;
1267 }
1268
1269 while (max_used_fringe_bitmap > MAX_STANDARD_FRINGE_BITMAPS
1270 && fringe_bitmaps[max_used_fringe_bitmap - 1] == NULL)
1271 max_used_fringe_bitmap--;
1272 }
1273
1274
1275 DEFUN ("destroy-fringe-bitmap", Fdestroy_fringe_bitmap, Sdestroy_fringe_bitmap,
1276 1, 1, 0,
1277 doc: /* Destroy fringe bitmap BITMAP.
1278 If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. */)
1279 (bitmap)
1280 Lisp_Object bitmap;
1281 {
1282 int n;
1283
1284 CHECK_SYMBOL (bitmap);
1285 n = lookup_fringe_bitmap (bitmap);
1286 if (!n)
1287 return Qnil;
1288
1289 destroy_fringe_bitmap (n);
1290
1291 if (n >= MAX_STANDARD_FRINGE_BITMAPS)
1292 {
1293 Vfringe_bitmaps = Fdelq (bitmap, Vfringe_bitmaps);
1294 /* It would be better to remove the fringe property. */
1295 Fput (bitmap, Qfringe, Qnil);
1296 }
1297
1298 return Qnil;
1299 }
1300
1301
1302 /* Initialize bitmap bit.
1303
1304 On X, we bit-swap the built-in bitmaps and reduce bitmap
1305 from short to char array if width is <= 8 bits.
1306
1307 On MAC with big-endian CPU, we need to byte-swap each short.
1308
1309 On W32 and MAC (little endian), there's no need to do this.
1310 */
1311
1312 #if defined (HAVE_X_WINDOWS)
1313 static const unsigned char swap_nibble[16] = {
1314 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
1315 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
1316 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
1317 0x3, 0xb, 0x7, 0xf}; /* 0011 1011 0111 1111 */
1318 #endif /* HAVE_X_WINDOWS */
1319
1320 void
1321 init_fringe_bitmap (int which, struct fringe_bitmap *fb, int once_p)
1322 {
1323 if (once_p || fb->dynamic)
1324 {
1325 #if defined (HAVE_X_WINDOWS)
1326 unsigned short *bits = fb->bits;
1327 int j;
1328
1329 if (fb->width <= 8)
1330 {
1331 unsigned char *cbits = (unsigned char *)fb->bits;
1332 for (j = 0; j < fb->height; j++)
1333 {
1334 unsigned short b = *bits++;
1335 unsigned char c;
1336 c = (unsigned char)((swap_nibble[b & 0xf] << 4)
1337 | (swap_nibble[(b>>4) & 0xf]));
1338 *cbits++ = (c >> (8 - fb->width));
1339 }
1340 }
1341 else
1342 {
1343 for (j = 0; j < fb->height; j++)
1344 {
1345 unsigned short b = *bits;
1346 b = (unsigned short)((swap_nibble[b & 0xf] << 12)
1347 | (swap_nibble[(b>>4) & 0xf] << 8)
1348 | (swap_nibble[(b>>8) & 0xf] << 4)
1349 | (swap_nibble[(b>>12) & 0xf]));
1350 b >>= (16 - fb->width);
1351 #ifdef WORDS_BIG_ENDIAN
1352 b = ((b >> 8) | (b << 8));
1353 #endif
1354 *bits++ = b;
1355 }
1356 }
1357 #endif /* HAVE_X_WINDOWS */
1358
1359 }
1360
1361 if (!once_p)
1362 {
1363 /* XXX Is SELECTED_FRAME OK here? */
1364 struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
1365
1366 destroy_fringe_bitmap (which);
1367
1368 if (rif && rif->define_fringe_bitmap)
1369 rif->define_fringe_bitmap (which, fb->bits, fb->height, fb->width);
1370
1371 fringe_bitmaps[which] = fb;
1372 if (which >= max_used_fringe_bitmap)
1373 max_used_fringe_bitmap = which + 1;
1374 }
1375 }
1376
1377
1378 DEFUN ("define-fringe-bitmap", Fdefine_fringe_bitmap, Sdefine_fringe_bitmap,
1379 2, 5, 0,
1380 doc: /* Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.
1381 BITMAP is a symbol identifying the new fringe bitmap.
1382 BITS is either a string or a vector of integers.
1383 HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.
1384 WIDTH must be an integer between 1 and 16, or nil which defaults to 8.
1385 Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
1386 indicating the positioning of the bitmap relative to the rows where it
1387 is used; the default is to center the bitmap. Fifth arg may also be a
1388 list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap
1389 should be repeated.
1390 If BITMAP already exists, the existing definition is replaced. */)
1391 (bitmap, bits, height, width, align)
1392 Lisp_Object bitmap, bits, height, width, align;
1393 {
1394 int n, h, i, j;
1395 unsigned short *b;
1396 struct fringe_bitmap fb, *xfb;
1397 int fill1 = 0, fill2 = 0;
1398
1399 CHECK_SYMBOL (bitmap);
1400
1401 if (STRINGP (bits))
1402 h = SCHARS (bits);
1403 else if (VECTORP (bits))
1404 h = XVECTOR (bits)->size;
1405 else
1406 wrong_type_argument (Qsequencep, bits);
1407
1408 if (NILP (height))
1409 fb.height = h;
1410 else
1411 {
1412 CHECK_NUMBER (height);
1413 fb.height = min (XINT (height), 255);
1414 if (fb.height > h)
1415 {
1416 fill1 = (fb.height - h) / 2;
1417 fill2 = fb.height - h - fill1;
1418 }
1419 }
1420
1421 if (NILP (width))
1422 fb.width = 8;
1423 else
1424 {
1425 CHECK_NUMBER (width);
1426 fb.width = min (XINT (width), 255);
1427 }
1428
1429 fb.period = 0;
1430 fb.align = ALIGN_BITMAP_CENTER;
1431
1432 if (CONSP (align))
1433 {
1434 Lisp_Object period = XCDR (align);
1435 if (CONSP (period))
1436 {
1437 period = XCAR (period);
1438 if (!NILP (period))
1439 {
1440 fb.period = fb.height;
1441 fb.height = 255;
1442 }
1443 }
1444 align = XCAR (align);
1445 }
1446 if (EQ (align, Qtop))
1447 fb.align = ALIGN_BITMAP_TOP;
1448 else if (EQ (align, Qbottom))
1449 fb.align = ALIGN_BITMAP_BOTTOM;
1450 else if (!NILP (align) && !EQ (align, Qcenter))
1451 error ("Bad align argument");
1452
1453 n = lookup_fringe_bitmap (bitmap);
1454 if (!n)
1455 {
1456 if (max_used_fringe_bitmap < max_fringe_bitmaps)
1457 n = max_used_fringe_bitmap++;
1458 else
1459 {
1460 for (n = MAX_STANDARD_FRINGE_BITMAPS;
1461 n < max_fringe_bitmaps;
1462 n++)
1463 if (fringe_bitmaps[n] == NULL)
1464 break;
1465
1466 if (n == max_fringe_bitmaps)
1467 {
1468 if ((max_fringe_bitmaps + 20) > MAX_FRINGE_BITMAPS)
1469 error ("No free fringe bitmap slots");
1470
1471 i = max_fringe_bitmaps;
1472 max_fringe_bitmaps += 20;
1473 fringe_bitmaps
1474 = ((struct fringe_bitmap **)
1475 xrealloc (fringe_bitmaps, max_fringe_bitmaps * sizeof (struct fringe_bitmap *)));
1476 fringe_faces
1477 = (Lisp_Object *) xrealloc (fringe_faces, max_fringe_bitmaps * sizeof (Lisp_Object));
1478
1479 for (; i < max_fringe_bitmaps; i++)
1480 {
1481 fringe_bitmaps[i] = NULL;
1482 fringe_faces[i] = Qnil;
1483 }
1484 }
1485 }
1486
1487 Vfringe_bitmaps = Fcons (bitmap, Vfringe_bitmaps);
1488 Fput (bitmap, Qfringe, make_number (n));
1489 }
1490
1491 fb.dynamic = 1;
1492
1493 xfb = (struct fringe_bitmap *) xmalloc (sizeof fb
1494 + fb.height * BYTES_PER_BITMAP_ROW);
1495 fb.bits = b = (unsigned short *) (xfb + 1);
1496 memset (b, 0, fb.height);
1497
1498 j = 0;
1499 while (j < fb.height)
1500 {
1501 for (i = 0; i < fill1 && j < fb.height; i++)
1502 b[j++] = 0;
1503 for (i = 0; i < h && j < fb.height; i++)
1504 {
1505 Lisp_Object elt = Faref (bits, make_number (i));
1506 b[j++] = NUMBERP (elt) ? XINT (elt) : 0;
1507 }
1508 for (i = 0; i < fill2 && j < fb.height; i++)
1509 b[j++] = 0;
1510 }
1511
1512 *xfb = fb;
1513
1514 init_fringe_bitmap (n, xfb, 0);
1515
1516 return bitmap;
1517 }
1518
1519 DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face, Sset_fringe_bitmap_face,
1520 1, 2, 0,
1521 doc: /* Set face for fringe bitmap BITMAP to FACE.
1522 If FACE is nil, reset face to default fringe face. */)
1523 (bitmap, face)
1524 Lisp_Object bitmap, face;
1525 {
1526 int n;
1527 int face_id;
1528
1529 CHECK_SYMBOL (bitmap);
1530 n = lookup_fringe_bitmap (bitmap);
1531 if (!n)
1532 error ("Undefined fringe bitmap");
1533
1534 if (!NILP (face))
1535 {
1536 face_id = lookup_derived_face (SELECTED_FRAME (), face,
1537 FRINGE_FACE_ID, 1);
1538 if (face_id < 0)
1539 error ("No such face");
1540 }
1541
1542 fringe_faces[n] = face;
1543
1544 return Qnil;
1545 }
1546
1547 DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos, Sfringe_bitmaps_at_pos,
1548 0, 2, 0,
1549 doc: /* Return fringe bitmaps of row containing position POS in window WINDOW.
1550 If WINDOW is nil, use selected window. If POS is nil, use value of point
1551 in that window. Return value is a list (LEFT RIGHT OV), where LEFT
1552 is the symbol for the bitmap in the left fringe (or nil if no bitmap),
1553 RIGHT is similar for the right fringe, and OV is non-nil if there is an
1554 overlay arrow in the left fringe.
1555 Return nil if POS is not visible in WINDOW. */)
1556 (pos, window)
1557 Lisp_Object pos, window;
1558 {
1559 struct window *w;
1560 struct glyph_row *row;
1561 int textpos;
1562
1563 if (NILP (window))
1564 window = selected_window;
1565 CHECK_WINDOW (window);
1566 w = XWINDOW (window);
1567
1568 if (!NILP (pos))
1569 {
1570 CHECK_NUMBER_COERCE_MARKER (pos);
1571 textpos = XINT (pos);
1572 }
1573 else if (w == XWINDOW (selected_window))
1574 textpos = PT;
1575 else
1576 textpos = XMARKER (w->pointm)->charpos;
1577
1578 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1579 row = row_containing_pos (w, textpos, row, NULL, 0);
1580 if (row)
1581 return list3 (get_fringe_bitmap_name (row->left_fringe_bitmap),
1582 get_fringe_bitmap_name (row->right_fringe_bitmap),
1583 (row->overlay_arrow_bitmap == 0 ? Qnil
1584 : row->overlay_arrow_bitmap < 0 ? Qt
1585 : get_fringe_bitmap_name (row->overlay_arrow_bitmap)));
1586 else
1587 return Qnil;
1588 }
1589
1590
1591 /***********************************************************************
1592 Initialization
1593 ***********************************************************************/
1594
1595 void
1596 syms_of_fringe (void)
1597 {
1598 Qtruncation = intern_c_string ("truncation");
1599 staticpro (&Qtruncation);
1600 Qcontinuation = intern_c_string ("continuation");
1601 staticpro (&Qcontinuation);
1602 Qoverlay_arrow = intern_c_string ("overlay-arrow");
1603 staticpro (&Qoverlay_arrow);
1604 Qempty_line = intern_c_string ("empty-line");
1605 staticpro (&Qempty_line);
1606 Qtop_bottom = intern_c_string ("top-bottom");
1607 staticpro (&Qtop_bottom);
1608 Qhollow_small = intern_c_string ("hollow-small");
1609 staticpro (&Qhollow_small);
1610
1611 defsubr (&Sdestroy_fringe_bitmap);
1612 defsubr (&Sdefine_fringe_bitmap);
1613 defsubr (&Sfringe_bitmaps_at_pos);
1614 defsubr (&Sset_fringe_bitmap_face);
1615
1616 DEFVAR_LISP ("overflow-newline-into-fringe", &Voverflow_newline_into_fringe,
1617 doc: /* *Non-nil means that newline may flow into the right fringe.
1618 This means that display lines which are exactly as wide as the window
1619 (not counting the final newline) will only occupy one screen line, by
1620 showing (or hiding) the final newline in the right fringe; when point
1621 is at the final newline, the cursor is shown in the right fringe.
1622 If nil, also continue lines which are exactly as wide as the window. */);
1623 Voverflow_newline_into_fringe = Qt;
1624
1625 DEFVAR_LISP ("fringe-bitmaps", &Vfringe_bitmaps,
1626 doc: /* List of fringe bitmap symbols. */);
1627 Vfringe_bitmaps = Qnil;
1628 }
1629
1630 /* Garbage collection hook */
1631
1632 void
1633 mark_fringe_data (void)
1634 {
1635 int i;
1636
1637 for (i = 0; i < max_fringe_bitmaps; i++)
1638 if (!NILP (fringe_faces[i]))
1639 mark_object (fringe_faces[i]);
1640 }
1641
1642 /* Initialize this module when Emacs starts. */
1643
1644 void
1645 init_fringe_once (void)
1646 {
1647 int bt;
1648
1649 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1650 init_fringe_bitmap(bt, &standard_bitmaps[bt], 1);
1651 }
1652
1653 void
1654 init_fringe (void)
1655 {
1656 int i;
1657
1658 max_fringe_bitmaps = MAX_STANDARD_FRINGE_BITMAPS + 20;
1659
1660 fringe_bitmaps
1661 = (struct fringe_bitmap **) xmalloc (max_fringe_bitmaps * sizeof (struct fringe_bitmap *));
1662 fringe_faces
1663 = (Lisp_Object *) xmalloc (max_fringe_bitmaps * sizeof (Lisp_Object));
1664
1665 for (i = 0; i < max_fringe_bitmaps; i++)
1666 {
1667 fringe_bitmaps[i] = NULL;
1668 fringe_faces[i] = Qnil;
1669 }
1670 }
1671
1672 #ifdef HAVE_NTGUI
1673
1674 void
1675 w32_init_fringe (struct redisplay_interface *rif)
1676 {
1677 int bt;
1678
1679 if (!rif)
1680 return;
1681
1682 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1683 {
1684 struct fringe_bitmap *fb = &standard_bitmaps[bt];
1685 rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
1686 }
1687 }
1688
1689 void
1690 w32_reset_fringes ()
1691 {
1692 /* Destroy row bitmaps. */
1693 int bt;
1694 struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ());
1695
1696 if (!rif)
1697 return;
1698
1699 for (bt = NO_FRINGE_BITMAP + 1; bt < max_used_fringe_bitmap; bt++)
1700 rif->destroy_fringe_bitmap (bt);
1701 }
1702
1703 #endif /* HAVE_NTGUI */
1704
1705 #endif /* HAVE_WINDOW_SYSTEM */
1706
1707 /* arch-tag: 04596920-43eb-473d-b319-82712338162d
1708 (do not change this comment) */