*** empty log message ***
[bpt/emacs.git] / src / fringe.c
CommitLineData
6b61353c
KH
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
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
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;
6b61353c 35extern Lisp_Object Qtop, Qbottom, Qcenter;
5797a7a0 36extern Lisp_Object Qup, Qdown, Qleft, Qright;
6b61353c
KH
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;
6b61353c
KH
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{
86 unsigned short *bits;
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*/
112static unsigned short unknown_bits[] = {
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*/
126static unsigned short left_arrow_bits[] = {
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*/
141static unsigned short right_arrow_bits[] = {
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*/
156static unsigned short up_arrow_bits[] = {
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*/
171static unsigned short down_arrow_bits[] = {
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*/
185static unsigned short continued_bits[] = {
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*/
199static unsigned short continuation_bits[] = {
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*/
213static unsigned short ov_bits[] = {
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*/
228static unsigned short rev_ov_bits[] = {
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*/
243static unsigned short top_left_angle_bits[] = {
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*/
257static unsigned short top_right_angle_bits[] = {
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*/
271static unsigned short bottom_left_angle_bits[] = {
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*/
285static unsigned short bottom_right_angle_bits[] = {
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*/
301static unsigned short left_bracket_bits[] = {
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*/
317static unsigned short right_bracket_bits[] = {
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*/
336static unsigned short filled_box_cursor_bits[] = {
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*/
355static unsigned short hollow_box_cursor_bits[] = {
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*/
374static unsigned short bar_cursor_bits[] = {
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*/
382static unsigned short hbar_cursor_bits[] = {
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*/
396static unsigned short zv_bits[] = {
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*/
415static unsigned short hollow_square_bits[] = {
416 0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e};
417
418
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)
422
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
KS
448static struct fringe_bitmap **fringe_bitmaps;
449static unsigned *fringe_faces;
450static int max_fringe_bitmaps;
6b61353c
KH
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. */
6b61353c
KH
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
6b61353c
KH
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)
550 face_id = fringe_faces[which];
551
552 fb = fringe_bitmaps[which];
553 if (fb == NULL)
554 fb = &standard_bitmaps[which < MAX_STANDARD_FRINGE_BITMAPS
555 ? which : UNDEF_FRINGE_BITMAP];
556
557 period = fb->period;
558
559 /* Convert row to frame coordinates. */
560 p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
561
562 p.which = which;
563 p.bits = fb->bits;
564 p.wd = fb->width;
565
566 p.h = fb->height;
567 p.dh = (period > 0 ? (p.y % period) : 0);
568 p.h -= p.dh;
569 /* Clip bitmap if too high. */
570 if (p.h > row->height)
571 p.h = row->height;
572
573 p.face = FACE_FROM_ID (f, face_id);
574
575 if (p.face == NULL)
576 {
577 /* Why does this happen? ++kfs */
578 return;
579 }
580
581 PREPARE_FACE_FOR_DISPLAY (f, p.face);
582
583 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
584 the fringe. */
585 p.bx = -1;
586 if (left_p)
587 {
588 int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
589 int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
590 ? LEFT_MARGIN_AREA
591 : TEXT_AREA));
592 if (p.wd > wd)
593 p.wd = wd;
594 p.x = x - p.wd - (wd - p.wd) / 2;
595
596 if (p.wd < wd || row->height > p.h)
597 {
598 /* If W has a vertical border to its left, don't draw over it. */
599 wd -= ((!WINDOW_LEFTMOST_P (w)
600 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
601 ? 1 : 0);
602 p.bx = x - wd;
603 p.nx = wd;
604 }
605 }
606 else
607 {
608 int x = window_box_right (w,
609 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
610 ? RIGHT_MARGIN_AREA
611 : TEXT_AREA));
612 int wd = WINDOW_RIGHT_FRINGE_WIDTH (w);
613 if (p.wd > wd)
614 p.wd = wd;
615 p.x = x + (wd - p.wd) / 2;
616 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
617 the fringe. */
618 if (p.wd < wd || row->height > p.h)
619 {
620 p.bx = x;
621 p.nx = wd;
622 }
623 }
624
625 if (p.bx >= 0)
626 {
627 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
628
629 p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
630 p.ny = row->visible_height;
631 }
632
633 /* Adjust y to the offset in the row to start drawing the bitmap. */
634 switch (fb->align)
635 {
636 case ALIGN_BITMAP_CENTER:
637 p.y += (row->height - p.h) / 2;
638 break;
639 case ALIGN_BITMAP_BOTTOM:
640 p.h = fb->height;
641 p.y += (row->visible_height - p.h);
642 break;
643 case ALIGN_BITMAP_TOP:
644 break;
645 }
646
647 rif->draw_fringe_bitmap (w, row, &p);
648}
649
650void
651draw_fringe_bitmap (w, row, left_p)
652 struct window *w;
653 struct glyph_row *row;
654 int left_p;
655{
656 int overlay = 0;
657
658 if (!left_p && row->cursor_in_fringe_p)
659 {
660 int cursor = NO_FRINGE_BITMAP;
661
662 switch (w->phys_cursor_type)
663 {
664 case HOLLOW_BOX_CURSOR:
665 if (row->visible_height >= STANDARD_BITMAP_HEIGHT (hollow_box_cursor_bits))
666 cursor = HOLLOW_BOX_CURSOR_BITMAP;
667 else
668 cursor = HOLLOW_SQUARE_BITMAP;
669 break;
670 case FILLED_BOX_CURSOR:
671 cursor = FILLED_BOX_CURSOR_BITMAP;
672 break;
673 case BAR_CURSOR:
674 cursor = BAR_CURSOR_BITMAP;
675 break;
676 case HBAR_CURSOR:
677 cursor = HBAR_CURSOR_BITMAP;
678 break;
679 case NO_CURSOR:
680 default:
681 w->phys_cursor_on_p = 0;
682 row->cursor_in_fringe_p = 0;
683 break;
684 }
685 if (cursor != NO_FRINGE_BITMAP)
686 {
687 draw_fringe_bitmap_1 (w, row, 0, 2, cursor);
688 overlay = cursor == FILLED_BOX_CURSOR_BITMAP ? 3 : 1;
689 }
690 }
691
692 draw_fringe_bitmap_1 (w, row, left_p, overlay, NO_FRINGE_BITMAP);
693
694 if (left_p && row->overlay_arrow_p)
695 draw_fringe_bitmap_1 (w, row, 1, 1,
696 (w->overlay_arrow_bitmap
697 ? w->overlay_arrow_bitmap
698 : OVERLAY_ARROW_BITMAP));
699}
700
701
702/* Draw fringe bitmaps for glyph row ROW on window W. Call this
703 function with input blocked. */
704
705void
706draw_row_fringe_bitmaps (w, row)
707 struct window *w;
708 struct glyph_row *row;
709{
710 xassert (interrupt_input_blocked);
711
712 /* If row is completely invisible, because of vscrolling, we
713 don't have to draw anything. */
714 if (row->visible_height <= 0)
715 return;
716
717 if (WINDOW_LEFT_FRINGE_WIDTH (w) != 0)
718 draw_fringe_bitmap (w, row, 1);
719
720 if (WINDOW_RIGHT_FRINGE_WIDTH (w) != 0)
721 draw_fringe_bitmap (w, row, 0);
722}
723
724/* Draw the fringes of window W. Only fringes for rows marked for
725 update in redraw_fringe_bitmaps_p are drawn. */
726
727void
728draw_window_fringes (w)
729 struct window *w;
730{
731 struct glyph_row *row;
732 int yb = window_text_bottom_y (w);
733 int nrows = w->current_matrix->nrows;
734 int y = 0, rn;
735
736 if (w->pseudo_window_p)
737 return;
738
739 for (y = 0, rn = 0, row = w->current_matrix->rows;
740 y < yb && rn < nrows;
741 y += row->height, ++row, ++rn)
742 {
743 if (!row->redraw_fringe_bitmaps_p)
744 continue;
745 draw_row_fringe_bitmaps (w, row);
746 row->redraw_fringe_bitmaps_p = 0;
747 }
748}
749
750
751/* Recalculate the bitmaps to show in the fringes of window W.
752 If FORCE_P is 0, only mark rows with modified bitmaps for update in
753 redraw_fringe_bitmaps_p; else mark all rows for update. */
754
755int
756update_window_fringes (w, force_p)
757 struct window *w;
758 int force_p;
759{
760 struct glyph_row *row, *cur = 0;
761 int yb = window_text_bottom_y (w);
762 int rn, nrows = w->current_matrix->nrows;
763 int y;
764 int redraw_p = 0;
5797a7a0
KS
765 Lisp_Object boundary_top = Qnil, boundary_bot = Qnil;
766 Lisp_Object arrow_top = Qnil, arrow_bot = Qnil;
767 Lisp_Object empty_pos;
768 Lisp_Object ind = Qnil;
6b61353c
KH
769
770 if (w->pseudo_window_p)
771 return 0;
772
773 if (!MINI_WINDOW_P (w)
774 && (ind = XBUFFER (w->buffer)->indicate_buffer_boundaries, !NILP (ind)))
775 {
5797a7a0
KS
776 if (EQ (ind, Qleft) || EQ (ind, Qright))
777 boundary_top = boundary_bot = arrow_top = arrow_bot = ind;
778 else if (CONSP (ind) && CONSP (XCAR (ind)))
779 {
780 Lisp_Object pos;
781 if (pos = Fassq (Qt, ind), !NILP (pos))
782 boundary_top = boundary_bot = arrow_top = arrow_bot = XCDR (pos);
783 if (pos = Fassq (Qtop, ind), !NILP (pos))
784 boundary_top = XCDR (pos);
785 if (pos = Fassq (Qbottom, ind), !NILP (pos))
786 boundary_bot = XCDR (pos);
787 if (pos = Fassq (Qup, ind), !NILP (pos))
788 arrow_top = XCDR (pos);
789 if (pos = Fassq (Qdown, ind), !NILP (pos))
790 arrow_bot = XCDR (pos);
791 }
6b61353c 792 else
5797a7a0
KS
793 ind = Qnil;
794 }
6b61353c 795
5797a7a0
KS
796 if (!NILP (ind))
797 {
798 int do_eob = 1, do_bob = 1;
6b61353c
KH
799
800 for (y = 0, rn = 0;
801 y < yb && rn < nrows;
802 y += row->height, ++rn)
803 {
804 unsigned indicate_bob_p, indicate_top_line_p;
805 unsigned indicate_eob_p, indicate_bottom_line_p;
806
807 row = w->desired_matrix->rows + rn;
808 if (!row->enabled_p)
809 row = w->current_matrix->rows + rn;
810
811 indicate_bob_p = row->indicate_bob_p;
812 indicate_top_line_p = row->indicate_top_line_p;
813 indicate_eob_p = row->indicate_eob_p;
814 indicate_bottom_line_p = row->indicate_bottom_line_p;
815
816 row->indicate_bob_p = row->indicate_top_line_p = 0;
817 row->indicate_eob_p = row->indicate_bottom_line_p = 0;
818
5797a7a0 819 if (!NILP (boundary_top)
6b61353c
KH
820 && MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer)))
821 row->indicate_bob_p = do_bob, do_bob = 0;
5797a7a0 822 else if (!NILP (arrow_top)
6b61353c
KH
823 && (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0) == rn)
824 row->indicate_top_line_p = 1;
825
5797a7a0 826 if (!NILP (boundary_bot)
6b61353c
KH
827 && MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer)))
828 row->indicate_eob_p = do_eob, do_eob = 0;
5797a7a0 829 else if (!NILP (arrow_bot)
6b61353c
KH
830 && y + row->height >= yb)
831 row->indicate_bottom_line_p = 1;
832
833 if (indicate_bob_p != row->indicate_bob_p
834 || indicate_top_line_p != row->indicate_top_line_p
835 || indicate_eob_p != row->indicate_eob_p
836 || indicate_bottom_line_p != row->indicate_bottom_line_p)
837 row->redraw_fringe_bitmaps_p = 1;
838 }
839 }
840
5797a7a0
KS
841 empty_pos = XBUFFER (w->buffer)->indicate_empty_lines;
842 if (!NILP (empty_pos) && !EQ (empty_pos, Qright))
843 empty_pos = WINDOW_LEFT_FRINGE_WIDTH (w) == 0 ? Qright : Qleft;
6b61353c
KH
844
845 for (y = 0, rn = 0;
846 y < yb && rn < nrows;
847 y += row->height, rn++)
848 {
849 enum fringe_bitmap_type left, right;
850 unsigned left_face_id, right_face_id;
851
852 row = w->desired_matrix->rows + rn;
853 cur = w->current_matrix->rows + rn;
854 if (!row->enabled_p)
855 row = cur;
856
857 left_face_id = right_face_id = DEFAULT_FACE_ID;
858
859 /* Decide which bitmap to draw in the left fringe. */
860 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
861 left = NO_FRINGE_BITMAP;
862 else if (row->left_user_fringe_bitmap != NO_FRINGE_BITMAP)
863 {
864 left = row->left_user_fringe_bitmap;
865 left_face_id = row->left_user_fringe_face_id;
866 }
5797a7a0
KS
867 else if (row->indicate_bob_p && EQ (boundary_top, Qleft))
868 left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
6b61353c 869 ? LEFT_BRACKET_BITMAP : TOP_LEFT_ANGLE_BITMAP);
5797a7a0 870 else if (row->indicate_eob_p && EQ (boundary_bot, Qleft))
6b61353c
KH
871 left = BOTTOM_LEFT_ANGLE_BITMAP;
872 else if (row->truncated_on_left_p)
873 left = LEFT_TRUNCATION_BITMAP;
874 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
875 left = CONTINUATION_LINE_BITMAP;
5797a7a0 876 else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft))
6b61353c 877 left = ZV_LINE_BITMAP;
5797a7a0 878 else if (row->indicate_top_line_p && EQ (arrow_top, Qleft))
6b61353c 879 left = UP_ARROW_BITMAP;
5797a7a0 880 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qleft))
6b61353c
KH
881 left = DOWN_ARROW_BITMAP;
882 else
883 left = NO_FRINGE_BITMAP;
884
885 /* Decide which bitmap to draw in the right fringe. */
886 if (WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)
887 right = NO_FRINGE_BITMAP;
888 else if (row->right_user_fringe_bitmap != NO_FRINGE_BITMAP)
889 {
890 right = row->right_user_fringe_bitmap;
891 right_face_id = row->right_user_fringe_face_id;
892 }
5797a7a0
KS
893 else if (row->indicate_bob_p && EQ (boundary_top, Qright))
894 right = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
6b61353c 895 ? RIGHT_BRACKET_BITMAP : TOP_RIGHT_ANGLE_BITMAP);
5797a7a0 896 else if (row->indicate_eob_p && EQ (boundary_bot, Qright))
6b61353c
KH
897 right = BOTTOM_RIGHT_ANGLE_BITMAP;
898 else if (row->truncated_on_right_p)
899 right = RIGHT_TRUNCATION_BITMAP;
900 else if (row->continued_p)
901 right = CONTINUED_LINE_BITMAP;
5797a7a0 902 else if (row->indicate_top_line_p && EQ (arrow_top, Qright))
6b61353c 903 right = UP_ARROW_BITMAP;
5797a7a0 904 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright))
6b61353c 905 right = DOWN_ARROW_BITMAP;
5797a7a0 906 else if (row->indicate_empty_line_p && EQ (empty_pos, Qright))
6b61353c
KH
907 right = ZV_LINE_BITMAP;
908 else
909 right = NO_FRINGE_BITMAP;
910
911 if (force_p
912 || row->y != cur->y
913 || row->visible_height != cur->visible_height
914 || left != cur->left_fringe_bitmap
915 || right != cur->right_fringe_bitmap
916 || left_face_id != cur->left_fringe_face_id
917 || right_face_id != cur->right_fringe_face_id
918 || cur->redraw_fringe_bitmaps_p)
919 {
920 redraw_p = row->redraw_fringe_bitmaps_p = cur->redraw_fringe_bitmaps_p = 1;
921 cur->left_fringe_bitmap = left;
922 cur->right_fringe_bitmap = right;
923 cur->left_fringe_face_id = left_face_id;
924 cur->right_fringe_face_id = right_face_id;
925 }
926
927 if (row->overlay_arrow_p != cur->overlay_arrow_p)
928 {
929 redraw_p = row->redraw_fringe_bitmaps_p = cur->redraw_fringe_bitmaps_p = 1;
930 cur->overlay_arrow_p = row->overlay_arrow_p;
931 }
932
933 row->left_fringe_bitmap = left;
934 row->right_fringe_bitmap = right;
935 row->left_fringe_face_id = left_face_id;
936 row->right_fringe_face_id = right_face_id;
937 }
938
939 return redraw_p;
940}
941
942
943/* Compute actual fringe widths for frame F.
944
945 If REDRAW is 1, redraw F if the fringe settings was actually
946 modified and F is visible.
947
948 Since the combined left and right fringe must occupy an integral
949 number of columns, we may need to add some pixels to each fringe.
950 Typically, we add an equal amount (+/- 1 pixel) to each fringe,
951 but a negative width value is taken literally (after negating it).
952
953 We never make the fringes narrower than specified. It is planned
954 to make fringe bitmaps customizable and expandable, and at that
955 time, the user will typically specify the minimum number of pixels
956 needed for his bitmaps, so we shouldn't select anything less than
957 what is specified.
958*/
959
960void
961compute_fringe_widths (f, redraw)
962 struct frame *f;
963 int redraw;
964{
965 int o_left = FRAME_LEFT_FRINGE_WIDTH (f);
966 int o_right = FRAME_RIGHT_FRINGE_WIDTH (f);
967 int o_cols = FRAME_FRINGE_COLS (f);
968
969 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
970 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
971 int left_fringe_width, right_fringe_width;
972
973 if (!NILP (left_fringe))
974 left_fringe = Fcdr (left_fringe);
975 if (!NILP (right_fringe))
976 right_fringe = Fcdr (right_fringe);
977
978 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
979 XINT (left_fringe));
980 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
981 XINT (right_fringe));
982
983 if (left_fringe_width || right_fringe_width)
984 {
985 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
986 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
987 int conf_wid = left_wid + right_wid;
988 int font_wid = FRAME_COLUMN_WIDTH (f);
989 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
990 int real_wid = cols * font_wid;
991 if (left_wid && right_wid)
992 {
993 if (left_fringe_width < 0)
994 {
995 /* Left fringe width is fixed, adjust right fringe if necessary */
996 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid;
997 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid;
998 }
999 else if (right_fringe_width < 0)
1000 {
1001 /* Right fringe width is fixed, adjust left fringe if necessary */
1002 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
1003 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid;
1004 }
1005 else
1006 {
1007 /* Adjust both fringes with an equal amount.
1008 Note that we are doing integer arithmetic here, so don't
1009 lose a pixel if the total width is an odd number. */
1010 int fill = real_wid - conf_wid;
1011 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2;
1012 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2;
1013 }
1014 }
1015 else if (left_fringe_width)
1016 {
1017 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid;
1018 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
1019 }
1020 else
1021 {
1022 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
1023 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid;
1024 }
1025 FRAME_FRINGE_COLS (f) = cols;
1026 }
1027 else
1028 {
1029 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
1030 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
1031 FRAME_FRINGE_COLS (f) = 0;
1032 }
1033
1034 if (redraw && FRAME_VISIBLE_P (f))
1035 if (o_left != FRAME_LEFT_FRINGE_WIDTH (f) ||
1036 o_right != FRAME_RIGHT_FRINGE_WIDTH (f) ||
1037 o_cols != FRAME_FRINGE_COLS (f))
1038 redraw_frame (f);
1039}
1040
7a2a85be 1041
4cce0ab7
KS
1042/* Free resources used by a user-defined bitmap. */
1043
1044int
7a2a85be
KS
1045destroy_fringe_bitmap (n)
1046 int n;
6b61353c 1047{
6b61353c
KH
1048 struct fringe_bitmap **fbp;
1049
6b61353c
KH
1050 fringe_faces[n] = FRINGE_FACE_ID;
1051
1052 fbp = &fringe_bitmaps[n];
1053 if (*fbp && (*fbp)->dynamic)
1054 {
f2be4fd0 1055 if (rif && rif->destroy_fringe_bitmap)
6b61353c
KH
1056 rif->destroy_fringe_bitmap (n);
1057 xfree (*fbp);
1058 *fbp = NULL;
1059 }
1060
1061 while (max_used_fringe_bitmap > MAX_STANDARD_FRINGE_BITMAPS
1062 && fringe_bitmaps[max_used_fringe_bitmap - 1] == NULL)
1063 max_used_fringe_bitmap--;
7a2a85be
KS
1064}
1065
6b61353c 1066
7a2a85be
KS
1067DEFUN ("destroy-fringe-bitmap", Fdestroy_fringe_bitmap, Sdestroy_fringe_bitmap,
1068 1, 1, 0,
1069 doc: /* Destroy fringe bitmap BITMAP.
1070If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. */)
1071 (bitmap)
1072 Lisp_Object bitmap;
1073{
1074 int n;
7a2a85be 1075
4cce0ab7
KS
1076 CHECK_SYMBOL (bitmap);
1077 n = lookup_fringe_bitmap (bitmap);
1078 if (!n)
7a2a85be
KS
1079 return Qnil;
1080
1081 destroy_fringe_bitmap (n);
2d05deef 1082
4cce0ab7 1083 if (n >= MAX_STANDARD_FRINGE_BITMAPS)
7a2a85be 1084 {
4cce0ab7 1085 Vfringe_bitmaps = Fdelq (bitmap, Vfringe_bitmaps);
7a2a85be 1086 /* It would be better to remove the fringe property. */
4cce0ab7 1087 Fput (bitmap, Qfringe, Qnil);
7a2a85be 1088 }
4cce0ab7 1089
6b61353c
KH
1090 return Qnil;
1091}
1092
1093
1094/* Initialize bitmap bit.
1095
1096 On X, we bit-swap the built-in bitmaps and reduce bitmap
1097 from short to char array if width is <= 8 bits.
1098
1099 On MAC with big-endian CPU, we need to byte-swap each short.
1100
1101 On W32 and MAC (little endian), there's no need to do this.
1102*/
1103
1104void
1105init_fringe_bitmap (which, fb, once_p)
1106 enum fringe_bitmap_type which;
1107 struct fringe_bitmap *fb;
1108 int once_p;
1109{
1110 if (once_p || fb->dynamic)
1111 {
1112#if defined (HAVE_X_WINDOWS)
1113 static unsigned char swap_nibble[16]
1114 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
1115 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
1116 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
1117 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
1118 unsigned short *bits = fb->bits;
1119 int j;
1120
1121 if (fb->width <= 8)
1122 {
1123 unsigned char *cbits = (unsigned char *)fb->bits;
1124 for (j = 0; j < fb->height; j++)
1125 {
1126 unsigned short b = *bits++;
1127 unsigned char c;
1128 c = (unsigned char)((swap_nibble[b & 0xf] << 4)
1129 | (swap_nibble[(b>>4) & 0xf]));
1130 *cbits++ = (c >> (8 - fb->width));
1131 }
1132 }
1133 else
1134 {
1135 for (j = 0; j < fb->height; j++)
1136 {
1137 unsigned short b = *bits;
1138 b = (unsigned short)((swap_nibble[b & 0xf] << 12)
1139 | (swap_nibble[(b>>4) & 0xf] << 8)
1140 | (swap_nibble[(b>>8) & 0xf] << 4)
1141 | (swap_nibble[(b>>12) & 0xf]));
1142 *bits++ = (b >> (16 - fb->width));
1143 }
1144 }
1145#endif /* HAVE_X_WINDOWS */
1146
1147#if defined (MAC_OS) && defined (WORDS_BIG_ENDIAN)
1148 unsigned short *bits = fb->bits;
1149 int j;
1150 for (j = 0; j < fb->height; j++)
1151 {
1152 unsigned short b = *bits;
1153 *bits++ = ((b >> 8) & 0xff) | ((b & 0xff) << 8);
1154 }
1155#endif /* MAC_OS && WORDS_BIG_ENDIAN */
1156 }
1157
1158 if (!once_p)
1159 {
7a2a85be 1160 destroy_fringe_bitmap (which);
6b61353c 1161
f2be4fd0 1162 if (rif && rif->define_fringe_bitmap)
6b61353c
KH
1163 rif->define_fringe_bitmap (which, fb->bits, fb->height, fb->width);
1164
1165 fringe_bitmaps[which] = fb;
1166 if (which >= max_used_fringe_bitmap)
1167 max_used_fringe_bitmap = which + 1;
1168 }
1169}
1170
1171
1172DEFUN ("define-fringe-bitmap", Fdefine_fringe_bitmap, Sdefine_fringe_bitmap,
7a2a85be
KS
1173 2, 5, 0,
1174 doc: /* Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.
1175BITMAP is a symbol or string naming the new fringe bitmap.
6b61353c
KH
1176BITS is either a string or a vector of integers.
1177HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.
1178WIDTH must be an integer between 1 and 16, or nil which defaults to 8.
7a2a85be 1179Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
6b61353c
KH
1180indicating the positioning of the bitmap relative to the rows where it
1181is used; the default is to center the bitmap. Fourth arg may also be a
1182list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap
1183should be repeated.
7a2a85be
KS
1184If BITMAP already exists, the existing definition is replaced. */)
1185 (bitmap, bits, height, width, align)
1186 Lisp_Object bitmap, bits, height, width, align;
6b61353c
KH
1187{
1188 Lisp_Object len;
1189 int n, h, i, j;
1190 unsigned short *b;
1191 struct fringe_bitmap fb, *xfb;
1192 int fill1 = 0, fill2 = 0;
7a2a85be 1193
4cce0ab7 1194 CHECK_SYMBOL (bitmap);
6b61353c
KH
1195
1196 if (!STRINGP (bits) && !VECTORP (bits))
1197 bits = wrong_type_argument (Qstringp, bits);
1198
1199 len = Flength (bits);
1200
1201 if (NILP (height))
1202 h = fb.height = XINT (len);
1203 else
1204 {
1205 CHECK_NUMBER (height);
1206 fb.height = min (XINT (height), 255);
1207 if (fb.height > XINT (len))
1208 {
1209 h = XINT (len);
1210 fill1 = (fb.height - h) / 2;
1211 fill2 = fb.height - h - fill1;
1212 }
1213 }
1214
1215 if (NILP (width))
1216 fb.width = 8;
1217 else
1218 {
1219 CHECK_NUMBER (width);
1220 fb.width = min (XINT (width), 255);
1221 }
1222
1223 fb.period = 0;
1224 fb.align = ALIGN_BITMAP_CENTER;
1225
1226 if (CONSP (align))
1227 {
1228 Lisp_Object period = XCDR (align);
1229 if (CONSP (period))
1230 {
1231 period = XCAR (period);
1232 if (!NILP (period))
1233 {
1234 fb.period = fb.height;
1235 fb.height = 255;
1236 }
1237 }
1238 align = XCAR (align);
1239 }
1240 if (EQ (align, Qtop))
1241 fb.align = ALIGN_BITMAP_TOP;
1242 else if (EQ (align, Qbottom))
1243 fb.align = ALIGN_BITMAP_BOTTOM;
1244 else if (!NILP (align) && !EQ (align, Qcenter))
1245 error ("Bad align argument");
1246
ad67849e 1247 n = lookup_fringe_bitmap (bitmap);
4cce0ab7 1248 if (!n)
6b61353c 1249 {
ad67849e 1250 if (max_used_fringe_bitmap < max_fringe_bitmaps)
6b61353c
KH
1251 n = max_used_fringe_bitmap++;
1252 else
1253 {
1254 for (n = MAX_STANDARD_FRINGE_BITMAPS;
ad67849e 1255 n < max_fringe_bitmaps;
6b61353c
KH
1256 n++)
1257 if (fringe_bitmaps[n] == NULL)
1258 break;
ad67849e
KS
1259
1260 if (n == max_fringe_bitmaps)
1261 {
1262 if ((max_fringe_bitmaps + 20) > MAX_FRINGE_BITMAPS)
1263 error ("No free fringe bitmap slots");
1264
1265 i = max_fringe_bitmaps;
1266 max_fringe_bitmaps += 20;
1267 fringe_bitmaps
1268 = ((struct fringe_bitmap **)
1269 xrealloc (fringe_bitmaps, max_fringe_bitmaps * sizeof (struct fringe_bitmap *)));
1270 fringe_faces
1271 = (unsigned *) xrealloc (fringe_faces, max_fringe_bitmaps * sizeof (unsigned));
1272
1273 for (; i < max_fringe_bitmaps; i++)
1274 {
1275 fringe_bitmaps[i] = NULL;
1276 fringe_faces[i] = FRINGE_FACE_ID;
1277 }
1278 }
6b61353c 1279 }
7a2a85be 1280
4cce0ab7
KS
1281 Vfringe_bitmaps = Fcons (bitmap, Vfringe_bitmaps);
1282 Fput (bitmap, Qfringe, make_number (n));
6b61353c
KH
1283 }
1284
1285 fb.dynamic = 1;
1286
1287 xfb = (struct fringe_bitmap *) xmalloc (sizeof fb
1288 + fb.height * BYTES_PER_BITMAP_ROW);
1289 fb.bits = b = (unsigned short *) (xfb + 1);
1290 bzero (b, fb.height);
1291
1292 j = 0;
1293 while (j < fb.height)
1294 {
1295 for (i = 0; i < fill1 && j < fb.height; i++)
1296 b[j++] = 0;
1297 for (i = 0; i < h && j < fb.height; i++)
1298 {
1299 Lisp_Object elt = Faref (bits, make_number (i));
1300 b[j++] = NUMBERP (elt) ? XINT (elt) : 0;
1301 }
1302 for (i = 0; i < fill2 && j < fb.height; i++)
1303 b[j++] = 0;
1304 }
1305
1306 *xfb = fb;
1307
1308 init_fringe_bitmap (n, xfb, 0);
1309
4cce0ab7 1310 return bitmap;
6b61353c
KH
1311}
1312
1313DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face, Sset_fringe_bitmap_face,
1314 1, 2, 0,
7a2a85be 1315 doc: /* Set face for fringe bitmap BITMAP to FACE.
6b61353c 1316If FACE is nil, reset face to default fringe face. */)
7a2a85be
KS
1317 (bitmap, face)
1318 Lisp_Object bitmap, face;
6b61353c 1319{
4cce0ab7 1320 int n;
6b61353c
KH
1321 int face_id;
1322
4cce0ab7
KS
1323 CHECK_SYMBOL (bitmap);
1324 n = lookup_fringe_bitmap (bitmap);
1325 if (!n)
7a2a85be 1326 error ("Undefined fringe bitmap");
6b61353c
KH
1327
1328 if (!NILP (face))
1329 {
1330 face_id = lookup_named_face (SELECTED_FRAME (), face);
1331 if (face_id < 0)
1332 error ("No such face");
1333 }
1334 else
1335 face_id = FRINGE_FACE_ID;
1336
4cce0ab7 1337 fringe_faces[n] = face_id;
6b61353c
KH
1338
1339 return Qnil;
1340}
1341
1342DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos, Sfringe_bitmaps_at_pos,
1343 0, 2, 0,
1344 doc: /* Return fringe bitmaps of row containing position POS in window WINDOW.
1345If WINDOW is nil, use selected window. If POS is nil, use value of point
1346in that window. Return value is a cons (LEFT . RIGHT) where LEFT and RIGHT
1347are the fringe bitmap numbers for the bitmaps in the left and right fringe,
5797a7a0
KS
1348resp. If left or right fringe is empty, the corresponding element is nil.
1349Return nil if POS is not visible in WINDOW. */)
6b61353c
KH
1350 (pos, window)
1351 Lisp_Object pos, window;
1352{
1353 struct window *w;
1354 struct buffer *old_buffer = NULL;
1355 struct glyph_row *row;
1356 int textpos;
1357
1358 if (NILP (window))
1359 window = selected_window;
1360 CHECK_WINDOW (window);
1361 w = XWINDOW (window);
1362
1363 if (!NILP (pos))
1364 {
1365 CHECK_NUMBER_COERCE_MARKER (pos);
1366 textpos = XINT (pos);
1367 }
1368 else if (w == XWINDOW (selected_window))
1369 textpos = PT;
1370 else
1371 textpos = XMARKER (w->pointm)->charpos;
1372
1373 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1374 row = row_containing_pos (w, textpos, row, NULL, 0);
1375 if (row)
7a2a85be
KS
1376 return Fcons (get_fringe_bitmap_name (row->left_fringe_bitmap),
1377 get_fringe_bitmap_name (row->right_fringe_bitmap));
6b61353c
KH
1378 else
1379 return Qnil;
1380}
1381
1382
1383/***********************************************************************
1384 Initialization
1385 ***********************************************************************/
1386
1387void
1388syms_of_fringe ()
1389{
6b61353c
KH
1390 defsubr (&Sdestroy_fringe_bitmap);
1391 defsubr (&Sdefine_fringe_bitmap);
1392 defsubr (&Sfringe_bitmaps_at_pos);
1393 defsubr (&Sset_fringe_bitmap_face);
1394
1395 DEFVAR_LISP ("overflow-newline-into-fringe", &Voverflow_newline_into_fringe,
1396 doc: /* *Non-nil means that newline may flow into the right fringe.
1397This means that display lines which are exactly as wide as the window
1398(not counting the final newline) will only occupy one screen line, by
1399showing (or hiding) the final newline in the right fringe; when point
1400is at the final newline, the cursor is shown in the right fringe.
1401If nil, also continue lines which are exactly as wide as the window. */);
1402 Voverflow_newline_into_fringe = Qt;
1403
7a2a85be
KS
1404 DEFVAR_LISP ("fringe-bitmaps", &Vfringe_bitmaps,
1405 doc: /* List of fringe bitmap symbols.
1406You must (require 'fringe) to use fringe bitmap symbols in your programs." */);
1407 Vfringe_bitmaps = Qnil;
6b61353c
KH
1408}
1409
1410/* Initialize this module when Emacs starts. */
1411
1412void
1413init_fringe_once ()
1414{
1415 enum fringe_bitmap_type bt;
1416
1417 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1418 init_fringe_bitmap(bt, &standard_bitmaps[bt], 1);
1419}
1420
1421void
1422init_fringe ()
1423{
1424 int i;
1425
ad67849e
KS
1426 max_fringe_bitmaps = MAX_STANDARD_FRINGE_BITMAPS + 20;
1427
1428 fringe_bitmaps
1429 = (struct fringe_bitmap **) xmalloc (max_fringe_bitmaps * sizeof (struct fringe_bitmap *));
1430 fringe_faces
1431 = (unsigned *) xmalloc (max_fringe_bitmaps * sizeof (unsigned));
1432
1433 for (i = 0; i < max_fringe_bitmaps; i++)
1434 {
1435 fringe_bitmaps[i] = NULL;
1436 fringe_faces[i] = FRINGE_FACE_ID;
1437 }
6b61353c
KH
1438}
1439
1440#ifdef HAVE_NTGUI
1441
1442void
1443w32_init_fringe ()
1444{
1445 enum fringe_bitmap_type bt;
1446
f2be4fd0
KS
1447 if (!rif)
1448 return;
1449
6b61353c
KH
1450 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1451 {
1452 struct fringe_bitmap *fb = &standard_bitmaps[bt];
1453 rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
1454 }
1455}
1456
1457void
1458w32_reset_fringes ()
1459{
1460 /* Destroy row bitmaps. */
1461 int bt;
1462
f2be4fd0
KS
1463 if (!rif)
1464 return;
1465
6b61353c
KH
1466 for (bt = NO_FRINGE_BITMAP + 1; bt < max_used_fringe_bitmap; bt++)
1467 rif->destroy_fringe_bitmap (bt);
1468}
1469
1470#endif /* HAVE_NTGUI */
1471
1472#endif /* HAVE_WINDOW_SYSTEM */
1473
1474/* arch-tag: 04596920-43eb-473d-b319-82712338162d
1475 (do not change this comment) */