*** empty log message ***
[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,
4 2005 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 {
853 if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer)))
854 row->indicate_bob_p = !NILP (boundary_top);
855 else
856 row->indicate_top_line_p = !NILP (arrow_top);
857 done_top = 1;
858 }
2d05deef 859
26a5d440
KS
860 if (!done_bot)
861 {
862 if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer)))
863 row->indicate_eob_p = !NILP (boundary_bot), done_bot = 1;
864 else if (y + row->height >= yb)
865 row->indicate_bottom_line_p = !NILP (arrow_bot), done_bot = 1;
866 }
867 }
2d05deef
KS
868
869 if (indicate_bob_p != row->indicate_bob_p
870 || indicate_top_line_p != row->indicate_top_line_p
871 || indicate_eob_p != row->indicate_eob_p
872 || indicate_bottom_line_p != row->indicate_bottom_line_p)
873 row->redraw_fringe_bitmaps_p = 1;
874 }
875 }
876
5797a7a0
KS
877 empty_pos = XBUFFER (w->buffer)->indicate_empty_lines;
878 if (!NILP (empty_pos) && !EQ (empty_pos, Qright))
879 empty_pos = WINDOW_LEFT_FRINGE_WIDTH (w) == 0 ? Qright : Qleft;
2d05deef
KS
880
881 for (y = 0, rn = 0;
882 y < yb && rn < nrows;
883 y += row->height, rn++)
884 {
885 enum fringe_bitmap_type left, right;
886 unsigned left_face_id, right_face_id;
887
888 row = w->desired_matrix->rows + rn;
889 cur = w->current_matrix->rows + rn;
890 if (!row->enabled_p)
891 row = cur;
892
893 left_face_id = right_face_id = DEFAULT_FACE_ID;
894
895 /* Decide which bitmap to draw in the left fringe. */
896 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
897 left = NO_FRINGE_BITMAP;
898 else if (row->left_user_fringe_bitmap != NO_FRINGE_BITMAP)
899 {
900 left = row->left_user_fringe_bitmap;
901 left_face_id = row->left_user_fringe_face_id;
902 }
cfd3af7a
KS
903 else if (row->truncated_on_left_p)
904 left = LEFT_TRUNCATION_BITMAP;
5797a7a0
KS
905 else if (row->indicate_bob_p && EQ (boundary_top, Qleft))
906 left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
2d05deef 907 ? LEFT_BRACKET_BITMAP : TOP_LEFT_ANGLE_BITMAP);
5797a7a0 908 else if (row->indicate_eob_p && EQ (boundary_bot, Qleft))
2d05deef 909 left = BOTTOM_LEFT_ANGLE_BITMAP;
2d05deef
KS
910 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
911 left = CONTINUATION_LINE_BITMAP;
5797a7a0 912 else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft))
2d05deef 913 left = ZV_LINE_BITMAP;
5797a7a0 914 else if (row->indicate_top_line_p && EQ (arrow_top, Qleft))
2d05deef 915 left = UP_ARROW_BITMAP;
5797a7a0 916 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qleft))
2d05deef
KS
917 left = DOWN_ARROW_BITMAP;
918 else
919 left = NO_FRINGE_BITMAP;
920
921 /* Decide which bitmap to draw in the right fringe. */
922 if (WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)
923 right = NO_FRINGE_BITMAP;
924 else if (row->right_user_fringe_bitmap != NO_FRINGE_BITMAP)
925 {
926 right = row->right_user_fringe_bitmap;
927 right_face_id = row->right_user_fringe_face_id;
928 }
cfd3af7a
KS
929 else if (row->truncated_on_right_p)
930 right = RIGHT_TRUNCATION_BITMAP;
5797a7a0
KS
931 else if (row->indicate_bob_p && EQ (boundary_top, Qright))
932 right = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
2d05deef 933 ? RIGHT_BRACKET_BITMAP : TOP_RIGHT_ANGLE_BITMAP);
5797a7a0 934 else if (row->indicate_eob_p && EQ (boundary_bot, Qright))
2d05deef 935 right = BOTTOM_RIGHT_ANGLE_BITMAP;
2d05deef
KS
936 else if (row->continued_p)
937 right = CONTINUED_LINE_BITMAP;
5797a7a0 938 else if (row->indicate_top_line_p && EQ (arrow_top, Qright))
2d05deef 939 right = UP_ARROW_BITMAP;
5797a7a0 940 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright))
2d05deef 941 right = DOWN_ARROW_BITMAP;
5797a7a0 942 else if (row->indicate_empty_line_p && EQ (empty_pos, Qright))
2d05deef
KS
943 right = ZV_LINE_BITMAP;
944 else
945 right = NO_FRINGE_BITMAP;
946
4dadc129 947 if (row->y != cur->y
2d05deef 948 || row->visible_height != cur->visible_height
81544a1d 949 || row->ends_at_zv_p != cur->ends_at_zv_p
2d05deef
KS
950 || left != cur->left_fringe_bitmap
951 || right != cur->right_fringe_bitmap
952 || left_face_id != cur->left_fringe_face_id
953 || right_face_id != cur->right_fringe_face_id
954 || cur->redraw_fringe_bitmaps_p)
955 {
4dadc129
KS
956 redraw_p = row->redraw_fringe_bitmaps_p = 1;
957 if (!keep_current_p)
958 {
959 cur->redraw_fringe_bitmaps_p = 1;
960 cur->left_fringe_bitmap = left;
961 cur->right_fringe_bitmap = right;
962 cur->left_fringe_face_id = left_face_id;
963 cur->right_fringe_face_id = right_face_id;
964 }
2d05deef
KS
965 }
966
a8b34fae 967 if (row->overlay_arrow_bitmap != cur->overlay_arrow_bitmap)
2d05deef
KS
968 {
969 redraw_p = row->redraw_fringe_bitmaps_p = cur->redraw_fringe_bitmaps_p = 1;
a8b34fae 970 cur->overlay_arrow_bitmap = row->overlay_arrow_bitmap;
2d05deef
KS
971 }
972
973 row->left_fringe_bitmap = left;
974 row->right_fringe_bitmap = right;
975 row->left_fringe_face_id = left_face_id;
976 row->right_fringe_face_id = right_face_id;
81544a1d
KS
977
978 if (rn > 0 && row->redraw_fringe_bitmaps_p)
979 row[-1].redraw_fringe_bitmaps_p = cur[-1].redraw_fringe_bitmaps_p = 1;
2d05deef
KS
980 }
981
4dadc129 982 return redraw_p && !keep_current_p;
2d05deef
KS
983}
984
985
bffe8c26 986/* Compute actual fringe widths for frame F.
2d05deef
KS
987
988 If REDRAW is 1, redraw F if the fringe settings was actually
989 modified and F is visible.
990
991 Since the combined left and right fringe must occupy an integral
992 number of columns, we may need to add some pixels to each fringe.
993 Typically, we add an equal amount (+/- 1 pixel) to each fringe,
994 but a negative width value is taken literally (after negating it).
995
11491cbb 996 We never make the fringes narrower than specified.
2d05deef
KS
997*/
998
999void
1000compute_fringe_widths (f, redraw)
1001 struct frame *f;
1002 int redraw;
1003{
1004 int o_left = FRAME_LEFT_FRINGE_WIDTH (f);
1005 int o_right = FRAME_RIGHT_FRINGE_WIDTH (f);
1006 int o_cols = FRAME_FRINGE_COLS (f);
1007
1008 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
1009 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
1010 int left_fringe_width, right_fringe_width;
1011
1012 if (!NILP (left_fringe))
1013 left_fringe = Fcdr (left_fringe);
1014 if (!NILP (right_fringe))
1015 right_fringe = Fcdr (right_fringe);
1016
1017 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
1018 XINT (left_fringe));
1019 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
1020 XINT (right_fringe));
1021
1022 if (left_fringe_width || right_fringe_width)
1023 {
1024 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
1025 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
1026 int conf_wid = left_wid + right_wid;
1027 int font_wid = FRAME_COLUMN_WIDTH (f);
1028 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
1029 int real_wid = cols * font_wid;
1030 if (left_wid && right_wid)
1031 {
1032 if (left_fringe_width < 0)
1033 {
1034 /* Left fringe width is fixed, adjust right fringe if necessary */
1035 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid;
1036 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid;
1037 }
1038 else if (right_fringe_width < 0)
1039 {
1040 /* Right fringe width is fixed, adjust left fringe if necessary */
1041 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
1042 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid;
1043 }
1044 else
1045 {
1046 /* Adjust both fringes with an equal amount.
1047 Note that we are doing integer arithmetic here, so don't
1048 lose a pixel if the total width is an odd number. */
1049 int fill = real_wid - conf_wid;
1050 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2;
1051 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2;
1052 }
1053 }
1054 else if (left_fringe_width)
1055 {
1056 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid;
1057 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
1058 }
1059 else
1060 {
1061 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
1062 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid;
1063 }
1064 FRAME_FRINGE_COLS (f) = cols;
1065 }
1066 else
1067 {
1068 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
1069 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
1070 FRAME_FRINGE_COLS (f) = 0;
1071 }
1072
1073 if (redraw && FRAME_VISIBLE_P (f))
1074 if (o_left != FRAME_LEFT_FRINGE_WIDTH (f) ||
1075 o_right != FRAME_RIGHT_FRINGE_WIDTH (f) ||
1076 o_cols != FRAME_FRINGE_COLS (f))
1077 redraw_frame (f);
1078}
1079
7a2a85be 1080
4cce0ab7
KS
1081/* Free resources used by a user-defined bitmap. */
1082
c3c69bb6 1083void
7a2a85be
KS
1084destroy_fringe_bitmap (n)
1085 int n;
2d05deef 1086{
2d05deef
KS
1087 struct fringe_bitmap **fbp;
1088
49ce2dbd 1089 fringe_faces[n] = Qnil;
2d05deef
KS
1090
1091 fbp = &fringe_bitmaps[n];
1092 if (*fbp && (*fbp)->dynamic)
1093 {
f2be4fd0 1094 if (rif && rif->destroy_fringe_bitmap)
2d05deef
KS
1095 rif->destroy_fringe_bitmap (n);
1096 xfree (*fbp);
1097 *fbp = NULL;
1098 }
1099
1100 while (max_used_fringe_bitmap > MAX_STANDARD_FRINGE_BITMAPS
1101 && fringe_bitmaps[max_used_fringe_bitmap - 1] == NULL)
1102 max_used_fringe_bitmap--;
7a2a85be
KS
1103}
1104
1105
1106DEFUN ("destroy-fringe-bitmap", Fdestroy_fringe_bitmap, Sdestroy_fringe_bitmap,
1107 1, 1, 0,
1108 doc: /* Destroy fringe bitmap BITMAP.
1109If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. */)
1110 (bitmap)
1111 Lisp_Object bitmap;
1112{
1113 int n;
7a2a85be 1114
4cce0ab7
KS
1115 CHECK_SYMBOL (bitmap);
1116 n = lookup_fringe_bitmap (bitmap);
1117 if (!n)
7a2a85be
KS
1118 return Qnil;
1119
1120 destroy_fringe_bitmap (n);
2d05deef 1121
4cce0ab7 1122 if (n >= MAX_STANDARD_FRINGE_BITMAPS)
7a2a85be 1123 {
4cce0ab7 1124 Vfringe_bitmaps = Fdelq (bitmap, Vfringe_bitmaps);
7a2a85be 1125 /* It would be better to remove the fringe property. */
4cce0ab7 1126 Fput (bitmap, Qfringe, Qnil);
7a2a85be 1127 }
4cce0ab7 1128
2d05deef
KS
1129 return Qnil;
1130}
1131
1132
1133/* Initialize bitmap bit.
0881a0fd
KS
1134
1135 On X, we bit-swap the built-in bitmaps and reduce bitmap
1136 from short to char array if width is <= 8 bits.
1137
bd231131
KS
1138 On MAC with big-endian CPU, we need to byte-swap each short.
1139
1140 On W32 and MAC (little endian), there's no need to do this.
2d05deef
KS
1141*/
1142
1143void
1144init_fringe_bitmap (which, fb, once_p)
1145 enum fringe_bitmap_type which;
1146 struct fringe_bitmap *fb;
1147 int once_p;
1148{
1149 if (once_p || fb->dynamic)
1150 {
0881a0fd
KS
1151#if defined (HAVE_X_WINDOWS)
1152 static unsigned char swap_nibble[16]
1153 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
1154 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
1155 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
bd231131 1156 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
0881a0fd 1157 unsigned short *bits = fb->bits;
2d05deef 1158 int j;
0881a0fd
KS
1159
1160 if (fb->width <= 8)
1161 {
1162 unsigned char *cbits = (unsigned char *)fb->bits;
1163 for (j = 0; j < fb->height; j++)
1164 {
1165 unsigned short b = *bits++;
1166 unsigned char c;
1167 c = (unsigned char)((swap_nibble[b & 0xf] << 4)
1168 | (swap_nibble[(b>>4) & 0xf]));
1169 *cbits++ = (c >> (8 - fb->width));
1170 }
1171 }
1172 else
2d05deef 1173 {
0881a0fd
KS
1174 for (j = 0; j < fb->height; j++)
1175 {
1176 unsigned short b = *bits;
1177 b = (unsigned short)((swap_nibble[b & 0xf] << 12)
1178 | (swap_nibble[(b>>4) & 0xf] << 8)
1179 | (swap_nibble[(b>>8) & 0xf] << 4)
1180 | (swap_nibble[(b>>12) & 0xf]));
1181 *bits++ = (b >> (16 - fb->width));
1182 }
2d05deef 1183 }
bd231131
KS
1184#endif /* HAVE_X_WINDOWS */
1185
1186#if defined (MAC_OS) && defined (WORDS_BIG_ENDIAN)
1187 unsigned short *bits = fb->bits;
159c348e 1188 int j;
bd231131
KS
1189 for (j = 0; j < fb->height; j++)
1190 {
1191 unsigned short b = *bits;
1192 *bits++ = ((b >> 8) & 0xff) | ((b & 0xff) << 8);
1193 }
1194#endif /* MAC_OS && WORDS_BIG_ENDIAN */
2d05deef
KS
1195 }
1196
1197 if (!once_p)
1198 {
7a2a85be 1199 destroy_fringe_bitmap (which);
2d05deef 1200
f2be4fd0 1201 if (rif && rif->define_fringe_bitmap)
2d05deef
KS
1202 rif->define_fringe_bitmap (which, fb->bits, fb->height, fb->width);
1203
1204 fringe_bitmaps[which] = fb;
1205 if (which >= max_used_fringe_bitmap)
1206 max_used_fringe_bitmap = which + 1;
1207 }
1208}
1209
1210
1211DEFUN ("define-fringe-bitmap", Fdefine_fringe_bitmap, Sdefine_fringe_bitmap,
7a2a85be
KS
1212 2, 5, 0,
1213 doc: /* Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.
1214BITMAP is a symbol or string naming the new fringe bitmap.
0881a0fd
KS
1215BITS is either a string or a vector of integers.
1216HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.
1217WIDTH must be an integer between 1 and 16, or nil which defaults to 8.
7a2a85be 1218Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
0881a0fd
KS
1219indicating the positioning of the bitmap relative to the rows where it
1220is used; the default is to center the bitmap. Fourth arg may also be a
1221list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap
1222should be repeated.
7a2a85be
KS
1223If BITMAP already exists, the existing definition is replaced. */)
1224 (bitmap, bits, height, width, align)
1225 Lisp_Object bitmap, bits, height, width, align;
2d05deef 1226{
2d05deef 1227 int n, h, i, j;
0881a0fd 1228 unsigned short *b;
2d05deef
KS
1229 struct fringe_bitmap fb, *xfb;
1230 int fill1 = 0, fill2 = 0;
7a2a85be 1231
4cce0ab7 1232 CHECK_SYMBOL (bitmap);
7a2a85be 1233
11e04b2d
KS
1234 if (STRINGP (bits))
1235 h = SCHARS (bits);
1236 else if (VECTORP (bits))
1237 h = XVECTOR (bits)->size;
1238 else
1239 bits = wrong_type_argument (Qsequencep, bits);
2d05deef
KS
1240
1241 if (NILP (height))
11e04b2d 1242 fb.height = h;
2d05deef
KS
1243 else
1244 {
1245 CHECK_NUMBER (height);
1246 fb.height = min (XINT (height), 255);
11e04b2d 1247 if (fb.height > h)
2d05deef 1248 {
2d05deef
KS
1249 fill1 = (fb.height - h) / 2;
1250 fill2 = fb.height - h - fill1;
1251 }
1252 }
bffe8c26 1253
2d05deef
KS
1254 if (NILP (width))
1255 fb.width = 8;
1256 else
1257 {
1258 CHECK_NUMBER (width);
1259 fb.width = min (XINT (width), 255);
1260 }
1261
1262 fb.period = 0;
1263 fb.align = ALIGN_BITMAP_CENTER;
1264
1265 if (CONSP (align))
1266 {
1267 Lisp_Object period = XCDR (align);
1268 if (CONSP (period))
1269 {
1270 period = XCAR (period);
1271 if (!NILP (period))
1272 {
1273 fb.period = fb.height;
1274 fb.height = 255;
1275 }
1276 }
1277 align = XCAR (align);
1278 }
1279 if (EQ (align, Qtop))
1280 fb.align = ALIGN_BITMAP_TOP;
1281 else if (EQ (align, Qbottom))
1282 fb.align = ALIGN_BITMAP_BOTTOM;
1283 else if (!NILP (align) && !EQ (align, Qcenter))
1284 error ("Bad align argument");
1285
ad67849e 1286 n = lookup_fringe_bitmap (bitmap);
4cce0ab7 1287 if (!n)
2d05deef 1288 {
ad67849e 1289 if (max_used_fringe_bitmap < max_fringe_bitmaps)
d2f14999 1290 n = max_used_fringe_bitmap++;
2d05deef
KS
1291 else
1292 {
1293 for (n = MAX_STANDARD_FRINGE_BITMAPS;
ad67849e 1294 n < max_fringe_bitmaps;
2d05deef
KS
1295 n++)
1296 if (fringe_bitmaps[n] == NULL)
1297 break;
ad67849e
KS
1298
1299 if (n == max_fringe_bitmaps)
1300 {
1301 if ((max_fringe_bitmaps + 20) > MAX_FRINGE_BITMAPS)
1302 error ("No free fringe bitmap slots");
1303
1304 i = max_fringe_bitmaps;
1305 max_fringe_bitmaps += 20;
1306 fringe_bitmaps
1307 = ((struct fringe_bitmap **)
1308 xrealloc (fringe_bitmaps, max_fringe_bitmaps * sizeof (struct fringe_bitmap *)));
1309 fringe_faces
50af5100 1310 = (Lisp_Object *) xrealloc (fringe_faces, max_fringe_bitmaps * sizeof (Lisp_Object));
ad67849e
KS
1311
1312 for (; i < max_fringe_bitmaps; i++)
1313 {
1314 fringe_bitmaps[i] = NULL;
49ce2dbd 1315 fringe_faces[i] = Qnil;
ad67849e
KS
1316 }
1317 }
2d05deef 1318 }
7a2a85be 1319
4cce0ab7
KS
1320 Vfringe_bitmaps = Fcons (bitmap, Vfringe_bitmaps);
1321 Fput (bitmap, Qfringe, make_number (n));
2d05deef
KS
1322 }
1323
1324 fb.dynamic = 1;
1325
beaedd56
AS
1326 xfb = (struct fringe_bitmap *) xmalloc (sizeof fb
1327 + fb.height * BYTES_PER_BITMAP_ROW);
1328 fb.bits = b = (unsigned short *) (xfb + 1);
2d05deef
KS
1329 bzero (b, fb.height);
1330
1331 j = 0;
1332 while (j < fb.height)
1333 {
1334 for (i = 0; i < fill1 && j < fb.height; i++)
1335 b[j++] = 0;
beaedd56 1336 for (i = 0; i < h && j < fb.height; i++)
2d05deef
KS
1337 {
1338 Lisp_Object elt = Faref (bits, make_number (i));
1339 b[j++] = NUMBERP (elt) ? XINT (elt) : 0;
1340 }
1341 for (i = 0; i < fill2 && j < fb.height; i++)
1342 b[j++] = 0;
1343 }
1344
1345 *xfb = fb;
1346
1347 init_fringe_bitmap (n, xfb, 0);
1348
4cce0ab7 1349 return bitmap;
2d05deef
KS
1350}
1351
1352DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face, Sset_fringe_bitmap_face,
1353 1, 2, 0,
7a2a85be 1354 doc: /* Set face for fringe bitmap BITMAP to FACE.
2d05deef 1355If FACE is nil, reset face to default fringe face. */)
7a2a85be
KS
1356 (bitmap, face)
1357 Lisp_Object bitmap, face;
2d05deef 1358{
4cce0ab7 1359 int n;
2d05deef
KS
1360 int face_id;
1361
4cce0ab7
KS
1362 CHECK_SYMBOL (bitmap);
1363 n = lookup_fringe_bitmap (bitmap);
1364 if (!n)
7a2a85be 1365 error ("Undefined fringe bitmap");
2d05deef
KS
1366
1367 if (!NILP (face))
1368 {
308785c1
KS
1369 face_id = lookup_derived_face (SELECTED_FRAME (), face,
1370 'A', FRINGE_FACE_ID, 1);
2d05deef
KS
1371 if (face_id < 0)
1372 error ("No such face");
1373 }
2d05deef 1374
49ce2dbd 1375 fringe_faces[n] = face;
2d05deef
KS
1376
1377 return Qnil;
1378}
1379
1380DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos, Sfringe_bitmaps_at_pos,
1381 0, 2, 0,
bffe8c26 1382 doc: /* Return fringe bitmaps of row containing position POS in window WINDOW.
2d05deef 1383If WINDOW is nil, use selected window. If POS is nil, use value of point
d3848fe9
KS
1384in that window. Return value is a list (LEFT RIGHT OV), where LEFT
1385is the symbol for the bitmap in the left fringe (or nil if no bitmap),
1386RIGHT is similar for the right fringe, and OV is non-nil if there is an
1387overlay arrow in the left fringe.
5797a7a0 1388Return nil if POS is not visible in WINDOW. */)
2d05deef 1389 (pos, window)
d30b6b33 1390 Lisp_Object pos, window;
2d05deef
KS
1391{
1392 struct window *w;
2d05deef
KS
1393 struct glyph_row *row;
1394 int textpos;
1395
1396 if (NILP (window))
1397 window = selected_window;
1398 CHECK_WINDOW (window);
1399 w = XWINDOW (window);
1400
1401 if (!NILP (pos))
1402 {
1403 CHECK_NUMBER_COERCE_MARKER (pos);
1404 textpos = XINT (pos);
1405 }
1406 else if (w == XWINDOW (selected_window))
1407 textpos = PT;
1408 else
1409 textpos = XMARKER (w->pointm)->charpos;
1410
1411 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1412 row = row_containing_pos (w, textpos, row, NULL, 0);
1413 if (row)
d3848fe9
KS
1414 return list3 (get_fringe_bitmap_name (row->left_fringe_bitmap),
1415 get_fringe_bitmap_name (row->right_fringe_bitmap),
a8b34fae
KS
1416 (row->overlay_arrow_bitmap == 0 ? Qnil
1417 : row->overlay_arrow_bitmap < 0 ? Qt
1418 : get_fringe_bitmap_name (row->overlay_arrow_bitmap)));
2d05deef
KS
1419 else
1420 return Qnil;
1421}
1422
1423
1424/***********************************************************************
1425 Initialization
1426 ***********************************************************************/
1427
1428void
1429syms_of_fringe ()
1430{
2d05deef
KS
1431 defsubr (&Sdestroy_fringe_bitmap);
1432 defsubr (&Sdefine_fringe_bitmap);
1433 defsubr (&Sfringe_bitmaps_at_pos);
1434 defsubr (&Sset_fringe_bitmap_face);
1435
1436 DEFVAR_LISP ("overflow-newline-into-fringe", &Voverflow_newline_into_fringe,
1437 doc: /* *Non-nil means that newline may flow into the right fringe.
1438This means that display lines which are exactly as wide as the window
1439(not counting the final newline) will only occupy one screen line, by
1440showing (or hiding) the final newline in the right fringe; when point
1441is at the final newline, the cursor is shown in the right fringe.
1442If nil, also continue lines which are exactly as wide as the window. */);
1443 Voverflow_newline_into_fringe = Qt;
1444
7a2a85be
KS
1445 DEFVAR_LISP ("fringe-bitmaps", &Vfringe_bitmaps,
1446 doc: /* List of fringe bitmap symbols.
1447You must (require 'fringe) to use fringe bitmap symbols in your programs." */);
1448 Vfringe_bitmaps = Qnil;
2d05deef
KS
1449}
1450
49ce2dbd
KS
1451/* Garbage collection hook */
1452
1453void
1454mark_fringe_data ()
1455{
1456 int i;
1457
1458 for (i = 0; i < max_fringe_bitmaps; i++)
1459 if (!NILP (fringe_faces[i]))
1460 mark_object (fringe_faces[i]);
1461}
1462
2d05deef
KS
1463/* Initialize this module when Emacs starts. */
1464
1465void
1466init_fringe_once ()
1467{
1468 enum fringe_bitmap_type bt;
1469
1470 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1471 init_fringe_bitmap(bt, &standard_bitmaps[bt], 1);
1472}
1473
1474void
1475init_fringe ()
1476{
1477 int i;
1478
ad67849e
KS
1479 max_fringe_bitmaps = MAX_STANDARD_FRINGE_BITMAPS + 20;
1480
1481 fringe_bitmaps
1482 = (struct fringe_bitmap **) xmalloc (max_fringe_bitmaps * sizeof (struct fringe_bitmap *));
1483 fringe_faces
50af5100 1484 = (Lisp_Object *) xmalloc (max_fringe_bitmaps * sizeof (Lisp_Object));
ad67849e
KS
1485
1486 for (i = 0; i < max_fringe_bitmaps; i++)
1487 {
1488 fringe_bitmaps[i] = NULL;
49ce2dbd 1489 fringe_faces[i] = Qnil;
ad67849e 1490 }
2d05deef
KS
1491}
1492
1493#ifdef HAVE_NTGUI
1494
1495void
1496w32_init_fringe ()
1497{
1498 enum fringe_bitmap_type bt;
1499
f2be4fd0
KS
1500 if (!rif)
1501 return;
1502
2d05deef
KS
1503 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1504 {
1505 struct fringe_bitmap *fb = &standard_bitmaps[bt];
1506 rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
1507 }
1508}
1509
1510void
1511w32_reset_fringes ()
1512{
1513 /* Destroy row bitmaps. */
1514 int bt;
bffe8c26 1515
f2be4fd0
KS
1516 if (!rif)
1517 return;
1518
2d05deef
KS
1519 for (bt = NO_FRINGE_BITMAP + 1; bt < max_used_fringe_bitmap; bt++)
1520 rif->destroy_fringe_bitmap (bt);
1521}
1522
bd231131 1523#endif /* HAVE_NTGUI */
2d05deef
KS
1524
1525#endif /* HAVE_WINDOW_SYSTEM */
1526
429e7e2d
MB
1527/* arch-tag: 04596920-43eb-473d-b319-82712338162d
1528 (do not change this comment) */