/* Display generation from window structure and buffer text.
-Copyright (C) 1985-1988, 1993-1995, 1997-2012 Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-1995, 1997-2012 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "window.h"
#include "termchar.h"
#include "dispextern.h"
-#include "buffer.h"
#include "character.h"
+#include "buffer.h"
#include "charset.h"
#include "indent.h"
#include "commands.h"
int redisplaying_p;
static Lisp_Object Qinhibit_free_realized_faces;
+static Lisp_Object Qmode_line_default_help_echo;
/* If a string, XTread_socket generates an event to display that string.
(The display is done in read_char.) */
onto the stack one more time, which is not
expected by the rest of the code that processes
overlay strings. */
- || (it->n_overlay_strings <= 0
+ || (it->current.overlay_string_index < 0
? !get_overlay_strings_1 (it, 0, 0)
: 0))
{
int i;
Lisp_Object from_overlay
= (it->current.overlay_string_index >= 0
- ? it->string_overlays[it->current.overlay_string_index]
+ ? it->string_overlays[it->current.overlay_string_index
+ % OVERLAY_STRING_CHUNK_SIZE]
: Qnil);
/* See if we got to this string directly or indirectly from
{
if (it->stack[i].current.overlay_string_index >= 0)
from_overlay
- = it->string_overlays[it->stack[i].current.overlay_string_index];
+ = it->string_overlays[it->stack[i].current.overlay_string_index
+ % OVERLAY_STRING_CHUNK_SIZE];
else if (! NILP (it->stack[i].from_overlay))
from_overlay = it->stack[i].from_overlay;
len = doprnt (FRAME_MESSAGE_BUF (f),
FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, ap);
- message2 (FRAME_MESSAGE_BUF (f), len, 0);
+ message2 (FRAME_MESSAGE_BUF (f), len, 1);
}
else
message1 (0);
|| update_mode_lines
|| ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
< BUF_MODIFF (XBUFFER (w->buffer)))
- != !NILP (w->last_had_star))
+ != w->last_had_star)
|| ((!NILP (Vtransient_mark_mode)
&& !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
!= !NILP (w->region_showing)))
else
/* On a terminal screen, the menu bar is an ordinary screen
line, and this makes it get updated. */
- w->update_mode_line = Qt;
+ w->update_mode_line = 1;
#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || HAVE_NS || USE_GTK) */
/* In the non-toolkit version, the menu bar is an ordinary screen
line, and this makes it get updated. */
- w->update_mode_line = Qt;
+ w->update_mode_line = 1;
#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || HAVE_NS || USE_GTK) */
unbind_to (count, Qnil);
the rest of the redisplay algorithm is about the same as
windows_or_buffers_changed anyway. */
if (windows_or_buffers_changed
- || !NILP (w->update_mode_line)
+ || w->update_mode_line
|| update_mode_lines
|| ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
< BUF_MODIFF (XBUFFER (w->buffer)))
- != !NILP (w->last_had_star))
+ != w->last_had_star)
|| ((!NILP (Vtransient_mark_mode)
&& !NILP (BVAR (XBUFFER (w->buffer), mark_active)))
!= !NILP (w->region_showing)))
BLOCK_INPUT;
f->tool_bar_items = new_tool_bar;
f->n_tool_bar_items = new_n_tool_bar;
- w->update_mode_line = Qt;
+ w->update_mode_line = 1;
UNBLOCK_INPUT;
}
update_mode_lines++;
/* Detect case that we need to write or remove a star in the mode line. */
- if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
+ if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
{
- w->update_mode_line = Qt;
+ w->update_mode_line = 1;
if (buffer_shared > 1)
update_mode_lines++;
}
&& XFASTINT (w->last_modified) >= MODIFF
&& XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
&& (XFASTINT (w->column_number_displayed) != current_column ()))
- w->update_mode_line = Qt;
+ w->update_mode_line = 1;
unbind_to (count1, Qnil);
tlendpos = this_line_end_pos;
if (!consider_all_windows_p
&& CHARPOS (tlbufpos) > 0
- && NILP (w->update_mode_line)
+ && !w->update_mode_line
&& !current_buffer->clip_changed
&& !current_buffer->prevent_redisplay_optimizations_p
&& FRAME_VISIBLE_P (XFRAME (w->frame))
/* Make sure recorded data applies to current buffer, etc. */
&& this_line_buffer == current_buffer
&& current_buffer == XBUFFER (w->buffer)
- && NILP (w->force_start)
- && NILP (w->optional_new_start)
+ && !w->force_start
+ && !w->optional_new_start
/* Point must be on the line that we have info recorded about. */
&& PT >= CHARPOS (tlbufpos)
&& PT <= Z - CHARPOS (tlendpos)
w->last_overlay_modified
= make_number (accurate_p ? BUF_OVERLAY_MODIFF (b) : 0);
w->last_had_star
- = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b) ? Qt : Qnil;
+ = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
if (accurate_p)
{
if (accurate_p)
{
w->window_end_valid = w->buffer;
- w->update_mode_line = Qnil;
+ w->update_mode_line = 0;
}
}
break;
}
/* See if we've found a better approximation to
- POS_BEFORE or to POS_AFTER. Note that we want the
- first (leftmost) glyph of all those that are the
- closest from below, and the last (rightmost) of all
- those from above. */
+ POS_BEFORE or to POS_AFTER. */
if (0 > dpos && dpos > pos_before - pt_old)
{
pos_before = glyph->charpos;
glyph_before = glyph;
}
- else if (0 < dpos && dpos <= pos_after - pt_old)
+ else if (0 < dpos && dpos < pos_after - pt_old)
{
pos_after = glyph->charpos;
glyph_after = glyph;
pos_before = glyph->charpos;
glyph_before = glyph;
}
- else if (0 < dpos && dpos <= pos_after - pt_old)
+ else if (0 < dpos && dpos < pos_after - pt_old)
{
pos_after = glyph->charpos;
glyph_after = glyph;
the cursor is not on this line. */
if (cursor == NULL
&& (row->reversed_p ? glyph <= end : glyph >= end)
+ && (row->reversed_p ? end > glyphs_end : end < glyphs_end)
&& STRINGP (end->object)
&& row->continued_p)
return 0;
compute_x:
if (cursor != NULL)
glyph = cursor;
+ else if (glyph == glyphs_end
+ && pos_before == pos_after
+ && STRINGP ((row->reversed_p
+ ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
+ : row->glyphs[TEXT_AREA])->object))
+ {
+ /* If all the glyphs of this row came from strings, put the
+ cursor on the first glyph of the row. This avoids having the
+ cursor outside of the text area in this very rare and hard
+ use case. */
+ glyph =
+ row->reversed_p
+ ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
+ : row->glyphs[TEXT_AREA];
+ }
if (x < 0)
{
struct glyph *g;
reconsider_clip_changes (w, buffer);
/* Has the mode line to be updated? */
- update_mode_line = (!NILP (w->update_mode_line)
+ update_mode_line = (w->update_mode_line
|| update_mode_lines
|| buffer->clip_changed
|| buffer->prevent_redisplay_optimizations_p);
/* If someone specified a new starting point but did not insist,
check whether it can be used. */
- if (!NILP (w->optional_new_start)
+ if (w->optional_new_start
&& CHARPOS (startp) >= BEGV
&& CHARPOS (startp) <= ZV)
{
- w->optional_new_start = Qnil;
+ w->optional_new_start = 0;
start_display (&it, w, startp);
move_it_to (&it, PT, 0, it.last_visible_y, -1,
MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
if (IT_CHARPOS (it) == PT)
- w->force_start = Qt;
+ w->force_start = 1;
/* IT may overshoot PT if text at PT is invisible. */
else if (IT_CHARPOS (it) > PT && CHARPOS (startp) <= PT)
- w->force_start = Qt;
+ w->force_start = 1;
}
force_start:
/* Handle case where place to start displaying has been specified,
unless the specified location is outside the accessible range. */
- if (!NILP (w->force_start)
- || w->frozen_window_start_p)
+ if (w->force_start || w->frozen_window_start_p)
{
/* We set this later on if we have to adjust point. */
int new_vpos = -1;
- w->force_start = Qnil;
+ w->force_start = 0;
w->vscroll = 0;
w->window_end_valid = Qnil;
|| ! NILP (Vwindow_scroll_functions))
{
update_mode_line = 1;
- w->update_mode_line = Qt;
+ w->update_mode_line = 1;
startp = run_window_scroll_functions (window, startp);
}
the scroll margin (bug#148) -- cyd */
if (!try_window (window, startp, 0))
{
- w->force_start = Qt;
+ w->force_start = 1;
clear_glyph_matrix (w->desired_matrix);
goto need_larger_matrices;
}
}
/* If current starting point was originally the beginning of a line
but no longer is, find a new starting point. */
- else if (!NILP (w->start_at_line_beg)
+ else if (w->start_at_line_beg
&& !(CHARPOS (startp) <= BEGV
|| FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
{
new window start, since that would change the position under
the mouse, resulting in an unwanted mouse-movement rather
than a simple mouse-click. */
- if (NILP (w->start_at_line_beg)
+ if (!w->start_at_line_beg
&& NILP (do_mouse_tracking)
&& CHARPOS (startp) > BEGV
&& CHARPOS (startp) > BEG + beg_unchanged
See bug#9324. */
&& pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &d6))
{
- w->force_start = Qt;
+ w->force_start = 1;
SET_TEXT_POS_FROM_MARKER (startp, w->start);
goto force_start;
}
if (!update_mode_line)
{
update_mode_line = 1;
- w->update_mode_line = Qt;
+ w->update_mode_line = 1;
}
/* Try to scroll by specified few lines. */
done:
SET_TEXT_POS_FROM_MARKER (startp, w->start);
- w->start_at_line_beg = ((CHARPOS (startp) == BEGV
- || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')
- ? Qt : Qnil);
+ w->start_at_line_beg = (CHARPOS (startp) == BEGV
+ || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
/* Display the mode line, if we must. */
if ((update_mode_line
/* If bottom moved off end of frame, change mode line percentage. */
if (XFASTINT (w->window_end_pos) <= 0
&& Z != IT_CHARPOS (it))
- w->update_mode_line = Qt;
+ w->update_mode_line = 1;
/* Set window_end_pos to the offset of the last character displayed
on the window from the end of current_buffer. Set
if (!VECTORP (val)) /* Not yet decided. */
{
- if (multibyte)
- *buf++ = '-';
+ *buf++ = multibyte ? '-' : ' ';
if (eol_flag)
eoltype = eol_mnemonic_undecided;
/* Don't mention EOL conversion if it isn't decided. */
attrs = AREF (val, 0);
eolvalue = AREF (val, 2);
- if (multibyte)
- *buf++ = XFASTINT (CODING_ATTR_MNEMONIC (attrs));
+ *buf++ = multibyte
+ ? XFASTINT (CODING_ATTR_MNEMONIC (attrs))
+ : ' ';
if (eol_flag)
{
return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
}
- prop = Fbuffer_local_value (prop, it->w->buffer);
+ prop = buffer_local_value_1 (prop, it->w->buffer);
+ if (EQ (prop, Qunbound))
+ prop = Qnil;
}
if (INTEGERP (prop) || FLOATP (prop))
return OK_PIXELS (pixels);
}
- car = Fbuffer_local_value (car, it->w->buffer);
+ car = buffer_local_value_1 (car, it->w->buffer);
+ if (EQ (car, Qunbound))
+ car = Qnil;
}
if (INTEGERP (car) || FLOATP (car))
int dx, dy, width, height;
ptrdiff_t charpos;
Lisp_Object string, object = Qnil;
- Lisp_Object pos, help;
+ Lisp_Object pos IF_LINT (= Qnil), help;
Lisp_Object mouse_face;
int original_x_pixel = x;
struct glyph * glyph = NULL, * row_start_glyph = NULL;
- struct glyph_row *row;
+ struct glyph_row *row IF_LINT (= 0);
if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
{
if (!NILP (help))
{
help_echo_string = help;
- /* Is this correct? ++kfs */
XSETWINDOW (help_echo_window, w);
help_echo_object = w->buffer;
help_echo_pos = charpos;
#endif /* HAVE_WINDOW_SYSTEM */
if (STRINGP (string))
+ pos = make_number (charpos);
+
+ /* Set the help text and mouse pointer. If the mouse is on a part
+ of the mode line without any text (e.g. past the right edge of
+ the mode line text), use the default help text and pointer. */
+ if (STRINGP (string) || area == ON_MODE_LINE)
{
- pos = make_number (charpos);
- /* 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. */
+ /* Arrange to display the help by setting the global variables
+ help_echo_string, help_echo_object, and help_echo_pos. */
if (NILP (help))
{
- help = Fget_text_property (pos, Qhelp_echo, string);
+ if (STRINGP (string))
+ help = Fget_text_property (pos, Qhelp_echo, string);
+
if (!NILP (help))
{
help_echo_string = help;
help_echo_object = string;
help_echo_pos = charpos;
}
+ else if (area == ON_MODE_LINE)
+ {
+ Lisp_Object default_help
+ = buffer_local_value_1 (Qmode_line_default_help_echo,
+ w->buffer);
+
+ if (STRINGP (default_help))
+ {
+ help_echo_string = default_help;
+ XSETWINDOW (help_echo_window, w);
+ help_echo_object = Qnil;
+ help_echo_pos = -1;
+ }
+ }
}
#ifdef HAVE_WINDOW_SYSTEM
+ /* Change the mouse pointer according to what is under it. */
if (FRAME_WINDOW_P (f))
{
dpyinfo = FRAME_X_DISPLAY_INFO (f);
- cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
- 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) || (area == ON_HEADER_LINE)))
+ if (STRINGP (string))
{
- Lisp_Object map;
- map = Fget_text_property (pos, Qlocal_map, string);
- if (!KEYMAPP (map))
- map = Fget_text_property (pos, Qkeymap, string);
- if (!KEYMAPP (map))
- cursor = dpyinfo->vertical_scroll_bar_cursor;
+ cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
+
+ 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) || (area == ON_HEADER_LINE)))
+ {
+ Lisp_Object map;
+ map = Fget_text_property (pos, Qlocal_map, string);
+ if (!KEYMAPP (map))
+ map = Fget_text_property (pos, Qkeymap, string);
+ if (!KEYMAPP (map))
+ cursor = dpyinfo->vertical_scroll_bar_cursor;
+ }
}
+ else
+ /* Default mode-line pointer. */
+ cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
}
#endif
+ }
- /* Change the mouse face according to what is under X/Y. */
+ /* Change the mouse face according to what is under X/Y. */
+ if (STRINGP (string))
+ {
mouse_face = Fget_text_property (pos, Qmouse_face, string);
if (!NILP (mouse_face)
&& ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE))
Vmode_line_unwind_vector = Qnil;
staticpro (&Vmode_line_unwind_vector);
+ DEFSYM (Qmode_line_default_help_echo, "mode-line-default-help-echo");
+
help_echo_string = Qnil;
staticpro (&help_echo_string);
help_echo_object = Qnil;
both - show both, text below image
both-horiz - show text to the right of the image
text-image-horiz - show text to the left of the image
- any other - use system default or image if no system default. */);
+ any other - use system default or image if no system default.
+
+This variable only affects the GTK+ toolkit version of Emacs. */);
Vtool_bar_style = Qnil;
DEFVAR_INT ("tool-bar-max-label-size", tool_bar_max_label_size,