#endif
#ifdef MAC_OS
#include "macterm.h"
-
-Cursor No_Cursor;
#endif
#ifndef FRAME_X_OUTPUT
extern int interrupt_input;
extern int command_loop_level;
+extern Lisp_Object do_mouse_tracking;
+
extern int minibuffer_auto_raise;
extern Lisp_Object Vminibuffer_list;
int auto_raise_tool_bar_buttons_p;
+/* Non-zero means to reposition window if cursor line is only partially visible. */
+
+int make_cursor_line_fully_visible_p;
+
/* Margin around tool bar buttons in pixels. */
Lisp_Object Vtool_bar_button_margin;
Lisp_Object Vdisplay_pixels_per_inch;
Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
+Lisp_Object Qslice;
+Lisp_Object Qcenter;
Lisp_Object Qmargin, Qpointer;
+Lisp_Object Qline_height, Qtotal;
extern Lisp_Object Qheight;
extern Lisp_Object QCwidth, QCheight, QCascent;
extern Lisp_Object Qscroll_bar;
+extern Lisp_Object Qcursor;
/* Non-nil means highlight trailing whitespace. */
extern Lisp_Object Voverflow_newline_into_fringe;
/* Test if overflow newline into fringe. Called with iterator IT
- at or past right window margin, and with IT->current_x set. */
+ at or past right window margin, and with IT->current_x set. */
#define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) \
(!NILP (Voverflow_newline_into_fringe) \
/* List of variables (symbols) which hold markers for overlay arrows.
The symbols on this list are examined during redisplay to determine
- where to display overlay arrows. */
+ where to display overlay arrows. */
Lisp_Object Voverlay_arrow_variable_list;
/* How much to scroll horizontally when point is inside the above margin. */
Lisp_Object Vhscroll_step;
-/* A list of symbols, one for each supported image type. */
-
-Lisp_Object Vimage_types;
-
/* The variable `resize-mini-windows'. If nil, don't resize
mini-windows. If t, always resize them to fit the text they
display. If `grow-only', let mini-windows grow only until they
Lisp_Object previous_help_echo_string;
+/* Null glyph slice */
+
+static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
\f
/* Function prototypes. */
static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *,
Lisp_Object));
static void extend_face_to_end_of_line P_ ((struct it *));
-static int append_space P_ ((struct it *, int));
-static int make_cursor_line_fully_visible P_ ((struct window *));
+static int append_space_for_newline P_ ((struct it *, int));
+static int make_cursor_line_fully_visible P_ ((struct window *, int));
static int try_scrolling P_ ((Lisp_Object, int, EMACS_INT, EMACS_INT, int, int));
static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *));
static int trailing_whitespace_p P_ ((int));
static void reseat P_ ((struct it *, struct text_pos, int));
static void reseat_1 P_ ((struct it *, struct text_pos, int));
static void back_to_previous_visible_line_start P_ ((struct it *));
-static void reseat_at_previous_visible_line_start P_ ((struct it *));
+void reseat_at_previous_visible_line_start P_ ((struct it *));
static void reseat_at_next_visible_line_start P_ ((struct it *, int));
static int next_element_from_display_vector P_ ((struct it *));
static int next_element_from_string P_ ((struct it *));
and header-lines heights. */
int
-pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
+pos_visible_p (w, charpos, fully, x, y, exact_mode_line_heights_p)
struct window *w;
- int charpos, *fully, exact_mode_line_heights_p;
+ int charpos, *fully, *x, *y, exact_mode_line_heights_p;
{
struct it it;
struct text_pos top;
visible_p = 1;
*fully = bottom_y <= it.last_visible_y;
}
+ if (visible_p && x)
+ {
+ *x = it.current_x;
+ *y = max (top_y + it.max_ascent - it.ascent, window_top_y);
+ }
}
else if (it.current_y + it.max_ascent + it.max_descent > it.last_visible_y)
{
+ struct it it2;
+
+ it2 = it;
move_it_by_lines (&it, 1, 0);
if (charpos < IT_CHARPOS (it))
{
visible_p = 1;
- *fully = 0;
+ if (x)
+ {
+ move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
+ *x = it2.current_x;
+ *y = it2.current_y + it2.max_ascent - it2.ascent;
+ }
}
}
set_buffer_internal_1 (old_buffer);
current_header_line_height = current_mode_line_height = -1;
+
return visible_p;
}
/* If drawing a tool-bar window, draw it over the internal border
at the top of the window. */
- if (s->w == XWINDOW (s->f->tool_bar_window))
+ if (WINDOWP (s->f->tool_bar_window)
+ && s->w == XWINDOW (s->f->tool_bar_window))
r.y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
}
height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
if (height < r.height)
{
- r.y = s->ybase + glyph->descent - height;
- r.height = height;
+ int max_y = r.y + r.height;
+ r.y = min (max_y, s->ybase + glyph->descent - height);
+ r.height = min (max_y - r.y, height);
}
}
{
if (NATNUMP (current_buffer->extra_line_spacing))
it->extra_line_spacing = XFASTINT (current_buffer->extra_line_spacing);
+ else if (FLOATP (current_buffer->extra_line_spacing))
+ it->extra_line_spacing = (XFLOAT_DATA (current_buffer->extra_line_spacing)
+ * FRAME_LINE_HEIGHT (it->f));
else if (it->f->extra_line_spacing > 0)
it->extra_line_spacing = it->f->extra_line_spacing;
+ it->max_extra_line_spacing = 0;
}
/* If realized faces have been removed, e.g. because of face
if (FRAME_FACE_CACHE (it->f)->used == 0)
recompute_basic_faces (it->f);
- /* Current value of the `space-width', and 'height' properties. */
+ /* Current value of the `slice', `space-width', and 'height' properties. */
+ it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
it->space_width = Qnil;
it->font_height = Qnil;
+ it->override_ascent = -1;
/* Are control characters displayed as `^C'? */
it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow);
int noverlays;
int endpos;
Lisp_Object *overlays;
- int len;
int i;
/* Get all overlays at the given position. */
- len = 10;
- overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
- noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
- if (noverlays > len)
- {
- len = noverlays;
- overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
- noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
- }
+ GET_OVERLAYS_AT (pos, overlays, noverlays, &endpos, 1);
/* If any of these overlays ends before endpos,
use its ending point instead. */
}
/* Reset those iterator values set from display property values. */
- it->font_height = Qnil;
+ it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
it->space_width = Qnil;
+ it->font_height = Qnil;
it->voffset = 0;
/* We don't support recursive `display' properties, i.e. string
&& !EQ (XCAR (prop), Qimage)
&& !EQ (XCAR (prop), Qspace)
&& !EQ (XCAR (prop), Qwhen)
+ && !EQ (XCAR (prop), Qslice)
&& !EQ (XCAR (prop), Qspace_width)
&& !EQ (XCAR (prop), Qheight)
&& !EQ (XCAR (prop), Qraise)
if (NUMBERP (value) && XFLOATINT (value) > 0)
it->space_width = value;
}
+ else if (CONSP (prop)
+ && EQ (XCAR (prop), Qslice))
+ {
+ /* `(slice X Y WIDTH HEIGHT)'. */
+ Lisp_Object tem;
+
+ if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+ return 0;
+
+ if (tem = XCDR (prop), CONSP (tem))
+ {
+ it->slice.x = XCAR (tem);
+ if (tem = XCDR (tem), CONSP (tem))
+ {
+ it->slice.y = XCAR (tem);
+ if (tem = XCDR (tem), CONSP (tem))
+ {
+ it->slice.width = XCAR (tem);
+ if (tem = XCDR (tem), CONSP (tem))
+ it->slice.height = XCAR (tem);
+ }
+ }
+ }
+ }
else if (CONSP (prop)
&& EQ (XCAR (prop), Qraise)
&& CONSP (XCDR (prop)))
&& CONSP (XCDR (prop)))
{
unsigned face_id = DEFAULT_FACE_ID;
+ int fringe_bitmap;
/* Save current settings of IT so that we can restore them
when we are finished with the glyph property value. */
#ifdef HAVE_WINDOW_SYSTEM
value = XCAR (XCDR (prop));
- if (!NUMBERP (value)
- || !valid_fringe_bitmap_id_p (XINT (value)))
+ if (!SYMBOLP (value)
+ || !(fringe_bitmap = lookup_fringe_bitmap (value)))
return 0;
if (CONSP (XCDR (XCDR (prop))))
if (EQ (XCAR (prop), Qleft_fringe))
{
- it->left_user_fringe_bitmap = XINT (value);
+ it->left_user_fringe_bitmap = fringe_bitmap;
it->left_user_fringe_face_id = face_id;
}
else
{
- it->right_user_fringe_bitmap = XINT (value);
+ it->right_user_fringe_bitmap = fringe_bitmap;
it->right_user_fringe_face_id = face_id;
}
#endif /* HAVE_WINDOW_SYSTEM */
value = prop;
}
+ valid_p = (STRINGP (value)
#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_TERMCAP_P (it->f))
- valid_p = STRINGP (value);
- else
- valid_p = (STRINGP (value)
- || (CONSP (value) && EQ (XCAR (value), Qspace))
- || valid_image_p (value));
-#else /* not HAVE_WINDOW_SYSTEM */
- valid_p = STRINGP (value);
+ || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value))
#endif /* not HAVE_WINDOW_SYSTEM */
+ || (CONSP (value) && EQ (XCAR (value), Qspace)));
if ((EQ (location, Qleft_margin)
|| EQ (location, Qright_margin)
p->string_nchars = it->string_nchars;
p->area = it->area;
p->multibyte_p = it->multibyte_p;
+ p->slice = it->slice;
p->space_width = it->space_width;
p->font_height = it->font_height;
p->voffset = it->voffset;
it->string_nchars = p->string_nchars;
it->area = p->area;
it->multibyte_p = p->multibyte_p;
+ it->slice = p->slice;
it->space_width = p->space_width;
it->font_height = p->font_height;
it->voffset = p->voffset;
{
Lisp_Object prop;
- prop = Fget_char_property (make_number (IT_CHARPOS (*it)),
+ /* Check the newline before point for invisibility. */
+ prop = Fget_char_property (make_number (IT_CHARPOS (*it) - 1),
Qinvisible, it->window);
if (TEXT_PROP_MEANS_INVISIBLE (prop))
visible_p = 0;
}
+ if (visible_p)
+ {
+ struct it it2 = *it;
+
+ if (handle_display_prop (&it2) == HANDLED_RETURN)
+ visible_p = 0;
+ }
+
/* Back one more newline if the current one is invisible. */
if (!visible_p)
back_to_previous_line_start (it);
selective display. At the end, update IT's overlay information,
face information etc. */
-static void
+void
reseat_at_previous_visible_line_start (it)
struct it *it;
{
translated to octal form. */
else if ((it->c < ' '
&& (it->area != TEXT_AREA
+ /* In mode line, treat \n like other crl chars. */
+ || (it->c != '\n'
+ && it->glyph_row && it->glyph_row->mode_line_p)
|| (it->c != '\n' && it->c != '\t')))
|| (it->multibyte_p
? ((it->c >= 127
&& it->len == 1)
|| !CHAR_PRINTABLE_P (it->c))
: (it->c >= 127
- && it->c == unibyte_char_to_multibyte (it->c))))
+ && (!unibyte_display_via_language_environment
+ || it->c == unibyte_char_to_multibyte (it->c)))))
{
/* IT->c is a control character which must be displayed
either as '\003' or as `^C' where the '\\' and '^'
saved_glyph_row = it->glyph_row;
it->glyph_row = NULL;
+#define BUFFER_POS_REACHED_P() \
+ ((op & MOVE_TO_POS) != 0 \
+ && BUFFERP (it->object) \
+ && IT_CHARPOS (*it) >= to_charpos)
+
while (1)
{
int x, i, ascent = 0, descent = 0;
- /* Stop when ZV or TO_CHARPOS reached. */
+ /* Stop when ZV reached.
+ We used to stop here when TO_CHARPOS reached as well, but that is
+ too soon if this glyph does not fit on this line. So we handle it
+ explicitly below. */
if (!get_next_display_element (it)
- || ((op & MOVE_TO_POS) != 0
- && BUFFERP (it->object)
- && IT_CHARPOS (*it) >= to_charpos))
+ || (it->truncate_lines_p
+ && BUFFER_POS_REACHED_P ()))
{
result = MOVE_POS_MATCH_OR_ZV;
break;
/* We want to leave anything reaching TO_X to the caller. */
if ((op & MOVE_TO_X) && new_x > to_x)
{
+ if (BUFFER_POS_REACHED_P ())
+ goto buffer_pos_reached;
it->current_x = x;
result = MOVE_X_REACHED;
break;
result = MOVE_POS_MATCH_OR_ZV;
break;
}
+ if (BUFFER_POS_REACHED_P ())
+ {
+ if (ITERATOR_AT_END_OF_LINE_P (it))
+ result = MOVE_POS_MATCH_OR_ZV;
+ else
+ result = MOVE_LINE_CONTINUED;
+ break;
+ }
if (ITERATOR_AT_END_OF_LINE_P (it))
{
result = MOVE_NEWLINE_OR_CR;
break;
}
+ if (it->method == next_element_from_display_vector)
+ it->face_id = it->saved_face_id;
}
#endif /* HAVE_WINDOW_SYSTEM */
}
result = MOVE_LINE_CONTINUED;
break;
}
+ else if (BUFFER_POS_REACHED_P ())
+ goto buffer_pos_reached;
else if (new_x > it->first_visible_x)
{
/* Glyph is visible. Increment number of glyphs that
if (result != MOVE_UNDEFINED)
break;
}
+ else if (BUFFER_POS_REACHED_P ())
+ {
+ buffer_pos_reached:
+ it->current_x = x;
+ it->max_ascent = ascent;
+ it->max_descent = descent;
+ result = MOVE_POS_MATCH_OR_ZV;
+ break;
+ }
else if ((op & MOVE_TO_X) && it->current_x >= to_x)
{
/* Stop when TO_X specified and reached. This check is
#ifdef HAVE_WINDOW_SYSTEM
if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
{
- if (!get_next_display_element (it))
+ if (!get_next_display_element (it)
+ || BUFFER_POS_REACHED_P ())
{
result = MOVE_POS_MATCH_OR_ZV;
break;
}
}
+#undef BUFFER_POS_REACHED_P
+
/* Restore the iterator settings altered at the beginning of this
function. */
it->glyph_row = saved_glyph_row;
{
int nlines, h;
struct it it2, it3;
- int start_pos = IT_CHARPOS (*it);
+ int start_pos;
+ move_further_back:
xassert (dy >= 0);
+ start_pos = IT_CHARPOS (*it);
+
/* Estimate how many newlines we must move back. */
nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f));
a line height of 13 pixels each, recentering with point
on the bottom line will try to move -39/2 = 19 pixels
backward. Try to avoid moving into the first line. */
- && it->current_y - target_y > line_height / 3 * 2
+ && it->current_y - target_y > line_height * 2 / 3
&& IT_CHARPOS (*it) > BEGV)
{
TRACE_MOVE ((stderr, " not far enough -> move_vert %d\n",
target_y - it->current_y));
- move_it_vertically (it, target_y - it->current_y);
- xassert (IT_CHARPOS (*it) >= BEGV);
+ dy = it->current_y - target_y;
+ goto move_further_back;
}
else if (target_y >= it->current_y + line_height
&& IT_CHARPOS (*it) < ZV)
{
if (dy <= 0)
move_it_vertically_backward (it, -dy);
- else if (dy > 0)
+ else
{
TRACE_MOVE ((stderr, "move_it_v: from %d, %d\n", IT_CHARPOS (*it), dy));
move_it_to (it, ZV, -1, it->current_y + dy, -1,
/* DVPOS == 0 means move to the start of the screen line. */
move_it_vertically_backward (it, 0);
xassert (it->current_x == 0 && it->hpos == 0);
+ /* Let next call to line_bottom_y calculate real line height */
+ last_height = 0;
}
else if (dvpos > 0)
move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
char *buffer;
int len;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+ USE_SAFE_ALLOCA;
/* Do nothing if called asynchronously. Inserting text into
a buffer may call after-change-functions and alike and
msg = Fformat (3, args);
len = SBYTES (msg) + 1;
- buffer = (char *) alloca (len);
+ SAFE_ALLOCA (buffer, char *, len);
bcopy (SDATA (msg), buffer, len);
message_dolog (buffer, len - 1, 1, 0);
+ SAFE_FREE ();
+
UNGCPRO;
}
struct gcpro gcpro1;
GCPRO1 (m);
+ clear_message (1,1);
/* First flush out any partial line written with print. */
message_log_maybe_newline ();
height = it.current_y + last_height;
else
height = it.current_y + it.max_ascent + it.max_descent;
- height -= it.extra_line_spacing;
+ height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
height = (height + unit - 1) / unit;
}
/* Copy at most PRECISION chars from STR. */
nbytes = strlen (str);
- n+= c_string_width (str, nbytes, precision, &dummy, &nbytes);
+ n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
while (nbytes--)
store_frame_title_char (*str++);
{
struct buffer *prev = current_buffer;
int count = SPECPDL_INDEX ();
- Lisp_Object old_tool_bar;
+ Lisp_Object new_tool_bar;
+ int new_n_tool_bar;
struct gcpro gcpro1;
/* Set current_buffer to the buffer of the selected
specbind (Qoverriding_local_map, Qnil);
}
- old_tool_bar = f->tool_bar_items;
- GCPRO1 (old_tool_bar);
+ GCPRO1 (new_tool_bar);
/* Build desired tool-bar items from keymaps. */
- BLOCK_INPUT;
- f->tool_bar_items
- = tool_bar_items (f->tool_bar_items, &f->n_tool_bar_items);
- UNBLOCK_INPUT;
+ new_tool_bar = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
+ &new_n_tool_bar);
/* Redisplay the tool-bar if we changed it. */
- if (! NILP (Fequal (old_tool_bar, f->tool_bar_items)))
- w->update_mode_line = Qt;
-
+ if (NILP (Fequal (new_tool_bar, f->tool_bar_items)))
+ {
+ /* Redisplay that happens asynchronously due to an expose event
+ may access f->tool_bar_items. Make sure we update both
+ variables within BLOCK_INPUT so no such event interrupts. */
+ BLOCK_INPUT;
+ f->tool_bar_items = new_tool_bar;
+ f->n_tool_bar_items = new_n_tool_bar;
+ w->update_mode_line = Qt;
+ UNBLOCK_INPUT;
+ }
+
UNGCPRO;
unbind_to (count, Qnil);
{
row->height = row->phys_height = it->last_visible_y - row->y;
row->ascent = row->phys_ascent = 0;
+ row->extra_line_spacing = 0;
}
row->full_width_p = 1;
if (!SYMBOLP (var))
continue;
- if (up_to_date)
+ if (up_to_date > 0)
{
Lisp_Object val = find_symbol_value (var);
Fput (var, Qlast_arrow_position,
}
-/* Return overlay arrow string at row, or nil. */
+/* Return overlay arrow string to display at row.
+ Return t if display as bitmap in left fringe.
+ Return nil if no overlay arrow. */
static Lisp_Object
-overlay_arrow_at_row (f, row, pbitmap)
- struct frame *f;
+overlay_arrow_at_row (it, row, pbitmap)
+ struct it *it;
struct glyph_row *row;
int *pbitmap;
{
continue;
val = find_symbol_value (var);
-
+
if (MARKERP (val)
&& current_buffer == XMARKER (val)->buffer
&& (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
{
val = overlay_arrow_string_or_property (var, pbitmap);
- if (FRAME_WINDOW_P (f))
+ if (FRAME_WINDOW_P (it->f)
+ && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
return Qt;
- else if (STRINGP (val))
+ if (STRINGP (val))
return val;
break;
}
{
Lisp_Object tail, sym, val;
Lisp_Object old = selected_frame;
-
+
selected_frame = frame;
for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail))
This is useful in situations where you need to redisplay but no
user action has occurred, making it inappropriate for the message
area to be cleared. See tracking_off and
- wait_reading_process_input for examples of these situations.
+ wait_reading_process_output for examples of these situations.
FROM_WHERE is an integer saying from where this function was
called. This is useful for debugging. */
}
else
redisplay_internal (1);
+
+ if (rif != NULL && rif->flush_display_optional)
+ rif->flush_display_optional (NULL);
}
{
struct glyph *glyph = row->glyphs[TEXT_AREA];
struct glyph *end = glyph + row->used[TEXT_AREA];
+ struct glyph *cursor = NULL;
/* The first glyph that starts a sequence of glyphs from string. */
struct glyph *string_start;
/* The X coordinate of string_start. */
/* The last known character position before string_start. */
int string_before_pos;
int x = row->x;
+ int cursor_x = x;
+ int cursor_from_overlay_pos = 0;
int pt_old = PT - delta;
/* Skip over glyphs not having an object at the start of the row.
string_start = NULL;
x += glyph->pixel_width;
++glyph;
+ if (cursor_from_overlay_pos
+ && last_pos > cursor_from_overlay_pos)
+ {
+ cursor_from_overlay_pos = 0;
+ cursor = 0;
+ }
}
else
{
string_start = glyph;
string_start_x = x;
/* Skip all glyphs from string. */
- SKIP_GLYPHS (glyph, end, x, STRINGP (glyph->object));
+ do
+ {
+ int pos;
+ if ((cursor == NULL || glyph > cursor)
+ && !NILP (Fget_char_property (make_number ((glyph)->charpos),
+ Qcursor, (glyph)->object))
+ && (pos = string_buffer_position (w, glyph->object,
+ string_before_pos),
+ (pos == 0 /* From overlay */
+ || pos == pt_old)))
+ {
+ /* Estimate overlay buffer position from the buffer
+ positions of the glyphs before and after the overlay.
+ Add 1 to last_pos so that if point corresponds to the
+ glyph right after the overlay, we still use a 'cursor'
+ property found in that overlay. */
+ cursor_from_overlay_pos = pos == 0 ? last_pos+1 : 0;
+ cursor = glyph;
+ cursor_x = x;
+ }
+ x += glyph->pixel_width;
+ ++glyph;
+ }
+ while (glyph < end && STRINGP (glyph->object));
}
}
- if (string_start
- && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old))
+ if (cursor != NULL)
+ {
+ glyph = cursor;
+ x = cursor_x;
+ }
+ else if (string_start
+ && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old))
{
/* We may have skipped over point because the previous glyphs
are from string. As there's no easy way to know the
A value of 1 means there is nothing to be done.
(Either the line is fully visible, or it cannot be made so,
or we cannot tell.)
+
+ If FORCE_P is non-zero, return 0 even if partial visible cursor row
+ is higher than window.
+
A value of 0 means the caller should do scrolling
as if point had gone off the screen. */
static int
-make_cursor_line_fully_visible (w)
+make_cursor_line_fully_visible (w, force_p)
struct window *w;
+ int force_p;
{
struct glyph_matrix *matrix;
struct glyph_row *row;
int window_height;
+ if (!make_cursor_line_fully_visible_p)
+ return 1;
+
/* It's not always possible to find the cursor, e.g, when a window
is full of overlay strings. Don't do anything in that case. */
if (w->cursor.vpos < 0)
row = MATRIX_ROW (matrix, w->cursor.vpos);
/* If the cursor row is not partially visible, there's nothing to do. */
- if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
+ if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row))
return 1;
/* If the row the cursor is in is taller than the window's height,
it's not clear what to do, so do nothing. */
window_height = window_box_height (w);
if (row->height >= window_height)
- return 1;
-
+ {
+ if (!force_p || w->vscroll)
+ return 1;
+ }
return 0;
#if 0
int amount_to_scroll = 0;
Lisp_Object aggressive;
int height;
- int end_scroll_margin;
+ int extra_scroll_margin_lines = last_line_misfit ? 1 : 0;
#if GLYPH_DEBUG
debug_method_add (w, "try_scrolling");
else
this_scroll_margin = 0;
+ /* Force scroll_conservatively to have a reasonable value so it doesn't
+ cause an overflow while computing how much to scroll. */
+ if (scroll_conservatively)
+ scroll_conservatively = min (scroll_conservatively,
+ MOST_POSITIVE_FIXNUM / FRAME_LINE_HEIGHT (f));
+
/* Compute how much we should try to scroll maximally to bring point
into view. */
if (scroll_step || scroll_conservatively || temp_scroll_step)
CHARPOS (scroll_margin_pos) = XINT (window_end);
BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
- end_scroll_margin = this_scroll_margin + !!last_line_misfit;
- if (end_scroll_margin)
+ if (this_scroll_margin || extra_scroll_margin_lines)
{
start_display (&it, w, scroll_margin_pos);
- move_it_vertically (&it, - end_scroll_margin);
+ if (this_scroll_margin)
+ move_it_vertically_backward (&it, this_scroll_margin);
+ if (extra_scroll_margin_lines)
+ move_it_by_lines (&it, - extra_scroll_margin_lines, 0);
scroll_margin_pos = it.current.pos;
}
aggressive = current_buffer->scroll_up_aggressively;
height = WINDOW_BOX_TEXT_HEIGHT (w);
if (NUMBERP (aggressive))
- amount_to_scroll = XFLOATINT (aggressive) * height;
+ {
+ double float_amount = XFLOATINT (aggressive) * height;
+ amount_to_scroll = float_amount;
+ if (amount_to_scroll == 0 && float_amount > 0)
+ amount_to_scroll = 1;
+ }
}
if (amount_to_scroll <= 0)
start_display (&it, w, startp);
if (scroll_conservatively)
- amount_to_scroll =
- max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step));
+ amount_to_scroll
+ = max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step));
else if (scroll_step || temp_scroll_step)
amount_to_scroll = scroll_max;
else
aggressive = current_buffer->scroll_down_aggressively;
height = WINDOW_BOX_TEXT_HEIGHT (w);
if (NUMBERP (aggressive))
- amount_to_scroll = XFLOATINT (aggressive) * height;
+ {
+ double float_amount = XFLOATINT (aggressive) * height;
+ amount_to_scroll = float_amount;
+ if (amount_to_scroll == 0 && float_amount > 0)
+ amount_to_scroll = 1;
+ }
}
if (amount_to_scroll <= 0)
return SCROLLING_FAILED;
- move_it_vertically (&it, - amount_to_scroll);
+ move_it_vertically_backward (&it, amount_to_scroll);
startp = it.current.pos;
}
}
/* If cursor ends up on a partially visible line,
treat that as being off the bottom of the screen. */
- if (! make_cursor_line_fully_visible (w))
+ if (! make_cursor_line_fully_visible (w, extra_scroll_margin_lines <= 1))
{
clear_glyph_matrix (w->desired_matrix);
- last_line_misfit = 1;
+ ++extra_scroll_margin_lines;
goto too_near_end;
}
rc = SCROLLING_SUCCESS;
&& (FRAME_WINDOW_P (f)
|| !overlay_arrow_in_current_buffer_p ()))
{
- int this_scroll_margin;
+ int this_scroll_margin, top_scroll_margin;
struct glyph_row *row = NULL;
#if GLYPH_DEBUG
this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
this_scroll_margin *= FRAME_LINE_HEIGHT (f);
+ top_scroll_margin = this_scroll_margin;
+ if (WINDOW_WANTS_HEADER_LINE_P (w))
+ top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
+
/* Start with the row the cursor was displayed during the last
not paused redisplay. Give up if that row is not valid. */
if (w->last_cursor.vpos < 0
else if (PT < XFASTINT (w->last_point))
{
/* Cursor has to be moved backward. Note that PT >=
- CHARPOS (startp) because of the outer
- if-statement. */
+ CHARPOS (startp) because of the outer if-statement. */
while (!row->mode_line_p
&& (MATRIX_ROW_START_CHARPOS (row) > PT
|| (MATRIX_ROW_START_CHARPOS (row) == PT
&& MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)))
- && (row->y > this_scroll_margin
+ && (row->y > top_scroll_margin
|| CHARPOS (startp) == BEGV))
{
xassert (row->enabled_p);
++row;
/* If within the scroll margin, scroll. */
- if (row->y < this_scroll_margin
+ if (row->y < top_scroll_margin
&& CHARPOS (startp) != BEGV)
scroll_p = 1;
}
/* if PT is not in the glyph row, give up. */
rc = CURSOR_MOVEMENT_MUST_SCROLL;
}
- else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
+ else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
+ && make_cursor_line_fully_visible_p)
{
if (PT == MATRIX_ROW_END_CHARPOS (row)
&& !row->ends_at_zv_p
else
{
set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
- if (!make_cursor_line_fully_visible (w))
+ if (!make_cursor_line_fully_visible (w, 0))
rc = CURSOR_MOVEMENT_MUST_SCROLL;
else
rc = CURSOR_MOVEMENT_SUCCESS;
which reflect the whole buffer size, with special markers
indicating narrowing, and scrollbars which reflect only the
visible region.
-
+
Note that mini-buffers sometimes aren't displaying any text. */
if (!MINI_WINDOW_P (w)
|| (w == XWINDOW (minibuf_window)
/* I don't think this is guaranteed to be right. For the
moment, we'll pretend it is. */
end = BUF_Z (buf) - XFASTINT (w->window_end_pos) - BUF_BEGV (buf);
-
+
if (end < start)
end = start;
if (whole < (end - start))
new_vpos = window_box_height (w) / 2;
}
- if (!make_cursor_line_fully_visible (w))
+ if (!make_cursor_line_fully_visible (w, 0))
{
/* Point does appear, but on a line partly visible at end of window.
Move it back to a fully-visible line. */
buffer. */
|| !NILP (Vwindow_scroll_functions)
|| MINI_WINDOW_P (w)
- || !(used_current_matrix_p =
- try_window_reusing_current_matrix (w)))
+ || !(used_current_matrix_p
+ = try_window_reusing_current_matrix (w)))
{
IF_DEBUG (debug_method_add (w, "1"));
try_window (window, startp);
/* Forget any recorded base line for line number display. */
w->base_line_number = Qnil;
- if (!make_cursor_line_fully_visible (w))
+ if (!make_cursor_line_fully_visible (w, 1))
{
clear_glyph_matrix (w->desired_matrix);
last_line_misfit = 1;
if (it.current_y <= 0)
{
init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
- move_it_vertically (&it, 0);
+ move_it_vertically_backward (&it, 0);
xassert (IT_CHARPOS (it) <= PT);
it.current_y = 0;
}
|| !NILP (Vwindow_scroll_functions)
|| !just_this_one_p
|| MINI_WINDOW_P (w)
- || !(used_current_matrix_p =
- try_window_reusing_current_matrix (w)))
+ || !(used_current_matrix_p
+ = try_window_reusing_current_matrix (w)))
try_window (window, startp);
/* If new fonts have been loaded (due to fontsets), give up. We
set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
}
- if (!make_cursor_line_fully_visible (w))
+ if (!make_cursor_line_fully_visible (w, centering_position > 0))
{
/* If vscroll is enabled, disable it and try again. */
if (w->vscroll)
/* If centering point failed to make the whole line visible,
put point at the top instead. That has to make the whole line
visible, if it can be done. */
+ clear_glyph_matrix (w->desired_matrix);
centering_position = 0;
goto point_at_top;
}
}
#ifdef HAVE_WINDOW_SYSTEM
- if (update_window_fringes (w, 0)
+ if (FRAME_WINDOW_P (f)
+ && update_window_fringes (w, 0)
&& !just_this_one_p
&& (used_current_matrix_p || overlay_arrow_seen)
&& !w->pseudo_window_p)
{
update_begin (f);
BLOCK_INPUT;
- draw_window_fringes (w);
+ if (draw_window_fringes (w, 1))
+ x_draw_vertical_border (w);
UNBLOCK_INPUT;
update_end (f);
}
/* Give up if old or new display is scrolled vertically. We could
make this function handle this, but right now it doesn't. */
start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
- if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row))
+ if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row))
return 0;
/* The variable new_start now holds the new window start. The old
last_text_row = last_reused_text_row = NULL;
while (it.current_y < it.last_visible_y
- && IT_CHARPOS (it) < CHARPOS (start)
&& !fonts_changed_p)
- if (display_line (&it))
- last_text_row = it.glyph_row - 1;
+ {
+ /* If we have reached into the characters in the START row,
+ that means the line boundaries have changed. So we
+ can't start copying with the row START. Maybe it will
+ work to start copying with the following row. */
+ while (IT_CHARPOS (it) > CHARPOS (start))
+ {
+ /* Advance to the next row as the "start". */
+ start_row++;
+ start = start_row->start.pos;
+ /* If there are no more rows to try, or just one, give up. */
+ if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
+ || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
+ || CHARPOS (start) == ZV)
+ {
+ clear_glyph_matrix (w->desired_matrix);
+ return 0;
+ }
+
+ start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
+ }
+ /* If we have reached alignment,
+ we can copy the rest of the rows. */
+ if (IT_CHARPOS (it) == CHARPOS (start))
+ break;
+
+ if (display_line (&it))
+ last_text_row = it.glyph_row - 1;
+ }
/* A value of current_y < last_visible_y means that we stopped
at the previous window start, which in turn means that we
if (it.current_y < it.last_visible_y)
{
/* IT.vpos always starts from 0; it counts text lines. */
- nrows_scrolled = it.vpos;
+ nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix));
/* Find PT if not already found in the lines displayed. */
if (w->cursor.vpos < 0)
{
- int dy = it.current_y - first_row_y;
+ int dy = it.current_y - start_row->y;
row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
row = row_containing_pos (w, PT, row, NULL, dy);
scroll_run_hook will clear the cursor, and use the
current matrix to get the height of the row the cursor is
in. */
- run.current_y = first_row_y;
+ run.current_y = start_row->y;
run.desired_y = it.current_y;
run.height = it.last_visible_y - it.current_y;
position. */
if (pt_row)
{
- w->cursor.vpos -= MATRIX_ROW_VPOS (first_reusable_row,
- w->current_matrix);
- w->cursor.y -= first_reusable_row->y;
+ w->cursor.vpos -= nrows_scrolled;
+ w->cursor.y -= first_reusable_row->y - start_row->y;
}
/* Scroll the display. */
for (row -= nrows_scrolled; row < bottom_row; ++row)
row->enabled_p = 0;
+ /* Point may have moved to a different line, so we cannot assume that
+ the previous cursor position is valid; locate the correct row. */
+ if (pt_row)
+ {
+ for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
+ row < bottom_row && PT >= MATRIX_ROW_END_CHARPOS (row);
+ row++)
+ {
+ w->cursor.vpos++;
+ w->cursor.y = row->y;
+ }
+ if (row < bottom_row)
+ {
+ struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
+ while (glyph->charpos < PT)
+ {
+ w->cursor.hpos++;
+ w->cursor.x += glyph->pixel_width;
+ glyph++;
+ }
+ }
+ }
+
/* Adjust window end. A null value of last_text_row means that
the window end is in reused rows which in turn means that
only its vpos can have changed. */
if ((w->cursor.y < this_scroll_margin
&& CHARPOS (start) > BEGV)
- /* Don't take scroll margin into account at the bottom because
- old redisplay didn't do it either. */
- || w->cursor.y + cursor_height > it.last_visible_y)
+ /* Old redisplay didn't take scroll margin into account at the bottom,
+ but then global-hl-line-mode doesn't scroll. KFS 2004-06-14 */
+ || (w->cursor.y + (make_cursor_line_fully_visible_p
+ ? cursor_height + this_scroll_margin
+ : 1)) > it.last_visible_y)
{
w->cursor.vpos = -1;
clear_glyph_matrix (w->desired_matrix);
Building Desired Matrix Rows
***********************************************************************/
-/* Return a temporary glyph row holding the glyphs of an overlay
- arrow. Only used for non-window-redisplay windows. */
+/* Return a temporary glyph row holding the glyphs of an overlay arrow.
+ Used for non-window-redisplay windows, and for windows w/o left fringe. */
static struct glyph_row *
get_overlay_arrow_glyph_row (w, overlay_arrow_string)
row->height = it->max_ascent + it->max_descent;
row->phys_ascent = it->max_phys_ascent;
row->phys_height = it->max_phys_ascent + it->max_phys_descent;
+ row->extra_line_spacing = it->max_extra_line_spacing;
}
/* Compute the width of this line. */
row->pixel_width -= it->truncation_pixel_width;
row->ascent = row->phys_ascent = 0;
row->height = row->phys_height = row->visible_height = 1;
+ row->extra_line_spacing = 0;
}
/* Compute a hash code for this row. */
/* Append one space to the glyph row of iterator IT if doing a
- window-based redisplay. DEFAULT_FACE_P non-zero means let the
- space have the default face, otherwise let it have the same face as
+ window-based redisplay. The space has the same face as
IT->face_id. Value is non-zero if a space was added.
This function is called to make sure that there is always one glyph
end of the line if the row ends in italic text. */
static int
-append_space (it, default_face_p)
+append_space_for_newline (it, default_face_p)
struct it *it;
int default_face_p;
{
/* Save some values that must not be changed.
Must save IT->c and IT->len because otherwise
ITERATOR_AT_END_P wouldn't work anymore after
- append_space has been called. */
+ append_space_for_newline has been called. */
enum display_element_type saved_what = it->what;
int saved_c = it->c, saved_len = it->len;
int saved_x = it->current_x;
PRODUCE_GLYPHS (it);
+ it->override_ascent = -1;
+ it->constrain_row_ascent_descent_p = 0;
it->current_x = saved_x;
it->object = saved_object;
it->position = saved_pos;
/* We always start displaying at hpos zero even if hscrolled. */
xassert (it->hpos == 0 && it->current_x == 0);
- /* We must not display in a row that's not a text row. */
- xassert (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
- < it->w->desired_matrix->nrows);
+ if (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
+ >= it->w->desired_matrix->nrows)
+ {
+ it->w->nrows_scale_factor++;
+ fonts_changed_p = 1;
+ return 0;
+ }
/* Is IT->w showing the region? */
it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil;
row->height = it->max_ascent + it->max_descent;
row->phys_ascent = it->max_phys_ascent;
row->phys_height = it->max_phys_ascent + it->max_phys_descent;
+ row->extra_line_spacing = it->max_extra_line_spacing;
/* Loop generating characters. The loop is left with IT on the next
character to display. */
row->exact_window_width_line_p = 1;
else
#endif /* HAVE_WINDOW_SYSTEM */
- if ((append_space (it, 1) && row->used[TEXT_AREA] == 1)
+ if ((append_space_for_newline (it, 1) && row->used[TEXT_AREA] == 1)
|| row->used[TEXT_AREA] == 0)
{
row->glyphs[TEXT_AREA]->charpos = -1;
row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
row->phys_height = max (row->phys_height,
it->max_phys_ascent + it->max_phys_descent);
+ row->extra_line_spacing = max (row->extra_line_spacing,
+ it->max_extra_line_spacing);
set_iterator_to_next (it, 1);
continue;
}
row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
row->phys_height = max (row->phys_height,
it->max_phys_ascent + it->max_phys_descent);
+ row->extra_line_spacing = max (row->extra_line_spacing,
+ it->max_extra_line_spacing);
if (it->current_x - it->pixel_width < it->first_visible_x)
row->x = x - it->first_visible_x;
}
row->continued_p = 0;
row->exact_window_width_line_p = 1;
}
+ else if (it->method == next_element_from_display_vector)
+ it->face_id = it->saved_face_id;
}
#endif /* HAVE_WINDOW_SYSTEM */
}
row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
row->phys_height = max (row->phys_height,
it->max_phys_ascent + it->max_phys_descent);
+ row->extra_line_spacing = max (row->extra_line_spacing,
+ it->max_extra_line_spacing);
/* End of this display line if row is continued. */
if (row->continued_p || row->ends_at_zv_p)
/* Add a space at the end of the line that is used to
display the cursor there. */
if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
- append_space (it, 0);
+ append_space_for_newline (it, 0);
#endif /* HAVE_WINDOW_SYSTEM */
/* Extend the face to the end of the line. */
{
if (!get_next_display_element (it))
{
-#ifdef HAVE_WINDOW_SYSTEM
it->continuation_lines_width = 0;
row->ends_at_zv_p = 1;
row->exact_window_width_line_p = 1;
break;
-#endif /* HAVE_WINDOW_SYSTEM */
}
if (ITERATOR_AT_END_OF_LINE_P (it))
{
better to let it be displayed like cursors under X. */
if (! overlay_arrow_seen
&& (overlay_arrow_string
- = overlay_arrow_at_row (it->f, row, &overlay_arrow_bitmap),
+ = overlay_arrow_at_row (it, row, &overlay_arrow_bitmap),
!NILP (overlay_arrow_string)))
{
/* Overlay arrow in window redisplay is a fringe bitmap. */
- if (!FRAME_WINDOW_P (it->f))
+ if (STRINGP (overlay_arrow_string))
{
struct glyph_row *arrow_row
= get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
}
}
-
+ else
+ {
+ it->w->overlay_arrow_bitmap = overlay_arrow_bitmap;
+ row->overlay_arrow_p = 1;
+ }
overlay_arrow_seen = 1;
- it->w->overlay_arrow_bitmap = overlay_arrow_bitmap;
- row->overlay_arrow_p = 1;
}
/* Compute pixel dimensions of this line. */
init_iterator (&it, w, -1, -1, NULL, face_id);
prepare_desired_row (it.glyph_row);
+ it.glyph_row->mode_line_p = 1;
+
if (! mode_line_inverse_video)
/* Force the mode-line to be displayed in the default face. */
it.base_face_id = it.face_id = DEFAULT_FACE_ID;
compute_line_metrics (&it);
it.glyph_row->full_width_p = 1;
- it.glyph_row->mode_line_p = 1;
it.glyph_row->continued_p = 0;
it.glyph_row->truncated_on_left_p = 0;
it.glyph_row->truncated_on_right_p = 0;
Lisp_Object oprops, aelt;
oprops = Ftext_properties_at (make_number (0), elt);
+ /* If the starting string's properties are not what
+ we want, translate the string. Also, if the string
+ is risky, do that anyway. */
+
if (NILP (Fequal (props, oprops)) || risky)
{
/* If the starting string has properties,
if (this - 1 != last)
{
+ int nchars, nbytes;
+
/* Output to end of string or up to '%'. Field width
is length of string. Don't output more than
PRECISION allows us. */
--this;
- prec = chars_in_text (last, this - last);
- if (precision > 0 && prec > precision - n)
- prec = precision - n;
+ prec = c_string_width (last, this - last, precision - n,
+ &nchars, &nbytes);
if (frame_title_ptr)
n += store_frame_title (last, 0, prec);
{
int bytepos = last - lisp_string;
int charpos = string_byte_to_char (elt, bytepos);
+ int endpos = (precision <= 0
+ ? string_byte_to_char (elt,
+ this - lisp_string)
+ : charpos + nchars);
+
n += store_mode_line_string (NULL,
Fsubstring (elt, make_number (charpos),
- make_number (charpos + prec)),
+ make_number (endpos)),
0, 0, 0, Qnil);
}
else
The mode_line_string_face face property is always added to the string.
*/
-static int store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props)
+static int
+store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props)
char *string;
Lisp_Object lisp_string;
int copy_string;
props = mode_line_string_face_prop;
else if (!NILP (mode_line_string_face))
{
- Lisp_Object face = Fplist_get (props, Qface);
+ Lisp_Object face = Fsafe_plist_get (props, Qface);
props = Fcopy_sequence (props);
if (NILP (face))
face = mode_line_string_face;
Lisp_Object face;
if (NILP (props))
props = Ftext_properties_at (make_number (0), lisp_string);
- face = Fplist_get (props, Qface);
+ face = Fsafe_plist_get (props, Qface);
if (NILP (face))
face = mode_line_string_face;
else
DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
- 0, 3, 0,
+ 0, 4, 0,
doc: /* Return the mode-line of selected window as a string.
First optional arg FORMAT specifies a different format string (see
`mode-line-format' for details) to use. If FORMAT is t, return
the buffer's header-line. Second optional arg WINDOW specifies a
different window to use as the context for the formatting.
-If third optional arg NO-PROPS is non-nil, string is not propertized. */)
- (format, window, no_props)
- Lisp_Object format, window, no_props;
+If third optional arg NO-PROPS is non-nil, string is not propertized.
+Fourth optional arg BUFFER specifies which buffer to use. */)
+ (format, window, no_props, buffer)
+ Lisp_Object format, window, no_props, buffer;
{
struct it it;
int len;
window = selected_window;
CHECK_WINDOW (window);
w = XWINDOW (window);
- CHECK_BUFFER (w->buffer);
- if (XBUFFER (w->buffer) != current_buffer)
+ if (NILP (buffer))
+ buffer = w->buffer;
+
+ CHECK_BUFFER (buffer);
+
+ if (XBUFFER (buffer) != current_buffer)
{
old_buffer = current_buffer;
- set_buffer_internal_1 (XBUFFER (w->buffer));
+ set_buffer_internal_1 (XBUFFER (buffer));
}
if (NILP (format) || EQ (format, Qt))
{
- face_id = NILP (format)
- ? CURRENT_MODE_LINE_FACE_ID (w) :
- HEADER_LINE_FACE_ID;
- format = NILP (format)
- ? current_buffer->mode_line_format
- : current_buffer->header_line_format;
+ face_id = (NILP (format)
+ ? CURRENT_MODE_LINE_FACE_ID (w)
+ : HEADER_LINE_FACE_ID);
+ format = (NILP (format)
+ ? current_buffer->mode_line_format
+ : current_buffer->header_line_format);
}
init_iterator (&it, w, -1, -1, NULL, face_id);
if (NILP (no_props))
{
- mode_line_string_face =
- (face_id == MODE_LINE_FACE_ID ? Qmode_line :
- face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive :
- face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil);
+ mode_line_string_face
+ = (face_id == MODE_LINE_FACE_ID ? Qmode_line
+ : face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive
+ : face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil);
- mode_line_string_face_prop =
- NILP (mode_line_string_face) ? Qnil :
- Fcons (Qface, Fcons (mode_line_string_face, Qnil));
+ mode_line_string_face_prop
+ = (NILP (mode_line_string_face) ? Qnil
+ : Fcons (Qface, Fcons (mode_line_string_face, Qnil)));
/* We need a dummy last element in mode_line_string_list to
indicate we are building the propertized mode-line string.
Using mode_line_string_face_prop here GC protects it. */
- mode_line_string_list =
- Fcons (mode_line_string_face_prop, Qnil);
+ mode_line_string_list
+ = Fcons (mode_line_string_face_prop, Qnil);
frame_title_ptr = NULL;
}
else
{
tenths = remainder / 100;
if (50 <= remainder % 100)
- if (tenths < 9)
- tenths++;
- else
- {
- quotient++;
- if (quotient == 10)
- tenths = -1;
- else
- tenths = 0;
- }
+ {
+ if (tenths < 9)
+ tenths++;
+ else
+ {
+ quotient++;
+ if (quotient == 10)
+ tenths = -1;
+ else
+ tenths = 0;
+ }
+ }
}
else
if (500 <= remainder)
- if (quotient < 999)
- quotient++;
- else
- {
- quotient = 1;
- exponent++;
- tenths = 0;
- }
+ {
+ if (quotient < 999)
+ quotient++;
+ else
+ {
+ quotient = 1;
+ exponent++;
+ tenths = 0;
+ }
+ }
}
/* Calculate the LENGTH of QUOTIENT.TENTHS as a string. */
generated by character C. PRECISION >= 0 means don't return a
string longer than that value. FIELD_WIDTH > 0 means pad the
string returned with spaces to that value. Return 1 in *MULTIBYTE
- if the result is multibyte text. */
+ if the result is multibyte text.
+
+ Note we operate on the current buffer for most purposes,
+ the exception being w->base_line_pos. */
static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
Lisp_Object obj;
struct frame *f = XFRAME (WINDOW_FRAME (w));
char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
- struct buffer *b = XBUFFER (w->buffer);
+ struct buffer *b = current_buffer;
obj = Qnil;
*multibyte = 0;
case 's':
/* status of process */
- obj = Fget_buffer_process (w->buffer);
+ obj = Fget_buffer_process (Fcurrent_buffer ());
if (NILP (obj))
return "no process";
#ifdef subprocesses
row->height = it->max_ascent + it->max_descent;
row->phys_ascent = it->max_phys_ascent;
row->phys_height = it->max_phys_ascent + it->max_phys_descent;
+ row->extra_line_spacing = it->max_extra_line_spacing;
/* This condition is for the case that we are called with current_x
past last_visible_x. */
row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
row->phys_height = max (row->phys_height,
it->max_phys_ascent + it->max_phys_descent);
+ row->extra_line_spacing = max (row->extra_line_spacing,
+ it->max_extra_line_spacing);
x += glyph->pixel_width;
++i;
}
return 0;
}
-\f
-/***********************************************************************
- Glyph Display
- ***********************************************************************/
+/* Calculate a width or height in pixels from a specification using
+ the following elements:
-#ifdef HAVE_WINDOW_SYSTEM
+ SPEC ::=
+ NUM - a (fractional) multiple of the default font width/height
+ (NUM) - specifies exactly NUM pixels
+ UNIT - a fixed number of pixels, see below.
+ ELEMENT - size of a display element in pixels, see below.
+ (NUM . SPEC) - equals NUM * SPEC
+ (+ SPEC SPEC ...) - add pixel values
+ (- SPEC SPEC ...) - subtract pixel values
+ (- SPEC) - negate pixel value
-#if GLYPH_DEBUG
+ NUM ::=
+ INT or FLOAT - a number constant
+ SYMBOL - use symbol's (buffer local) variable binding.
-void
-dump_glyph_string (s)
- struct glyph_string *s;
-{
- fprintf (stderr, "glyph string\n");
- fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
- s->x, s->y, s->width, s->height);
- fprintf (stderr, " ybase = %d\n", s->ybase);
- fprintf (stderr, " hl = %d\n", s->hl);
- fprintf (stderr, " left overhang = %d, right = %d\n",
- s->left_overhang, s->right_overhang);
- fprintf (stderr, " nchars = %d\n", s->nchars);
- fprintf (stderr, " extends to end of line = %d\n",
- s->extends_to_end_of_line_p);
- fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
- fprintf (stderr, " bg width = %d\n", s->background_width);
-}
+ UNIT ::=
+ in - pixels per inch *)
+ mm - pixels per 1/1000 meter *)
+ cm - pixels per 1/100 meter *)
+ width - width of current font in pixels.
+ height - height of current font in pixels.
-#endif /* GLYPH_DEBUG */
+ *) using the ratio(s) defined in display-pixels-per-inch.
-/* Initialize glyph string S. CHAR2B is a suitably allocated vector
- of XChar2b structures for S; it can't be allocated in
- init_glyph_string because it must be allocated via `alloca'. W
- is the window on which S is drawn. ROW and AREA are the glyph row
- and area within the row from which S is constructed. START is the
- index of the first glyph structure covered by S. HL is a
- face-override for drawing S. */
+ ELEMENT ::=
-#ifdef HAVE_NTGUI
-#define OPTIONAL_HDC(hdc) hdc,
-#define DECLARE_HDC(hdc) HDC hdc;
-#define ALLOCATE_HDC(hdc, f) hdc = get_frame_dc ((f))
-#define RELEASE_HDC(hdc, f) release_frame_dc ((f), (hdc))
-#endif
+ left-fringe - left fringe width in pixels
+ right-fringe - right fringe width in pixels
-#ifndef OPTIONAL_HDC
-#define OPTIONAL_HDC(hdc)
-#define DECLARE_HDC(hdc)
-#define ALLOCATE_HDC(hdc, f)
-#define RELEASE_HDC(hdc, f)
-#endif
+ left-margin - left margin width in pixels
+ right-margin - right margin width in pixels
-static void
-init_glyph_string (s, OPTIONAL_HDC (hdc) char2b, w, row, area, start, hl)
- struct glyph_string *s;
- DECLARE_HDC (hdc)
- XChar2b *char2b;
- struct window *w;
- struct glyph_row *row;
- enum glyph_row_area area;
- int start;
- enum draw_glyphs_face hl;
-{
- bzero (s, sizeof *s);
- s->w = w;
- s->f = XFRAME (w->frame);
-#ifdef HAVE_NTGUI
- s->hdc = hdc;
-#endif
- s->display = FRAME_X_DISPLAY (s->f);
- s->window = FRAME_X_WINDOW (s->f);
- s->char2b = char2b;
- s->hl = hl;
- s->row = row;
- s->area = area;
- s->first_glyph = row->glyphs[area] + start;
- s->height = row->height;
- s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+ scroll-bar - scroll-bar area width in pixels
- /* Display the internal border below the tool-bar window. */
- if (s->w == XWINDOW (s->f->tool_bar_window))
- s->y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
+ Examples:
- s->ybase = s->y + row->ascent;
+ Pixels corresponding to 5 inches:
+ (5 . in)
+
+ Total width of non-text areas on left side of window (if scroll-bar is on left):
+ '(space :width (+ left-fringe left-margin scroll-bar))
+
+ Align to first text column (in header line):
+ '(space :align-to 0)
+
+ Align to middle of text area minus half the width of variable `my-image'
+ containing a loaded image:
+ '(space :align-to (0.5 . (- text my-image)))
+
+ Width of left margin minus width of 1 character in the default font:
+ '(space :width (- left-margin 1))
+
+ Width of left margin minus width of 2 characters in the current font:
+ '(space :width (- left-margin (2 . width)))
+
+ Center 1 character over left-margin (in header line):
+ '(space :align-to (+ left-margin (0.5 . left-margin) -0.5))
+
+ Different ways to express width of left fringe plus left margin minus one pixel:
+ '(space :width (- (+ left-fringe left-margin) (1)))
+ '(space :width (+ left-fringe left-margin (- (1))))
+ '(space :width (+ left-fringe left-margin (-1)))
+
+*/
+
+#define NUMVAL(X) \
+ ((INTEGERP (X) || FLOATP (X)) \
+ ? XFLOATINT (X) \
+ : - 1)
+
+int
+calc_pixel_width_or_height (res, it, prop, font, width_p, align_to)
+ double *res;
+ struct it *it;
+ Lisp_Object prop;
+ void *font;
+ int width_p, *align_to;
+{
+ double pixels;
+
+#define OK_PIXELS(val) ((*res = (double)(val)), 1)
+#define OK_ALIGN_TO(val) ((*align_to = (int)(val)), 1)
+
+ if (NILP (prop))
+ return OK_PIXELS (0);
+
+ if (SYMBOLP (prop))
+ {
+ if (SCHARS (SYMBOL_NAME (prop)) == 2)
+ {
+ char *unit = SDATA (SYMBOL_NAME (prop));
+
+ if (unit[0] == 'i' && unit[1] == 'n')
+ pixels = 1.0;
+ else if (unit[0] == 'm' && unit[1] == 'm')
+ pixels = 25.4;
+ else if (unit[0] == 'c' && unit[1] == 'm')
+ pixels = 2.54;
+ else
+ pixels = 0;
+ if (pixels > 0)
+ {
+ double ppi;
+ if ((ppi = NUMVAL (Vdisplay_pixels_per_inch), ppi > 0)
+ || (CONSP (Vdisplay_pixels_per_inch)
+ && (ppi = (width_p
+ ? NUMVAL (XCAR (Vdisplay_pixels_per_inch))
+ : NUMVAL (XCDR (Vdisplay_pixels_per_inch))),
+ ppi > 0)))
+ return OK_PIXELS (ppi / pixels);
+
+ return 0;
+ }
+ }
+
+#ifdef HAVE_WINDOW_SYSTEM
+ if (EQ (prop, Qheight))
+ return OK_PIXELS (font ? FONT_HEIGHT ((XFontStruct *)font) : FRAME_LINE_HEIGHT (it->f));
+ if (EQ (prop, Qwidth))
+ return OK_PIXELS (font ? FONT_WIDTH ((XFontStruct *)font) : FRAME_COLUMN_WIDTH (it->f));
+#else
+ if (EQ (prop, Qheight) || EQ (prop, Qwidth))
+ return OK_PIXELS (1);
+#endif
+
+ if (EQ (prop, Qtext))
+ return OK_PIXELS (width_p
+ ? window_box_width (it->w, TEXT_AREA)
+ : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
+
+ if (align_to && *align_to < 0)
+ {
+ *res = 0;
+ if (EQ (prop, Qleft))
+ return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA));
+ if (EQ (prop, Qright))
+ return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
+ if (EQ (prop, Qcenter))
+ return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
+ + window_box_width (it->w, TEXT_AREA) / 2);
+ if (EQ (prop, Qleft_fringe))
+ return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
+ ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w)
+ : window_box_right_offset (it->w, LEFT_MARGIN_AREA));
+ if (EQ (prop, Qright_fringe))
+ return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
+ ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
+ : window_box_right_offset (it->w, TEXT_AREA));
+ if (EQ (prop, Qleft_margin))
+ return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA));
+ if (EQ (prop, Qright_margin))
+ return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA));
+ if (EQ (prop, Qscroll_bar))
+ return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
+ ? 0
+ : (window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
+ + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
+ ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
+ : 0)));
+ }
+ else
+ {
+ if (EQ (prop, Qleft_fringe))
+ return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
+ if (EQ (prop, Qright_fringe))
+ return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
+ if (EQ (prop, Qleft_margin))
+ return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
+ if (EQ (prop, Qright_margin))
+ return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
+ if (EQ (prop, Qscroll_bar))
+ return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
+ }
+
+ prop = Fbuffer_local_value (prop, it->w->buffer);
+ }
+
+ if (INTEGERP (prop) || FLOATP (prop))
+ {
+ int base_unit = (width_p
+ ? FRAME_COLUMN_WIDTH (it->f)
+ : FRAME_LINE_HEIGHT (it->f));
+ return OK_PIXELS (XFLOATINT (prop) * base_unit);
+ }
+
+ if (CONSP (prop))
+ {
+ Lisp_Object car = XCAR (prop);
+ Lisp_Object cdr = XCDR (prop);
+
+ if (SYMBOLP (car))
+ {
+#ifdef HAVE_WINDOW_SYSTEM
+ if (valid_image_p (prop))
+ {
+ int id = lookup_image (it->f, prop);
+ struct image *img = IMAGE_FROM_ID (it->f, id);
+
+ return OK_PIXELS (width_p ? img->width : img->height);
+ }
+#endif
+ if (EQ (car, Qplus) || EQ (car, Qminus))
+ {
+ int first = 1;
+ double px;
+
+ pixels = 0;
+ while (CONSP (cdr))
+ {
+ if (!calc_pixel_width_or_height (&px, it, XCAR (cdr),
+ font, width_p, align_to))
+ return 0;
+ if (first)
+ pixels = (EQ (car, Qplus) ? px : -px), first = 0;
+ else
+ pixels += px;
+ cdr = XCDR (cdr);
+ }
+ if (EQ (car, Qminus))
+ pixels = -pixels;
+ return OK_PIXELS (pixels);
+ }
+
+ car = Fbuffer_local_value (car, it->w->buffer);
+ }
+
+ if (INTEGERP (car) || FLOATP (car))
+ {
+ double fact;
+ pixels = XFLOATINT (car);
+ if (NILP (cdr))
+ return OK_PIXELS (pixels);
+ if (calc_pixel_width_or_height (&fact, it, cdr,
+ font, width_p, align_to))
+ return OK_PIXELS (pixels * fact);
+ return 0;
+ }
+
+ return 0;
+ }
+
+ return 0;
+}
+
+\f
+/***********************************************************************
+ Glyph Display
+ ***********************************************************************/
+
+#ifdef HAVE_WINDOW_SYSTEM
+
+#if GLYPH_DEBUG
+
+void
+dump_glyph_string (s)
+ struct glyph_string *s;
+{
+ fprintf (stderr, "glyph string\n");
+ fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
+ s->x, s->y, s->width, s->height);
+ fprintf (stderr, " ybase = %d\n", s->ybase);
+ fprintf (stderr, " hl = %d\n", s->hl);
+ fprintf (stderr, " left overhang = %d, right = %d\n",
+ s->left_overhang, s->right_overhang);
+ fprintf (stderr, " nchars = %d\n", s->nchars);
+ fprintf (stderr, " extends to end of line = %d\n",
+ s->extends_to_end_of_line_p);
+ fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
+ fprintf (stderr, " bg width = %d\n", s->background_width);
+}
+
+#endif /* GLYPH_DEBUG */
+
+/* Initialize glyph string S. CHAR2B is a suitably allocated vector
+ of XChar2b structures for S; it can't be allocated in
+ init_glyph_string because it must be allocated via `alloca'. W
+ is the window on which S is drawn. ROW and AREA are the glyph row
+ and area within the row from which S is constructed. START is the
+ index of the first glyph structure covered by S. HL is a
+ face-override for drawing S. */
+
+#ifdef HAVE_NTGUI
+#define OPTIONAL_HDC(hdc) hdc,
+#define DECLARE_HDC(hdc) HDC hdc;
+#define ALLOCATE_HDC(hdc, f) hdc = get_frame_dc ((f))
+#define RELEASE_HDC(hdc, f) release_frame_dc ((f), (hdc))
+#endif
+
+#ifndef OPTIONAL_HDC
+#define OPTIONAL_HDC(hdc)
+#define DECLARE_HDC(hdc)
+#define ALLOCATE_HDC(hdc, f)
+#define RELEASE_HDC(hdc, f)
+#endif
+
+static void
+init_glyph_string (s, OPTIONAL_HDC (hdc) char2b, w, row, area, start, hl)
+ struct glyph_string *s;
+ DECLARE_HDC (hdc)
+ XChar2b *char2b;
+ struct window *w;
+ struct glyph_row *row;
+ enum glyph_row_area area;
+ int start;
+ enum draw_glyphs_face hl;
+{
+ bzero (s, sizeof *s);
+ s->w = w;
+ s->f = XFRAME (w->frame);
+#ifdef HAVE_NTGUI
+ s->hdc = hdc;
+#endif
+ s->display = FRAME_X_DISPLAY (s->f);
+ s->window = FRAME_X_WINDOW (s->f);
+ s->char2b = char2b;
+ s->hl = hl;
+ s->row = row;
+ s->area = area;
+ s->first_glyph = row->glyphs[area] + start;
+ s->height = row->height;
+ s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+
+ /* Display the internal border below the tool-bar window. */
+ if (WINDOWP (s->f->tool_bar_window)
+ && s->w == XWINDOW (s->f->tool_bar_window))
+ s->y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
+
+ s->ybase = s->y + row->ascent;
}
xassert (s->first_glyph->type == IMAGE_GLYPH);
s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
xassert (s->img);
+ s->slice = s->first_glyph->slice;
s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
s->font = s->face->font;
s->width = s->first_glyph->pixel_width;
return x_reached;
}
+/* Expand row matrix if too narrow. Don't expand if area
+ is not present. */
+
+#define IT_EXPAND_MATRIX_WIDTH(it, area) \
+ { \
+ if (!fonts_changed_p \
+ && (it->glyph_row->glyphs[area] \
+ < it->glyph_row->glyphs[area + 1])) \
+ { \
+ it->w->ncols_scale_factor++; \
+ fonts_changed_p = 1; \
+ } \
+ }
/* Store one glyph for IT->char_to_display in IT->glyph_row.
Called from x_produce_glyphs when IT->glyph_row is non-null. */
glyph->glyph_not_available_p = it->glyph_not_available_p;
glyph->face_id = it->face_id;
glyph->u.ch = it->char_to_display;
+ glyph->slice = null_glyph_slice;
glyph->font_type = FONT_TYPE_UNKNOWN;
++it->glyph_row->used[area];
}
+ else
+ IT_EXPAND_MATRIX_WIDTH (it, area);
}
/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
glyph->glyph_not_available_p = 0;
glyph->face_id = it->face_id;
glyph->u.cmp_id = it->cmp_id;
+ glyph->slice = null_glyph_slice;
glyph->font_type = FONT_TYPE_UNKNOWN;
++it->glyph_row->used[area];
}
+ else
+ IT_EXPAND_MATRIX_WIDTH (it, area);
}
if (it->voffset < 0)
/* Increase the ascent so that we can display the text higher
in the line. */
- it->ascent += abs (it->voffset);
+ it->ascent -= it->voffset;
else
/* Increase the descent so that we can display the text lower
in the line. */
{
struct image *img;
struct face *face;
- int face_ascent, glyph_ascent;
+ int glyph_ascent;
+ struct glyph_slice slice;
xassert (it->what == IT_IMAGE);
/* Make sure X resources of the image is loaded. */
prepare_image_for_display (it->f, img);
- it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face);
- it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
- it->pixel_width = img->width + 2 * img->hmargin;
+ slice.x = slice.y = 0;
+ slice.width = img->width;
+ slice.height = img->height;
+
+ if (INTEGERP (it->slice.x))
+ slice.x = XINT (it->slice.x);
+ else if (FLOATP (it->slice.x))
+ slice.x = XFLOAT_DATA (it->slice.x) * img->width;
+
+ if (INTEGERP (it->slice.y))
+ slice.y = XINT (it->slice.y);
+ else if (FLOATP (it->slice.y))
+ slice.y = XFLOAT_DATA (it->slice.y) * img->height;
+
+ if (INTEGERP (it->slice.width))
+ slice.width = XINT (it->slice.width);
+ else if (FLOATP (it->slice.width))
+ slice.width = XFLOAT_DATA (it->slice.width) * img->width;
+
+ if (INTEGERP (it->slice.height))
+ slice.height = XINT (it->slice.height);
+ else if (FLOATP (it->slice.height))
+ slice.height = XFLOAT_DATA (it->slice.height) * img->height;
+
+ if (slice.x >= img->width)
+ slice.x = img->width;
+ if (slice.y >= img->height)
+ slice.y = img->height;
+ if (slice.x + slice.width >= img->width)
+ slice.width = img->width - slice.x;
+ if (slice.y + slice.height > img->height)
+ slice.height = img->height - slice.y;
+
+ if (slice.width == 0 || slice.height == 0)
+ return;
+
+ it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face, &slice);
+
+ it->descent = slice.height - glyph_ascent;
+ if (slice.y == 0)
+ it->descent += img->vmargin;
+ if (slice.y + slice.height == img->height)
+ it->descent += img->vmargin;
+ it->phys_descent = it->descent;
+
+ it->pixel_width = slice.width;
+ if (slice.x == 0)
+ it->pixel_width += img->hmargin;
+ if (slice.x + slice.width == img->width)
+ it->pixel_width += img->hmargin;
/* It's quite possible for images to have an ascent greater than
their height, so don't get confused in that case. */
if (it->descent < 0)
it->descent = 0;
+#if 0 /* this breaks image tiling */
/* If this glyph is alone on the last line, adjust it.ascent to minimum row ascent. */
- face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f);
+ int face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f);
if (face_ascent > it->ascent)
it->ascent = it->phys_ascent = face_ascent;
+#endif
it->nglyphs = 1;
{
if (face->box_line_width > 0)
{
- it->ascent += face->box_line_width;
- it->descent += face->box_line_width;
+ if (slice.y == 0)
+ it->ascent += face->box_line_width;
+ if (slice.y + slice.height == img->height)
+ it->descent += face->box_line_width;
}
- if (it->start_of_box_run_p)
+ if (it->start_of_box_run_p && slice.x == 0)
it->pixel_width += abs (face->box_line_width);
- if (it->end_of_box_run_p)
+ if (it->end_of_box_run_p && slice.x + slice.width == img->width)
it->pixel_width += abs (face->box_line_width);
}
glyph->glyph_not_available_p = 0;
glyph->face_id = it->face_id;
glyph->u.img_id = img->id;
+ glyph->slice = slice;
glyph->font_type = FONT_TYPE_UNKNOWN;
++it->glyph_row->used[area];
}
+ else
+ IT_EXPAND_MATRIX_WIDTH (it, area);
}
}
glyph->face_id = it->face_id;
glyph->u.stretch.ascent = ascent;
glyph->u.stretch.height = height;
+ glyph->slice = null_glyph_slice;
glyph->font_type = FONT_TYPE_UNKNOWN;
++it->glyph_row->used[area];
}
+ else
+ IT_EXPAND_MATRIX_WIDTH (it, area);
}
-/* Calculate a width or height in pixels from a specification using
- the following elements:
-
- SPEC ::=
- NUM - a (fractional) multiple of the default font width/height
- (NUM) - specifies exactly NUM pixels
- UNIT - a fixed number of pixels, see below.
- ELEMENT - size of a display element in pixels, see below.
- (NUM . SPEC) - equals NUM * SPEC
- (+ SPEC SPEC ...) - add pixel values
- (- SPEC SPEC ...) - subtract pixel values
- (- SPEC) - negate pixel value
-
- NUM ::=
- INT or FLOAT - a number constant
- SYMBOL - use symbol's (buffer local) variable binding.
-
- UNIT ::=
- in - pixels per inch *)
- mm - pixels per 1/1000 meter *)
- cm - pixels per 1/100 meter *)
- width - width of current font in pixels.
- height - height of current font in pixels.
-
- *) using the ratio(s) defined in display-pixels-per-inch.
-
- ELEMENT ::=
-
- left-fringe - left fringe width in pixels
- (left-fringe . nil) - left fringe width if inside margins, else 0
- (left-fringe . t) - left fringe width if outside margins, else 0
-
- right-fringe - right fringe width in pixels
- (right-fringe . nil) - right fringe width if inside margins, else 0
- (right-fringe . t) - right fringe width if outside margins, else 0
-
- left-margin - left margin width in pixels
- right-margin - right margin width in pixels
-
- scroll-bar - scroll-bar area width in pixels
- (scroll-bar . left) - scroll-bar width if on left, else 0
- (scroll-bar . right) - scroll-bar width if on right, else 0
-
- Examples:
-
- Pixels corresponding to 5 inches:
- (5 . in)
-
- Total width of non-text areas on left side of window:
- (+ left-fringe left-margin (scroll-bar . left))
-
- Total width of fringes if inside display margins:
- (+ (left-fringe) (right-fringe))
-
- Width of left margin minus width of 1 character in the default font:
- (- left-margin 1)
-
- Width of left margin minus width of 2 characters in the current font:
- (- left-margin (2 . width))
-
- Width of left fringe plus left margin minus one pixel:
- (- (+ left-fringe left-margin) (1))
- (+ left-fringe left-margin (- (1)))
- (+ left-fringe left-margin (-1))
-
-*/
-
-#define NUMVAL(X) \
- ((INTEGERP (X) || FLOATP (X)) \
- ? XFLOATINT (X) \
- : - 1)
-
-static int
-calc_pixel_width_or_height (res, it, prop, font, width_p)
- double *res;
- struct it *it;
- Lisp_Object prop;
- XFontStruct *font;
- int width_p;
-{
- double pixels;
-
-#define OK_PIXELS(val) ((*res = (val)), 1)
-
- if (SYMBOLP (prop))
- {
- if (SCHARS (SYMBOL_NAME (prop)) == 2)
- {
- char *unit = SDATA (SYMBOL_NAME (prop));
-
- if (unit[0] == 'i' && unit[1] == 'n')
- pixels = 1.0;
- else if (unit[0] == 'm' && unit[1] == 'm')
- pixels = 25.4;
- else if (unit[0] == 'c' && unit[1] == 'm')
- pixels = 2.54;
- else
- pixels = 0;
- if (pixels > 0)
- {
- double ppi;
- if ((ppi = NUMVAL (Vdisplay_pixels_per_inch), ppi > 0)
- || (CONSP (Vdisplay_pixels_per_inch)
- && (ppi = (width_p
- ? NUMVAL (XCAR (Vdisplay_pixels_per_inch))
- : NUMVAL (XCDR (Vdisplay_pixels_per_inch))),
- ppi > 0)))
- return OK_PIXELS (ppi / pixels);
-
- return 0;
- }
- }
-
- if (EQ (prop, Qheight))
- return OK_PIXELS (font ? FONT_HEIGHT (font) : FRAME_LINE_HEIGHT (it->f));
- if (EQ (prop, Qwidth))
- return OK_PIXELS (font ? FONT_WIDTH (font) : FRAME_COLUMN_WIDTH (it->f));
- if (EQ (prop, Qleft_fringe))
- return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
- if (EQ (prop, Qright_fringe))
- return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
- if (EQ (prop, Qleft_margin))
- return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
- if (EQ (prop, Qright_margin))
- return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
- if (EQ (prop, Qscroll_bar))
- return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
-
- prop = Fbuffer_local_value (prop, it->w->buffer);
- }
-
- if (INTEGERP (prop) || FLOATP (prop))
- {
- int base_unit = (width_p
- ? FRAME_COLUMN_WIDTH (it->f)
- : FRAME_LINE_HEIGHT (it->f));
- return OK_PIXELS (XFLOATINT (prop) * base_unit);
- }
-
- if (CONSP (prop))
- {
- Lisp_Object car = XCAR (prop);
- Lisp_Object cdr = XCDR (prop);
-
- if (SYMBOLP (car))
- {
- if (EQ (car, Qplus) || EQ (car, Qminus))
- {
- int first = 1;
- double px;
-
- pixels = 0;
- while (CONSP (cdr))
- {
- if (!calc_pixel_width_or_height (&px, it, XCAR (cdr), font, width_p))
- return 0;
- if (first)
- pixels = (EQ (car, Qplus) ? px : -px), first = 0;
- else
- pixels += px;
- cdr = XCDR (cdr);
- }
- if (EQ (car, Qminus))
- pixels = -pixels;
- return OK_PIXELS (pixels);
- }
-
- if (EQ (car, Qleft_fringe))
- return OK_PIXELS ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
- == !NILP (cdr))
- ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
- : 0);
- if (EQ (car, Qright_fringe))
- return OK_PIXELS ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
- == !NILP (cdr))
- ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
- : 0);
- if (EQ (car, Qscroll_bar))
- return OK_PIXELS ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
- == EQ (cdr, Qleft))
- ? WINDOW_SCROLL_BAR_AREA_WIDTH (it->w)
- : 0);
-
- car = Fbuffer_local_value (car, it->w->buffer);
- }
-
- if (INTEGERP (car) || FLOATP (car))
- {
- double fact;
- pixels = XFLOATINT (car);
- if (NILP (cdr))
- return OK_PIXELS (pixels);
- if (calc_pixel_width_or_height (&fact, it, cdr, font, width_p))
- return OK_PIXELS (pixels * fact);
- return 0;
- }
-
- return 0;
- }
-
- return 0;
-}
-
/* Produce a stretch glyph for iterator IT. IT->object is the value
of the glyph property displayed. The value must be a list
`(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
{
/* (space :width WIDTH :height HEIGHT ...) */
Lisp_Object prop, plist;
- int width = 0, height = 0;
+ int width = 0, height = 0, align_to = -1;
int zero_width_ok_p = 0, zero_height_ok_p = 0;
int ascent = 0;
double tem;
plist = XCDR (it->object);
/* Compute the width of the stretch. */
- if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
- && calc_pixel_width_or_height (&tem, it, prop, font, 1))
+ if ((prop = Fsafe_plist_get (plist, QCwidth), !NILP (prop))
+ && calc_pixel_width_or_height (&tem, it, prop, font, 1, 0))
{
/* Absolute width `:width WIDTH' specified and valid. */
zero_width_ok_p = 1;
width = (int)tem;
}
- else if (prop = Fplist_get (plist, QCrelative_width),
+ else if (prop = Fsafe_plist_get (plist, QCrelative_width),
NUMVAL (prop) > 0)
{
/* Relative width `:relative-width FACTOR' specified and valid.
x_produce_glyphs (&it2);
width = NUMVAL (prop) * it2.pixel_width;
}
- else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
- && calc_pixel_width_or_height (&tem, it, prop, font, 1))
+ else if ((prop = Fsafe_plist_get (plist, QCalign_to), !NILP (prop))
+ && calc_pixel_width_or_height (&tem, it, prop, font, 1, &align_to))
{
- width = max (0, (int)tem - it->current_x);
+ if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
+ align_to = (align_to < 0
+ ? 0
+ : align_to - window_box_left_offset (it->w, TEXT_AREA));
+ else if (align_to < 0)
+ align_to = window_box_left_offset (it->w, TEXT_AREA);
+ width = max (0, (int)tem + align_to - it->current_x);
zero_width_ok_p = 1;
}
else
width = 1;
/* Compute height. */
- if ((prop = Fplist_get (plist, QCheight), !NILP (prop))
- && calc_pixel_width_or_height (&tem, it, prop, font, 0))
+ if ((prop = Fsafe_plist_get (plist, QCheight), !NILP (prop))
+ && calc_pixel_width_or_height (&tem, it, prop, font, 0, 0))
{
height = (int)tem;
zero_height_ok_p = 1;
}
- else if (prop = Fplist_get (plist, QCrelative_height),
+ else if (prop = Fsafe_plist_get (plist, QCrelative_height),
NUMVAL (prop) > 0)
height = FONT_HEIGHT (font) * NUMVAL (prop);
else
/* Compute percentage of height used for ascent. If
`:ascent ASCENT' is present and valid, use that. Otherwise,
derive the ascent from the font in use. */
- if (prop = Fplist_get (plist, QCascent),
+ if (prop = Fsafe_plist_get (plist, QCascent),
NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
ascent = height * NUMVAL (prop) / 100.0;
else if (!NILP (prop)
- && calc_pixel_width_or_height (&tem, it, prop, font, 0))
+ && calc_pixel_width_or_height (&tem, it, prop, font, 0, 0))
ascent = min (max (0, (int)tem), height);
else
ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
take_vertical_position_into_account (it);
}
+/* Calculate line-height and line-spacing properties.
+ An integer value specifies explicit pixel value.
+ A float value specifies relative value to current face height.
+ A cons (float . face-name) specifies relative value to
+ height of specified face font.
+
+ Returns height in pixels, or nil. */
+
+static Lisp_Object
+calc_line_height_property (it, prop, font, boff, total)
+ struct it *it;
+ Lisp_Object prop;
+ XFontStruct *font;
+ int boff, *total;
+{
+ Lisp_Object position, val;
+ Lisp_Object face_name = Qnil;
+ int ascent, descent, height, override;
+
+ if (STRINGP (it->object))
+ position = make_number (IT_STRING_CHARPOS (*it));
+ else if (BUFFERP (it->object))
+ position = make_number (IT_CHARPOS (*it));
+ else
+ return Qnil;
+
+ val = Fget_char_property (position, prop, it->object);
+
+ if (NILP (val))
+ return val;
+
+ if (total && CONSP (val) && EQ (XCAR (val), Qtotal))
+ {
+ *total = 1;
+ val = XCDR (val);
+ }
+
+ if (INTEGERP (val))
+ return val;
+
+ if (CONSP (val))
+ {
+ face_name = XCDR (val);
+ val = XCAR (val);
+ }
+ else if (SYMBOLP (val))
+ {
+ face_name = val;
+ val = Qnil;
+ }
+
+ override = EQ (prop, Qline_height);
+
+ if (NILP (face_name))
+ {
+ font = FRAME_FONT (it->f);
+ boff = FRAME_BASELINE_OFFSET (it->f);
+ }
+ else if (EQ (face_name, Qt))
+ {
+ override = 0;
+ }
+ else
+ {
+ int face_id;
+ struct face *face;
+ struct font_info *font_info;
+
+ face_id = lookup_named_face (it->f, face_name, ' ');
+ if (face_id < 0)
+ return make_number (-1);
+
+ face = FACE_FROM_ID (it->f, face_id);
+ font = face->font;
+ if (font == NULL)
+ return make_number (-1);
+
+ font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+ boff = font_info->baseline_offset;
+ if (font_info->vertical_centering)
+ boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+ }
+
+ ascent = FONT_BASE (font) + boff;
+ descent = FONT_DESCENT (font) - boff;
+
+ if (override)
+ {
+ it->override_ascent = ascent;
+ it->override_descent = descent;
+ it->override_boff = boff;
+ }
+
+ height = ascent + descent;
+ if (FLOATP (val))
+ height = (int)(XFLOAT_DATA (val) * height);
+ else if (INTEGERP (val))
+ height *= XINT (val);
+
+ return make_number (height);
+}
+
+
/* RIF:
Produce glyphs/get display metrics for the display element IT is
loaded with. See the description of struct display_iterator in
x_produce_glyphs (it)
struct it *it;
{
+ int extra_line_spacing = it->extra_line_spacing;
+
it->glyph_not_available_p = 0;
if (it->what == IT_CHARACTER)
pcm = rif->per_char_metric (font, &char2b,
FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
- it->ascent = FONT_BASE (font) + boff;
- it->descent = FONT_DESCENT (font) - boff;
+
+ if (it->override_ascent >= 0)
+ {
+ it->ascent = it->override_ascent;
+ it->descent = it->override_descent;
+ boff = it->override_boff;
+ }
+ else
+ {
+ it->ascent = FONT_BASE (font) + boff;
+ it->descent = FONT_DESCENT (font) - boff;
+ }
if (pcm)
{
else
{
it->glyph_not_available_p = 1;
- it->phys_ascent = FONT_BASE (font) + boff;
- it->phys_descent = FONT_DESCENT (font) - boff;
+ it->phys_ascent = it->ascent;
+ it->phys_descent = it->descent;
it->pixel_width = FONT_WIDTH (font);
}
+ if (it->constrain_row_ascent_descent_p)
+ {
+ if (it->descent > it->max_descent)
+ {
+ it->ascent += it->descent - it->max_descent;
+ it->descent = it->max_descent;
+ }
+ if (it->ascent > it->max_ascent)
+ {
+ it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
+ it->ascent = it->max_ascent;
+ }
+ it->phys_ascent = min (it->phys_ascent, it->ascent);
+ it->phys_descent = min (it->phys_descent, it->descent);
+ extra_line_spacing = 0;
+ }
+
/* If this is a space inside a region of text with
`space-width' property, change its width. */
stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
if (face->overline_p)
it->ascent += 2;
+ if (it->constrain_row_ascent_descent_p)
+ {
+ if (it->ascent > it->max_ascent)
+ it->ascent = it->max_ascent;
+ if (it->descent > it->max_descent)
+ it->descent = it->max_descent;
+ }
+
take_vertical_position_into_account (it);
/* If we have to actually produce glyphs, do it. */
}
else if (it->char_to_display == '\n')
{
- /* A newline has no width but we need the height of the line. */
+ /* A newline has no width but we need the height of the line.
+ But if previous part of the line set a height, don't
+ increase that height */
+
+ Lisp_Object height;
+
+ it->override_ascent = -1;
it->pixel_width = 0;
it->nglyphs = 0;
- it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
- it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
- if (face->box != FACE_NO_BOX
- && face->box_line_width > 0)
+ height = calc_line_height_property(it, Qline_height, font, boff, 0);
+
+ if (it->override_ascent >= 0)
+ {
+ it->ascent = it->override_ascent;
+ it->descent = it->override_descent;
+ boff = it->override_boff;
+ }
+ else
{
- it->ascent += face->box_line_width;
- it->descent += face->box_line_width;
+ it->ascent = FONT_BASE (font) + boff;
+ it->descent = FONT_DESCENT (font) - boff;
+ }
+
+ if (EQ (height, make_number(0)))
+ {
+ if (it->descent > it->max_descent)
+ {
+ it->ascent += it->descent - it->max_descent;
+ it->descent = it->max_descent;
+ }
+ if (it->ascent > it->max_ascent)
+ {
+ it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
+ it->ascent = it->max_ascent;
+ }
+ it->phys_ascent = min (it->phys_ascent, it->ascent);
+ it->phys_descent = min (it->phys_descent, it->descent);
+ it->constrain_row_ascent_descent_p = 1;
+ extra_line_spacing = 0;
+ }
+ else
+ {
+ Lisp_Object spacing;
+ int total = 0;
+
+ it->phys_ascent = it->ascent;
+ it->phys_descent = it->descent;
+
+ if ((it->max_ascent > 0 || it->max_descent > 0)
+ && face->box != FACE_NO_BOX
+ && face->box_line_width > 0)
+ {
+ it->ascent += face->box_line_width;
+ it->descent += face->box_line_width;
+ }
+ if (!NILP (height)
+ && XINT (height) > it->ascent + it->descent)
+ it->ascent = XINT (height) - it->descent;
+
+ spacing = calc_line_height_property(it, Qline_spacing, font, boff, &total);
+ if (INTEGERP (spacing))
+ {
+ extra_line_spacing = XINT (spacing);
+ if (total)
+ extra_line_spacing -= (it->phys_ascent + it->phys_descent);
+ }
}
}
else if (it->char_to_display == '\t')
if (it->area == TEXT_AREA)
it->current_x += it->pixel_width;
- it->descent += it->extra_line_spacing;
+ if (extra_line_spacing > 0)
+ {
+ it->descent += extra_line_spacing;
+ if (extra_line_spacing > it->max_extra_line_spacing)
+ it->max_extra_line_spacing = extra_line_spacing;
+ }
it->max_ascent = max (it->max_ascent, it->ascent);
it->max_descent = max (it->max_descent, it->descent);
if (!cursor_row->enabled_p)
goto mark_cursor_off;
+ /* If line spacing is > 0, old cursor may only be partially visible in
+ window after split-window. So adjust visible height. */
+ cursor_row->visible_height = min (cursor_row->visible_height,
+ window_text_bottom_y (w) - cursor_row->y);
+
/* If row is completely invisible, don't attempt to delete a cursor which
isn't there. This can happen if cursor is at top of a window, and
we switch to a buffer with a header line in that window. */
{
int x, y;
int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+ int width;
cursor_glyph = get_phys_cursor_glyph (w);
if (cursor_glyph == NULL)
x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y));
+ width = min (cursor_glyph->pixel_width,
+ window_box_width (w, TEXT_AREA) - w->phys_cursor.x);
- rif->clear_frame_area (f, x, y,
- cursor_glyph->pixel_width, cursor_row->visible_height);
+ rif->clear_frame_area (f, x, y, width, cursor_row->visible_height);
}
/* Erase the cursor by redrawing the character underneath it. */
{
int cleared = 0;
- if (!NILP (dpyinfo->mouse_face_window))
+ if (!dpyinfo->mouse_face_hidden && !NILP (dpyinfo->mouse_face_window))
{
show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
cleared = 1;
int past_end = 0;
first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+ if (charpos < MATRIX_ROW_START_CHARPOS (first))
+ {
+ *x = first->x;
+ *y = first->y;
+ *hpos = 0;
+ *vpos = MATRIX_ROW_VPOS (first, w->current_matrix);
+ return 1;
+ }
+
row = row_containing_pos (w, charpos, first, NULL, 0);
if (row == NULL)
{
- if (charpos < MATRIX_ROW_START_CHARPOS (first))
- {
- *x = *y = *hpos = *vpos = 0;
- return 1;
- }
- else
- {
- row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
- past_end = 1;
- }
+ row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+ past_end = 1;
}
*x = row->x;
int x0, y0;
/* Need an even number of coordinates, and at least 3 edges. */
- if (n < 6 || n & 1)
+ if (n < 6 || n & 1)
return 0;
/* Count edge segments intersecting line from (X,Y) to (X,infinity).
return inside;
}
}
- else
- return 0;
+ /* If we don't understand the format, pretend we're not in the hot-spot. */
+ return 0;
}
Lisp_Object
return XCAR (map);
map = XCDR (map);
}
-
+
return Qnil;
}
DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
3, 3, 0,
- doc: /* Lookup in image map MAP coordinates X and Y.
+ doc: /* Lookup in image map MAP coordinates X and Y.
An image map is an alist where each element has the format (AREA ID PLIST).
An AREA is specified as either a rectangle, a circle, or a polygon:
A rectangle is a cons (rect . ((x0 . y0) . (x1 . y1))) specifying the
Lisp_Object map;
Lisp_Object x, y;
{
- int ix, iy;
if (NILP (map))
return Qnil;
Cursor cursor;
Lisp_Object pointer;
{
+ /* Do not change cursor shape while dragging mouse. */
+ if (!NILP (do_mouse_tracking))
+ return;
+
if (!NILP (pointer))
{
if (EQ (pointer, Qarrow))
cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
}
-#ifndef HAVE_CARBON
if (cursor != No_Cursor)
-#else
- if (bcmp (&cursor, &No_Cursor, sizeof (Cursor)))
-#endif
rif->define_frame_cursor (f, cursor);
}
Lisp_Object pointer = Qnil;
int charpos, dx, dy, width, height;
Lisp_Object string, object = Qnil;
- Lisp_Object pos, help, image;
+ Lisp_Object pos, help;
if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
string = mode_line_string (w, area, &x, &y, &charpos,
if (IMAGEP (object))
{
Lisp_Object image_map, hotspot;
- if ((image_map = Fplist_get (XCDR (object), QCmap),
+ if ((image_map = Fsafe_plist_get (XCDR (object), QCmap),
!NILP (image_map))
&& (hotspot = find_hot_spot (image_map, dx, dy),
CONSP (hotspot))
/* Could check AREA_ID to see if we enter/leave this hot-spot.
If so, we could look for mouse-enter, mouse-leave
properties in PLIST (and do something...). */
- if ((plist = XCDR (hotspot), CONSP (plist)))
+ hotspot = XCDR (hotspot);
+ if (CONSP (hotspot)
+ && (plist = XCAR (hotspot), CONSP (plist)))
{
- pointer = Fplist_get (plist, Qpointer);
+ pointer = Fsafe_plist_get (plist, Qpointer);
if (NILP (pointer))
pointer = Qhand;
- help = Fplist_get (plist, Qhelp_echo);
+ help = Fsafe_plist_get (plist, Qhelp_echo);
if (!NILP (help))
{
help_echo_string = help;
}
}
if (NILP (pointer))
- pointer = Fplist_get (XCDR (object), QCpointer);
+ pointer = Fsafe_plist_get (XCDR (object), QCpointer);
}
}
/* If we're on a string with `help-echo' text property, arrange
for the help to be displayed. This is done by setting the
global variable help_echo_string to the help string. */
- help = Fget_text_property (pos, Qhelp_echo, string);
- if (!NILP (help))
+ if (NILP (help))
{
- help_echo_string = help;
- XSETWINDOW (help_echo_window, w);
- help_echo_object = string;
- help_echo_pos = charpos;
+ help = Fget_text_property (pos, Qhelp_echo, string);
+ if (!NILP (help))
+ {
+ help_echo_string = help;
+ XSETWINDOW (help_echo_window, w);
+ help_echo_object = string;
+ help_echo_pos = charpos;
+ }
}
if (NILP (pointer))
pointer = Fget_text_property (pos, Qpointer, string);
/* Change the mouse pointer according to what is under X/Y. */
- if (NILP (pointer) && area == ON_MODE_LINE)
+ if (NILP (pointer) && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)))
{
Lisp_Object map;
map = Fget_text_property (pos, Qlocal_map, string);
/* Which window is that in? */
window = window_from_coordinates (f, x, y, &part, 0, 0, 1);
- /* If we were displaying active text in another window, clear that. */
- if (! EQ (window, dpyinfo->mouse_face_window))
+ /* If we were displaying active text in another window, clear that.
+ Also clear if we move out of text area in same window. */
+ if (! EQ (window, dpyinfo->mouse_face_window)
+ || (part != ON_TEXT && !NILP (dpyinfo->mouse_face_window)))
clear_mouse_face (dpyinfo);
/* Not on a window -> return. */
if (part == ON_VERTICAL_BORDER)
cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
- else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE)
+ else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
+ || part == ON_SCROLL_BAR)
cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
else
cursor = FRAME_X_OUTPUT (f)->text_cursor;
Lisp_Object object;
Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
Lisp_Object *overlay_vec = NULL;
- int len, noverlays;
+ int noverlays;
struct buffer *obuf;
int obegv, ozv, same_region;
if (img != NULL && IMAGEP (img->spec))
{
Lisp_Object image_map, hotspot;
- if ((image_map = Fplist_get (XCDR (img->spec), QCmap),
+ if ((image_map = Fsafe_plist_get (XCDR (img->spec), QCmap),
!NILP (image_map))
- && (hotspot = find_hot_spot (image_map, dx, dy),
+ && (hotspot = find_hot_spot (image_map,
+ glyph->slice.x + dx,
+ glyph->slice.y + dy),
CONSP (hotspot))
&& (hotspot = XCDR (hotspot), CONSP (hotspot)))
{
/* Could check AREA_ID to see if we enter/leave this hot-spot.
If so, we could look for mouse-enter, mouse-leave
properties in PLIST (and do something...). */
- if ((plist = XCDR (hotspot), CONSP (plist)))
+ hotspot = XCDR (hotspot);
+ if (CONSP (hotspot)
+ && (plist = XCAR (hotspot), CONSP (plist)))
{
- pointer = Fplist_get (plist, Qpointer);
+ pointer = Fsafe_plist_get (plist, Qpointer);
if (NILP (pointer))
pointer = Qhand;
- help_echo_string = Fplist_get (plist, Qhelp_echo);
+ help_echo_string = Fsafe_plist_get (plist, Qhelp_echo);
if (!NILP (help_echo_string))
{
help_echo_window = window;
}
}
if (NILP (pointer))
- pointer = Fplist_get (XCDR (img->spec), QCpointer);
+ pointer = Fsafe_plist_get (XCDR (img->spec), QCpointer);
}
}
if (BUFFERP (object))
{
- /* Put all the overlays we want in a vector in overlay_vec.
- Store the length in len. If there are more than 10, make
- enough space for all, and try again. */
- len = 10;
- overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
- if (noverlays > len)
- {
- len = noverlays;
- overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
- }
-
+ /* Put all the overlays we want in a vector in overlay_vec. */
+ GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
/* Sort overlays into increasing priority order. */
noverlays = sort_overlays (overlay_vec, noverlays, w);
}
cursor_glyph = get_phys_cursor_glyph (w);
if (cursor_glyph)
{
- /* r is relative to W's box, but w->phys_cursor.x is relative
+ /* r is relative to W's box, but w->phys_cursor.x is relative
to left edge of W's TEXT area. Adjust it. */
cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
cr.y = w->phys_cursor.y;
cr.width = cursor_glyph->pixel_width;
cr.height = w->phys_cursor_height;
- /* ++KFS: W32 version used W32-specific IntersectRect here, but
+ /* ++KFS: W32 version used W32-specific IntersectRect here, but
I assume the effect is the same -- and this is portable. */
return x_intersect_rectangles (&cr, r, &result);
}
struct window *w;
{
/* We could do better, if we knew what type of scroll-bar the adjacent
- windows (on either side) have... But we don't :-(
+ windows (on either side) have... But we don't :-(
However, I think this works ok. ++KFS 2003-04-25 */
/* Redraw borders between horizontally adjacent windows. Don't
do it for frames with vertical scroll bars because either the
right scroll bar of a window, or the left scroll bar of its
neighbor will suffice as a border. */
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (w->frame)))
+ return;
+
if (!WINDOW_RIGHTMOST_P (w)
&& !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
{
staticpro (&Qspace_width);
Qraise = intern ("raise");
staticpro (&Qraise);
+ Qslice = intern ("slice");
+ staticpro (&Qslice);
Qspace = intern ("space");
staticpro (&Qspace);
Qmargin = intern ("margin");
staticpro (&Qleft_margin);
Qright_margin = intern ("right-margin");
staticpro (&Qright_margin);
+ Qcenter = intern ("center");
+ staticpro (&Qcenter);
+ Qline_height = intern ("line-height");
+ staticpro (&Qline_height);
+ Qtotal = intern ("total");
+ staticpro (&Qtotal);
QCalign_to = intern (":align-to");
staticpro (&QCalign_to);
QCrelative_width = intern (":relative-width");
Qinhibit_free_realized_faces = intern ("inhibit-free-realized-faces");
staticpro (&Qinhibit_free_realized_faces);
- list_of_error = Fcons (intern ("error"), Qnil);
+ list_of_error = Fcons (Fcons (intern ("error"),
+ Fcons (intern ("void-variable"), Qnil)),
+ Qnil);
staticpro (&list_of_error);
Qlast_arrow_position = intern ("last-arrow-position");
DEFVAR_LISP ("void-text-area-pointer", &Vvoid_text_area_pointer,
doc: /* *The pointer shape to show in void text areas.
Nil means to show the text pointer. Other options are `arrow', `text',
-`hand', `vdrag', `hdrag', `modeline', and `hourglass'. */);
+`hand', `vdrag', `hdrag', `modeline', and `hourglass'. */);
Vvoid_text_area_pointer = Qarrow;
DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
Vwindow_size_change_functions = Qnil;
DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
- doc: /* List of Functions to call before redisplaying a window with scrolling.
+ doc: /* List of functions to call before redisplaying a window with scrolling.
Each function is called with two arguments, the window
and its new display-start position. Note that the value of `window-end'
is not valid when these functions are called. */);
doc: /* *Non-nil means raise tool-bar buttons when the mouse moves over them. */);
auto_raise_tool_bar_buttons_p = 1;
+ DEFVAR_BOOL ("make-cursor-line-fully-visible", &make_cursor_line_fully_visible_p,
+ doc: /* *Non-nil means to scroll (recenter) cursor line if it is not fully visible. */);
+ make_cursor_line_fully_visible_p = 1;
+
DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin,
doc: /* *Margin around tool-bar buttons in pixels.
If an integer, use that for both horizontal and vertical margins.
and `scroll-right' overrides this variable's effect. */);
Vhscroll_step = make_number (0);
- DEFVAR_LISP ("image-types", &Vimage_types,
- doc: /* List of supported image types.
-Each element of the list is a symbol for a supported image type. */);
- Vimage_types = Qnil;
-
DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines,
doc: /* If non-nil, messages are truncated instead of resizing the echo area.
Bind this around calls to `message' to let it take effect. */);