/* 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>
#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.
+
+ 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;
enum fringe_bitmap_type
{
{ 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_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
}
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)
- draw_fringe_bitmap_1 (w, row, 1, 1, OVERLAY_ARROW_BITMAP);
+ if (left_p && row->overlay_arrow_bitmap != NO_FRINGE_BITMAP)
+ draw_fringe_bitmap_1 (w, row, 1, 1,
+ (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);
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;
if (w->pseudo_window_p)
return 0;
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;
{
unsigned indicate_bob_p, indicate_top_line_p;
unsigned indicate_eob_p, indicate_bottom_line_p;
-
+
row = w->desired_matrix->rows + rn;
if (!row->enabled_p)
row = w->current_matrix->rows + rn;
indicate_top_line_p = row->indicate_top_line_p;
indicate_eob_p = row->indicate_eob_p;
indicate_bottom_line_p = row->indicate_bottom_line_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
}
}
- 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, rn = 0;
y < yb && rn < nrows;
left = row->left_user_fringe_bitmap;
left_face_id = row->left_user_fringe_face_id;
}
-#if 0 /* this is now done via an overlay */
- else if (row->overlay_arrow_p)
- left = OVERLAY_ARROW_BITMAP;
-#endif
- 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;
+ 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 (MATRIX_ROW_CONTINUATION_LINE_P (row))
left = CONTINUATION_LINE_BITMAP;
- else if (row->indicate_empty_line_p && empty_pos <= 0)
+ else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft))
left = ZV_LINE_BITMAP;
- else if (row->indicate_top_line_p && arrow_pos <= 0)
+ else if (row->indicate_top_line_p && EQ (arrow_top, Qleft))
left = UP_ARROW_BITMAP;
- else if (row->indicate_bottom_line_p && arrow_pos < 0)
+ else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qleft))
left = DOWN_ARROW_BITMAP;
else
left = NO_FRINGE_BITMAP;
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;
+ 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->continued_p)
right = CONTINUED_LINE_BITMAP;
- else if (row->indicate_top_line_p && arrow_pos > 0)
+ else if (row->indicate_top_line_p && EQ (arrow_top, Qright))
right = UP_ARROW_BITMAP;
- else if (row->indicate_bottom_line_p && arrow_pos >= 0)
+ else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright))
right = DOWN_ARROW_BITMAP;
- else if (row->indicate_empty_line_p
- && (empty_pos > 0
- || (WINDOW_LEFT_FRINGE_WIDTH (w) == 0 && empty_pos == 0)))
+ else if (row->indicate_empty_line_p && EQ (empty_pos, Qright))
right = ZV_LINE_BITMAP;
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;
}
-/* Compute actual fringe widths for frame F.
+/* Compute actual fringe widths for frame F.
If REDRAW is 1, redraw F if the fringe settings was actually
modified and F is visible.
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
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)
{
- if (rif->destroy_fringe_bitmap)
+ if (rif && rif->destroy_fringe_bitmap)
rif->destroy_fringe_bitmap (n);
xfree (*fbp);
*fbp = NULL;
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;
}
On X, we bit-swap the built-in bitmaps and reduce bitmap
from short to char array if width is <= 8 bits.
- On W32 and MAC, there's no need to do this.
+ On MAC with big-endian CPU, we need to byte-swap each short.
+
+ On W32 and MAC (little endian), there's no need to do this.
*/
void
= { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
- 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
+ 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
unsigned short *bits = fb->bits;
int j;
*bits++ = (b >> (16 - fb->width));
}
}
-#endif
+#endif /* HAVE_X_WINDOWS */
+
+#if defined (MAC_OS) && defined (WORDS_BIG_ENDIAN)
+ unsigned short *bits = fb->bits;
+ int j;
+ for (j = 0; j < fb->height; j++)
+ {
+ unsigned short b = *bits;
+ *bits++ = ((b >> 8) & 0xff) | ((b & 0xff) << 8);
+ }
+#endif /* MAC_OS && WORDS_BIG_ENDIAN */
}
if (!once_p)
{
- Fdestroy_fringe_bitmap (make_number (which));
+ destroy_fringe_bitmap (which);
- if (rif->define_fringe_bitmap)
+ if (rif && rif->define_fringe_bitmap)
rif->define_fringe_bitmap (which, fb->bits, fb->height, fb->width);
fringe_bitmaps[which] = fb;
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 forth 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;
}
}
-
+
if (NILP (width))
fb.width = 8;
else
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)
- n = make_number (max_used_fringe_bitmap++);
+ 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;
- xfb = (struct fringe_bitmap *)xmalloc (sizeof fb
- + fb.height * BYTES_PER_BITMAP_ROW);
- fb.bits = b = (unsigned short *)(xfb+1);
+ xfb = (struct fringe_bitmap *) xmalloc (sizeof fb
+ + fb.height * BYTES_PER_BITMAP_ROW);
+ fb.bits = b = (unsigned short *) (xfb + 1);
bzero (b, fb.height);
j = 0;
{
for (i = 0; i < fill1 && j < fb.height; i++)
b[j++] = 0;
- for (i = 0; i < h & j < fb.height; i++)
+ for (i = 0; i < h && j < fb.height; i++)
{
Lisp_Object elt = Faref (bits, make_number (i));
b[j++] = NUMBERP (elt) ? XINT (elt) : 0;
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;
}
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.
+ 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;
{
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 (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;
}
void
syms_of_fringe ()
{
-
defsubr (&Sdestroy_fringe_bitmap);
defsubr (&Sdefine_fringe_bitmap);
defsubr (&Sfringe_bitmaps_at_pos);
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.
+You must (require 'fringe) to use fringe bitmap symbols in your programs." */);
+ 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. */
{
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
{
enum fringe_bitmap_type bt;
+ if (!rif)
+ return;
+
for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
{
struct fringe_bitmap *fb = &standard_bitmaps[bt];
{
/* 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);
}
-#endif
+#endif /* HAVE_NTGUI */
#endif /* HAVE_WINDOW_SYSTEM */