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