X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/4e1bb54039da0e3d5c84e231104703d62ace938d..b336ee388ed5300440e7bab24bf9eec9f250911a:/src/fringe.c diff --git a/src/fringe.c b/src/fringe.c index aecb51349f..721b572e37 100644 --- a/src/fringe.c +++ b/src/fringe.c @@ -1,6 +1,7 @@ /* Fringe handling (split from xdisp.c). - Copyright (C) 1985,86,87,88,93,94,95,97,98,99,2000,01,02,03,04 - Free Software Foundation, Inc. + Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1997, + 1998, 1999, 2000, 2000, 2001, 2002, 2003, 2004, + 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -16,8 +17,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ #include #include @@ -32,38 +33,62 @@ Boston, MA 02111-1307, USA. */ #ifdef HAVE_WINDOW_SYSTEM +extern Lisp_Object Qfringe; extern Lisp_Object Qtop, Qbottom, Qcenter; +extern Lisp_Object Qup, Qdown, Qleft, Qright; /* Non-nil means that newline may flow into the right fringe. */ Lisp_Object Voverflow_newline_into_fringe; +/* List of known fringe bitmap symbols. -enum fringe_bitmap_type -{ - NO_FRINGE_BITMAP = 0, - UNDEF_FRINGE_BITMAP, - LEFT_TRUNCATION_BITMAP, - RIGHT_TRUNCATION_BITMAP, - UP_ARROW_BITMAP, - DOWN_ARROW_BITMAP, - CONTINUED_LINE_BITMAP, - CONTINUATION_LINE_BITMAP, - OVERLAY_ARROW_BITMAP, - TOP_LEFT_ANGLE_BITMAP, - TOP_RIGHT_ANGLE_BITMAP, - BOTTOM_LEFT_ANGLE_BITMAP, - BOTTOM_RIGHT_ANGLE_BITMAP, - LEFT_BRACKET_BITMAP, - RIGHT_BRACKET_BITMAP, - FILLED_BOX_CURSOR_BITMAP, - HOLLOW_BOX_CURSOR_BITMAP, - HOLLOW_SQUARE_BITMAP, - BAR_CURSOR_BITMAP, - HBAR_CURSOR_BITMAP, - ZV_LINE_BITMAP, - MAX_STANDARD_FRINGE_BITMAPS -}; + The fringe bitmap number is stored in the `fringe' property on + those symbols. Names for the built-in bitmaps are installed by + loading fringe.el. + */ + +Lisp_Object Vfringe_bitmaps; + +/* Fringe bitmaps are represented in three different ways: + + Logical bitmaps are used internally to denote things like + 'end-of-buffer', 'left-truncation', 'overlay-arrow', etc. + + Physical bitmaps specify the visual appearence of the bitmap, + e.g. 'bottom-left-angle', 'left-arrow', 'left-triangle', etc. + User defined bitmaps are physical bitmaps. + + Internally, fringe bitmaps for a specific display row are + represented as a simple integer that is used as an index + into the table of all defined bitmaps. This index is stored + in the `fringe' property of the physical bitmap symbol. + + Logical bitmaps are mapped to physical bitmaps through the + buffer-local `fringe-indicator-alist' variable. + + Each element of this alist is a cons (LOGICAL . PHYSICAL) + mapping a logical bitmap to a physical bitmap. + PHYSICAL is either a symbol to use in both left and right fringe, + or a cons of two symbols (LEFT . RIGHT) denoting different + bitmaps to use in left and right fringe. + + LOGICAL is first looked up in the window's buffer's buffer-local + value of the fringe-indicator-alist variable, and if not present, + in the global value of fringe-indicator-alist. + + If LOGICAL is not present in either alist, or the PHYSICAL value + found is nil, no bitmap is shown for the logical bitmap. + + The `left-fringe' and `right-fringe' display properties + must specify physical bitmap symbols. +*/ + +extern Lisp_Object Qunknown; +Lisp_Object Qtruncation, Qcontinuation, Qoverlay_arrow; +Lisp_Object Qempty_line, Qtop_bottom; +extern Lisp_Object Qbar, Qhbar, Qbox, Qhollow; +Lisp_Object Qhollow_small; enum fringe_bitmap_align { @@ -100,7 +125,7 @@ struct fringe_bitmap ...xx... ...xx... */ -static unsigned short unknown_bits[] = { +static unsigned short question_mark_bits[] = { 0x3c, 0x7e, 0x7e, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18}; /* An arrow like this: `<-'. */ @@ -162,20 +187,6 @@ static unsigned short up_arrow_bits[] = { static unsigned short down_arrow_bits[] = { 0x18, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18}; -/* Marker for continued lines. */ -/* - ..xxxx.. - ..xxxxx. - ......xx - ..x..xxx - ..xxxxxx - ..xxxxx. - ..xxxx.. - ..xxxxx. -*/ -static unsigned short continued_bits[] = { - 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e}; - /* Marker for continuation lines. */ /* ..xxxx.. @@ -187,24 +198,23 @@ static unsigned short continued_bits[] = { ..xxxx.. .xxxxx.. */ -static unsigned short continuation_bits[] = { +static unsigned short left_curly_arrow_bits[] = { 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c}; -/* Overlay arrow bitmap. A triangular arrow. */ +/* Marker for continued lines. */ /* - xx...... - xxxx.... - xxxxx... - xxxxxx.. - xxxxxx.. - xxxxx... - xxxx.... - xx...... + ..xxxx.. + ..xxxxx. + ......xx + ..x..xxx + ..xxxxxx + ..xxxxx. + ..xxxx.. + ..xxxxx. */ -static unsigned short ov_bits[] = { - 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0}; +static unsigned short right_curly_arrow_bits[] = { + 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e}; -#if 0 /* Reverse Overlay arrow bitmap. A triangular arrow. */ /* ......xx @@ -216,9 +226,22 @@ static unsigned short ov_bits[] = { ....xxxx ......xx */ -static unsigned short rev_ov_bits[] = { +static unsigned short left_triangle_bits[] = { 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03}; -#endif + +/* Overlay arrow bitmap. A triangular arrow. */ +/* + xx...... + xxxx.... + xxxxx... + xxxxxx.. + xxxxxx.. + xxxxx... + xxxx.... + xx...... +*/ +static unsigned short right_triangle_bits[] = { + 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0}; /* First line bitmap. An top-left angle. */ /* @@ -324,7 +347,7 @@ static unsigned short right_bracket_bits[] = { xxxxxxx. xxxxxxx. */ -static unsigned short filled_box_cursor_bits[] = { +static unsigned short filled_rectangle_bits[] = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe}; /* Hollow box cursor bitmap. A hollow box; max 13 pixels high. */ @@ -343,9 +366,33 @@ static unsigned short filled_box_cursor_bits[] = { x.....x. xxxxxxx. */ -static unsigned short hollow_box_cursor_bits[] = { +static unsigned short hollow_rectangle_bits[] = { 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe}; +/* Hollow square bitmap. */ +/* + .xxxxxx. + .x....x. + .x....x. + .x....x. + .x....x. + .xxxxxx. +*/ +static unsigned short hollow_square_bits[] = { + 0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e}; + +/* Filled square bitmap. */ +/* + .xxxxxx. + .xxxxxx. + .xxxxxx. + .xxxxxx. + .xxxxxx. + .xxxxxx. +*/ +static unsigned short filled_square_bits[] = { + 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e}; + /* Bar cursor bitmap. A vertical bar; max 13 pixels high. */ /* xx...... @@ -362,15 +409,15 @@ static unsigned short hollow_box_cursor_bits[] = { xx...... xx...... */ -static unsigned short bar_cursor_bits[] = { +static unsigned short vertical_bar_bits[] = { 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}; -/* HBar cursor bitmap. A horisontal bar; 2 pixels high. */ +/* HBar cursor bitmap. A horizontal bar; 2 pixels high. */ /* xxxxxxx. xxxxxxx. */ -static unsigned short hbar_cursor_bits[] = { +static unsigned short horizontal_bar_bits[] = { 0xfe, 0xfe}; @@ -384,7 +431,7 @@ static unsigned short hbar_cursor_bits[] = { ..xxxx.. ........ */ -static unsigned short zv_bits[] = { +static unsigned short empty_line_bits[] = { 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, @@ -394,65 +441,108 @@ static unsigned short zv_bits[] = { 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00}; -/* Hollow square bitmap. */ -/* - .xxxxxx. - .x....x. - .x....x. - .x....x. - .x....x. - .xxxxxx. -*/ -static unsigned short hollow_square_bits[] = { - 0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e}; - #define BYTES_PER_BITMAP_ROW (sizeof (unsigned short)) #define STANDARD_BITMAP_HEIGHT(bits) (sizeof (bits)/BYTES_PER_BITMAP_ROW) #define FRBITS(bits) bits, STANDARD_BITMAP_HEIGHT (bits) -struct fringe_bitmap standard_bitmaps[MAX_STANDARD_FRINGE_BITMAPS] = +/* NOTE: The order of these bitmaps must match the sequence + used in fringe.el to define the corresponding symbols. */ + +struct fringe_bitmap standard_bitmaps[] = { { NULL, 0, 0, 0, 0, 0 }, /* NO_FRINGE_BITMAP */ - { FRBITS (unknown_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, + { FRBITS (question_mark_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, { FRBITS (left_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, { FRBITS (right_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, { FRBITS (up_arrow_bits), 8, 0, ALIGN_BITMAP_TOP, 0 }, { FRBITS (down_arrow_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 }, - { FRBITS (continued_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, - { FRBITS (continuation_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, - { FRBITS (ov_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, + { FRBITS (left_curly_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, + { FRBITS (right_curly_arrow_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, + { FRBITS (left_triangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, + { FRBITS (right_triangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, { FRBITS (top_left_angle_bits), 8, 0, ALIGN_BITMAP_TOP, 0 }, { FRBITS (top_right_angle_bits), 8, 0, ALIGN_BITMAP_TOP, 0 }, { FRBITS (bottom_left_angle_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 }, { FRBITS (bottom_right_angle_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 }, { FRBITS (left_bracket_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, { FRBITS (right_bracket_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, - { FRBITS (filled_box_cursor_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, - { FRBITS (hollow_box_cursor_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, + { FRBITS (filled_rectangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, + { FRBITS (hollow_rectangle_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, + { FRBITS (filled_square_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, { FRBITS (hollow_square_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, - { FRBITS (bar_cursor_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, - { FRBITS (hbar_cursor_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 }, - { FRBITS (zv_bits), 8, 3, ALIGN_BITMAP_TOP, 0 }, + { FRBITS (vertical_bar_bits), 8, 0, ALIGN_BITMAP_CENTER, 0 }, + { FRBITS (horizontal_bar_bits), 8, 0, ALIGN_BITMAP_BOTTOM, 0 }, + { FRBITS (empty_line_bits), 8, 3, ALIGN_BITMAP_TOP, 0 }, }; -static struct fringe_bitmap *fringe_bitmaps[MAX_FRINGE_BITMAPS]; -static unsigned fringe_faces[MAX_FRINGE_BITMAPS]; +#define NO_FRINGE_BITMAP 0 +#define UNDEF_FRINGE_BITMAP 1 +#define MAX_STANDARD_FRINGE_BITMAPS (sizeof(standard_bitmaps)/sizeof(standard_bitmaps[0])) + +static struct fringe_bitmap **fringe_bitmaps; +static Lisp_Object *fringe_faces; +static int max_fringe_bitmaps; static int max_used_fringe_bitmap = MAX_STANDARD_FRINGE_BITMAPS; -/* Return 1 if FRINGE_ID is a valid fringe bitmap id. */ + +/* Lookup bitmap number for symbol BITMAP. + Return 0 if not a bitmap. */ int -valid_fringe_bitmap_id_p (fringe_id) - int fringe_id; +lookup_fringe_bitmap (bitmap) + Lisp_Object bitmap; { - return (fringe_id >= NO_FRINGE_BITMAP - && fringe_id < max_used_fringe_bitmap - && (fringe_id < MAX_STANDARD_FRINGE_BITMAPS - || fringe_bitmaps[fringe_id] != NULL)); + int bn; + + bitmap = Fget (bitmap, Qfringe); + if (!INTEGERP (bitmap)) + return 0; + + bn = XINT (bitmap); + if (bn > NO_FRINGE_BITMAP + && bn < max_used_fringe_bitmap + && (bn < MAX_STANDARD_FRINGE_BITMAPS + || fringe_bitmaps[bn] != NULL)) + return bn; + + return 0; } +/* Get fringe bitmap name for bitmap number BN. + + Found by traversing Vfringe_bitmaps comparing BN to the + fringe property for each symbol. + + Return BN if not found in Vfringe_bitmaps. */ + +static Lisp_Object +get_fringe_bitmap_name (bn) + int bn; +{ + Lisp_Object bitmaps; + Lisp_Object num; + + /* Zero means no bitmap -- return nil. */ + if (bn <= 0) + return Qnil; + + bitmaps = Vfringe_bitmaps; + num = make_number (bn); + + while (CONSP (bitmaps)) + { + Lisp_Object bitmap = XCAR (bitmaps); + if (EQ (num, Fget (bitmap, Qfringe))) + return bitmap; + bitmaps = XCDR (bitmaps); + } + + return num; +} + + /* Draw the bitmap WHICH in one of the left or right fringes of window W. ROW is the glyph row for which to display the bitmap; it determines the vertical position at which the bitmap has to be @@ -460,12 +550,12 @@ valid_fringe_bitmap_id_p (fringe_id) LEFT_P is 1 for left fringe, 0 for right fringe. */ -void +static void draw_fringe_bitmap_1 (w, row, left_p, overlay, which) struct window *w; struct glyph_row *row; int left_p, overlay; - enum fringe_bitmap_type which; + int which; { struct frame *f = XFRAME (WINDOW_FRAME (w)); struct draw_fringe_bitmap_params p; @@ -492,7 +582,14 @@ draw_fringe_bitmap_1 (w, row, left_p, overlay, which) } if (face_id == DEFAULT_FACE_ID) - face_id = fringe_faces[which]; + { + Lisp_Object face; + + if ((face = fringe_faces[which], NILP (face)) + || (face_id = lookup_derived_face (f, face, 'A', FRINGE_FACE_ID, 0), + face_id < 0)) + face_id = FRINGE_FACE_ID; + } fb = fringe_bitmaps[which]; if (fb == NULL) @@ -519,7 +616,8 @@ draw_fringe_bitmap_1 (w, row, left_p, overlay, which) if (p.face == NULL) { - /* Why does this happen? ++kfs */ + /* This could happen after clearing face cache. + But it shouldn't happen anymore. ++kfs */ return; } @@ -592,6 +690,134 @@ draw_fringe_bitmap_1 (w, row, left_p, overlay, which) FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p); } +static int +get_logical_cursor_bitmap (w, cursor) + struct window *w; + Lisp_Object cursor; +{ + Lisp_Object cmap, bm = Qnil; + + if ((cmap = XBUFFER (w->buffer)->fringe_cursor_alist), !NILP (cmap)) + { + bm = Fassq (cursor, cmap); + if (CONSP (bm)) + { + if ((bm = XCDR (bm)), NILP (bm)) + return NO_FRINGE_BITMAP; + return lookup_fringe_bitmap (bm); + } + } + if (EQ (cmap, buffer_defaults.fringe_cursor_alist)) + return NO_FRINGE_BITMAP; + bm = Fassq (cursor, buffer_defaults.fringe_cursor_alist); + if (!CONSP (bm) || ((bm = XCDR (bm)), NILP (bm))) + return NO_FRINGE_BITMAP; + return lookup_fringe_bitmap (bm); +} + +static int +get_logical_fringe_bitmap (w, bitmap, right_p, partial_p) + struct window *w; + Lisp_Object bitmap; + int right_p, partial_p; +{ + Lisp_Object cmap, bm1 = Qnil, bm2 = Qnil, bm; + int ln1 = 0, ln2 = 0; + int ix1 = right_p; + int ix2 = ix1 + (partial_p ? 2 : 0); + + /* Lookup in buffer-local fringe-indicator-alist before global alist. + + Elements are: + BITMAP -- use for all + (L R) -- use for left right (whether partial or not) + (L R PL PR) -- use for left rigth partial-left partial-right + If any value in local binding is not present or t, use global value. + + If partial, lookup partial bitmap in default value if not found here. + If not partial, or no partial spec is present, use non-partial bitmap. */ + + if ((cmap = XBUFFER (w->buffer)->fringe_indicator_alist), !NILP (cmap)) + { + bm1 = Fassq (bitmap, cmap); + if (CONSP (bm1)) + { + if ((bm1 = XCDR (bm1)), NILP (bm1)) + return NO_FRINGE_BITMAP; + if (CONSP (bm1)) + { + ln1 = XINT (Flength (bm1)); + if (partial_p) + { + if (ln1 > ix2) + { + bm = Fnth (make_number (ix2), bm1); + if (!EQ (bm, Qt)) + goto found; + } + } + else + { + if (ln1 > ix1) + { + bm = Fnth (make_number (ix1), bm1); + if (!EQ (bm, Qt)) + goto found; + } + } + } + else if ((bm = bm1, !EQ (bm, Qt))) + goto found; + } + } + + if (!EQ (cmap, buffer_defaults.fringe_indicator_alist) + && !NILP (buffer_defaults.fringe_indicator_alist)) + { + bm2 = Fassq (bitmap, buffer_defaults.fringe_indicator_alist); + if (CONSP (bm2)) + { + if ((bm2 = XCDR (bm2)), !NILP (bm2)) + { + if (CONSP (bm2)) + { + ln2 = XINT (Flength (bm2)); + if (partial_p) + { + if (ln2 > ix2) + { + bm = Fnth (make_number (ix2), bm2); + if (!EQ (bm, Qt)) + goto found; + } + } + } + } + } + } + + if (ln1 > ix1) + { + bm = Fnth (make_number (ix1), bm1); + if (!EQ (bm, Qt)) + goto found; + } + + if (ln2 > ix1) + { + bm = Fnth (make_number (ix1), bm2); + if (!EQ (bm, Qt)) + goto found; + return NO_FRINGE_BITMAP; + } + else if ((bm = bm2, NILP (bm))) + return NO_FRINGE_BITMAP; + + found: + return lookup_fringe_bitmap (bm); +} + + void draw_fringe_bitmap (w, row, left_p) struct window *w; @@ -602,24 +828,24 @@ draw_fringe_bitmap (w, row, left_p) if (!left_p && row->cursor_in_fringe_p) { - int cursor = NO_FRINGE_BITMAP; + Lisp_Object cursor = Qnil; switch (w->phys_cursor_type) { case HOLLOW_BOX_CURSOR: - if (row->visible_height >= STANDARD_BITMAP_HEIGHT (hollow_box_cursor_bits)) - cursor = HOLLOW_BOX_CURSOR_BITMAP; + if (row->visible_height >= STANDARD_BITMAP_HEIGHT (hollow_rectangle_bits)) + cursor = Qhollow; else - cursor = HOLLOW_SQUARE_BITMAP; + cursor = Qhollow_small; break; case FILLED_BOX_CURSOR: - cursor = FILLED_BOX_CURSOR_BITMAP; + cursor = Qbox; break; case BAR_CURSOR: - cursor = BAR_CURSOR_BITMAP; + cursor = Qbar; break; case HBAR_CURSOR: - cursor = HBAR_CURSOR_BITMAP; + cursor = Qhbar; break; case NO_CURSOR: default: @@ -627,20 +853,24 @@ draw_fringe_bitmap (w, row, left_p) row->cursor_in_fringe_p = 0; break; } - if (cursor != NO_FRINGE_BITMAP) + if (!NILP (cursor)) { - draw_fringe_bitmap_1 (w, row, 0, 2, cursor); - overlay = cursor == FILLED_BOX_CURSOR_BITMAP ? 3 : 1; + int bm = get_logical_cursor_bitmap (w, cursor); + if (bm != NO_FRINGE_BITMAP) + { + draw_fringe_bitmap_1 (w, row, 0, 2, bm); + overlay = EQ (cursor, Qbox) ? 3 : 1; + } } } draw_fringe_bitmap_1 (w, row, left_p, overlay, NO_FRINGE_BITMAP); - if (left_p && row->overlay_arrow_p) + if (left_p && row->overlay_arrow_bitmap != NO_FRINGE_BITMAP) draw_fringe_bitmap_1 (w, row, 1, 1, - (w->overlay_arrow_bitmap - ? w->overlay_arrow_bitmap - : OVERLAY_ARROW_BITMAP)); + (row->overlay_arrow_bitmap < 0 + ? get_logical_fringe_bitmap (w, Qoverlay_arrow, 0, 0) + : row->overlay_arrow_bitmap)); } @@ -667,19 +897,35 @@ draw_row_fringe_bitmaps (w, row) } /* Draw the fringes of window W. Only fringes for rows marked for - update in redraw_fringe_bitmaps_p are drawn. */ + update in redraw_fringe_bitmaps_p are drawn. -void -draw_window_fringes (w) + Return >0 if left or right fringe was redrawn in any way. + + If NO_FRINGE is non-zero, also return >0 if either fringe has zero width. + + A return value >0 indicates that the vertical line between windows + needs update (as it may be drawn in the fringe). +*/ + +int +draw_window_fringes (w, no_fringe) struct window *w; + int no_fringe; { struct glyph_row *row; int yb = window_text_bottom_y (w); int nrows = w->current_matrix->nrows; int y = 0, rn; + int updated = 0; if (w->pseudo_window_p) - return; + return 0; + + /* Must draw line if no fringe */ + if (no_fringe + && (WINDOW_LEFT_FRINGE_WIDTH (w) == 0 + || WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)) + updated++; for (y = 0, rn = 0, row = w->current_matrix->rows; y < yb && rn < nrows; @@ -689,27 +935,34 @@ draw_window_fringes (w) continue; draw_row_fringe_bitmaps (w, row); row->redraw_fringe_bitmaps_p = 0; + updated++; } + + return updated; } /* Recalculate the bitmaps to show in the fringes of window W. - If FORCE_P is 0, only mark rows with modified bitmaps for update in - redraw_fringe_bitmaps_p; else mark all rows for update. */ + Only mark rows with modified bitmaps for update in redraw_fringe_bitmaps_p. + + If KEEP_CURRENT_P is 0, update current_matrix too. */ int -update_window_fringes (w, force_p) +update_window_fringes (w, keep_current_p) struct window *w; - int force_p; + int keep_current_p; { struct glyph_row *row, *cur = 0; int yb = window_text_bottom_y (w); int rn, nrows = w->current_matrix->nrows; int y; int redraw_p = 0; - Lisp_Object ind; - int boundary_pos = 0, arrow_pos = 0; - int empty_pos = 0; + Lisp_Object boundary_top = Qnil, boundary_bot = Qnil; + Lisp_Object arrow_top = Qnil, arrow_bot = Qnil; + Lisp_Object empty_pos; + Lisp_Object ind = Qnil; +#define MAX_BITMAP_CACHE (8*4) + int bitmap_cache[MAX_BITMAP_CACHE]; if (w->pseudo_window_p) return 0; @@ -717,23 +970,30 @@ update_window_fringes (w, force_p) if (!MINI_WINDOW_P (w) && (ind = XBUFFER (w->buffer)->indicate_buffer_boundaries, !NILP (ind))) { - int do_eob = 1, do_bob = 1; - Lisp_Object arrows; - - if (CONSP (ind)) - arrows = XCDR (ind), ind = XCAR (ind); + if (EQ (ind, Qleft) || EQ (ind, Qright)) + boundary_top = boundary_bot = arrow_top = arrow_bot = ind; + else if (CONSP (ind) && CONSP (XCAR (ind))) + { + Lisp_Object pos; + if (pos = Fassq (Qt, ind), !NILP (pos)) + boundary_top = boundary_bot = arrow_top = arrow_bot = XCDR (pos); + if (pos = Fassq (Qtop, ind), !NILP (pos)) + boundary_top = XCDR (pos); + if (pos = Fassq (Qbottom, ind), !NILP (pos)) + boundary_bot = XCDR (pos); + if (pos = Fassq (Qup, ind), !NILP (pos)) + arrow_top = XCDR (pos); + if (pos = Fassq (Qdown, ind), !NILP (pos)) + arrow_bot = XCDR (pos); + } else - arrows = ind; - - if (EQ (ind, Qleft)) - boundary_pos = -1; - else if (EQ (ind, Qright)) - boundary_pos = 1; + /* Anything else means boundary on left and no arrows. */ + boundary_top = boundary_bot = Qleft; + } - if (EQ (arrows, Qleft)) - arrow_pos = -1; - else if (EQ (arrows, Qright)) - arrow_pos = 1; + if (!NILP (ind)) + { + int done_top = 0, done_bot = 0; for (y = 0, rn = 0; y < yb && rn < nrows; @@ -754,19 +1014,27 @@ update_window_fringes (w, force_p) row->indicate_bob_p = row->indicate_top_line_p = 0; row->indicate_eob_p = row->indicate_bottom_line_p = 0; - if (!NILP (ind) - && MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer))) - row->indicate_bob_p = do_bob, do_bob = 0; - else if (!NILP (arrows) - && (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0) == rn) - row->indicate_top_line_p = 1; - - if (!NILP (ind) - && MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer))) - row->indicate_eob_p = do_eob, do_eob = 0; - else if (!NILP (arrows) - && y + row->height >= yb) - row->indicate_bottom_line_p = 1; + if (!row->mode_line_p) + { + if (!done_top) + { + if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer)) + && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row)) + row->indicate_bob_p = !NILP (boundary_top); + else + row->indicate_top_line_p = !NILP (arrow_top); + done_top = 1; + } + + if (!done_bot) + { + if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer)) + && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row)) + row->indicate_eob_p = !NILP (boundary_bot), done_bot = 1; + else if (y + row->height >= yb) + row->indicate_bottom_line_p = !NILP (arrow_bot), done_bot = 1; + } + } if (indicate_bob_p != row->indicate_bob_p || indicate_top_line_p != row->indicate_top_line_p @@ -776,16 +1044,31 @@ update_window_fringes (w, force_p) } } - if (EQ (XBUFFER (w->buffer)->indicate_empty_lines, Qright)) - empty_pos = 1; - else if (EQ (XBUFFER (w->buffer)->indicate_empty_lines, Qleft)) - empty_pos = -1; + empty_pos = XBUFFER (w->buffer)->indicate_empty_lines; + if (!NILP (empty_pos) && !EQ (empty_pos, Qright)) + empty_pos = WINDOW_LEFT_FRINGE_WIDTH (w) == 0 ? Qright : Qleft; + + for (y = 0; y < MAX_BITMAP_CACHE; y++) + bitmap_cache[y] = -1; + +#define LEFT_FRINGE(cache, which, partial_p) \ + (bitmap_cache[cache*4+partial_p] >= 0 \ + ? bitmap_cache[cache*4+partial_p] \ + : (bitmap_cache[cache*4+partial_p] = \ + get_logical_fringe_bitmap (w, which, 0, partial_p))) + +#define RIGHT_FRINGE(cache, which, partial_p) \ + (bitmap_cache[cache*4+2+partial_p] >= 0 \ + ? bitmap_cache[cache*4+2+partial_p] \ + : (bitmap_cache[cache*4+2+partial_p] = \ + get_logical_fringe_bitmap (w, which, 1, partial_p))) + for (y = 0, rn = 0; y < yb && rn < nrows; y += row->height, rn++) { - enum fringe_bitmap_type left, right; + int left, right; unsigned left_face_id, right_face_id; row = w->desired_matrix->rows + rn; @@ -803,21 +1086,22 @@ update_window_fringes (w, force_p) left = row->left_user_fringe_bitmap; left_face_id = row->left_user_fringe_face_id; } - else if (row->indicate_bob_p && boundary_pos <= 0) - left = ((row->indicate_eob_p && boundary_pos < 0) - ? LEFT_BRACKET_BITMAP : TOP_LEFT_ANGLE_BITMAP); - else if (row->indicate_eob_p && boundary_pos < 0) - left = BOTTOM_LEFT_ANGLE_BITMAP; else if (row->truncated_on_left_p) - left = LEFT_TRUNCATION_BITMAP; + left = LEFT_FRINGE(0, Qtruncation, 0); + else if (row->indicate_bob_p && EQ (boundary_top, Qleft)) + left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft)) + ? LEFT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p) + : LEFT_FRINGE (2, Qtop, 0)); + else if (row->indicate_eob_p && EQ (boundary_bot, Qleft)) + left = LEFT_FRINGE (3, Qbottom, row->ends_at_zv_p); else if (MATRIX_ROW_CONTINUATION_LINE_P (row)) - left = CONTINUATION_LINE_BITMAP; - else if (row->indicate_empty_line_p && empty_pos <= 0) - left = ZV_LINE_BITMAP; - else if (row->indicate_top_line_p && arrow_pos <= 0) - left = UP_ARROW_BITMAP; - else if (row->indicate_bottom_line_p && arrow_pos < 0) - left = DOWN_ARROW_BITMAP; + left = LEFT_FRINGE (4, Qcontinuation, 0); + else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft)) + left = LEFT_FRINGE (5, Qempty_line, 0); + else if (row->indicate_top_line_p && EQ (arrow_top, Qleft)) + left = LEFT_FRINGE (6, Qup, 0); + else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qleft)) + left = LEFT_FRINGE (7, Qdown, 0); else left = NO_FRINGE_BITMAP; @@ -829,55 +1113,61 @@ update_window_fringes (w, force_p) right = row->right_user_fringe_bitmap; right_face_id = row->right_user_fringe_face_id; } - else if (row->indicate_bob_p && boundary_pos > 0) - right = ((row->indicate_eob_p && boundary_pos >= 0) - ? RIGHT_BRACKET_BITMAP : TOP_RIGHT_ANGLE_BITMAP); - else if (row->indicate_eob_p && boundary_pos >= 0) - right = BOTTOM_RIGHT_ANGLE_BITMAP; else if (row->truncated_on_right_p) - right = RIGHT_TRUNCATION_BITMAP; + right = RIGHT_FRINGE (0, Qtruncation, 0); + else if (row->indicate_bob_p && EQ (boundary_top, Qright)) + right = ((row->indicate_eob_p && EQ (boundary_bot, Qright)) + ? RIGHT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p) + : RIGHT_FRINGE (2, Qtop, 0)); + else if (row->indicate_eob_p && EQ (boundary_bot, Qright)) + right = RIGHT_FRINGE (3, Qbottom, row->ends_at_zv_p); else if (row->continued_p) - right = CONTINUED_LINE_BITMAP; - else if (row->indicate_top_line_p && arrow_pos > 0) - right = UP_ARROW_BITMAP; - else if (row->indicate_bottom_line_p && arrow_pos >= 0) - right = DOWN_ARROW_BITMAP; - else if (row->indicate_empty_line_p - && (empty_pos > 0 - || (WINDOW_LEFT_FRINGE_WIDTH (w) == 0 && empty_pos == 0))) - right = ZV_LINE_BITMAP; + right = RIGHT_FRINGE (4, Qcontinuation, 0); + else if (row->indicate_top_line_p && EQ (arrow_top, Qright)) + right = RIGHT_FRINGE (6, Qup, 0); + else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright)) + right = RIGHT_FRINGE (7, Qdown, 0); + else if (row->indicate_empty_line_p && EQ (empty_pos, Qright)) + right = RIGHT_FRINGE (5, Qempty_line, 0); else right = NO_FRINGE_BITMAP; - if (force_p - || row->y != cur->y + if (row->y != cur->y || row->visible_height != cur->visible_height + || row->ends_at_zv_p != cur->ends_at_zv_p || left != cur->left_fringe_bitmap || right != cur->right_fringe_bitmap || left_face_id != cur->left_fringe_face_id || right_face_id != cur->right_fringe_face_id || cur->redraw_fringe_bitmaps_p) { - redraw_p = row->redraw_fringe_bitmaps_p = cur->redraw_fringe_bitmaps_p = 1; - cur->left_fringe_bitmap = left; - cur->right_fringe_bitmap = right; - cur->left_fringe_face_id = left_face_id; - cur->right_fringe_face_id = right_face_id; + redraw_p = row->redraw_fringe_bitmaps_p = 1; + if (!keep_current_p) + { + cur->redraw_fringe_bitmaps_p = 1; + cur->left_fringe_bitmap = left; + cur->right_fringe_bitmap = right; + cur->left_fringe_face_id = left_face_id; + cur->right_fringe_face_id = right_face_id; + } } - if (row->overlay_arrow_p != cur->overlay_arrow_p) + if (row->overlay_arrow_bitmap != cur->overlay_arrow_bitmap) { redraw_p = row->redraw_fringe_bitmaps_p = cur->redraw_fringe_bitmaps_p = 1; - cur->overlay_arrow_p = row->overlay_arrow_p; + cur->overlay_arrow_bitmap = row->overlay_arrow_bitmap; } row->left_fringe_bitmap = left; row->right_fringe_bitmap = right; row->left_fringe_face_id = left_face_id; row->right_fringe_face_id = right_face_id; + + if (rn > 0 && row->redraw_fringe_bitmaps_p) + row[-1].redraw_fringe_bitmaps_p = cur[-1].redraw_fringe_bitmaps_p = 1; } - return redraw_p; + return redraw_p && !keep_current_p; } @@ -891,11 +1181,7 @@ update_window_fringes (w, force_p) Typically, we add an equal amount (+/- 1 pixel) to each fringe, but a negative width value is taken literally (after negating it). - We never make the fringes narrower than specified. It is planned - to make fringe bitmaps customizable and expandable, and at that - time, the user will typically specify the minimum number of pixels - needed for his bitmaps, so we shouldn't select anything less than - what is specified. + We never make the fringes narrower than specified. */ void @@ -979,28 +1265,24 @@ compute_fringe_widths (f, redraw) redraw_frame (f); } -DEFUN ("destroy-fringe-bitmap", Fdestroy_fringe_bitmap, Sdestroy_fringe_bitmap, - 1, 1, 0, - doc: /* Destroy fringe bitmap WHICH. -If WHICH overrides a standard fringe bitmap, the original bitmap is restored. */) - (which) - Lisp_Object which; + +/* Free resources used by a user-defined bitmap. */ + +void +destroy_fringe_bitmap (n) + int n; { - int n; struct fringe_bitmap **fbp; - CHECK_NUMBER (which); - if (n = XINT (which), n >= max_used_fringe_bitmap) - return Qnil; - - fringe_faces[n] = FRINGE_FACE_ID; + fringe_faces[n] = Qnil; fbp = &fringe_bitmaps[n]; if (*fbp && (*fbp)->dynamic) { /* XXX Is SELECTED_FRAME OK here? */ - if (FRAME_RIF (SELECTED_FRAME ())->destroy_fringe_bitmap) - FRAME_RIF (SELECTED_FRAME ())->destroy_fringe_bitmap (n); + struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ()); + if (rif && rif->destroy_fringe_bitmap) + rif->destroy_fringe_bitmap (n); xfree (*fbp); *fbp = NULL; } @@ -1008,6 +1290,31 @@ If WHICH overrides a standard fringe bitmap, the original bitmap is restored. * while (max_used_fringe_bitmap > MAX_STANDARD_FRINGE_BITMAPS && fringe_bitmaps[max_used_fringe_bitmap - 1] == NULL) max_used_fringe_bitmap--; +} + + +DEFUN ("destroy-fringe-bitmap", Fdestroy_fringe_bitmap, Sdestroy_fringe_bitmap, + 1, 1, 0, + doc: /* Destroy fringe bitmap BITMAP. +If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. */) + (bitmap) + Lisp_Object bitmap; +{ + int n; + + CHECK_SYMBOL (bitmap); + n = lookup_fringe_bitmap (bitmap); + if (!n) + return Qnil; + + destroy_fringe_bitmap (n); + + if (n >= MAX_STANDARD_FRINGE_BITMAPS) + { + Vfringe_bitmaps = Fdelq (bitmap, Vfringe_bitmaps); + /* It would be better to remove the fringe property. */ + Fput (bitmap, Qfringe, Qnil); + } return Qnil; } @@ -1025,7 +1332,7 @@ If WHICH overrides a standard fringe bitmap, the original bitmap is restored. * void init_fringe_bitmap (which, fb, once_p) - enum fringe_bitmap_type which; + int which; struct fringe_bitmap *fb; int once_p; { @@ -1079,11 +1386,13 @@ init_fringe_bitmap (which, fb, once_p) if (!once_p) { - Fdestroy_fringe_bitmap (make_number (which)); - /* XXX Is SELECTED_FRAME OK here? */ - if (FRAME_RIF (SELECTED_FRAME ())->define_fringe_bitmap) - FRAME_RIF (SELECTED_FRAME ())->define_fringe_bitmap (which, fb->bits, fb->height, fb->width); + struct redisplay_interface *rif = FRAME_RIF (SELECTED_FRAME ()); + + destroy_fringe_bitmap (which); + + if (rif && rif->define_fringe_bitmap) + rif->define_fringe_bitmap (which, fb->bits, fb->height, fb->width); fringe_bitmaps[which] = fb; if (which >= max_used_fringe_bitmap) @@ -1093,41 +1402,43 @@ init_fringe_bitmap (which, fb, once_p) DEFUN ("define-fringe-bitmap", Fdefine_fringe_bitmap, Sdefine_fringe_bitmap, - 1, 5, 0, - doc: /* Define a fringe bitmap from BITS of height HEIGHT and width WIDTH. + 2, 5, 0, + doc: /* Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH. +BITMAP is a symbol or string naming the new fringe bitmap. BITS is either a string or a vector of integers. HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS. WIDTH must be an integer between 1 and 16, or nil which defaults to 8. -Optional fourth arg ALIGN may be one of `top', `center', or `bottom', +Optional fifth arg ALIGN may be one of `top', `center', or `bottom', indicating the positioning of the bitmap relative to the rows where it is used; the default is to center the bitmap. Fourth arg may also be a list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap should be repeated. -Optional fifth argument WHICH is bitmap number to redefine. -Return new bitmap number, or nil of no more free bitmap slots. */) - (bits, height, width, align, which) - Lisp_Object bits, height, width, align, which; +If BITMAP already exists, the existing definition is replaced. */) + (bitmap, bits, height, width, align) + Lisp_Object bitmap, bits, height, width, align; { - Lisp_Object len; int n, h, i, j; unsigned short *b; struct fringe_bitmap fb, *xfb; int fill1 = 0, fill2 = 0; - if (!STRINGP (bits) && !VECTORP (bits)) - bits = wrong_type_argument (Qstringp, bits); + CHECK_SYMBOL (bitmap); - len = Flength (bits); + if (STRINGP (bits)) + h = SCHARS (bits); + else if (VECTORP (bits)) + h = XVECTOR (bits)->size; + else + bits = wrong_type_argument (Qsequencep, bits); if (NILP (height)) - h = fb.height = XINT (len); + fb.height = h; else { CHECK_NUMBER (height); fb.height = min (XINT (height), 255); - if (fb.height > XINT (len)) + if (fb.height > h) { - h = XINT (len); fill1 = (fb.height - h) / 2; fill2 = fb.height - h - fill1; } @@ -1165,28 +1476,42 @@ Return new bitmap number, or nil of no more free bitmap slots. */) else if (!NILP (align) && !EQ (align, Qcenter)) error ("Bad align argument"); - if (NILP (which)) + n = lookup_fringe_bitmap (bitmap); + if (!n) { - if (max_used_fringe_bitmap < MAX_FRINGE_BITMAPS) + if (max_used_fringe_bitmap < max_fringe_bitmaps) n = max_used_fringe_bitmap++; else { for (n = MAX_STANDARD_FRINGE_BITMAPS; - n < MAX_FRINGE_BITMAPS; + n < max_fringe_bitmaps; n++) if (fringe_bitmaps[n] == NULL) break; - if (n == MAX_FRINGE_BITMAPS) - return Qnil; + + if (n == max_fringe_bitmaps) + { + if ((max_fringe_bitmaps + 20) > MAX_FRINGE_BITMAPS) + error ("No free fringe bitmap slots"); + + i = max_fringe_bitmaps; + max_fringe_bitmaps += 20; + fringe_bitmaps + = ((struct fringe_bitmap **) + xrealloc (fringe_bitmaps, max_fringe_bitmaps * sizeof (struct fringe_bitmap *))); + fringe_faces + = (Lisp_Object *) xrealloc (fringe_faces, max_fringe_bitmaps * sizeof (Lisp_Object)); + + for (; i < max_fringe_bitmaps; i++) + { + fringe_bitmaps[i] = NULL; + fringe_faces[i] = Qnil; + } + } } - which = make_number (n); - } - else - { - CHECK_NUMBER (which); - n = XINT (which); - if (n <= NO_FRINGE_BITMAP || n >= MAX_FRINGE_BITMAPS) - error ("Invalid fringe bitmap number"); + + Vfringe_bitmaps = Fcons (bitmap, Vfringe_bitmaps); + Fput (bitmap, Qfringe, make_number (n)); } fb.dynamic = 1; @@ -1214,32 +1539,33 @@ Return new bitmap number, or nil of no more free bitmap slots. */) init_fringe_bitmap (n, xfb, 0); - return which; + return bitmap; } DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face, Sset_fringe_bitmap_face, 1, 2, 0, - doc: /* Set face for fringe bitmap FRINGE-ID to FACE. + doc: /* Set face for fringe bitmap BITMAP to FACE. If FACE is nil, reset face to default fringe face. */) - (fringe_id, face) - Lisp_Object fringe_id, face; + (bitmap, face) + Lisp_Object bitmap, face; { + int n; int face_id; - CHECK_NUMBER (fringe_id); - if (!valid_fringe_bitmap_id_p (XINT (fringe_id))) - error ("Invalid fringe id"); + CHECK_SYMBOL (bitmap); + n = lookup_fringe_bitmap (bitmap); + if (!n) + error ("Undefined fringe bitmap"); if (!NILP (face)) { - face_id = lookup_named_face (SELECTED_FRAME (), face, 'A'); + face_id = lookup_derived_face (SELECTED_FRAME (), face, + 'A', FRINGE_FACE_ID, 1); if (face_id < 0) error ("No such face"); } - else - face_id = FRINGE_FACE_ID; - fringe_faces [XINT (fringe_id)] = face_id; + fringe_faces[n] = face; return Qnil; } @@ -1248,9 +1574,11 @@ DEFUN ("fringe-bitmaps-at-pos", Ffringe_bitmaps_at_pos, Sfringe_bitmaps_at_pos, 0, 2, 0, doc: /* Return fringe bitmaps of row containing position POS in window WINDOW. If WINDOW is nil, use selected window. If POS is nil, use value of point -in that window. Return value is a cons (LEFT . RIGHT) where LEFT and RIGHT -are the fringe bitmap numbers for the bitmaps in the left and right fringe, -resp. Return nil if POS is not visible in WINDOW. */) +in that window. Return value is a list (LEFT RIGHT OV), where LEFT +is the symbol for the bitmap in the left fringe (or nil if no bitmap), +RIGHT is similar for the right fringe, and OV is non-nil if there is an +overlay arrow in the left fringe. +Return nil if POS is not visible in WINDOW. */) (pos, window) Lisp_Object pos, window; { @@ -1276,8 +1604,11 @@ resp. Return nil if POS is not visible in WINDOW. */) row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); row = row_containing_pos (w, textpos, row, NULL, 0); if (row) - return Fcons (make_number (row->left_fringe_bitmap), - make_number (row->right_fringe_bitmap)); + return list3 (get_fringe_bitmap_name (row->left_fringe_bitmap), + get_fringe_bitmap_name (row->right_fringe_bitmap), + (row->overlay_arrow_bitmap == 0 ? Qnil + : row->overlay_arrow_bitmap < 0 ? Qt + : get_fringe_bitmap_name (row->overlay_arrow_bitmap))); else return Qnil; } @@ -1290,6 +1621,18 @@ resp. Return nil if POS is not visible in WINDOW. */) void syms_of_fringe () { + Qtruncation = intern ("truncation"); + staticpro (&Qtruncation); + Qcontinuation = intern ("continuation"); + staticpro (&Qcontinuation); + Qoverlay_arrow = intern ("overlay-arrow"); + staticpro (&Qoverlay_arrow); + Qempty_line = intern ("empty-line"); + staticpro (&Qempty_line); + Qtop_bottom = intern ("top-bottom"); + staticpro (&Qtop_bottom); + Qhollow_small = intern ("hollow-small"); + staticpro (&Qhollow_small); defsubr (&Sdestroy_fringe_bitmap); defsubr (&Sdefine_fringe_bitmap); @@ -1305,6 +1648,21 @@ is at the final newline, the cursor is shown in the right fringe. If nil, also continue lines which are exactly as wide as the window. */); Voverflow_newline_into_fringe = Qt; + DEFVAR_LISP ("fringe-bitmaps", &Vfringe_bitmaps, + doc: /* List of fringe bitmap symbols. */); + Vfringe_bitmaps = Qnil; +} + +/* Garbage collection hook */ + +void +mark_fringe_data () +{ + int i; + + for (i = 0; i < max_fringe_bitmaps; i++) + if (!NILP (fringe_faces[i])) + mark_object (fringe_faces[i]); } /* Initialize this module when Emacs starts. */ @@ -1312,7 +1670,7 @@ If nil, also continue lines which are exactly as wide as the window. */); void init_fringe_once () { - enum fringe_bitmap_type bt; + int bt; for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++) init_fringe_bitmap(bt, &standard_bitmaps[bt], 1); @@ -1323,9 +1681,18 @@ init_fringe () { int i; - bzero (fringe_bitmaps, sizeof fringe_bitmaps); - for (i = 0; i < MAX_FRINGE_BITMAPS; i++) - fringe_faces[i] = FRINGE_FACE_ID; + max_fringe_bitmaps = MAX_STANDARD_FRINGE_BITMAPS + 20; + + fringe_bitmaps + = (struct fringe_bitmap **) xmalloc (max_fringe_bitmaps * sizeof (struct fringe_bitmap *)); + fringe_faces + = (Lisp_Object *) xmalloc (max_fringe_bitmaps * sizeof (Lisp_Object)); + + for (i = 0; i < max_fringe_bitmaps; i++) + { + fringe_bitmaps[i] = NULL; + fringe_faces[i] = Qnil; + } } #ifdef HAVE_NTGUI @@ -1333,7 +1700,10 @@ init_fringe () void w32_init_fringe () { - enum fringe_bitmap_type bt; + int bt; + + if (!rif) + return; for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++) { @@ -1348,6 +1718,9 @@ w32_reset_fringes () /* Destroy row bitmaps. */ int bt; + if (!rif) + return; + for (bt = NO_FRINGE_BITMAP + 1; bt < max_used_fringe_bitmap; bt++) rif->destroy_fringe_bitmap (bt); }