/* 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 Free Software Foundation, Inc.
This file is part of GNU Emacs.
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 <config.h>
#include <stdio.h>
{ FRBITS (zv_bits), 8, 3, ALIGN_BITMAP_TOP, 0 },
};
-static struct fringe_bitmap *fringe_bitmaps[MAX_FRINGE_BITMAPS];
-static unsigned fringe_faces[MAX_FRINGE_BITMAPS];
+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_p (bitmap)
+lookup_fringe_bitmap (bitmap)
Lisp_Object bitmap;
{
int bn;
+ bitmap = Fget (bitmap, Qfringe);
if (!INTEGERP (bitmap))
return 0;
bn = XINT (bitmap);
- return (bn >= NO_FRINGE_BITMAP
- && bn < max_used_fringe_bitmap
- && (bn < MAX_STANDARD_FRINGE_BITMAPS
- || fringe_bitmaps[bn] != NULL));
+ 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.
}
-/* Resolve a BITMAP parameter.
-
- An INTEGER, corresponding to a bitmap number.
- A STRING which is interned to a symbol.
- A SYMBOL which has a fringe property which is a bitmap number.
-*/
-
-static int
-resolve_fringe_bitmap (bitmap, namep)
- Lisp_Object bitmap;
- Lisp_Object *namep;
-{
- if (namep)
- *namep = Qnil;
-
- if (STRINGP (bitmap))
- bitmap = intern (SDATA (bitmap));
-
- if (SYMBOLP (bitmap))
- {
- if (namep)
- *namep = bitmap;
- bitmap = Fget (bitmap, Qfringe);
- }
-
- if (valid_fringe_bitmap_p (bitmap))
- {
- if (namep && NILP (*namep))
- *namep = get_fringe_bitmap_name (XINT (bitmap));
- return XINT (bitmap);
- }
-
- return -1;
-}
-
-
/* 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
}
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)
if (p.face == NULL)
{
- /* Why does this happen? ++kfs */
+ /* This could happen after clearing face cache.
+ But it shouldn't happen anymore. ++kfs */
return;
}
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
+ ? OVERLAY_ARROW_BITMAP
+ : row->overlay_arrow_bitmap));
}
}
/* 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;
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);
arrow_bot = XCDR (pos);
}
else
- ind = Qnil;
+ /* Anything else means boundary on left and no arrows. */
+ boundary_top = boundary_bot = Qleft;
}
if (!NILP (ind))
{
- int do_eob = 1, do_bob = 1;
+ int done_top = 0, done_bot = 0;
for (y = 0, rn = 0;
y < yb && rn < nrows;
row->indicate_bob_p = row->indicate_top_line_p = 0;
row->indicate_eob_p = row->indicate_bottom_line_p = 0;
- if (!NILP (boundary_top)
- && MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer)))
- row->indicate_bob_p = do_bob, do_bob = 0;
- else if (!NILP (arrow_top)
- && (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0) == rn)
- row->indicate_top_line_p = 1;
-
- if (!NILP (boundary_bot)
- && MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer)))
- row->indicate_eob_p = do_eob, do_eob = 0;
- else if (!NILP (arrow_bot)
- && 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 (row->ends_at_zv_p
+ && !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
left = row->left_user_fringe_bitmap;
left_face_id = row->left_user_fringe_face_id;
}
+ else if (row->truncated_on_left_p)
+ left = LEFT_TRUNCATION_BITMAP;
else if (row->indicate_bob_p && EQ (boundary_top, Qleft))
left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
? LEFT_BRACKET_BITMAP : TOP_LEFT_ANGLE_BITMAP);
else if (row->indicate_eob_p && EQ (boundary_bot, Qleft))
left = BOTTOM_LEFT_ANGLE_BITMAP;
- else if (row->truncated_on_left_p)
- left = LEFT_TRUNCATION_BITMAP;
else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
left = CONTINUATION_LINE_BITMAP;
else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft))
right = row->right_user_fringe_bitmap;
right_face_id = row->right_user_fringe_face_id;
}
+ else if (row->truncated_on_right_p)
+ right = RIGHT_TRUNCATION_BITMAP;
else if (row->indicate_bob_p && EQ (boundary_top, Qright))
right = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
? RIGHT_BRACKET_BITMAP : TOP_RIGHT_ANGLE_BITMAP);
else if (row->indicate_eob_p && EQ (boundary_bot, Qright))
right = BOTTOM_RIGHT_ANGLE_BITMAP;
- else if (row->truncated_on_right_p)
- right = RIGHT_TRUNCATION_BITMAP;
else if (row->continued_p)
right = CONTINUED_LINE_BITMAP;
else if (row->indicate_top_line_p && EQ (arrow_top, Qright))
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;
}
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
}
+/* Free resources used by a user-defined bitmap. */
+
void
destroy_fringe_bitmap (n)
int n;
{
struct fringe_bitmap **fbp;
- fringe_faces[n] = FRINGE_FACE_ID;
+ fringe_faces[n] = Qnil;
fbp = &fringe_bitmaps[n];
if (*fbp && (*fbp)->dynamic)
Lisp_Object bitmap;
{
int n;
- Lisp_Object sym;
- n = resolve_fringe_bitmap (bitmap, &sym);
- if (n < 0)
+ CHECK_SYMBOL (bitmap);
+ n = lookup_fringe_bitmap (bitmap);
+ if (!n)
return Qnil;
destroy_fringe_bitmap (n);
- if (SYMBOLP (sym))
+ if (n >= MAX_STANDARD_FRINGE_BITMAPS)
{
- Vfringe_bitmaps = Fdelq (sym, Vfringe_bitmaps);
+ Vfringe_bitmaps = Fdelq (bitmap, Vfringe_bitmaps);
/* It would be better to remove the fringe property. */
- Fput (sym, Qfringe, Qnil);
+ Fput (bitmap, Qfringe, Qnil);
}
+
return Qnil;
}
(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;
- Lisp_Object sym;
-
- n = resolve_fringe_bitmap (bitmap, &sym);
- if (NILP (sym) || INTEGERP (sym))
- sym = wrong_type_argument (Qsymbolp, bitmap);
+ CHECK_SYMBOL (bitmap);
- if (!STRINGP (bits) && !VECTORP (bits))
- bits = wrong_type_argument (Qstringp, bits);
-
- 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;
}
else if (!NILP (align) && !EQ (align, Qcenter))
error ("Bad align argument");
- if (n < 0)
+ 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)
- error ("Cannot define more fringe bitmaps");
+
+ 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;
+ }
+ }
}
- Vfringe_bitmaps = Fcons (sym, Vfringe_bitmaps);
- Fput (sym, Qfringe, make_number (n));
+ Vfringe_bitmaps = Fcons (bitmap, Vfringe_bitmaps);
+ Fput (bitmap, Qfringe, make_number (n));
}
fb.dynamic = 1;
init_fringe_bitmap (n, xfb, 0);
- return sym;
+ return bitmap;
}
DEFUN ("set-fringe-bitmap-face", Fset_fringe_bitmap_face, Sset_fringe_bitmap_face,
(bitmap, face)
Lisp_Object bitmap, face;
{
- int bn;
+ int n;
int face_id;
- bn = resolve_fringe_bitmap (bitmap, 0);
- if (bn < 0)
+ 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 [bn] = face_id;
+ fringe_faces[n] = face;
return Qnil;
}
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. If left or right fringe is empty, the corresponding element is nil.
+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;
{
struct window *w;
- struct buffer *old_buffer = NULL;
struct glyph_row *row;
int textpos;
row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
row = row_containing_pos (w, textpos, row, NULL, 0);
if (row)
- return Fcons (get_fringe_bitmap_name (row->left_fringe_bitmap),
- get_fringe_bitmap_name (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;
}
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. */
void
{
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