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