(Fload, load_unwind): Use make_save_value to unwind
[bpt/emacs.git] / src / fringe.c
CommitLineData
2d05deef
KS
1/* Fringe handling (split from xdisp.c).
2 Copyright (C) 1985,86,87,88,93,94,95,97,98,99,2000,01,02,03,04
3 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
4fc5845f
LK
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA. */
2d05deef
KS
21
22#include <config.h>
23#include <stdio.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
32#ifdef HAVE_WINDOW_SYSTEM
33
7a2a85be 34extern Lisp_Object Qfringe;
2d05deef 35extern Lisp_Object Qtop, Qbottom, Qcenter;
5797a7a0 36extern Lisp_Object Qup, Qdown, Qleft, Qright;
2d05deef
KS
37
38/* Non-nil means that newline may flow into the right fringe. */
39
40Lisp_Object Voverflow_newline_into_fringe;
41
7a2a85be
KS
42/* List of known fringe bitmap symbols.
43
44 The fringe bitmap number is stored in the `fringe' property on
45 those symbols. Names for the built-in bitmaps are installed by
46 loading fringe.el.
47 */
48
49Lisp_Object Vfringe_bitmaps;
2d05deef
KS
50
51enum fringe_bitmap_type
52{
53 NO_FRINGE_BITMAP = 0,
54 UNDEF_FRINGE_BITMAP,
55 LEFT_TRUNCATION_BITMAP,
56 RIGHT_TRUNCATION_BITMAP,
57 UP_ARROW_BITMAP,
58 DOWN_ARROW_BITMAP,
59 CONTINUED_LINE_BITMAP,
60 CONTINUATION_LINE_BITMAP,
61 OVERLAY_ARROW_BITMAP,
62 TOP_LEFT_ANGLE_BITMAP,
63 TOP_RIGHT_ANGLE_BITMAP,
64 BOTTOM_LEFT_ANGLE_BITMAP,
65 BOTTOM_RIGHT_ANGLE_BITMAP,
66 LEFT_BRACKET_BITMAP,
67 RIGHT_BRACKET_BITMAP,
68 FILLED_BOX_CURSOR_BITMAP,
69 HOLLOW_BOX_CURSOR_BITMAP,
70 HOLLOW_SQUARE_BITMAP,
71 BAR_CURSOR_BITMAP,
72 HBAR_CURSOR_BITMAP,
73 ZV_LINE_BITMAP,
74 MAX_STANDARD_FRINGE_BITMAPS
75};
76
77enum fringe_bitmap_align
78{
79 ALIGN_BITMAP_CENTER = 0,
80 ALIGN_BITMAP_TOP,
81 ALIGN_BITMAP_BOTTOM
82};
83
84struct fringe_bitmap
85{
0881a0fd 86 unsigned short *bits;
2d05deef
KS
87 unsigned height : 8;
88 unsigned width : 8;
89 unsigned period : 8;
90 unsigned align : 2;
91 unsigned dynamic : 1;
92};
93
94\f
95/***********************************************************************
96 Fringe bitmaps
97 ***********************************************************************/
98
99/* Undefined bitmap. A question mark. */
100/*
101 ..xxxx..
102 .xxxxxx.
103 xx....xx
104 xx....xx
105 ....xx..
106 ...xx...
107 ...xx...
108 ........
109 ...xx...
110 ...xx...
111*/
0881a0fd 112static unsigned short unknown_bits[] = {
2d05deef
KS
113 0x3c, 0x7e, 0x7e, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18};
114
115/* An arrow like this: `<-'. */
116/*
117 ...xx...
118 ..xx....
119 .xx.....
120 xxxxxx..
121 xxxxxx..
122 .xx.....
123 ..xx....
124 ...xx...
125*/
0881a0fd 126static unsigned short left_arrow_bits[] = {
2d05deef
KS
127 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
128
129
130/* Right truncation arrow bitmap `->'. */
131/*
132 ...xx...
133 ....xx..
134 .....xx.
135 ..xxxxxx
136 ..xxxxxx
137 .....xx.
138 ....xx..
139 ...xx...
140*/
0881a0fd 141static unsigned short right_arrow_bits[] = {
2d05deef
KS
142 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
143
144
145/* Up arrow bitmap. */
146/*
147 ...xx...
148 ..xxxx..
149 .xxxxxx.
150 xxxxxxxx
151 ...xx...
152 ...xx...
153 ...xx...
154 ...xx...
155*/
0881a0fd 156static unsigned short up_arrow_bits[] = {
2d05deef
KS
157 0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0x18};
158
159
160/* Down arrow bitmap. */
161/*
162 ...xx...
163 ...xx...
164 ...xx...
165 ...xx...
166 xxxxxxxx
167 .xxxxxx.
168 ..xxxx..
169 ...xx...
170*/
0881a0fd 171static unsigned short down_arrow_bits[] = {
2d05deef
KS
172 0x18, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18};
173
174/* Marker for continued lines. */
175/*
176 ..xxxx..
177 ..xxxxx.
178 ......xx
179 ..x..xxx
180 ..xxxxxx
181 ..xxxxx.
182 ..xxxx..
183 ..xxxxx.
184*/
0881a0fd 185static unsigned short continued_bits[] = {
2d05deef
KS
186 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
187
188/* Marker for continuation lines. */
189/*
190 ..xxxx..
191 .xxxxx..
192 xx......
193 xxx..x..
194 xxxxxx..
195 .xxxxx..
196 ..xxxx..
197 .xxxxx..
198*/
0881a0fd 199static unsigned short continuation_bits[] = {
2d05deef
KS
200 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
201
202/* Overlay arrow bitmap. A triangular arrow. */
203/*
204 xx......
205 xxxx....
206 xxxxx...
207 xxxxxx..
208 xxxxxx..
209 xxxxx...
210 xxxx....
211 xx......
212*/
0881a0fd 213static unsigned short ov_bits[] = {
2d05deef
KS
214 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
215
216#if 0
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*/
0881a0fd 228static unsigned short rev_ov_bits[] = {
2d05deef
KS
229 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
230#endif
231
232/* First line bitmap. An top-left angle. */
233/*
234 xxxxxx..
235 xxxxxx..
236 xx......
237 xx......
238 xx......
239 xx......
240 xx......
241 ........
242*/
0881a0fd 243static unsigned short top_left_angle_bits[] = {
2d05deef
KS
244 0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00};
245
246/* First line bitmap. An right-up angle. */
247/*
248 ..xxxxxx
249 ..xxxxxx
250 ......xx
251 ......xx
252 ......xx
253 ......xx
254 ......xx
255 ........
256*/
0881a0fd 257static unsigned short top_right_angle_bits[] = {
2d05deef
KS
258 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00};
259
260/* Last line bitmap. An left-down angle. */
261/*
262 ........
263 xx......
264 xx......
265 xx......
266 xx......
267 xx......
268 xxxxxx..
269 xxxxxx..
270*/
0881a0fd 271static unsigned short bottom_left_angle_bits[] = {
2d05deef
KS
272 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
273
274/* Last line bitmap. An right-down angle. */
275/*
276 ........
277 ......xx
278 ......xx
279 ......xx
280 ......xx
281 ......xx
282 ..xxxxxx
283 ..xxxxxx
284*/
0881a0fd 285static unsigned short bottom_right_angle_bits[] = {
2d05deef
KS
286 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
287
288/* First/last line bitmap. An left bracket. */
289/*
290 xxxxxx..
291 xxxxxx..
292 xx......
293 xx......
294 xx......
295 xx......
296 xx......
297 xx......
298 xxxxxx..
299 xxxxxx..
300*/
0881a0fd 301static unsigned short left_bracket_bits[] = {
2d05deef
KS
302 0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
303
304/* First/last line bitmap. An right bracket. */
305/*
306 ..xxxxxx
307 ..xxxxxx
308 ......xx
309 ......xx
310 ......xx
311 ......xx
312 ......xx
313 ......xx
314 ..xxxxxx
315 ..xxxxxx
316*/
0881a0fd 317static unsigned short right_bracket_bits[] = {
2d05deef
KS
318 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
319
320/* Filled box cursor bitmap. A filled box; max 13 pixels high. */
321/*
322 xxxxxxx.
323 xxxxxxx.
324 xxxxxxx.
325 xxxxxxx.
326 xxxxxxx.
327 xxxxxxx.
328 xxxxxxx.
329 xxxxxxx.
330 xxxxxxx.
331 xxxxxxx.
332 xxxxxxx.
333 xxxxxxx.
334 xxxxxxx.
335*/
0881a0fd 336static unsigned short filled_box_cursor_bits[] = {
2d05deef
KS
337 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
338
339/* Hollow box cursor bitmap. A hollow box; max 13 pixels high. */
340/*
341 xxxxxxx.
342 x.....x.
343 x.....x.
344 x.....x.
345 x.....x.
346 x.....x.
347 x.....x.
348 x.....x.
349 x.....x.
350 x.....x.
351 x.....x.
352 x.....x.
353 xxxxxxx.
354*/
0881a0fd 355static unsigned short hollow_box_cursor_bits[] = {
2d05deef
KS
356 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe};
357
358/* Bar cursor bitmap. A vertical bar; max 13 pixels high. */
359/*
360 xx......
361 xx......
362 xx......
363 xx......
364 xx......
365 xx......
366 xx......
367 xx......
368 xx......
369 xx......
370 xx......
371 xx......
372 xx......
373*/
0881a0fd 374static unsigned short bar_cursor_bits[] = {
2d05deef
KS
375 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0};
376
377/* HBar cursor bitmap. A horisontal bar; 2 pixels high. */
378/*
379 xxxxxxx.
380 xxxxxxx.
381*/
0881a0fd 382static unsigned short hbar_cursor_bits[] = {
2d05deef
KS
383 0xfe, 0xfe};
384
385
386/* Bitmap drawn to indicate lines not displaying text if
387 `indicate-empty-lines' is non-nil. */
388/*
389 ........
390 ..xxxx..
391 ........
392 ........
393 ..xxxx..
394 ........
395*/
0881a0fd 396static unsigned short zv_bits[] = {
2d05deef
KS
397 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
398 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
399 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
400 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
401 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
402 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
403 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
404 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
405
406/* Hollow square bitmap. */
407/*
408 .xxxxxx.
409 .x....x.
410 .x....x.
411 .x....x.
412 .x....x.
413 .xxxxxx.
414*/
0881a0fd 415static unsigned short hollow_square_bits[] = {
2d05deef
KS
416 0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e};
417
418
0881a0fd
KS
419#define BYTES_PER_BITMAP_ROW (sizeof (unsigned short))
420#define STANDARD_BITMAP_HEIGHT(bits) (sizeof (bits)/BYTES_PER_BITMAP_ROW)
421#define FRBITS(bits) bits, STANDARD_BITMAP_HEIGHT (bits)
2d05deef 422
2d05deef
KS
423struct fringe_bitmap standard_bitmaps[MAX_STANDARD_FRINGE_BITMAPS] =
424{
425 { NULL, 0, 0, 0, 0, 0 }, /* NO_FRINGE_BITMAP */
426 { FRBITS (unknown_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
427 { FRBITS (left_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
428 { FRBITS (right_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
429 { FRBITS (up_arrow_bits), 8, 0, ALIGN_BITMAP_TOP, 0 },
430 { FRBITS (down_arrow_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
431 { FRBITS (continued_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
432 { FRBITS (continuation_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
433 { FRBITS (ov_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
434 { FRBITS (top_left_angle_bits), 8, 0, ALIGN_BITMAP_TOP, 0 },
435 { FRBITS (top_right_angle_bits), 8, 0, ALIGN_BITMAP_TOP, 0 },
436 { FRBITS (bottom_left_angle_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
437 { FRBITS (bottom_right_angle_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
438 { FRBITS (left_bracket_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
439 { FRBITS (right_bracket_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
440 { FRBITS (filled_box_cursor_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
441 { FRBITS (hollow_box_cursor_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
442 { FRBITS (hollow_square_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
443 { FRBITS (bar_cursor_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
444 { FRBITS (hbar_cursor_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
445 { FRBITS (zv_bits), 8, 3, ALIGN_BITMAP_TOP, 0 },
446};
447
ad67849e 448static struct fringe_bitmap **fringe_bitmaps;
49ce2dbd 449static Lisp_Object *fringe_faces;
ad67849e 450static int max_fringe_bitmaps;
2d05deef
KS
451
452static int max_used_fringe_bitmap = MAX_STANDARD_FRINGE_BITMAPS;
453
4cce0ab7
KS
454
455/* Lookup bitmap number for symbol BITMAP.
456 Return 0 if not a bitmap. */
2d05deef
KS
457
458int
4cce0ab7 459lookup_fringe_bitmap (bitmap)
7a2a85be
KS
460 Lisp_Object bitmap;
461{
462 int bn;
463
4cce0ab7 464 bitmap = Fget (bitmap, Qfringe);
7a2a85be
KS
465 if (!INTEGERP (bitmap))
466 return 0;
467
468 bn = XINT (bitmap);
4cce0ab7
KS
469 if (bn > NO_FRINGE_BITMAP
470 && bn < max_used_fringe_bitmap
471 && (bn < MAX_STANDARD_FRINGE_BITMAPS
472 || fringe_bitmaps[bn] != NULL))
473 return bn;
474
475 return 0;
7a2a85be
KS
476}
477
478/* Get fringe bitmap name for bitmap number BN.
479
480 Found by traversing Vfringe_bitmaps comparing BN to the
481 fringe property for each symbol.
482
483 Return BN if not found in Vfringe_bitmaps. */
484
485static Lisp_Object
486get_fringe_bitmap_name (bn)
487 int bn;
488{
489 Lisp_Object bitmaps;
490 Lisp_Object num;
491
492 /* Zero means no bitmap -- return nil. */
493 if (bn <= 0)
494 return Qnil;
495
496 bitmaps = Vfringe_bitmaps;
497 num = make_number (bn);
498
499 while (CONSP (bitmaps))
500 {
501 Lisp_Object bitmap = XCAR (bitmaps);
502 if (EQ (num, Fget (bitmap, Qfringe)))
503 return bitmap;
504 bitmaps = XCDR (bitmaps);
505 }
506
507 return num;
508}
509
510
2d05deef
KS
511/* Draw the bitmap WHICH in one of the left or right fringes of
512 window W. ROW is the glyph row for which to display the bitmap; it
513 determines the vertical position at which the bitmap has to be
514 drawn.
515 LEFT_P is 1 for left fringe, 0 for right fringe.
516*/
517
518void
519draw_fringe_bitmap_1 (w, row, left_p, overlay, which)
520 struct window *w;
521 struct glyph_row *row;
522 int left_p, overlay;
523 enum fringe_bitmap_type which;
524{
525 struct frame *f = XFRAME (WINDOW_FRAME (w));
526 struct draw_fringe_bitmap_params p;
527 struct fringe_bitmap *fb;
528 int period;
529 int face_id = DEFAULT_FACE_ID;
530
531 p.cursor_p = 0;
532 p.overlay_p = (overlay & 1) == 1;
533 p.cursor_p = (overlay & 2) == 2;
534
535 if (which != NO_FRINGE_BITMAP)
536 {
537 }
538 else if (left_p)
539 {
540 which = row->left_fringe_bitmap;
541 face_id = row->left_fringe_face_id;
542 }
543 else
544 {
545 which = row->right_fringe_bitmap;
546 face_id = row->right_fringe_face_id;
547 }
548
549 if (face_id == DEFAULT_FACE_ID)
49ce2dbd
KS
550 {
551 Lisp_Object face;
552
553 if ((face = fringe_faces[which], NILP (face))
308785c1
KS
554 || (face_id = lookup_derived_face (f, face, 'A', FRINGE_FACE_ID, 0),
555 face_id < 0))
49ce2dbd
KS
556 face_id = FRINGE_FACE_ID;
557 }
2d05deef
KS
558
559 fb = fringe_bitmaps[which];
560 if (fb == NULL)
561 fb = &standard_bitmaps[which < MAX_STANDARD_FRINGE_BITMAPS
562 ? which : UNDEF_FRINGE_BITMAP];
563
564 period = fb->period;
565
566 /* Convert row to frame coordinates. */
567 p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
568
569 p.which = which;
570 p.bits = fb->bits;
571 p.wd = fb->width;
572
573 p.h = fb->height;
574 p.dh = (period > 0 ? (p.y % period) : 0);
575 p.h -= p.dh;
576 /* Clip bitmap if too high. */
577 if (p.h > row->height)
578 p.h = row->height;
579
580 p.face = FACE_FROM_ID (f, face_id);
581
582 if (p.face == NULL)
583 {
49ce2dbd
KS
584 /* This could happen after clearing face cache.
585 But it shouldn't happen anymore. ++kfs */
2d05deef
KS
586 return;
587 }
588
589 PREPARE_FACE_FOR_DISPLAY (f, p.face);
590
591 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
592 the fringe. */
593 p.bx = -1;
594 if (left_p)
595 {
596 int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
597 int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
598 ? LEFT_MARGIN_AREA
599 : TEXT_AREA));
600 if (p.wd > wd)
601 p.wd = wd;
602 p.x = x - p.wd - (wd - p.wd) / 2;
603
604 if (p.wd < wd || row->height > p.h)
605 {
606 /* If W has a vertical border to its left, don't draw over it. */
607 wd -= ((!WINDOW_LEFTMOST_P (w)
608 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
609 ? 1 : 0);
610 p.bx = x - wd;
611 p.nx = wd;
612 }
613 }
614 else
615 {
616 int x = window_box_right (w,
617 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
618 ? RIGHT_MARGIN_AREA
619 : TEXT_AREA));
620 int wd = WINDOW_RIGHT_FRINGE_WIDTH (w);
621 if (p.wd > wd)
622 p.wd = wd;
623 p.x = x + (wd - p.wd) / 2;
624 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
625 the fringe. */
626 if (p.wd < wd || row->height > p.h)
627 {
628 p.bx = x;
629 p.nx = wd;
630 }
631 }
632
633 if (p.bx >= 0)
634 {
635 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
636
637 p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
638 p.ny = row->visible_height;
639 }
640
641 /* Adjust y to the offset in the row to start drawing the bitmap. */
642 switch (fb->align)
643 {
644 case ALIGN_BITMAP_CENTER:
645 p.y += (row->height - p.h) / 2;
646 break;
647 case ALIGN_BITMAP_BOTTOM:
648 p.h = fb->height;
649 p.y += (row->visible_height - p.h);
650 break;
651 case ALIGN_BITMAP_TOP:
652 break;
653 }
654
655 rif->draw_fringe_bitmap (w, row, &p);
656}
657
658void
659draw_fringe_bitmap (w, row, left_p)
660 struct window *w;
661 struct glyph_row *row;
662 int left_p;
663{
664 int overlay = 0;
665
666 if (!left_p && row->cursor_in_fringe_p)
667 {
668 int cursor = NO_FRINGE_BITMAP;
669
670 switch (w->phys_cursor_type)
671 {
672 case HOLLOW_BOX_CURSOR:
0881a0fd 673 if (row->visible_height >= STANDARD_BITMAP_HEIGHT (hollow_box_cursor_bits))
2d05deef
KS
674 cursor = HOLLOW_BOX_CURSOR_BITMAP;
675 else
676 cursor = HOLLOW_SQUARE_BITMAP;
677 break;
678 case FILLED_BOX_CURSOR:
679 cursor = FILLED_BOX_CURSOR_BITMAP;
680 break;
681 case BAR_CURSOR:
682 cursor = BAR_CURSOR_BITMAP;
683 break;
684 case HBAR_CURSOR:
685 cursor = HBAR_CURSOR_BITMAP;
686 break;
687 case NO_CURSOR:
688 default:
689 w->phys_cursor_on_p = 0;
690 row->cursor_in_fringe_p = 0;
691 break;
692 }
693 if (cursor != NO_FRINGE_BITMAP)
694 {
695 draw_fringe_bitmap_1 (w, row, 0, 2, cursor);
696 overlay = cursor == FILLED_BOX_CURSOR_BITMAP ? 3 : 1;
697 }
698 }
699
700 draw_fringe_bitmap_1 (w, row, left_p, overlay, NO_FRINGE_BITMAP);
701
a8b34fae 702 if (left_p && row->overlay_arrow_bitmap != NO_FRINGE_BITMAP)
1c2a9e98 703 draw_fringe_bitmap_1 (w, row, 1, 1,
a8b34fae
KS
704 (row->overlay_arrow_bitmap < 0
705 ? OVERLAY_ARROW_BITMAP
706 : row->overlay_arrow_bitmap));
2d05deef
KS
707}
708
709
710/* Draw fringe bitmaps for glyph row ROW on window W. Call this
711 function with input blocked. */
712
713void
714draw_row_fringe_bitmaps (w, row)
715 struct window *w;
716 struct glyph_row *row;
717{
718 xassert (interrupt_input_blocked);
719
720 /* If row is completely invisible, because of vscrolling, we
721 don't have to draw anything. */
722 if (row->visible_height <= 0)
723 return;
724
725 if (WINDOW_LEFT_FRINGE_WIDTH (w) != 0)
726 draw_fringe_bitmap (w, row, 1);
727
728 if (WINDOW_RIGHT_FRINGE_WIDTH (w) != 0)
729 draw_fringe_bitmap (w, row, 0);
730}
731
732/* Draw the fringes of window W. Only fringes for rows marked for
11491cbb 733 update in redraw_fringe_bitmaps_p are drawn.
2d05deef 734
11491cbb
KS
735 Return >0 if left or right fringe was redrawn in any way.
736
737 If NO_FRINGE is non-zero, also return >0 if either fringe has zero width.
738
739 A return value >0 indicates that the vertical line between windows
740 needs update (as it may be drawn in the fringe).
741*/
742
743int
744draw_window_fringes (w, no_fringe)
2d05deef 745 struct window *w;
11491cbb 746 int no_fringe;
2d05deef
KS
747{
748 struct glyph_row *row;
749 int yb = window_text_bottom_y (w);
750 int nrows = w->current_matrix->nrows;
751 int y = 0, rn;
11491cbb 752 int updated = 0;
2d05deef
KS
753
754 if (w->pseudo_window_p)
11491cbb
KS
755 return 0;
756
757 /* Must draw line if no fringe */
758 if (no_fringe
759 && (WINDOW_LEFT_FRINGE_WIDTH (w) == 0
760 || WINDOW_RIGHT_FRINGE_WIDTH (w) == 0))
761 updated++;
2d05deef
KS
762
763 for (y = 0, rn = 0, row = w->current_matrix->rows;
764 y < yb && rn < nrows;
765 y += row->height, ++row, ++rn)
766 {
767 if (!row->redraw_fringe_bitmaps_p)
768 continue;
769 draw_row_fringe_bitmaps (w, row);
770 row->redraw_fringe_bitmaps_p = 0;
11491cbb 771 updated++;
2d05deef 772 }
11491cbb
KS
773
774 return updated;
2d05deef
KS
775}
776
777
778/* Recalculate the bitmaps to show in the fringes of window W.
779 If FORCE_P is 0, only mark rows with modified bitmaps for update in
780 redraw_fringe_bitmaps_p; else mark all rows for update. */
781
782int
783update_window_fringes (w, force_p)
784 struct window *w;
785 int force_p;
786{
787 struct glyph_row *row, *cur = 0;
788 int yb = window_text_bottom_y (w);
789 int rn, nrows = w->current_matrix->nrows;
790 int y;
791 int redraw_p = 0;
5797a7a0
KS
792 Lisp_Object boundary_top = Qnil, boundary_bot = Qnil;
793 Lisp_Object arrow_top = Qnil, arrow_bot = Qnil;
794 Lisp_Object empty_pos;
795 Lisp_Object ind = Qnil;
2d05deef
KS
796
797 if (w->pseudo_window_p)
798 return 0;
799
800 if (!MINI_WINDOW_P (w)
801 && (ind = XBUFFER (w->buffer)->indicate_buffer_boundaries, !NILP (ind)))
802 {
5797a7a0
KS
803 if (EQ (ind, Qleft) || EQ (ind, Qright))
804 boundary_top = boundary_bot = arrow_top = arrow_bot = ind;
805 else if (CONSP (ind) && CONSP (XCAR (ind)))
806 {
807 Lisp_Object pos;
808 if (pos = Fassq (Qt, ind), !NILP (pos))
809 boundary_top = boundary_bot = arrow_top = arrow_bot = XCDR (pos);
810 if (pos = Fassq (Qtop, ind), !NILP (pos))
811 boundary_top = XCDR (pos);
812 if (pos = Fassq (Qbottom, ind), !NILP (pos))
813 boundary_bot = XCDR (pos);
814 if (pos = Fassq (Qup, ind), !NILP (pos))
815 arrow_top = XCDR (pos);
816 if (pos = Fassq (Qdown, ind), !NILP (pos))
817 arrow_bot = XCDR (pos);
818 }
2d05deef 819 else
a208b89c
KS
820 /* Anything else means boundary on left and no arrows. */
821 boundary_top = boundary_bot = Qleft;
5797a7a0 822 }
2d05deef 823
5797a7a0
KS
824 if (!NILP (ind))
825 {
26a5d440 826 int done_top = 0, done_bot = 0;
2d05deef
KS
827
828 for (y = 0, rn = 0;
829 y < yb && rn < nrows;
830 y += row->height, ++rn)
831 {
832 unsigned indicate_bob_p, indicate_top_line_p;
833 unsigned indicate_eob_p, indicate_bottom_line_p;
bffe8c26 834
2d05deef
KS
835 row = w->desired_matrix->rows + rn;
836 if (!row->enabled_p)
837 row = w->current_matrix->rows + rn;
838
839 indicate_bob_p = row->indicate_bob_p;
840 indicate_top_line_p = row->indicate_top_line_p;
841 indicate_eob_p = row->indicate_eob_p;
842 indicate_bottom_line_p = row->indicate_bottom_line_p;
bffe8c26 843
2d05deef
KS
844 row->indicate_bob_p = row->indicate_top_line_p = 0;
845 row->indicate_eob_p = row->indicate_bottom_line_p = 0;
846
26a5d440
KS
847 if (!row->mode_line_p)
848 {
849 if (!done_top)
850 {
851 if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer)))
852 row->indicate_bob_p = !NILP (boundary_top);
853 else
854 row->indicate_top_line_p = !NILP (arrow_top);
855 done_top = 1;
856 }
2d05deef 857
26a5d440
KS
858 if (!done_bot)
859 {
860 if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer)))
861 row->indicate_eob_p = !NILP (boundary_bot), done_bot = 1;
862 else if (y + row->height >= yb)
863 row->indicate_bottom_line_p = !NILP (arrow_bot), done_bot = 1;
864 }
865 }
2d05deef
KS
866
867 if (indicate_bob_p != row->indicate_bob_p
868 || indicate_top_line_p != row->indicate_top_line_p
869 || indicate_eob_p != row->indicate_eob_p
870 || indicate_bottom_line_p != row->indicate_bottom_line_p)
871 row->redraw_fringe_bitmaps_p = 1;
872 }
873 }
874
5797a7a0
KS
875 empty_pos = XBUFFER (w->buffer)->indicate_empty_lines;
876 if (!NILP (empty_pos) && !EQ (empty_pos, Qright))
877 empty_pos = WINDOW_LEFT_FRINGE_WIDTH (w) == 0 ? Qright : Qleft;
2d05deef
KS
878
879 for (y = 0, rn = 0;
880 y < yb && rn < nrows;
881 y += row->height, rn++)
882 {
883 enum fringe_bitmap_type left, right;
884 unsigned left_face_id, right_face_id;
885
886 row = w->desired_matrix->rows + rn;
887 cur = w->current_matrix->rows + rn;
888 if (!row->enabled_p)
889 row = cur;
890
891 left_face_id = right_face_id = DEFAULT_FACE_ID;
892
893 /* Decide which bitmap to draw in the left fringe. */
894 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
895 left = NO_FRINGE_BITMAP;
896 else if (row->left_user_fringe_bitmap != NO_FRINGE_BITMAP)
897 {
898 left = row->left_user_fringe_bitmap;
899 left_face_id = row->left_user_fringe_face_id;
900 }
cfd3af7a
KS
901 else if (row->truncated_on_left_p)
902 left = LEFT_TRUNCATION_BITMAP;
5797a7a0
KS
903 else if (row->indicate_bob_p && EQ (boundary_top, Qleft))
904 left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
2d05deef 905 ? LEFT_BRACKET_BITMAP : TOP_LEFT_ANGLE_BITMAP);
5797a7a0 906 else if (row->indicate_eob_p && EQ (boundary_bot, Qleft))
2d05deef 907 left = BOTTOM_LEFT_ANGLE_BITMAP;
2d05deef
KS
908 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
909 left = CONTINUATION_LINE_BITMAP;
5797a7a0 910 else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft))
2d05deef 911 left = ZV_LINE_BITMAP;
5797a7a0 912 else if (row->indicate_top_line_p && EQ (arrow_top, Qleft))
2d05deef 913 left = UP_ARROW_BITMAP;
5797a7a0 914 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qleft))
2d05deef
KS
915 left = DOWN_ARROW_BITMAP;
916 else
917 left = NO_FRINGE_BITMAP;
918
919 /* Decide which bitmap to draw in the right fringe. */
920 if (WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)
921 right = NO_FRINGE_BITMAP;
922 else if (row->right_user_fringe_bitmap != NO_FRINGE_BITMAP)
923 {
924 right = row->right_user_fringe_bitmap;
925 right_face_id = row->right_user_fringe_face_id;
926 }
cfd3af7a
KS
927 else if (row->truncated_on_right_p)
928 right = RIGHT_TRUNCATION_BITMAP;
5797a7a0
KS
929 else if (row->indicate_bob_p && EQ (boundary_top, Qright))
930 right = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
2d05deef 931 ? RIGHT_BRACKET_BITMAP : TOP_RIGHT_ANGLE_BITMAP);
5797a7a0 932 else if (row->indicate_eob_p && EQ (boundary_bot, Qright))
2d05deef 933 right = BOTTOM_RIGHT_ANGLE_BITMAP;
2d05deef
KS
934 else if (row->continued_p)
935 right = CONTINUED_LINE_BITMAP;
5797a7a0 936 else if (row->indicate_top_line_p && EQ (arrow_top, Qright))
2d05deef 937 right = UP_ARROW_BITMAP;
5797a7a0 938 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright))
2d05deef 939 right = DOWN_ARROW_BITMAP;
5797a7a0 940 else if (row->indicate_empty_line_p && EQ (empty_pos, Qright))
2d05deef
KS
941 right = ZV_LINE_BITMAP;
942 else
943 right = NO_FRINGE_BITMAP;
944
945 if (force_p
946 || row->y != cur->y
947 || row->visible_height != cur->visible_height
81544a1d 948 || row->ends_at_zv_p != cur->ends_at_zv_p
2d05deef
KS
949 || left != cur->left_fringe_bitmap
950 || right != cur->right_fringe_bitmap
951 || left_face_id != cur->left_fringe_face_id
952 || right_face_id != cur->right_fringe_face_id
953 || cur->redraw_fringe_bitmaps_p)
954 {
955 redraw_p = row->redraw_fringe_bitmaps_p = cur->redraw_fringe_bitmaps_p = 1;
956 cur->left_fringe_bitmap = left;
957 cur->right_fringe_bitmap = right;
958 cur->left_fringe_face_id = left_face_id;
959 cur->right_fringe_face_id = right_face_id;
960 }
961
a8b34fae 962 if (row->overlay_arrow_bitmap != cur->overlay_arrow_bitmap)
2d05deef
KS
963 {
964 redraw_p = row->redraw_fringe_bitmaps_p = cur->redraw_fringe_bitmaps_p = 1;
a8b34fae 965 cur->overlay_arrow_bitmap = row->overlay_arrow_bitmap;
2d05deef
KS
966 }
967
968 row->left_fringe_bitmap = left;
969 row->right_fringe_bitmap = right;
970 row->left_fringe_face_id = left_face_id;
971 row->right_fringe_face_id = right_face_id;
81544a1d
KS
972
973 if (rn > 0 && row->redraw_fringe_bitmaps_p)
974 row[-1].redraw_fringe_bitmaps_p = cur[-1].redraw_fringe_bitmaps_p = 1;
2d05deef
KS
975 }
976
977 return redraw_p;
978}
979
980
bffe8c26 981/* Compute actual fringe widths for frame F.
2d05deef
KS
982
983 If REDRAW is 1, redraw F if the fringe settings was actually
984 modified and F is visible.
985
986 Since the combined left and right fringe must occupy an integral
987 number of columns, we may need to add some pixels to each fringe.
988 Typically, we add an equal amount (+/- 1 pixel) to each fringe,
989 but a negative width value is taken literally (after negating it).
990
11491cbb 991 We never make the fringes narrower than specified.
2d05deef
KS
992*/
993
994void
995compute_fringe_widths (f, redraw)
996 struct frame *f;
997 int redraw;
998{
999 int o_left = FRAME_LEFT_FRINGE_WIDTH (f);
1000 int o_right = FRAME_RIGHT_FRINGE_WIDTH (f);
1001 int o_cols = FRAME_FRINGE_COLS (f);
1002
1003 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
1004 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
1005 int left_fringe_width, right_fringe_width;
1006
1007 if (!NILP (left_fringe))
1008 left_fringe = Fcdr (left_fringe);
1009 if (!NILP (right_fringe))
1010 right_fringe = Fcdr (right_fringe);
1011
1012 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
1013 XINT (left_fringe));
1014 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
1015 XINT (right_fringe));
1016
1017 if (left_fringe_width || right_fringe_width)
1018 {
1019 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
1020 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
1021 int conf_wid = left_wid + right_wid;
1022 int font_wid = FRAME_COLUMN_WIDTH (f);
1023 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
1024 int real_wid = cols * font_wid;
1025 if (left_wid && right_wid)
1026 {
1027 if (left_fringe_width < 0)
1028 {
1029 /* Left fringe width is fixed, adjust right fringe if necessary */
1030 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid;
1031 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid;
1032 }
1033 else if (right_fringe_width < 0)
1034 {
1035 /* Right fringe width is fixed, adjust left fringe if necessary */
1036 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
1037 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid;
1038 }
1039 else
1040 {
1041 /* Adjust both fringes with an equal amount.
1042 Note that we are doing integer arithmetic here, so don't
1043 lose a pixel if the total width is an odd number. */
1044 int fill = real_wid - conf_wid;
1045 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2;
1046 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2;
1047 }
1048 }
1049 else if (left_fringe_width)
1050 {
1051 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid;
1052 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
1053 }
1054 else
1055 {
1056 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
1057 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid;
1058 }
1059 FRAME_FRINGE_COLS (f) = cols;
1060 }
1061 else
1062 {
1063 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
1064 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
1065 FRAME_FRINGE_COLS (f) = 0;
1066 }
1067
1068 if (redraw && FRAME_VISIBLE_P (f))
1069 if (o_left != FRAME_LEFT_FRINGE_WIDTH (f) ||
1070 o_right != FRAME_RIGHT_FRINGE_WIDTH (f) ||
1071 o_cols != FRAME_FRINGE_COLS (f))
1072 redraw_frame (f);
1073}
1074
7a2a85be 1075
4cce0ab7
KS
1076/* Free resources used by a user-defined bitmap. */
1077
c3c69bb6 1078void
7a2a85be
KS
1079destroy_fringe_bitmap (n)
1080 int n;
2d05deef 1081{
2d05deef
KS
1082 struct fringe_bitmap **fbp;
1083
49ce2dbd 1084 fringe_faces[n] = Qnil;
2d05deef
KS
1085
1086 fbp = &fringe_bitmaps[n];
1087 if (*fbp && (*fbp)->dynamic)
1088 {
f2be4fd0 1089 if (rif && rif->destroy_fringe_bitmap)
2d05deef
KS
1090 rif->destroy_fringe_bitmap (n);
1091 xfree (*fbp);
1092 *fbp = NULL;
1093 }
1094
1095 while (max_used_fringe_bitmap > MAX_STANDARD_FRINGE_BITMAPS
1096 && fringe_bitmaps[max_used_fringe_bitmap - 1] == NULL)
1097 max_used_fringe_bitmap--;
7a2a85be
KS
1098}
1099
1100
1101DEFUN ("destroy-fringe-bitmap", Fdestroy_fringe_bitmap, Sdestroy_fringe_bitmap,
1102 1, 1, 0,
1103 doc: /* Destroy fringe bitmap BITMAP.
1104If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. */)
1105 (bitmap)
1106 Lisp_Object bitmap;
1107{
1108 int n;
7a2a85be 1109
4cce0ab7
KS
1110 CHECK_SYMBOL (bitmap);
1111 n = lookup_fringe_bitmap (bitmap);
1112 if (!n)
7a2a85be
KS
1113 return Qnil;
1114
1115 destroy_fringe_bitmap (n);
2d05deef 1116
4cce0ab7 1117 if (n >= MAX_STANDARD_FRINGE_BITMAPS)
7a2a85be 1118 {
4cce0ab7 1119 Vfringe_bitmaps = Fdelq (bitmap, Vfringe_bitmaps);
7a2a85be 1120 /* It would be better to remove the fringe property. */
4cce0ab7 1121 Fput (bitmap, Qfringe, Qnil);
7a2a85be 1122 }
4cce0ab7 1123
2d05deef
KS
1124 return Qnil;
1125}
1126
1127
1128/* Initialize bitmap bit.
0881a0fd
KS
1129
1130 On X, we bit-swap the built-in bitmaps and reduce bitmap
1131 from short to char array if width is <= 8 bits.
1132
bd231131
KS
1133 On MAC with big-endian CPU, we need to byte-swap each short.
1134
1135 On W32 and MAC (little endian), there's no need to do this.
2d05deef
KS
1136*/
1137
1138void
1139init_fringe_bitmap (which, fb, once_p)
1140 enum fringe_bitmap_type which;
1141 struct fringe_bitmap *fb;
1142 int once_p;
1143{
1144 if (once_p || fb->dynamic)
1145 {
0881a0fd
KS
1146#if defined (HAVE_X_WINDOWS)
1147 static unsigned char swap_nibble[16]
1148 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
1149 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
1150 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
bd231131 1151 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
0881a0fd 1152 unsigned short *bits = fb->bits;
2d05deef 1153 int j;
0881a0fd
KS
1154
1155 if (fb->width <= 8)
1156 {
1157 unsigned char *cbits = (unsigned char *)fb->bits;
1158 for (j = 0; j < fb->height; j++)
1159 {
1160 unsigned short b = *bits++;
1161 unsigned char c;
1162 c = (unsigned char)((swap_nibble[b & 0xf] << 4)
1163 | (swap_nibble[(b>>4) & 0xf]));
1164 *cbits++ = (c >> (8 - fb->width));
1165 }
1166 }
1167 else
2d05deef 1168 {
0881a0fd
KS
1169 for (j = 0; j < fb->height; j++)
1170 {
1171 unsigned short b = *bits;
1172 b = (unsigned short)((swap_nibble[b & 0xf] << 12)
1173 | (swap_nibble[(b>>4) & 0xf] << 8)
1174 | (swap_nibble[(b>>8) & 0xf] << 4)
1175 | (swap_nibble[(b>>12) & 0xf]));
1176 *bits++ = (b >> (16 - fb->width));
1177 }
2d05deef 1178 }
bd231131
KS
1179#endif /* HAVE_X_WINDOWS */
1180
1181#if defined (MAC_OS) && defined (WORDS_BIG_ENDIAN)
1182 unsigned short *bits = fb->bits;
159c348e 1183 int j;
bd231131
KS
1184 for (j = 0; j < fb->height; j++)
1185 {
1186 unsigned short b = *bits;
1187 *bits++ = ((b >> 8) & 0xff) | ((b & 0xff) << 8);
1188 }
1189#endif /* MAC_OS && WORDS_BIG_ENDIAN */
2d05deef
KS
1190 }
1191
1192 if (!once_p)
1193 {
7a2a85be 1194 destroy_fringe_bitmap (which);
2d05deef 1195
f2be4fd0 1196 if (rif && rif->define_fringe_bitmap)
2d05deef
KS
1197 rif->define_fringe_bitmap (which, fb->bits, fb->height, fb->width);
1198
1199 fringe_bitmaps[which] = fb;
1200 if (which >= max_used_fringe_bitmap)
1201 max_used_fringe_bitmap = which + 1;
1202 }
1203}
1204
1205
1206DEFUN ("define-fringe-bitmap", Fdefine_fringe_bitmap, Sdefine_fringe_bitmap,
7a2a85be
KS
1207 2, 5, 0,
1208 doc: /* Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.
1209BITMAP is a symbol or string naming the new fringe bitmap.
0881a0fd
KS
1210BITS is either a string or a vector of integers.
1211HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.
1212WIDTH must be an integer between 1 and 16, or nil which defaults to 8.
7a2a85be 1213Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
0881a0fd
KS
1214indicating the positioning of the bitmap relative to the rows where it
1215is used; the default is to center the bitmap. Fourth arg may also be a
1216list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap
1217should be repeated.
7a2a85be
KS
1218If BITMAP already exists, the existing definition is replaced. */)
1219 (bitmap, bits, height, width, align)
1220 Lisp_Object bitmap, bits, height, width, align;
2d05deef 1221{
2d05deef 1222 int n, h, i, j;
0881a0fd 1223 unsigned short *b;
2d05deef
KS
1224 struct fringe_bitmap fb, *xfb;
1225 int fill1 = 0, fill2 = 0;
7a2a85be 1226
4cce0ab7 1227 CHECK_SYMBOL (bitmap);
7a2a85be 1228
11e04b2d
KS
1229 if (STRINGP (bits))
1230 h = SCHARS (bits);
1231 else if (VECTORP (bits))
1232 h = XVECTOR (bits)->size;
1233 else
1234 bits = wrong_type_argument (Qsequencep, bits);
2d05deef
KS
1235
1236 if (NILP (height))
11e04b2d 1237 fb.height = h;
2d05deef
KS
1238 else
1239 {
1240 CHECK_NUMBER (height);
1241 fb.height = min (XINT (height), 255);
11e04b2d 1242 if (fb.height > h)
2d05deef 1243 {
2d05deef
KS
1244 fill1 = (fb.height - h) / 2;
1245 fill2 = fb.height - h - fill1;
1246 }
1247 }
bffe8c26 1248
2d05deef
KS
1249 if (NILP (width))
1250 fb.width = 8;
1251 else
1252 {
1253 CHECK_NUMBER (width);
1254 fb.width = min (XINT (width), 255);
1255 }
1256
1257 fb.period = 0;
1258 fb.align = ALIGN_BITMAP_CENTER;
1259
1260 if (CONSP (align))
1261 {
1262 Lisp_Object period = XCDR (align);
1263 if (CONSP (period))
1264 {
1265 period = XCAR (period);
1266 if (!NILP (period))
1267 {
1268 fb.period = fb.height;
1269 fb.height = 255;
1270 }
1271 }
1272 align = XCAR (align);
1273 }
1274 if (EQ (align, Qtop))
1275 fb.align = ALIGN_BITMAP_TOP;
1276 else if (EQ (align, Qbottom))
1277 fb.align = ALIGN_BITMAP_BOTTOM;
1278 else if (!NILP (align) && !EQ (align, Qcenter))
1279 error ("Bad align argument");
1280
ad67849e 1281 n = lookup_fringe_bitmap (bitmap);
4cce0ab7 1282 if (!n)
2d05deef 1283 {
ad67849e 1284 if (max_used_fringe_bitmap < max_fringe_bitmaps)
d2f14999 1285 n = max_used_fringe_bitmap++;
2d05deef
KS
1286 else
1287 {
1288 for (n = MAX_STANDARD_FRINGE_BITMAPS;
ad67849e 1289 n < max_fringe_bitmaps;
2d05deef
KS
1290 n++)
1291 if (fringe_bitmaps[n] == NULL)
1292 break;
ad67849e
KS
1293
1294 if (n == max_fringe_bitmaps)
1295 {
1296 if ((max_fringe_bitmaps + 20) > MAX_FRINGE_BITMAPS)
1297 error ("No free fringe bitmap slots");
1298
1299 i = max_fringe_bitmaps;
1300 max_fringe_bitmaps += 20;
1301 fringe_bitmaps
1302 = ((struct fringe_bitmap **)
1303 xrealloc (fringe_bitmaps, max_fringe_bitmaps * sizeof (struct fringe_bitmap *)));
1304 fringe_faces
50af5100 1305 = (Lisp_Object *) xrealloc (fringe_faces, max_fringe_bitmaps * sizeof (Lisp_Object));
ad67849e
KS
1306
1307 for (; i < max_fringe_bitmaps; i++)
1308 {
1309 fringe_bitmaps[i] = NULL;
49ce2dbd 1310 fringe_faces[i] = Qnil;
ad67849e
KS
1311 }
1312 }
2d05deef 1313 }
7a2a85be 1314
4cce0ab7
KS
1315 Vfringe_bitmaps = Fcons (bitmap, Vfringe_bitmaps);
1316 Fput (bitmap, Qfringe, make_number (n));
2d05deef
KS
1317 }
1318
1319 fb.dynamic = 1;
1320
beaedd56
AS
1321 xfb = (struct fringe_bitmap *) xmalloc (sizeof fb
1322 + fb.height * BYTES_PER_BITMAP_ROW);
1323 fb.bits = b = (unsigned short *) (xfb + 1);
2d05deef
KS
1324 bzero (b, fb.height);
1325
1326 j = 0;
1327 while (j < fb.height)
1328 {
1329 for (i = 0; i < fill1 && j < fb.height; i++)
1330 b[j++] = 0;
beaedd56 1331 for (i = 0; i < h && j < fb.height; i++)
2d05deef
KS
1332 {
1333 Lisp_Object elt = Faref (bits, make_number (i));
1334 b[j++] = NUMBERP (elt) ? XINT (elt) : 0;
1335 }
1336 for (i = 0; i < fill2 && j < fb.height; i++)
1337 b[j++] = 0;
1338 }
1339
1340 *xfb = fb;
1341
1342 init_fringe_bitmap (n, xfb, 0);
1343
4cce0ab7 1344 return bitmap;
2d05deef
KS
1345}
1346
1347DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face, Sset_fringe_bitmap_face,
1348 1, 2, 0,
7a2a85be 1349 doc: /* Set face for fringe bitmap BITMAP to FACE.
2d05deef 1350If FACE is nil, reset face to default fringe face. */)
7a2a85be
KS
1351 (bitmap, face)
1352 Lisp_Object bitmap, face;
2d05deef 1353{
4cce0ab7 1354 int n;
2d05deef
KS
1355 int face_id;
1356
4cce0ab7
KS
1357 CHECK_SYMBOL (bitmap);
1358 n = lookup_fringe_bitmap (bitmap);
1359 if (!n)
7a2a85be 1360 error ("Undefined fringe bitmap");
2d05deef
KS
1361
1362 if (!NILP (face))
1363 {
308785c1
KS
1364 face_id = lookup_derived_face (SELECTED_FRAME (), face,
1365 'A', FRINGE_FACE_ID, 1);
2d05deef
KS
1366 if (face_id < 0)
1367 error ("No such face");
1368 }
2d05deef 1369
49ce2dbd 1370 fringe_faces[n] = face;
2d05deef
KS
1371
1372 return Qnil;
1373}
1374
1375DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos, Sfringe_bitmaps_at_pos,
1376 0, 2, 0,
bffe8c26 1377 doc: /* Return fringe bitmaps of row containing position POS in window WINDOW.
2d05deef 1378If WINDOW is nil, use selected window. If POS is nil, use value of point
d3848fe9
KS
1379in that window. Return value is a list (LEFT RIGHT OV), where LEFT
1380is the symbol for the bitmap in the left fringe (or nil if no bitmap),
1381RIGHT is similar for the right fringe, and OV is non-nil if there is an
1382overlay arrow in the left fringe.
5797a7a0 1383Return nil if POS is not visible in WINDOW. */)
2d05deef 1384 (pos, window)
d30b6b33 1385 Lisp_Object pos, window;
2d05deef
KS
1386{
1387 struct window *w;
2d05deef
KS
1388 struct glyph_row *row;
1389 int textpos;
1390
1391 if (NILP (window))
1392 window = selected_window;
1393 CHECK_WINDOW (window);
1394 w = XWINDOW (window);
1395
1396 if (!NILP (pos))
1397 {
1398 CHECK_NUMBER_COERCE_MARKER (pos);
1399 textpos = XINT (pos);
1400 }
1401 else if (w == XWINDOW (selected_window))
1402 textpos = PT;
1403 else
1404 textpos = XMARKER (w->pointm)->charpos;
1405
1406 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1407 row = row_containing_pos (w, textpos, row, NULL, 0);
1408 if (row)
d3848fe9
KS
1409 return list3 (get_fringe_bitmap_name (row->left_fringe_bitmap),
1410 get_fringe_bitmap_name (row->right_fringe_bitmap),
a8b34fae
KS
1411 (row->overlay_arrow_bitmap == 0 ? Qnil
1412 : row->overlay_arrow_bitmap < 0 ? Qt
1413 : get_fringe_bitmap_name (row->overlay_arrow_bitmap)));
2d05deef
KS
1414 else
1415 return Qnil;
1416}
1417
1418
1419/***********************************************************************
1420 Initialization
1421 ***********************************************************************/
1422
1423void
1424syms_of_fringe ()
1425{
2d05deef
KS
1426 defsubr (&Sdestroy_fringe_bitmap);
1427 defsubr (&Sdefine_fringe_bitmap);
1428 defsubr (&Sfringe_bitmaps_at_pos);
1429 defsubr (&Sset_fringe_bitmap_face);
1430
1431 DEFVAR_LISP ("overflow-newline-into-fringe", &Voverflow_newline_into_fringe,
1432 doc: /* *Non-nil means that newline may flow into the right fringe.
1433This means that display lines which are exactly as wide as the window
1434(not counting the final newline) will only occupy one screen line, by
1435showing (or hiding) the final newline in the right fringe; when point
1436is at the final newline, the cursor is shown in the right fringe.
1437If nil, also continue lines which are exactly as wide as the window. */);
1438 Voverflow_newline_into_fringe = Qt;
1439
7a2a85be
KS
1440 DEFVAR_LISP ("fringe-bitmaps", &Vfringe_bitmaps,
1441 doc: /* List of fringe bitmap symbols.
1442You must (require 'fringe) to use fringe bitmap symbols in your programs." */);
1443 Vfringe_bitmaps = Qnil;
2d05deef
KS
1444}
1445
49ce2dbd
KS
1446/* Garbage collection hook */
1447
1448void
1449mark_fringe_data ()
1450{
1451 int i;
1452
1453 for (i = 0; i < max_fringe_bitmaps; i++)
1454 if (!NILP (fringe_faces[i]))
1455 mark_object (fringe_faces[i]);
1456}
1457
2d05deef
KS
1458/* Initialize this module when Emacs starts. */
1459
1460void
1461init_fringe_once ()
1462{
1463 enum fringe_bitmap_type bt;
1464
1465 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1466 init_fringe_bitmap(bt, &standard_bitmaps[bt], 1);
1467}
1468
1469void
1470init_fringe ()
1471{
1472 int i;
1473
ad67849e
KS
1474 max_fringe_bitmaps = MAX_STANDARD_FRINGE_BITMAPS + 20;
1475
1476 fringe_bitmaps
1477 = (struct fringe_bitmap **) xmalloc (max_fringe_bitmaps * sizeof (struct fringe_bitmap *));
1478 fringe_faces
50af5100 1479 = (Lisp_Object *) xmalloc (max_fringe_bitmaps * sizeof (Lisp_Object));
ad67849e
KS
1480
1481 for (i = 0; i < max_fringe_bitmaps; i++)
1482 {
1483 fringe_bitmaps[i] = NULL;
49ce2dbd 1484 fringe_faces[i] = Qnil;
ad67849e 1485 }
2d05deef
KS
1486}
1487
1488#ifdef HAVE_NTGUI
1489
1490void
1491w32_init_fringe ()
1492{
1493 enum fringe_bitmap_type bt;
1494
f2be4fd0
KS
1495 if (!rif)
1496 return;
1497
2d05deef
KS
1498 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1499 {
1500 struct fringe_bitmap *fb = &standard_bitmaps[bt];
1501 rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
1502 }
1503}
1504
1505void
1506w32_reset_fringes ()
1507{
1508 /* Destroy row bitmaps. */
1509 int bt;
bffe8c26 1510
f2be4fd0
KS
1511 if (!rif)
1512 return;
1513
2d05deef
KS
1514 for (bt = NO_FRINGE_BITMAP + 1; bt < max_used_fringe_bitmap; bt++)
1515 rif->destroy_fringe_bitmap (bt);
1516}
1517
bd231131 1518#endif /* HAVE_NTGUI */
2d05deef
KS
1519
1520#endif /* HAVE_WINDOW_SYSTEM */
1521
429e7e2d
MB
1522/* arch-tag: 04596920-43eb-473d-b319-82712338162d
1523 (do not change this comment) */