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