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