*** empty log message ***
[bpt/emacs.git] / src / fringe.c
CommitLineData
2d05deef
KS
1/* Fringe handling (split from xdisp.c).
2 Copyright (C) 1985,86,87,88,93,94,95,97,98,99,2000,01,02,03,04
3 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22#include <config.h>
23#include <stdio.h>
24
25#include "lisp.h"
26#include "frame.h"
27#include "window.h"
28#include "dispextern.h"
29#include "buffer.h"
30#include "blockinput.h"
31
32#ifdef HAVE_WINDOW_SYSTEM
33
7a2a85be 34extern Lisp_Object Qfringe;
2d05deef 35extern Lisp_Object Qtop, Qbottom, Qcenter;
5797a7a0 36extern Lisp_Object Qup, Qdown, Qleft, Qright;
2d05deef
KS
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;
2d05deef
KS
50
51enum fringe_bitmap_type
52{
53 NO_FRINGE_BITMAP = 0,
54 UNDEF_FRINGE_BITMAP,
55 LEFT_TRUNCATION_BITMAP,
56 RIGHT_TRUNCATION_BITMAP,
57 UP_ARROW_BITMAP,
58 DOWN_ARROW_BITMAP,
59 CONTINUED_LINE_BITMAP,
60 CONTINUATION_LINE_BITMAP,
61 OVERLAY_ARROW_BITMAP,
62 TOP_LEFT_ANGLE_BITMAP,
63 TOP_RIGHT_ANGLE_BITMAP,
64 BOTTOM_LEFT_ANGLE_BITMAP,
65 BOTTOM_RIGHT_ANGLE_BITMAP,
66 LEFT_BRACKET_BITMAP,
67 RIGHT_BRACKET_BITMAP,
68 FILLED_BOX_CURSOR_BITMAP,
69 HOLLOW_BOX_CURSOR_BITMAP,
70 HOLLOW_SQUARE_BITMAP,
71 BAR_CURSOR_BITMAP,
72 HBAR_CURSOR_BITMAP,
73 ZV_LINE_BITMAP,
74 MAX_STANDARD_FRINGE_BITMAPS
75};
76
77enum fringe_bitmap_align
78{
79 ALIGN_BITMAP_CENTER = 0,
80 ALIGN_BITMAP_TOP,
81 ALIGN_BITMAP_BOTTOM
82};
83
84struct fringe_bitmap
85{
0881a0fd 86 unsigned short *bits;
2d05deef
KS
87 unsigned height : 8;
88 unsigned width : 8;
89 unsigned period : 8;
90 unsigned align : 2;
91 unsigned dynamic : 1;
92};
93
94\f
95/***********************************************************************
96 Fringe bitmaps
97 ***********************************************************************/
98
99/* Undefined bitmap. A question mark. */
100/*
101 ..xxxx..
102 .xxxxxx.
103 xx....xx
104 xx....xx
105 ....xx..
106 ...xx...
107 ...xx...
108 ........
109 ...xx...
110 ...xx...
111*/
0881a0fd 112static unsigned short unknown_bits[] = {
2d05deef
KS
113 0x3c, 0x7e, 0x7e, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18};
114
115/* An arrow like this: `<-'. */
116/*
117 ...xx...
118 ..xx....
119 .xx.....
120 xxxxxx..
121 xxxxxx..
122 .xx.....
123 ..xx....
124 ...xx...
125*/
0881a0fd 126static unsigned short left_arrow_bits[] = {
2d05deef
KS
127 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
128
129
130/* Right truncation arrow bitmap `->'. */
131/*
132 ...xx...
133 ....xx..
134 .....xx.
135 ..xxxxxx
136 ..xxxxxx
137 .....xx.
138 ....xx..
139 ...xx...
140*/
0881a0fd 141static unsigned short right_arrow_bits[] = {
2d05deef
KS
142 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
143
144
145/* Up arrow bitmap. */
146/*
147 ...xx...
148 ..xxxx..
149 .xxxxxx.
150 xxxxxxxx
151 ...xx...
152 ...xx...
153 ...xx...
154 ...xx...
155*/
0881a0fd 156static unsigned short up_arrow_bits[] = {
2d05deef
KS
157 0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0x18};
158
159
160/* Down arrow bitmap. */
161/*
162 ...xx...
163 ...xx...
164 ...xx...
165 ...xx...
166 xxxxxxxx
167 .xxxxxx.
168 ..xxxx..
169 ...xx...
170*/
0881a0fd 171static unsigned short down_arrow_bits[] = {
2d05deef
KS
172 0x18, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18};
173
174/* Marker for continued lines. */
175/*
176 ..xxxx..
177 ..xxxxx.
178 ......xx
179 ..x..xxx
180 ..xxxxxx
181 ..xxxxx.
182 ..xxxx..
183 ..xxxxx.
184*/
0881a0fd 185static unsigned short continued_bits[] = {
2d05deef
KS
186 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
187
188/* Marker for continuation lines. */
189/*
190 ..xxxx..
191 .xxxxx..
192 xx......
193 xxx..x..
194 xxxxxx..
195 .xxxxx..
196 ..xxxx..
197 .xxxxx..
198*/
0881a0fd 199static unsigned short continuation_bits[] = {
2d05deef
KS
200 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
201
202/* Overlay arrow bitmap. A triangular arrow. */
203/*
204 xx......
205 xxxx....
206 xxxxx...
207 xxxxxx..
208 xxxxxx..
209 xxxxx...
210 xxxx....
211 xx......
212*/
0881a0fd 213static unsigned short ov_bits[] = {
2d05deef
KS
214 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
215
216#if 0
217/* Reverse Overlay arrow bitmap. A triangular arrow. */
218/*
219 ......xx
220 ....xxxx
221 ...xxxxx
222 ..xxxxxx
223 ..xxxxxx
224 ...xxxxx
225 ....xxxx
226 ......xx
227*/
0881a0fd 228static unsigned short rev_ov_bits[] = {
2d05deef
KS
229 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
230#endif
231
232/* First line bitmap. An top-left angle. */
233/*
234 xxxxxx..
235 xxxxxx..
236 xx......
237 xx......
238 xx......
239 xx......
240 xx......
241 ........
242*/
0881a0fd 243static unsigned short top_left_angle_bits[] = {
2d05deef
KS
244 0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00};
245
246/* First line bitmap. An right-up angle. */
247/*
248 ..xxxxxx
249 ..xxxxxx
250 ......xx
251 ......xx
252 ......xx
253 ......xx
254 ......xx
255 ........
256*/
0881a0fd 257static unsigned short top_right_angle_bits[] = {
2d05deef
KS
258 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00};
259
260/* Last line bitmap. An left-down angle. */
261/*
262 ........
263 xx......
264 xx......
265 xx......
266 xx......
267 xx......
268 xxxxxx..
269 xxxxxx..
270*/
0881a0fd 271static unsigned short bottom_left_angle_bits[] = {
2d05deef
KS
272 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
273
274/* Last line bitmap. An right-down angle. */
275/*
276 ........
277 ......xx
278 ......xx
279 ......xx
280 ......xx
281 ......xx
282 ..xxxxxx
283 ..xxxxxx
284*/
0881a0fd 285static unsigned short bottom_right_angle_bits[] = {
2d05deef
KS
286 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
287
288/* First/last line bitmap. An left bracket. */
289/*
290 xxxxxx..
291 xxxxxx..
292 xx......
293 xx......
294 xx......
295 xx......
296 xx......
297 xx......
298 xxxxxx..
299 xxxxxx..
300*/
0881a0fd 301static unsigned short left_bracket_bits[] = {
2d05deef
KS
302 0xfc, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
303
304/* First/last line bitmap. An right bracket. */
305/*
306 ..xxxxxx
307 ..xxxxxx
308 ......xx
309 ......xx
310 ......xx
311 ......xx
312 ......xx
313 ......xx
314 ..xxxxxx
315 ..xxxxxx
316*/
0881a0fd 317static unsigned short right_bracket_bits[] = {
2d05deef
KS
318 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f};
319
320/* Filled box cursor bitmap. A filled box; max 13 pixels high. */
321/*
322 xxxxxxx.
323 xxxxxxx.
324 xxxxxxx.
325 xxxxxxx.
326 xxxxxxx.
327 xxxxxxx.
328 xxxxxxx.
329 xxxxxxx.
330 xxxxxxx.
331 xxxxxxx.
332 xxxxxxx.
333 xxxxxxx.
334 xxxxxxx.
335*/
0881a0fd 336static unsigned short filled_box_cursor_bits[] = {
2d05deef
KS
337 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
338
339/* Hollow box cursor bitmap. A hollow box; max 13 pixels high. */
340/*
341 xxxxxxx.
342 x.....x.
343 x.....x.
344 x.....x.
345 x.....x.
346 x.....x.
347 x.....x.
348 x.....x.
349 x.....x.
350 x.....x.
351 x.....x.
352 x.....x.
353 xxxxxxx.
354*/
0881a0fd 355static unsigned short hollow_box_cursor_bits[] = {
2d05deef
KS
356 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe};
357
358/* Bar cursor bitmap. A vertical bar; max 13 pixels high. */
359/*
360 xx......
361 xx......
362 xx......
363 xx......
364 xx......
365 xx......
366 xx......
367 xx......
368 xx......
369 xx......
370 xx......
371 xx......
372 xx......
373*/
0881a0fd 374static unsigned short bar_cursor_bits[] = {
2d05deef
KS
375 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0};
376
377/* HBar cursor bitmap. A horisontal bar; 2 pixels high. */
378/*
379 xxxxxxx.
380 xxxxxxx.
381*/
0881a0fd 382static unsigned short hbar_cursor_bits[] = {
2d05deef
KS
383 0xfe, 0xfe};
384
385
386/* Bitmap drawn to indicate lines not displaying text if
387 `indicate-empty-lines' is non-nil. */
388/*
389 ........
390 ..xxxx..
391 ........
392 ........
393 ..xxxx..
394 ........
395*/
0881a0fd 396static unsigned short zv_bits[] = {
2d05deef
KS
397 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
398 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
399 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
400 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
401 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
402 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
403 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
404 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
405
406/* Hollow square bitmap. */
407/*
408 .xxxxxx.
409 .x....x.
410 .x....x.
411 .x....x.
412 .x....x.
413 .xxxxxx.
414*/
0881a0fd 415static unsigned short hollow_square_bits[] = {
2d05deef
KS
416 0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e};
417
418
0881a0fd
KS
419#define BYTES_PER_BITMAP_ROW (sizeof (unsigned short))
420#define STANDARD_BITMAP_HEIGHT(bits) (sizeof (bits)/BYTES_PER_BITMAP_ROW)
421#define FRBITS(bits) bits, STANDARD_BITMAP_HEIGHT (bits)
2d05deef 422
2d05deef
KS
423struct fringe_bitmap standard_bitmaps[MAX_STANDARD_FRINGE_BITMAPS] =
424{
425 { NULL, 0, 0, 0, 0, 0 }, /* NO_FRINGE_BITMAP */
426 { FRBITS (unknown_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
427 { FRBITS (left_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
428 { FRBITS (right_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
429 { FRBITS (up_arrow_bits), 8, 0, ALIGN_BITMAP_TOP, 0 },
430 { FRBITS (down_arrow_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
431 { FRBITS (continued_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
432 { FRBITS (continuation_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
433 { FRBITS (ov_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
434 { FRBITS (top_left_angle_bits), 8, 0, ALIGN_BITMAP_TOP, 0 },
435 { FRBITS (top_right_angle_bits), 8, 0, ALIGN_BITMAP_TOP, 0 },
436 { FRBITS (bottom_left_angle_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
437 { FRBITS (bottom_right_angle_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
438 { FRBITS (left_bracket_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
439 { FRBITS (right_bracket_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
440 { FRBITS (filled_box_cursor_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
441 { FRBITS (hollow_box_cursor_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
442 { FRBITS (hollow_square_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
443 { FRBITS (bar_cursor_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 },
444 { FRBITS (hbar_cursor_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 },
445 { FRBITS (zv_bits), 8, 3, ALIGN_BITMAP_TOP, 0 },
446};
447
448static struct fringe_bitmap *fringe_bitmaps[MAX_FRINGE_BITMAPS];
449static unsigned fringe_faces[MAX_FRINGE_BITMAPS];
450
451static int max_used_fringe_bitmap = MAX_STANDARD_FRINGE_BITMAPS;
452
453/* Return 1 if FRINGE_ID is a valid fringe bitmap id. */
454
455int
7a2a85be
KS
456valid_fringe_bitmap_p (bitmap)
457 Lisp_Object bitmap;
458{
459 int bn;
460
461 if (!INTEGERP (bitmap))
462 return 0;
463
464 bn = XINT (bitmap);
465 return (bn >= NO_FRINGE_BITMAP
466 && bn < max_used_fringe_bitmap
467 && (bn < MAX_STANDARD_FRINGE_BITMAPS
468 || fringe_bitmaps[bn] != NULL));
469}
470
471/* Get fringe bitmap name for bitmap number BN.
472
473 Found by traversing Vfringe_bitmaps comparing BN to the
474 fringe property for each symbol.
475
476 Return BN if not found in Vfringe_bitmaps. */
477
478static Lisp_Object
479get_fringe_bitmap_name (bn)
480 int bn;
481{
482 Lisp_Object bitmaps;
483 Lisp_Object num;
484
485 /* Zero means no bitmap -- return nil. */
486 if (bn <= 0)
487 return Qnil;
488
489 bitmaps = Vfringe_bitmaps;
490 num = make_number (bn);
491
492 while (CONSP (bitmaps))
493 {
494 Lisp_Object bitmap = XCAR (bitmaps);
495 if (EQ (num, Fget (bitmap, Qfringe)))
496 return bitmap;
497 bitmaps = XCDR (bitmaps);
498 }
499
500 return num;
501}
502
503
504/* Resolve a BITMAP parameter.
505
506 An INTEGER, corresponding to a bitmap number.
507 A STRING which is interned to a symbol.
508 A SYMBOL which has a fringe property which is a bitmap number.
509*/
510
511static int
512resolve_fringe_bitmap (bitmap, namep)
513 Lisp_Object bitmap;
514 Lisp_Object *namep;
2d05deef 515{
7a2a85be
KS
516 if (namep)
517 *namep = Qnil;
518
519 if (STRINGP (bitmap))
520 bitmap = intern (SDATA (bitmap));
521
522 if (SYMBOLP (bitmap))
523 {
524 if (namep)
525 *namep = bitmap;
526 bitmap = Fget (bitmap, Qfringe);
527 }
528
529 if (valid_fringe_bitmap_p (bitmap))
530 {
531 if (namep && NILP (*namep))
532 *namep = get_fringe_bitmap_name (XINT (bitmap));
533 return XINT (bitmap);
534 }
535
536 return -1;
2d05deef
KS
537}
538
7a2a85be 539
2d05deef
KS
540/* Draw the bitmap WHICH in one of the left or right fringes of
541 window W. ROW is the glyph row for which to display the bitmap; it
542 determines the vertical position at which the bitmap has to be
543 drawn.
544 LEFT_P is 1 for left fringe, 0 for right fringe.
545*/
546
547void
548draw_fringe_bitmap_1 (w, row, left_p, overlay, which)
549 struct window *w;
550 struct glyph_row *row;
551 int left_p, overlay;
552 enum fringe_bitmap_type which;
553{
554 struct frame *f = XFRAME (WINDOW_FRAME (w));
555 struct draw_fringe_bitmap_params p;
556 struct fringe_bitmap *fb;
557 int period;
558 int face_id = DEFAULT_FACE_ID;
559
560 p.cursor_p = 0;
561 p.overlay_p = (overlay & 1) == 1;
562 p.cursor_p = (overlay & 2) == 2;
563
564 if (which != NO_FRINGE_BITMAP)
565 {
566 }
567 else if (left_p)
568 {
569 which = row->left_fringe_bitmap;
570 face_id = row->left_fringe_face_id;
571 }
572 else
573 {
574 which = row->right_fringe_bitmap;
575 face_id = row->right_fringe_face_id;
576 }
577
578 if (face_id == DEFAULT_FACE_ID)
579 face_id = fringe_faces[which];
580
581 fb = fringe_bitmaps[which];
582 if (fb == NULL)
583 fb = &standard_bitmaps[which < MAX_STANDARD_FRINGE_BITMAPS
584 ? which : UNDEF_FRINGE_BITMAP];
585
586 period = fb->period;
587
588 /* Convert row to frame coordinates. */
589 p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
590
591 p.which = which;
592 p.bits = fb->bits;
593 p.wd = fb->width;
594
595 p.h = fb->height;
596 p.dh = (period > 0 ? (p.y % period) : 0);
597 p.h -= p.dh;
598 /* Clip bitmap if too high. */
599 if (p.h > row->height)
600 p.h = row->height;
601
602 p.face = FACE_FROM_ID (f, face_id);
603
604 if (p.face == NULL)
605 {
606 /* Why does this happen? ++kfs */
607 return;
608 }
609
610 PREPARE_FACE_FOR_DISPLAY (f, p.face);
611
612 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
613 the fringe. */
614 p.bx = -1;
615 if (left_p)
616 {
617 int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
618 int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
619 ? LEFT_MARGIN_AREA
620 : TEXT_AREA));
621 if (p.wd > wd)
622 p.wd = wd;
623 p.x = x - p.wd - (wd - p.wd) / 2;
624
625 if (p.wd < wd || row->height > p.h)
626 {
627 /* If W has a vertical border to its left, don't draw over it. */
628 wd -= ((!WINDOW_LEFTMOST_P (w)
629 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
630 ? 1 : 0);
631 p.bx = x - wd;
632 p.nx = wd;
633 }
634 }
635 else
636 {
637 int x = window_box_right (w,
638 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
639 ? RIGHT_MARGIN_AREA
640 : TEXT_AREA));
641 int wd = WINDOW_RIGHT_FRINGE_WIDTH (w);
642 if (p.wd > wd)
643 p.wd = wd;
644 p.x = x + (wd - p.wd) / 2;
645 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
646 the fringe. */
647 if (p.wd < wd || row->height > p.h)
648 {
649 p.bx = x;
650 p.nx = wd;
651 }
652 }
653
654 if (p.bx >= 0)
655 {
656 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
657
658 p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
659 p.ny = row->visible_height;
660 }
661
662 /* Adjust y to the offset in the row to start drawing the bitmap. */
663 switch (fb->align)
664 {
665 case ALIGN_BITMAP_CENTER:
666 p.y += (row->height - p.h) / 2;
667 break;
668 case ALIGN_BITMAP_BOTTOM:
669 p.h = fb->height;
670 p.y += (row->visible_height - p.h);
671 break;
672 case ALIGN_BITMAP_TOP:
673 break;
674 }
675
676 rif->draw_fringe_bitmap (w, row, &p);
677}
678
679void
680draw_fringe_bitmap (w, row, left_p)
681 struct window *w;
682 struct glyph_row *row;
683 int left_p;
684{
685 int overlay = 0;
686
687 if (!left_p && row->cursor_in_fringe_p)
688 {
689 int cursor = NO_FRINGE_BITMAP;
690
691 switch (w->phys_cursor_type)
692 {
693 case HOLLOW_BOX_CURSOR:
0881a0fd 694 if (row->visible_height >= STANDARD_BITMAP_HEIGHT (hollow_box_cursor_bits))
2d05deef
KS
695 cursor = HOLLOW_BOX_CURSOR_BITMAP;
696 else
697 cursor = HOLLOW_SQUARE_BITMAP;
698 break;
699 case FILLED_BOX_CURSOR:
700 cursor = FILLED_BOX_CURSOR_BITMAP;
701 break;
702 case BAR_CURSOR:
703 cursor = BAR_CURSOR_BITMAP;
704 break;
705 case HBAR_CURSOR:
706 cursor = HBAR_CURSOR_BITMAP;
707 break;
708 case NO_CURSOR:
709 default:
710 w->phys_cursor_on_p = 0;
711 row->cursor_in_fringe_p = 0;
712 break;
713 }
714 if (cursor != NO_FRINGE_BITMAP)
715 {
716 draw_fringe_bitmap_1 (w, row, 0, 2, cursor);
717 overlay = cursor == FILLED_BOX_CURSOR_BITMAP ? 3 : 1;
718 }
719 }
720
721 draw_fringe_bitmap_1 (w, row, left_p, overlay, NO_FRINGE_BITMAP);
722
723 if (left_p && row->overlay_arrow_p)
1c2a9e98
KS
724 draw_fringe_bitmap_1 (w, row, 1, 1,
725 (w->overlay_arrow_bitmap
726 ? w->overlay_arrow_bitmap
727 : OVERLAY_ARROW_BITMAP));
2d05deef
KS
728}
729
730
731/* Draw fringe bitmaps for glyph row ROW on window W. Call this
732 function with input blocked. */
733
734void
735draw_row_fringe_bitmaps (w, row)
736 struct window *w;
737 struct glyph_row *row;
738{
739 xassert (interrupt_input_blocked);
740
741 /* If row is completely invisible, because of vscrolling, we
742 don't have to draw anything. */
743 if (row->visible_height <= 0)
744 return;
745
746 if (WINDOW_LEFT_FRINGE_WIDTH (w) != 0)
747 draw_fringe_bitmap (w, row, 1);
748
749 if (WINDOW_RIGHT_FRINGE_WIDTH (w) != 0)
750 draw_fringe_bitmap (w, row, 0);
751}
752
753/* Draw the fringes of window W. Only fringes for rows marked for
754 update in redraw_fringe_bitmaps_p are drawn. */
755
756void
757draw_window_fringes (w)
758 struct window *w;
759{
760 struct glyph_row *row;
761 int yb = window_text_bottom_y (w);
762 int nrows = w->current_matrix->nrows;
763 int y = 0, rn;
764
765 if (w->pseudo_window_p)
766 return;
767
768 for (y = 0, rn = 0, row = w->current_matrix->rows;
769 y < yb && rn < nrows;
770 y += row->height, ++row, ++rn)
771 {
772 if (!row->redraw_fringe_bitmaps_p)
773 continue;
774 draw_row_fringe_bitmaps (w, row);
775 row->redraw_fringe_bitmaps_p = 0;
776 }
777}
778
779
780/* Recalculate the bitmaps to show in the fringes of window W.
781 If FORCE_P is 0, only mark rows with modified bitmaps for update in
782 redraw_fringe_bitmaps_p; else mark all rows for update. */
783
784int
785update_window_fringes (w, force_p)
786 struct window *w;
787 int force_p;
788{
789 struct glyph_row *row, *cur = 0;
790 int yb = window_text_bottom_y (w);
791 int rn, nrows = w->current_matrix->nrows;
792 int y;
793 int redraw_p = 0;
5797a7a0
KS
794 Lisp_Object boundary_top = Qnil, boundary_bot = Qnil;
795 Lisp_Object arrow_top = Qnil, arrow_bot = Qnil;
796 Lisp_Object empty_pos;
797 Lisp_Object ind = Qnil;
2d05deef
KS
798
799 if (w->pseudo_window_p)
800 return 0;
801
802 if (!MINI_WINDOW_P (w)
803 && (ind = XBUFFER (w->buffer)->indicate_buffer_boundaries, !NILP (ind)))
804 {
5797a7a0
KS
805 if (EQ (ind, Qleft) || EQ (ind, Qright))
806 boundary_top = boundary_bot = arrow_top = arrow_bot = ind;
807 else if (CONSP (ind) && CONSP (XCAR (ind)))
808 {
809 Lisp_Object pos;
810 if (pos = Fassq (Qt, ind), !NILP (pos))
811 boundary_top = boundary_bot = arrow_top = arrow_bot = XCDR (pos);
812 if (pos = Fassq (Qtop, ind), !NILP (pos))
813 boundary_top = XCDR (pos);
814 if (pos = Fassq (Qbottom, ind), !NILP (pos))
815 boundary_bot = XCDR (pos);
816 if (pos = Fassq (Qup, ind), !NILP (pos))
817 arrow_top = XCDR (pos);
818 if (pos = Fassq (Qdown, ind), !NILP (pos))
819 arrow_bot = XCDR (pos);
820 }
2d05deef 821 else
5797a7a0
KS
822 ind = Qnil;
823 }
2d05deef 824
5797a7a0
KS
825 if (!NILP (ind))
826 {
827 int do_eob = 1, do_bob = 1;
2d05deef
KS
828
829 for (y = 0, rn = 0;
830 y < yb && rn < nrows;
831 y += row->height, ++rn)
832 {
833 unsigned indicate_bob_p, indicate_top_line_p;
834 unsigned indicate_eob_p, indicate_bottom_line_p;
bffe8c26 835
2d05deef
KS
836 row = w->desired_matrix->rows + rn;
837 if (!row->enabled_p)
838 row = w->current_matrix->rows + rn;
839
840 indicate_bob_p = row->indicate_bob_p;
841 indicate_top_line_p = row->indicate_top_line_p;
842 indicate_eob_p = row->indicate_eob_p;
843 indicate_bottom_line_p = row->indicate_bottom_line_p;
bffe8c26 844
2d05deef
KS
845 row->indicate_bob_p = row->indicate_top_line_p = 0;
846 row->indicate_eob_p = row->indicate_bottom_line_p = 0;
847
5797a7a0 848 if (!NILP (boundary_top)
2d05deef
KS
849 && MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer)))
850 row->indicate_bob_p = do_bob, do_bob = 0;
5797a7a0 851 else if (!NILP (arrow_top)
2d05deef
KS
852 && (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0) == rn)
853 row->indicate_top_line_p = 1;
854
5797a7a0 855 if (!NILP (boundary_bot)
2d05deef
KS
856 && MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer)))
857 row->indicate_eob_p = do_eob, do_eob = 0;
5797a7a0 858 else if (!NILP (arrow_bot)
2d05deef
KS
859 && y + row->height >= yb)
860 row->indicate_bottom_line_p = 1;
861
862 if (indicate_bob_p != row->indicate_bob_p
863 || indicate_top_line_p != row->indicate_top_line_p
864 || indicate_eob_p != row->indicate_eob_p
865 || indicate_bottom_line_p != row->indicate_bottom_line_p)
866 row->redraw_fringe_bitmaps_p = 1;
867 }
868 }
869
5797a7a0
KS
870 empty_pos = XBUFFER (w->buffer)->indicate_empty_lines;
871 if (!NILP (empty_pos) && !EQ (empty_pos, Qright))
872 empty_pos = WINDOW_LEFT_FRINGE_WIDTH (w) == 0 ? Qright : Qleft;
2d05deef
KS
873
874 for (y = 0, rn = 0;
875 y < yb && rn < nrows;
876 y += row->height, rn++)
877 {
878 enum fringe_bitmap_type left, right;
879 unsigned left_face_id, right_face_id;
880
881 row = w->desired_matrix->rows + rn;
882 cur = w->current_matrix->rows + rn;
883 if (!row->enabled_p)
884 row = cur;
885
886 left_face_id = right_face_id = DEFAULT_FACE_ID;
887
888 /* Decide which bitmap to draw in the left fringe. */
889 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
890 left = NO_FRINGE_BITMAP;
891 else if (row->left_user_fringe_bitmap != NO_FRINGE_BITMAP)
892 {
893 left = row->left_user_fringe_bitmap;
894 left_face_id = row->left_user_fringe_face_id;
895 }
5797a7a0
KS
896 else if (row->indicate_bob_p && EQ (boundary_top, Qleft))
897 left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
2d05deef 898 ? LEFT_BRACKET_BITMAP : TOP_LEFT_ANGLE_BITMAP);
5797a7a0 899 else if (row->indicate_eob_p && EQ (boundary_bot, Qleft))
2d05deef
KS
900 left = BOTTOM_LEFT_ANGLE_BITMAP;
901 else if (row->truncated_on_left_p)
902 left = LEFT_TRUNCATION_BITMAP;
903 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
904 left = CONTINUATION_LINE_BITMAP;
5797a7a0 905 else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft))
2d05deef 906 left = ZV_LINE_BITMAP;
5797a7a0 907 else if (row->indicate_top_line_p && EQ (arrow_top, Qleft))
2d05deef 908 left = UP_ARROW_BITMAP;
5797a7a0 909 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qleft))
2d05deef
KS
910 left = DOWN_ARROW_BITMAP;
911 else
912 left = NO_FRINGE_BITMAP;
913
914 /* Decide which bitmap to draw in the right fringe. */
915 if (WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)
916 right = NO_FRINGE_BITMAP;
917 else if (row->right_user_fringe_bitmap != NO_FRINGE_BITMAP)
918 {
919 right = row->right_user_fringe_bitmap;
920 right_face_id = row->right_user_fringe_face_id;
921 }
5797a7a0
KS
922 else if (row->indicate_bob_p && EQ (boundary_top, Qright))
923 right = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
2d05deef 924 ? RIGHT_BRACKET_BITMAP : TOP_RIGHT_ANGLE_BITMAP);
5797a7a0 925 else if (row->indicate_eob_p && EQ (boundary_bot, Qright))
2d05deef
KS
926 right = BOTTOM_RIGHT_ANGLE_BITMAP;
927 else if (row->truncated_on_right_p)
928 right = RIGHT_TRUNCATION_BITMAP;
929 else if (row->continued_p)
930 right = CONTINUED_LINE_BITMAP;
5797a7a0 931 else if (row->indicate_top_line_p && EQ (arrow_top, Qright))
2d05deef 932 right = UP_ARROW_BITMAP;
5797a7a0 933 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright))
2d05deef 934 right = DOWN_ARROW_BITMAP;
5797a7a0 935 else if (row->indicate_empty_line_p && EQ (empty_pos, Qright))
2d05deef
KS
936 right = ZV_LINE_BITMAP;
937 else
938 right = NO_FRINGE_BITMAP;
939
940 if (force_p
941 || row->y != cur->y
942 || row->visible_height != cur->visible_height
943 || left != cur->left_fringe_bitmap
944 || right != cur->right_fringe_bitmap
945 || left_face_id != cur->left_fringe_face_id
946 || right_face_id != cur->right_fringe_face_id
947 || cur->redraw_fringe_bitmaps_p)
948 {
949 redraw_p = row->redraw_fringe_bitmaps_p = cur->redraw_fringe_bitmaps_p = 1;
950 cur->left_fringe_bitmap = left;
951 cur->right_fringe_bitmap = right;
952 cur->left_fringe_face_id = left_face_id;
953 cur->right_fringe_face_id = right_face_id;
954 }
955
956 if (row->overlay_arrow_p != cur->overlay_arrow_p)
957 {
958 redraw_p = row->redraw_fringe_bitmaps_p = cur->redraw_fringe_bitmaps_p = 1;
959 cur->overlay_arrow_p = row->overlay_arrow_p;
960 }
961
962 row->left_fringe_bitmap = left;
963 row->right_fringe_bitmap = right;
964 row->left_fringe_face_id = left_face_id;
965 row->right_fringe_face_id = right_face_id;
966 }
967
968 return redraw_p;
969}
970
971
bffe8c26 972/* Compute actual fringe widths for frame F.
2d05deef
KS
973
974 If REDRAW is 1, redraw F if the fringe settings was actually
975 modified and F is visible.
976
977 Since the combined left and right fringe must occupy an integral
978 number of columns, we may need to add some pixels to each fringe.
979 Typically, we add an equal amount (+/- 1 pixel) to each fringe,
980 but a negative width value is taken literally (after negating it).
981
982 We never make the fringes narrower than specified. It is planned
983 to make fringe bitmaps customizable and expandable, and at that
984 time, the user will typically specify the minimum number of pixels
985 needed for his bitmaps, so we shouldn't select anything less than
986 what is specified.
987*/
988
989void
990compute_fringe_widths (f, redraw)
991 struct frame *f;
992 int redraw;
993{
994 int o_left = FRAME_LEFT_FRINGE_WIDTH (f);
995 int o_right = FRAME_RIGHT_FRINGE_WIDTH (f);
996 int o_cols = FRAME_FRINGE_COLS (f);
997
998 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
999 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
1000 int left_fringe_width, right_fringe_width;
1001
1002 if (!NILP (left_fringe))
1003 left_fringe = Fcdr (left_fringe);
1004 if (!NILP (right_fringe))
1005 right_fringe = Fcdr (right_fringe);
1006
1007 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
1008 XINT (left_fringe));
1009 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
1010 XINT (right_fringe));
1011
1012 if (left_fringe_width || right_fringe_width)
1013 {
1014 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
1015 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
1016 int conf_wid = left_wid + right_wid;
1017 int font_wid = FRAME_COLUMN_WIDTH (f);
1018 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
1019 int real_wid = cols * font_wid;
1020 if (left_wid && right_wid)
1021 {
1022 if (left_fringe_width < 0)
1023 {
1024 /* Left fringe width is fixed, adjust right fringe if necessary */
1025 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid;
1026 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid;
1027 }
1028 else if (right_fringe_width < 0)
1029 {
1030 /* Right fringe width is fixed, adjust left fringe if necessary */
1031 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
1032 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid;
1033 }
1034 else
1035 {
1036 /* Adjust both fringes with an equal amount.
1037 Note that we are doing integer arithmetic here, so don't
1038 lose a pixel if the total width is an odd number. */
1039 int fill = real_wid - conf_wid;
1040 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2;
1041 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2;
1042 }
1043 }
1044 else if (left_fringe_width)
1045 {
1046 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid;
1047 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
1048 }
1049 else
1050 {
1051 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
1052 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid;
1053 }
1054 FRAME_FRINGE_COLS (f) = cols;
1055 }
1056 else
1057 {
1058 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
1059 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
1060 FRAME_FRINGE_COLS (f) = 0;
1061 }
1062
1063 if (redraw && FRAME_VISIBLE_P (f))
1064 if (o_left != FRAME_LEFT_FRINGE_WIDTH (f) ||
1065 o_right != FRAME_RIGHT_FRINGE_WIDTH (f) ||
1066 o_cols != FRAME_FRINGE_COLS (f))
1067 redraw_frame (f);
1068}
1069
7a2a85be
KS
1070
1071void
1072destroy_fringe_bitmap (n)
1073 int n;
2d05deef 1074{
2d05deef
KS
1075 struct fringe_bitmap **fbp;
1076
2d05deef
KS
1077 fringe_faces[n] = FRINGE_FACE_ID;
1078
1079 fbp = &fringe_bitmaps[n];
1080 if (*fbp && (*fbp)->dynamic)
1081 {
1082 if (rif->destroy_fringe_bitmap)
1083 rif->destroy_fringe_bitmap (n);
1084 xfree (*fbp);
1085 *fbp = NULL;
1086 }
1087
1088 while (max_used_fringe_bitmap > MAX_STANDARD_FRINGE_BITMAPS
1089 && fringe_bitmaps[max_used_fringe_bitmap - 1] == NULL)
1090 max_used_fringe_bitmap--;
7a2a85be
KS
1091}
1092
1093
1094DEFUN ("destroy-fringe-bitmap", Fdestroy_fringe_bitmap, Sdestroy_fringe_bitmap,
1095 1, 1, 0,
1096 doc: /* Destroy fringe bitmap BITMAP.
1097If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. */)
1098 (bitmap)
1099 Lisp_Object bitmap;
1100{
1101 int n;
1102 Lisp_Object sym;
1103
1104 n = resolve_fringe_bitmap (bitmap, &sym);
1105 if (n < 0)
1106 return Qnil;
1107
1108 destroy_fringe_bitmap (n);
2d05deef 1109
7a2a85be
KS
1110 if (SYMBOLP (sym))
1111 {
1112 Vfringe_bitmaps = Fdelq (sym, Vfringe_bitmaps);
1113 /* It would be better to remove the fringe property. */
1114 Fput (sym, Qfringe, Qnil);
1115 }
2d05deef
KS
1116 return Qnil;
1117}
1118
1119
1120/* Initialize bitmap bit.
0881a0fd
KS
1121
1122 On X, we bit-swap the built-in bitmaps and reduce bitmap
1123 from short to char array if width is <= 8 bits.
1124
bd231131
KS
1125 On MAC with big-endian CPU, we need to byte-swap each short.
1126
1127 On W32 and MAC (little endian), there's no need to do this.
2d05deef
KS
1128*/
1129
1130void
1131init_fringe_bitmap (which, fb, once_p)
1132 enum fringe_bitmap_type which;
1133 struct fringe_bitmap *fb;
1134 int once_p;
1135{
1136 if (once_p || fb->dynamic)
1137 {
0881a0fd
KS
1138#if defined (HAVE_X_WINDOWS)
1139 static unsigned char swap_nibble[16]
1140 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
1141 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
1142 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
bd231131 1143 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
0881a0fd 1144 unsigned short *bits = fb->bits;
2d05deef 1145 int j;
0881a0fd
KS
1146
1147 if (fb->width <= 8)
1148 {
1149 unsigned char *cbits = (unsigned char *)fb->bits;
1150 for (j = 0; j < fb->height; j++)
1151 {
1152 unsigned short b = *bits++;
1153 unsigned char c;
1154 c = (unsigned char)((swap_nibble[b & 0xf] << 4)
1155 | (swap_nibble[(b>>4) & 0xf]));
1156 *cbits++ = (c >> (8 - fb->width));
1157 }
1158 }
1159 else
2d05deef 1160 {
0881a0fd
KS
1161 for (j = 0; j < fb->height; j++)
1162 {
1163 unsigned short b = *bits;
1164 b = (unsigned short)((swap_nibble[b & 0xf] << 12)
1165 | (swap_nibble[(b>>4) & 0xf] << 8)
1166 | (swap_nibble[(b>>8) & 0xf] << 4)
1167 | (swap_nibble[(b>>12) & 0xf]));
1168 *bits++ = (b >> (16 - fb->width));
1169 }
2d05deef 1170 }
bd231131
KS
1171#endif /* HAVE_X_WINDOWS */
1172
1173#if defined (MAC_OS) && defined (WORDS_BIG_ENDIAN)
1174 unsigned short *bits = fb->bits;
159c348e 1175 int j;
bd231131
KS
1176 for (j = 0; j < fb->height; j++)
1177 {
1178 unsigned short b = *bits;
1179 *bits++ = ((b >> 8) & 0xff) | ((b & 0xff) << 8);
1180 }
1181#endif /* MAC_OS && WORDS_BIG_ENDIAN */
2d05deef
KS
1182 }
1183
1184 if (!once_p)
1185 {
7a2a85be 1186 destroy_fringe_bitmap (which);
2d05deef
KS
1187
1188 if (rif->define_fringe_bitmap)
1189 rif->define_fringe_bitmap (which, fb->bits, fb->height, fb->width);
1190
1191 fringe_bitmaps[which] = fb;
1192 if (which >= max_used_fringe_bitmap)
1193 max_used_fringe_bitmap = which + 1;
1194 }
1195}
1196
1197
1198DEFUN ("define-fringe-bitmap", Fdefine_fringe_bitmap, Sdefine_fringe_bitmap,
7a2a85be
KS
1199 2, 5, 0,
1200 doc: /* Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.
1201BITMAP is a symbol or string naming the new fringe bitmap.
0881a0fd
KS
1202BITS is either a string or a vector of integers.
1203HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.
1204WIDTH must be an integer between 1 and 16, or nil which defaults to 8.
7a2a85be 1205Optional fifth arg ALIGN may be one of `top', `center', or `bottom',
0881a0fd
KS
1206indicating the positioning of the bitmap relative to the rows where it
1207is used; the default is to center the bitmap. Fourth arg may also be a
1208list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap
1209should be repeated.
7a2a85be
KS
1210If BITMAP already exists, the existing definition is replaced. */)
1211 (bitmap, bits, height, width, align)
1212 Lisp_Object bitmap, bits, height, width, align;
2d05deef
KS
1213{
1214 Lisp_Object len;
1215 int n, h, i, j;
0881a0fd 1216 unsigned short *b;
2d05deef
KS
1217 struct fringe_bitmap fb, *xfb;
1218 int fill1 = 0, fill2 = 0;
7a2a85be
KS
1219 Lisp_Object sym;
1220
1221 n = resolve_fringe_bitmap (bitmap, &sym);
1222
1223 if (NILP (sym) || INTEGERP (sym))
1224 sym = wrong_type_argument (Qsymbolp, bitmap);
2d05deef
KS
1225
1226 if (!STRINGP (bits) && !VECTORP (bits))
1227 bits = wrong_type_argument (Qstringp, bits);
1228
1229 len = Flength (bits);
1230
1231 if (NILP (height))
1232 h = fb.height = XINT (len);
1233 else
1234 {
1235 CHECK_NUMBER (height);
1236 fb.height = min (XINT (height), 255);
1237 if (fb.height > XINT (len))
1238 {
1239 h = XINT (len);
1240 fill1 = (fb.height - h) / 2;
1241 fill2 = fb.height - h - fill1;
1242 }
1243 }
bffe8c26 1244
2d05deef
KS
1245 if (NILP (width))
1246 fb.width = 8;
1247 else
1248 {
1249 CHECK_NUMBER (width);
1250 fb.width = min (XINT (width), 255);
1251 }
1252
1253 fb.period = 0;
1254 fb.align = ALIGN_BITMAP_CENTER;
1255
1256 if (CONSP (align))
1257 {
1258 Lisp_Object period = XCDR (align);
1259 if (CONSP (period))
1260 {
1261 period = XCAR (period);
1262 if (!NILP (period))
1263 {
1264 fb.period = fb.height;
1265 fb.height = 255;
1266 }
1267 }
1268 align = XCAR (align);
1269 }
1270 if (EQ (align, Qtop))
1271 fb.align = ALIGN_BITMAP_TOP;
1272 else if (EQ (align, Qbottom))
1273 fb.align = ALIGN_BITMAP_BOTTOM;
1274 else if (!NILP (align) && !EQ (align, Qcenter))
1275 error ("Bad align argument");
1276
7a2a85be 1277 if (n < 0)
2d05deef
KS
1278 {
1279 if (max_used_fringe_bitmap < MAX_FRINGE_BITMAPS)
d2f14999 1280 n = max_used_fringe_bitmap++;
2d05deef
KS
1281 else
1282 {
1283 for (n = MAX_STANDARD_FRINGE_BITMAPS;
1284 n < MAX_FRINGE_BITMAPS;
1285 n++)
1286 if (fringe_bitmaps[n] == NULL)
1287 break;
1288 if (n == MAX_FRINGE_BITMAPS)
7a2a85be 1289 error ("Cannot define more fringe bitmaps");
2d05deef 1290 }
7a2a85be
KS
1291
1292 Vfringe_bitmaps = Fcons (sym, Vfringe_bitmaps);
1293 Fput (sym, Qfringe, make_number (n));
2d05deef
KS
1294 }
1295
1296 fb.dynamic = 1;
1297
beaedd56
AS
1298 xfb = (struct fringe_bitmap *) xmalloc (sizeof fb
1299 + fb.height * BYTES_PER_BITMAP_ROW);
1300 fb.bits = b = (unsigned short *) (xfb + 1);
2d05deef
KS
1301 bzero (b, fb.height);
1302
1303 j = 0;
1304 while (j < fb.height)
1305 {
1306 for (i = 0; i < fill1 && j < fb.height; i++)
1307 b[j++] = 0;
beaedd56 1308 for (i = 0; i < h && j < fb.height; i++)
2d05deef
KS
1309 {
1310 Lisp_Object elt = Faref (bits, make_number (i));
1311 b[j++] = NUMBERP (elt) ? XINT (elt) : 0;
1312 }
1313 for (i = 0; i < fill2 && j < fb.height; i++)
1314 b[j++] = 0;
1315 }
1316
1317 *xfb = fb;
1318
1319 init_fringe_bitmap (n, xfb, 0);
1320
7a2a85be 1321 return sym;
2d05deef
KS
1322}
1323
1324DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face, Sset_fringe_bitmap_face,
1325 1, 2, 0,
7a2a85be 1326 doc: /* Set face for fringe bitmap BITMAP to FACE.
2d05deef 1327If FACE is nil, reset face to default fringe face. */)
7a2a85be
KS
1328 (bitmap, face)
1329 Lisp_Object bitmap, face;
2d05deef 1330{
7a2a85be 1331 int bn;
2d05deef
KS
1332 int face_id;
1333
7a2a85be
KS
1334 bn = resolve_fringe_bitmap (bitmap, 0);
1335 if (bn < 0)
1336 error ("Undefined fringe bitmap");
2d05deef
KS
1337
1338 if (!NILP (face))
1339 {
1340 face_id = lookup_named_face (SELECTED_FRAME (), face, 'A');
1341 if (face_id < 0)
1342 error ("No such face");
1343 }
1344 else
1345 face_id = FRINGE_FACE_ID;
1346
7a2a85be 1347 fringe_faces [bn] = face_id;
2d05deef
KS
1348
1349 return Qnil;
1350}
1351
1352DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos, Sfringe_bitmaps_at_pos,
1353 0, 2, 0,
bffe8c26 1354 doc: /* Return fringe bitmaps of row containing position POS in window WINDOW.
2d05deef
KS
1355If WINDOW is nil, use selected window. If POS is nil, use value of point
1356in that window. Return value is a cons (LEFT . RIGHT) where LEFT and RIGHT
1357are the fringe bitmap numbers for the bitmaps in the left and right fringe,
5797a7a0
KS
1358resp. If left or right fringe is empty, the corresponding element is nil.
1359Return nil if POS is not visible in WINDOW. */)
2d05deef 1360 (pos, window)
d30b6b33 1361 Lisp_Object pos, window;
2d05deef
KS
1362{
1363 struct window *w;
1364 struct buffer *old_buffer = NULL;
1365 struct glyph_row *row;
1366 int textpos;
1367
1368 if (NILP (window))
1369 window = selected_window;
1370 CHECK_WINDOW (window);
1371 w = XWINDOW (window);
1372
1373 if (!NILP (pos))
1374 {
1375 CHECK_NUMBER_COERCE_MARKER (pos);
1376 textpos = XINT (pos);
1377 }
1378 else if (w == XWINDOW (selected_window))
1379 textpos = PT;
1380 else
1381 textpos = XMARKER (w->pointm)->charpos;
1382
1383 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1384 row = row_containing_pos (w, textpos, row, NULL, 0);
1385 if (row)
7a2a85be
KS
1386 return Fcons (get_fringe_bitmap_name (row->left_fringe_bitmap),
1387 get_fringe_bitmap_name (row->right_fringe_bitmap));
2d05deef
KS
1388 else
1389 return Qnil;
1390}
1391
1392
1393/***********************************************************************
1394 Initialization
1395 ***********************************************************************/
1396
1397void
1398syms_of_fringe ()
1399{
2d05deef
KS
1400 defsubr (&Sdestroy_fringe_bitmap);
1401 defsubr (&Sdefine_fringe_bitmap);
1402 defsubr (&Sfringe_bitmaps_at_pos);
1403 defsubr (&Sset_fringe_bitmap_face);
1404
1405 DEFVAR_LISP ("overflow-newline-into-fringe", &Voverflow_newline_into_fringe,
1406 doc: /* *Non-nil means that newline may flow into the right fringe.
1407This means that display lines which are exactly as wide as the window
1408(not counting the final newline) will only occupy one screen line, by
1409showing (or hiding) the final newline in the right fringe; when point
1410is at the final newline, the cursor is shown in the right fringe.
1411If nil, also continue lines which are exactly as wide as the window. */);
1412 Voverflow_newline_into_fringe = Qt;
1413
7a2a85be
KS
1414 DEFVAR_LISP ("fringe-bitmaps", &Vfringe_bitmaps,
1415 doc: /* List of fringe bitmap symbols.
1416You must (require 'fringe) to use fringe bitmap symbols in your programs." */);
1417 Vfringe_bitmaps = Qnil;
2d05deef
KS
1418}
1419
1420/* Initialize this module when Emacs starts. */
1421
1422void
1423init_fringe_once ()
1424{
1425 enum fringe_bitmap_type bt;
1426
1427 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1428 init_fringe_bitmap(bt, &standard_bitmaps[bt], 1);
1429}
1430
1431void
1432init_fringe ()
1433{
1434 int i;
1435
1436 bzero (fringe_bitmaps, sizeof fringe_bitmaps);
1437 for (i = 0; i < MAX_FRINGE_BITMAPS; i++)
1438 fringe_faces[i] = FRINGE_FACE_ID;
1439}
1440
1441#ifdef HAVE_NTGUI
1442
1443void
1444w32_init_fringe ()
1445{
1446 enum fringe_bitmap_type bt;
1447
1448 for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
1449 {
1450 struct fringe_bitmap *fb = &standard_bitmaps[bt];
1451 rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
1452 }
1453}
1454
1455void
1456w32_reset_fringes ()
1457{
1458 /* Destroy row bitmaps. */
1459 int bt;
bffe8c26 1460
2d05deef
KS
1461 for (bt = NO_FRINGE_BITMAP + 1; bt < max_used_fringe_bitmap; bt++)
1462 rif->destroy_fringe_bitmap (bt);
1463}
1464
bd231131 1465#endif /* HAVE_NTGUI */
2d05deef
KS
1466
1467#endif /* HAVE_WINDOW_SYSTEM */
1468
429e7e2d
MB
1469/* arch-tag: 04596920-43eb-473d-b319-82712338162d
1470 (do not change this comment) */