Lisp_Object Vfontification_functions;
Lisp_Object Qfontification_functions;
-/* Non-zero means automatically select any window when the mouse
+/* Non-nil means automatically select any window when the mouse
cursor moves into it. */
-int mouse_autoselect_window;
+Lisp_Object Vmouse_autoselect_window;
/* Non-zero means draw tool bar buttons raised when the mouse moves
over them. */
Lisp_Object Qinhibit_menubar_update;
int inhibit_menubar_update;
+/* When evaluating expressions from menu bar items (enable conditions,
+ for instance), this is the frame they are being processed for. */
+
+Lisp_Object Vmenu_updating_frame;
+
/* Maximum height for resizing mini-windows. Either a float
specifying a fraction of the available height, or an integer
specifying a number of lines. */
struct buffer *displayed_buffer;
+/* Space between overline and text. */
+
+EMACS_INT overline_margin;
+
/* Value returned from text property handlers (see below). */
enum prop_handled
static Lisp_Object redisplay_window_error ();
static Lisp_Object redisplay_window_0 P_ ((Lisp_Object));
static Lisp_Object redisplay_window_1 P_ ((Lisp_Object));
-static void update_menu_bar P_ ((struct frame *, int));
+static int update_menu_bar P_ ((struct frame *, int, int));
static int try_window_reusing_current_matrix P_ ((struct window *));
static int try_window_id P_ ((struct window *));
static int display_line P_ ((struct it *));
/* Return 1 if position CHARPOS is visible in window W.
+ CHARPOS < 0 means return info about WINDOW_END position.
If visible, set *X and *Y to pixel coordinates of top left corner.
Set *RTOP and *RBOT to pixel height of an invisible area of glyph at POS.
- EXACT_MODE_LINE_HEIGHTS_P non-zero means compute exact mode-line
- and header-lines heights. */
+ Set *ROWH and *VPOS to row's visible height and VPOS (row number). */
int
-pos_visible_p (w, charpos, x, y, rtop, rbot, exact_mode_line_heights_p)
+pos_visible_p (w, charpos, x, y, rtop, rbot, rowh, vpos)
struct window *w;
- int charpos, *x, *y, *rtop, *rbot, exact_mode_line_heights_p;
+ int charpos, *x, *y, *rtop, *rbot, *rowh, *vpos;
{
struct it it;
struct text_pos top;
SET_TEXT_POS_FROM_MARKER (top, w->start);
- /* Compute exact mode line heights, if requested. */
- if (exact_mode_line_heights_p)
- {
- if (WINDOW_WANTS_MODELINE_P (w))
- current_mode_line_height
- = display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w),
- current_buffer->mode_line_format);
+ /* Compute exact mode line heights. */
+ if (WINDOW_WANTS_MODELINE_P (w))
+ current_mode_line_height
+ = display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w),
+ current_buffer->mode_line_format);
- if (WINDOW_WANTS_HEADER_LINE_P (w))
- current_header_line_height
- = display_mode_line (w, HEADER_LINE_FACE_ID,
+ if (WINDOW_WANTS_HEADER_LINE_P (w))
+ current_header_line_height
+ = display_mode_line (w, HEADER_LINE_FACE_ID,
current_buffer->header_line_format);
- }
start_display (&it, w, top);
- move_it_to (&it, charpos, -1, it.last_visible_y, -1,
- MOVE_TO_POS | MOVE_TO_Y);
+ move_it_to (&it, charpos, -1, it.last_visible_y-1, -1,
+ (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
/* Note that we may overshoot because of invisible text. */
- if (IT_CHARPOS (it) >= charpos)
+ if (charpos >= 0 && IT_CHARPOS (it) >= charpos)
{
int top_x = it.current_x;
int top_y = it.current_y;
*y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
*rtop = max (0, window_top_y - top_y);
*rbot = max (0, bottom_y - it.last_visible_y);
+ *rowh = max (0, (min (bottom_y, it.last_visible_y)
+ - max (top_y, window_top_y)));
+ *vpos = it.vpos;
}
}
else
it2 = it;
if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
move_it_by_lines (&it, 1, 0);
- if (charpos < IT_CHARPOS (it))
+ if (charpos < IT_CHARPOS (it)
+ || (it.what == IT_EOB && charpos == IT_CHARPOS (it)))
{
visible_p = 1;
move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
*rtop = max (0, -it2.current_y);
*rbot = max (0, ((it2.current_y + it2.max_ascent + it2.max_descent)
- it.last_visible_y));
+ *rowh = max (0, (min (it2.current_y + it2.max_ascent + it2.max_descent,
+ it.last_visible_y)
+ - max (it2.current_y,
+ WINDOW_HEADER_LINE_HEIGHT (w))));
+ *vpos = it2.vpos;
}
}
if (visible_p && XFASTINT (w->hscroll) > 0)
*x -= XFASTINT (w->hscroll) * WINDOW_FRAME_COLUMN_WIDTH (w);
+#if 0
+ /* Debugging code. */
+ if (visible_p)
+ fprintf (stderr, "+pv pt=%d vs=%d --> x=%d y=%d rt=%d rb=%d rh=%d vp=%d\n",
+ charpos, w->vscroll, *x, *y, *rtop, *rbot, *rowh, *vpos);
+ else
+ fprintf (stderr, "-pv pt=%d vs=%d\n", charpos, w->vscroll);
+#endif
+
return visible_p;
}
/* Try to determine frame pixel position and size of the glyph under
frame pixel coordinates X/Y on frame F. */
- window = window_from_coordinates (f, gx, gy, &part, &x, &y, 0);
- if (NILP (window))
+ if (!f->glyphs_initialized_p
+ || (window = window_from_coordinates (f, gx, gy, &part, &x, &y, 0),
+ NILP (window)))
{
width = FRAME_SMALLEST_CHAR_WIDTH (f);
height = FRAME_SMALLEST_FONT_HEIGHT (f);
return;
if (!get_overlay_strings_1 (it, 0, 0))
return;
+ it->ignore_overlay_strings_at_pos_p = 1;
it->string_from_display_prop_p = 0;
handle_overlay_change_p = 0;
handled = HANDLED_RECOMPUTE_PROPS;
&& !NILP (Vrun_hooks)
&& (pos = make_number (IT_CHARPOS (*it)),
prop = Fget_char_property (pos, Qfontified, Qnil),
- NILP (prop)))
+ /* Ignore the special cased nil value always present at EOB since
+ no amount of fontifying will be able to change it. */
+ NILP (prop) && IT_CHARPOS (*it) < Z))
{
int count = SPECPDL_INDEX ();
Lisp_Object val;
{
Lisp_Object form;
Lisp_Object location, value;
- struct text_pos start_pos;
+ struct text_pos start_pos, save_pos;
int valid_p;
/* If SPEC is a list of the form `(when FORM . VALUE)', evaluate FORM.
/* Save current settings of IT so that we can restore them
when we are finished with the glyph property value. */
+ save_pos = it->position;
+ it->position = *position;
push_it (it);
+ it->position = save_pos;
it->area = TEXT_AREA;
it->what = IT_IMAGE;
{
/* Save current settings of IT so that we can restore them
when we are finished with the glyph property value. */
+ save_pos = it->position;
+ it->position = *position;
push_it (it);
+ it->position = save_pos;
if (NILP (location))
it->area = TEXT_AREA;
}
return HANDLED_RECOMPUTE_PROPS;
}
+
+ it->stop_charpos = end;
+ push_it (it);
+
it->method = GET_FROM_COMPOSITION;
it->cmp_id = id;
it->cmp_len = COMPOSITION_LENGTH (prop);
it->len = (STRINGP (it->string)
? string_char_to_byte (it->string, end)
: CHAR_TO_BYTE (end)) - pos_byte;
- it->stop_charpos = end;
handled = HANDLED_RETURN;
}
}
pop_it (it);
xassert (it->sp > 0
+ || it->method == GET_FROM_COMPOSITION
|| (NILP (it->string)
&& it->method == GET_FROM_BUFFER
&& it->stop_charpos >= BEGV
p->stop_charpos = it->stop_charpos;
xassert (it->face_id >= 0);
p->face_id = it->face_id;
- p->image_id = it->image_id;
+ p->string = it->string;
p->method = it->method;
- if (it->method == GET_FROM_IMAGE)
- p->string = it->object;
- else
- p->string = it->string;
- p->pos = it->current;
+ switch (p->method)
+ {
+ case GET_FROM_IMAGE:
+ p->u.image.object = it->object;
+ p->u.image.image_id = it->image_id;
+ p->u.image.slice = it->slice;
+ break;
+ case GET_FROM_COMPOSITION:
+ p->u.comp.object = it->object;
+ p->u.comp.c = it->c;
+ p->u.comp.len = it->len;
+ p->u.comp.cmp_id = it->cmp_id;
+ p->u.comp.cmp_len = it->cmp_len;
+ break;
+ case GET_FROM_STRETCH:
+ p->u.stretch.object = it->object;
+ break;
+ }
+ p->position = it->position;
+ p->current = it->current;
p->end_charpos = it->end_charpos;
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;
p = it->stack + it->sp;
it->stop_charpos = p->stop_charpos;
it->face_id = p->face_id;
+ it->current = p->current;
+ it->position = p->position;
+ it->string = p->string;
+ if (NILP (it->string))
+ SET_TEXT_POS (it->current.string_pos, -1, -1);
it->method = p->method;
- it->image_id = p->image_id;
- it->current = p->pos;
- if (it->method == GET_FROM_IMAGE)
+ switch (it->method)
{
+ case GET_FROM_IMAGE:
+ it->image_id = p->u.image.image_id;
+ it->object = p->u.image.object;
+ it->slice = p->u.image.slice;
+ break;
+ case GET_FROM_COMPOSITION:
+ it->object = p->u.comp.object;
+ it->c = p->u.comp.c;
+ it->len = p->u.comp.len;
+ it->cmp_id = p->u.comp.cmp_id;
+ it->cmp_len = p->u.comp.cmp_len;
+ break;
+ case GET_FROM_STRETCH:
+ it->object = p->u.comp.object;
+ break;
+ case GET_FROM_BUFFER:
+ it->object = it->w->buffer;
+ break;
+ case GET_FROM_STRING:
it->object = it->string;
- it->string = Qnil;
+ break;
}
- else
- it->string = p->string;
- if (NILP (it->string))
- SET_TEXT_POS (it->current.string_pos, -1, -1);
it->end_charpos = p->end_charpos;
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;
while (IT_CHARPOS (*it) > BEGV)
{
back_to_previous_line_start (it);
+
if (IT_CHARPOS (*it) <= BEGV)
break;
continue;
}
- /* If newline has a display property that replaces the newline with something
- else (image or text), find start of overlay or interval and continue search
- from that point. */
- if (IT_CHARPOS (*it) > BEGV)
- {
- struct it it2 = *it;
- int pos;
- int beg, end;
- Lisp_Object val, overlay;
-
- pos = --IT_CHARPOS (it2);
- --IT_BYTEPOS (it2);
- it2.sp = 0;
- if (handle_display_prop (&it2) == HANDLED_RETURN
- && !NILP (val = get_char_property_and_overlay
- (make_number (pos), Qdisplay, Qnil, &overlay))
- && (OVERLAYP (overlay)
- ? (beg = OVERLAY_POSITION (OVERLAY_START (overlay)))
- : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
- {
- if (beg < BEGV)
- beg = BEGV;
- IT_CHARPOS (*it) = beg;
- IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
- continue;
- }
- }
+ if (IT_CHARPOS (*it) <= BEGV)
+ break;
- break;
+ {
+ struct it it2;
+ int pos;
+ int beg, end;
+ Lisp_Object val, overlay;
+
+ /* If newline is part of a composition, continue from start of composition */
+ if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil)
+ && beg < IT_CHARPOS (*it))
+ goto replaced;
+
+ /* If newline is replaced by a display property, find start of overlay
+ or interval and continue search from that point. */
+ it2 = *it;
+ pos = --IT_CHARPOS (it2);
+ --IT_BYTEPOS (it2);
+ it2.sp = 0;
+ if (handle_display_prop (&it2) == HANDLED_RETURN
+ && !NILP (val = get_char_property_and_overlay
+ (make_number (pos), Qdisplay, Qnil, &overlay))
+ && (OVERLAYP (overlay)
+ ? (beg = OVERLAY_POSITION (OVERLAY_START (overlay)))
+ : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
+ goto replaced;
+
+ /* Newline is not replaced by anything -- so we are done. */
+ break;
+
+ replaced:
+ if (beg < BEGV)
+ beg = BEGV;
+ IT_CHARPOS (*it) = beg;
+ IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
+ }
}
it->continuation_lines_width = 0;
xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
it->current.pos = it->position = pos;
- XSETBUFFER (it->object, current_buffer);
it->end_charpos = ZV;
it->dpvec = NULL;
it->current.dpvec_index = -1;
IT_STRING_BYTEPOS (*it) = -1;
it->string = Qnil;
it->method = GET_FROM_BUFFER;
+ it->object = it->w->buffer;
it->area = TEXT_AREA;
it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
it->sp = 0;
case GET_FROM_COMPOSITION:
xassert (it->cmp_id >= 0 && it->cmp_id < n_compositions);
- if (STRINGP (it->string))
+ xassert (it->sp > 0);
+ pop_it (it);
+ if (it->method == GET_FROM_STRING)
{
IT_STRING_BYTEPOS (*it) += it->len;
IT_STRING_CHARPOS (*it) += it->cmp_len;
- it->method = GET_FROM_STRING;
goto consider_string_end;
}
- else
+ else if (it->method == GET_FROM_BUFFER)
{
IT_BYTEPOS (*it) += it->len;
IT_CHARPOS (*it) += it->cmp_len;
- it->method = GET_FROM_BUFFER;
}
break;
else if (STRINGP (it->string))
it->method = GET_FROM_STRING;
else
- it->method = GET_FROM_BUFFER;
+ {
+ it->method = GET_FROM_BUFFER;
+ it->object = it->w->buffer;
+ }
it->dpvec = NULL;
it->current.dpvec_index = -1;
}
}
- /* Record what we have and where it came from. Note that we store a
- buffer position in IT->position although it could arguably be a
- string position. */
+ /* Record what we have and where it came from. */
it->what = IT_CHARACTER;
it->object = it->string;
it->position = position;
setting face_before_selective_p. */
it->saved_face_id = it->face_id;
it->method = GET_FROM_BUFFER;
+ it->object = it->w->buffer;
reseat_at_next_visible_line_start (it, 1);
it->face_before_selective_p = 1;
}
: it->current.pos);
if (STRINGP (it->string))
it->object = it->string;
+ else
+ it->object = it->w->buffer;
return 1;
}
if (reached)
break;
}
+ else if (BUFFERP (it->object)
+ && it->method == GET_FROM_BUFFER
+ && IT_CHARPOS (*it) >= to_charpos)
+ skip = MOVE_POS_MATCH_OR_ZV;
else
skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
{
Lisp_Object tail, frame;
int count = SPECPDL_INDEX ();
+ /* 1 means that update_menu_bar has run its hooks
+ so any further calls to update_menu_bar shouldn't do so again. */
+ int menu_bar_hooks_run = 0;
record_unwind_save_match_data ();
}
GCPRO1 (tail);
- update_menu_bar (f, 0);
+ menu_bar_hooks_run = update_menu_bar (f, 0, menu_bar_hooks_run);
#ifdef HAVE_WINDOW_SYSTEM
update_tool_bar (f, 0);
#ifdef MAC_OS
else
{
struct frame *sf = SELECTED_FRAME ();
- update_menu_bar (sf, 1);
+ update_menu_bar (sf, 1, 0);
#ifdef HAVE_WINDOW_SYSTEM
update_tool_bar (sf, 1);
#ifdef MAC_OS
before we start to fill in any display lines, because it can call
eval.
- If SAVE_MATCH_DATA is non-zero, we must save and restore it here. */
+ If SAVE_MATCH_DATA is non-zero, we must save and restore it here.
-static void
-update_menu_bar (f, save_match_data)
+ If HOOKS_RUN is 1, that means a previous call to update_menu_bar
+ already ran the menu bar hooks for this redisplay, so there
+ is no need to run them again. The return value is the
+ updated value of this flag, to pass to the next call. */
+
+static int
+update_menu_bar (f, save_match_data, hooks_run)
struct frame *f;
int save_match_data;
+ int hooks_run;
{
Lisp_Object window;
register struct window *w;
happen when, for instance, an activate-menubar-hook causes a
redisplay. */
if (inhibit_menubar_update)
- return;
+ return hooks_run;
window = FRAME_SELECTED_WINDOW (f);
w = XWINDOW (window);
specbind (Qoverriding_local_map, Qnil);
}
- /* Run the Lucid hook. */
- safe_run_hooks (Qactivate_menubar_hook);
+ if (!hooks_run)
+ {
+ /* Run the Lucid hook. */
+ safe_run_hooks (Qactivate_menubar_hook);
+
+ /* If it has changed current-menubar from previous value,
+ really recompute the menu-bar from the value. */
+ if (! NILP (Vlucid_menu_bar_dirty_flag))
+ call0 (Qrecompute_lucid_menubar);
- /* If it has changed current-menubar from previous value,
- really recompute the menu-bar from the value. */
- if (! NILP (Vlucid_menu_bar_dirty_flag))
- call0 (Qrecompute_lucid_menubar);
+ safe_run_hooks (Qmenu_bar_update_hook);
- safe_run_hooks (Qmenu_bar_update_hook);
+ hooks_run = 1;
+ }
+
+ XSETFRAME (Vmenu_updating_frame, f);
FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
/* Redisplay the menu bar in case we changed it. */
set_buffer_internal_1 (prev);
}
}
+
+ return hooks_run;
}
&new_n_tool_bar);
/* Redisplay the tool-bar if we changed it. */
- if (NILP (Fequal (new_tool_bar, f->tool_bar_items)))
+ if (new_n_tool_bar != f->n_tool_bar_items
+ || 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
/* Glyph doesn't fit on line. Backtrack. */
row->used[TEXT_AREA] = n_glyphs_before;
*it = it_before;
+ /* If this is the only glyph on this line, it will never fit on the
+ toolbar, so skip it. But ensure there is at least one glyph,
+ so we don't accidentally disable the tool-bar. */
+ if (n_glyphs_before == 0
+ && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
+ break;
goto out;
}
}
+/* Max tool-bar height. */
+
+#define MAX_FRAME_TOOL_BAR_HEIGHT(f) \
+ ((FRAME_LINE_HEIGHT (f) * FRAME_LINES (f)))
+
/* Value is the number of screen lines needed to make all tool-bar
items of frame F visible. The number of actual rows needed is
returned in *N_ROWS if non-NULL. */
{
struct window *w = XWINDOW (f->tool_bar_window);
struct it it;
- struct glyph_row *temp_row = w->desired_matrix->rows;
+ /* tool_bar_lines_needed is called from redisplay_tool_bar after building
+ the desired matrix, so use (unused) mode-line row as temporary row to
+ avoid destroying the first tool-bar row. */
+ struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
/* Initialize an iterator for iteration over
F->desired_tool_bar_string in the tool-bar window of frame F. */
int old_height = WINDOW_TOTAL_LINES (w);
XSETFRAME (frame, f);
- clear_glyph_matrix (w->desired_matrix);
Fmodify_frame_parameters (frame,
Fcons (Fcons (Qtool_bar_lines,
make_number (nlines)),
Qnil));
if (WINDOW_TOTAL_LINES (w) != old_height)
{
+ clear_glyph_matrix (w->desired_matrix);
fonts_changed_p = 1;
return 1;
}
if (auto_resize_tool_bars_p)
{
- int nlines;
+ int nlines, nrows;
+ int max_tool_bar_height = MAX_FRAME_TOOL_BAR_HEIGHT (f);
/* If we couldn't display everything, change the tool-bar's
- height. */
- if (IT_STRING_CHARPOS (it) < it.end_charpos)
+ height if there is room for more. */
+ if (IT_STRING_CHARPOS (it) < it.end_charpos
+ && it.current_y < max_tool_bar_height)
change_height_p = 1;
+ row = it.glyph_row - 1;
+
/* If there are blank lines at the end, except for a partially
visible blank line at the end that is smaller than
FRAME_LINE_HEIGHT, change the tool-bar's height. */
- row = it.glyph_row - 1;
if (!row->displays_text_p
&& row->height >= FRAME_LINE_HEIGHT (f))
change_height_p = 1;
/* If row displays tool-bar items, but is partially visible,
change the tool-bar's height. */
if (row->displays_text_p
- && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
+ && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y
+ && MATRIX_ROW_BOTTOM_Y (row) < max_tool_bar_height)
change_height_p = 1;
/* Resize windows as needed by changing the `tool-bar-lines'
frame parameter. */
if (change_height_p
- && (nlines = tool_bar_lines_needed (f, &f->n_tool_bar_rows),
+ && (nlines = tool_bar_lines_needed (f, &nrows),
nlines != WINDOW_TOTAL_LINES (w)))
{
extern Lisp_Object Qtool_bar_lines;
int old_height = WINDOW_TOTAL_LINES (w);
XSETFRAME (frame, f);
- clear_glyph_matrix (w->desired_matrix);
Fmodify_frame_parameters (frame,
Fcons (Fcons (Qtool_bar_lines,
make_number (nlines)),
Qnil));
if (WINDOW_TOTAL_LINES (w) != old_height)
- fonts_changed_p = 1;
+ {
+ clear_glyph_matrix (w->desired_matrix);
+ f->n_tool_bar_rows = nrows;
+ fonts_changed_p = 1;
+ }
}
}
int preserve_echo_area;
{
struct window *w = XWINDOW (selected_window);
- struct frame *f = XFRAME (w->frame);
+ struct frame *f;
int pause;
int must_finish = 0;
struct text_pos tlbufpos, tlendpos;
int number_of_visible_frames;
int count;
- struct frame *sf = SELECTED_FRAME ();
+ struct frame *sf;
int polling_stopped_here = 0;
/* Non-zero means redisplay has to consider all windows on all
initialized, or redisplay is explicitly turned off by setting
Vinhibit_redisplay. */
if (noninteractive
- || !NILP (Vinhibit_redisplay)
- || !f->glyphs_initialized_p)
+ || !NILP (Vinhibit_redisplay))
+ return;
+
+ /* Don't examine these until after testing Vinhibit_redisplay.
+ When Emacs is shutting down, perhaps because its connection to
+ X has dropped, we should not look at them at all. */
+ f = XFRAME (w->frame);
+ sf = SELECTED_FRAME ();
+
+ if (!f->glyphs_initialized_p)
return;
/* The flag redisplay_performed_directly_p is set by
}
else
{
- string_before_pos = last_pos;
- string_start = glyph;
- string_start_x = x;
+ if (string_start == NULL)
+ {
+ string_before_pos = last_pos;
+ string_start = glyph;
+ string_start_x = x;
+ }
/* Skip all glyphs from string. */
do
{
glyph on point by scanning from string_start again. */
Lisp_Object limit;
Lisp_Object string;
+ struct glyph *stop = glyph;
int pos;
limit = make_number (pt_old + 1);
- end = glyph;
glyph = string_start;
x = string_start_x;
string = glyph->object;
pos = string_buffer_position (w, string, string_before_pos);
/* If STRING is from overlay, LAST_POS == 0. We skip such glyphs
because we always put cursor after overlay strings. */
- while (pos == 0 && glyph < end)
+ while (pos == 0 && glyph < stop)
{
string = glyph->object;
- SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
- if (glyph < end)
+ SKIP_GLYPHS (glyph, stop, x, EQ (glyph->object, string));
+ if (glyph < stop)
pos = string_buffer_position (w, glyph->object, string_before_pos);
}
- while (glyph < end)
+ while (glyph < stop)
{
pos = XINT (Fnext_single_char_property_change
(make_number (pos), Qdisplay, Qnil, limit));
break;
/* Skip glyphs from the same string. */
string = glyph->object;
- SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
+ SKIP_GLYPHS (glyph, stop, x, EQ (glyph->object, string));
/* Skip glyphs from an overlay. */
- while (glyph < end
+ while (glyph < stop
&& ! string_buffer_position (w, glyph->object, pos))
{
string = glyph->object;
- SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
+ SKIP_GLYPHS (glyph, stop, x, EQ (glyph->object, string));
}
}
window_height = window_box_height (w);
if (row->height >= window_height)
{
- if (!force_p || MINI_WINDOW_P (w) || w->vscroll)
+ if (!force_p || MINI_WINDOW_P (w)
+ || w->vscroll || w->cursor.vpos == 0)
return 1;
}
return 0;
this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
- if ((w->cursor.y < this_scroll_margin
+ if ((w->cursor.y >= 0 /* not vscrolled */
+ && w->cursor.y < this_scroll_margin
&& CHARPOS (pos) > BEGV
&& IT_CHARPOS (it) < ZV)
/* rms: considering make_cursor_line_fully_visible_p here
int count = SPECPDL_INDEX ();
init_iterator (&it, w, -1, -1, NULL, face_id);
+ /* Don't extend on a previously drawn mode-line.
+ This may happen if called from pos_visible_p. */
+ it.glyph_row->enabled_p = 0;
prepare_desired_row (it.glyph_row);
it.glyph_row->mode_line_p = 1;
kboard-local variables in the mode_line_format will get the right
values. */
push_frame_kboard (it.f);
+ record_unwind_save_match_data ();
display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
pop_frame_kboard ();
break;
case 'c':
- {
- int col = (int) current_column (); /* iftc */
- w->column_number_displayed = make_number (col);
- pint2str (decode_mode_spec_buf, field_width, col);
- return decode_mode_spec_buf;
- }
+ /* %c and %l are ignored in `frame-title-format'.
+ (In redisplay_internal, the frame title is drawn _before_ the
+ windows are updated, so the stuff which depends on actual
+ window contents (such as %l) may fail to render properly, or
+ even crash emacs.) */
+ if (mode_line_target == MODE_LINE_TITLE)
+ return "";
+ else
+ {
+ int col = (int) current_column (); /* iftc */
+ w->column_number_displayed = make_number (col);
+ pint2str (decode_mode_spec_buf, field_width, col);
+ return decode_mode_spec_buf;
+ }
case 'e':
#ifndef SYSTEM_MALLOC
case 'l':
{
- int startpos = XMARKER (w->start)->charpos;
- int startpos_byte = marker_byte_position (w->start);
- int line, linepos, linepos_byte, topline;
- int nlines, junk;
- int height = WINDOW_TOTAL_LINES (w);
+ int startpos, startpos_byte, line, linepos, linepos_byte;
+ int topline, nlines, junk, height;
+
+ /* %c and %l are ignored in `frame-title-format'. */
+ if (mode_line_target == MODE_LINE_TITLE)
+ return "";
+
+ startpos = XMARKER (w->start)->charpos;
+ startpos_byte = marker_byte_position (w->start);
+ height = WINDOW_TOTAL_LINES (w);
/* If we decided that this buffer isn't suitable for line numbers,
don't forget that too fast. */
{
struct image *img;
struct face *face;
- int glyph_ascent;
+ int glyph_ascent, crop;
struct glyph_slice slice;
xassert (it->what == IT_IMAGE);
take_vertical_position_into_account (it);
+ /* Automatically crop wide image glyphs at right edge so we can
+ draw the cursor on same display row. */
+ if ((crop = it->pixel_width - (it->last_visible_x - it->current_x), crop > 0)
+ && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
+ {
+ it->pixel_width -= crop;
+ slice.width -= crop;
+ }
+
if (it->glyph_row)
{
struct glyph *glyph;
/* If face has an overline, add the height of the overline
(1 pixel) and a 1 pixel margin to the character height. */
if (face->overline_p)
- it->ascent += 2;
+ it->ascent += overline_margin;
if (it->constrain_row_ascent_descent_p)
{
/* If face has an overline, add the height of the overline
(1 pixel) and a 1 pixel margin to the character height. */
if (face->overline_p)
- it->ascent += 2;
+ it->ascent += overline_margin;
take_vertical_position_into_account (it);
/* If face has an overline, add the height of the overline
(1 pixel) and a 1 pixel margin to the character height. */
if (face->overline_p)
- it->ascent += 2;
+ it->ascent += overline_margin;
take_vertical_position_into_account (it);
/* Use normal cursor if not blinked off. */
if (!w->cursor_off_p)
{
- if (glyph != NULL && glyph->type == IMAGE_GLYPH) {
- if (cursor_type == FILLED_BOX_CURSOR)
- cursor_type = HOLLOW_BOX_CURSOR;
+#ifdef HAVE_WINDOW_SYSTEM
+ if (glyph != NULL && glyph->type == IMAGE_GLYPH)
+ {
+ if (cursor_type == FILLED_BOX_CURSOR)
+ {
+ /* Using a block cursor on large images can be very annoying.
+ So use a hollow cursor for "large" images.
+ If image is not transparent (no mask), also use hollow cursor. */
+ struct image *img = IMAGE_FROM_ID (f, glyph->u.img_id);
+ if (img != NULL && IMAGEP (img->spec))
+ {
+ /* Arbitrarily, interpret "Large" as >32x32 and >NxN
+ where N = size of default frame font size.
+ This should cover most of the "tiny" icons people may use. */
+ if (!img->mask
+ || img->width > max (32, WINDOW_FRAME_COLUMN_WIDTH (w))
+ || img->height > max (32, WINDOW_FRAME_LINE_HEIGHT (w)))
+ cursor_type = HOLLOW_BOX_CURSOR;
+ }
+ }
+ else if (cursor_type != NO_CURSOR)
+ {
+ /* Display current only supports BOX and HOLLOW cursors for images.
+ So for now, unconditionally use a HOLLOW cursor when cursor is
+ not a solid box cursor. */
+ cursor_type = HOLLOW_BOX_CURSOR;
+ }
}
+#endif
return cursor_type;
}
DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
doc: /* Template for displaying the title bar of visible frames.
\(Assuming the window manager supports this feature.)
-This variable has the same structure as `mode-line-format' (which see),
-and is used only on frames for which no explicit name has been set
-\(see `modify-frame-parameters'). */);
+
+This variable has the same structure as `mode-line-format', except that
+the %c and %l constructs are ignored. It is used only on frames for
+which no explicit name has been set \(see `modify-frame-parameters'). */);
DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
doc: /* Template for displaying the title bar of an iconified frame.
See `set-window-redisplay-end-trigger'. */);
Vredisplay_end_trigger_functions = Qnil;
- DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
- doc: /* *Non-nil means autoselect window with mouse pointer. */);
- mouse_autoselect_window = 0;
+ DEFVAR_LISP ("mouse-autoselect-window", &Vmouse_autoselect_window,
+ doc: /* *Non-nil means autoselect window with mouse pointer.
+If nil, do not autoselect windows.
+A positive number means delay autoselection by that many seconds: a
+window is autoselected only after the mouse has remained in that
+window for the duration of the delay.
+A negative number has a similar effect, but causes windows to be
+autoselected only after the mouse has stopped moving. \(Because of
+the way Emacs compares mouse events, you will occasionally wait twice
+that time before the window gets selected.\)
+Any other value means to autoselect window instantaneously when the
+mouse pointer enters it.
+
+Autoselection selects the minibuffer only if it is active, and never
+unselects the minibuffer if it is active. */);
+ Vmouse_autoselect_window = Qnil;
DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
doc: /* *Non-nil means automatically resize tool-bars.
whose contents depend on various data. */);
Vmenu_bar_update_hook = Qnil;
+ DEFVAR_LISP ("menu-updating-frame", &Vmenu_updating_frame,
+ doc: /* Frame for which we are updating a menu.
+The enable predicate for a menu binding should check this variable. */);
+ Vmenu_updating_frame = Qnil;
+
DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update,
doc: /* Non-nil means don't update menu bars. Internal use only. */);
inhibit_menubar_update = 0;
doc: /* Inhibit try_cursor_movement display optimization. */);
inhibit_try_cursor_movement = 0;
#endif /* GLYPH_DEBUG */
+
+ DEFVAR_INT ("overline-margin", &overline_margin,
+ doc: /* *Space between overline and text, in pixels.
+The default value is 2: the height of the overline (1 pixel) plus 1 pixel
+margin to the caracter height. */);
+ overline_margin = 2;
}