#define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) 0
#endif /* HAVE_WINDOW_SYSTEM */
-/* Test if the display element loaded in IT is a space or tab
- character. This is used to determine word wrapping. */
-
-#define IT_DISPLAYING_WHITESPACE(it) \
- (it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t'))
+/* Test if the display element loaded in IT, or the underlying buffer
+ or string character, is a space or a TAB character. This is used
+ to determine where word wrapping can occur. */
+
+#define IT_DISPLAYING_WHITESPACE(it) \
+ ((it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t')) \
+ || ((STRINGP (it->string) \
+ && (SREF (it->string, IT_STRING_BYTEPOS (*it)) == ' ' \
+ || SREF (it->string, IT_STRING_BYTEPOS (*it)) == '\t')) \
+ || (it->s \
+ && (it->s[IT_BYTEPOS (*it)] == ' ' \
+ || it->s[IT_BYTEPOS (*it)] == '\t')) \
+ || (IT_BYTEPOS (*it) < ZV_BYTE \
+ && (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \
+ || *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t')))) \
/* Name of the face used to highlight trailing whitespace. */
static int trailing_whitespace_p (ptrdiff_t);
static intmax_t message_log_check_duplicate (ptrdiff_t, ptrdiff_t);
static void push_it (struct it *, struct text_pos *);
+static void iterate_out_of_display_property (struct it *);
static void pop_it (struct it *);
static void sync_frame_with_window_matrix_rows (struct window *);
static void select_frame_for_redisplay (Lisp_Object);
}
SET_TEXT_POS_FROM_MARKER (top, w->start);
+ /* Scrolling a minibuffer window via scroll bar when the echo area
+ shows long text sometimes resets the minibuffer contents behind
+ our backs. */
+ if (CHARPOS (top) > ZV)
+ SET_TEXT_POS (top, BEGV, BEGV_BYTE);
/* Compute exact mode line heights. */
if (WINDOW_WANTS_MODELINE_P (w))
glyph. */
int top_x = it.current_x;
int top_y = it.current_y;
- enum it_method it_method = it.method;
/* Calling line_bottom_y may change it.method, it.position, etc. */
+ enum it_method it_method = it.method;
int bottom_y = (last_height = 0, line_bottom_y (&it));
int window_top_y = WINDOW_HEADER_LINE_HEIGHT (w);
visible_p = bottom_y > window_top_y;
else if (top_y < it.last_visible_y)
visible_p = 1;
+ if (bottom_y >= it.last_visible_y
+ && it.bidi_p && it.bidi_it.scan_dir == -1
+ && IT_CHARPOS (it) < charpos)
+ {
+ /* When the last line of the window is scanned backwards
+ under bidi iteration, we could be duped into thinking
+ that we have passed CHARPOS, when in fact move_it_to
+ simply stopped short of CHARPOS because it reached
+ last_visible_y. To see if that's what happened, we call
+ move_it_to again with a slightly larger vertical limit,
+ and see if it actually moved vertically; if it did, we
+ didn't really reach CHARPOS, which is beyond window end. */
+ struct it save_it = it;
+ /* Why 10? because we don't know how many canonical lines
+ will the height of the next line(s) be. So we guess. */
+ int ten_more_lines =
+ 10 * FRAME_LINE_HEIGHT (XFRAME (WINDOW_FRAME (w)));
+
+ move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1,
+ MOVE_TO_POS | MOVE_TO_Y);
+ if (it.current_y > top_y)
+ visible_p = 0;
+
+ it = save_it;
+ }
if (visible_p)
{
if (it_method == GET_FROM_DISPLAY_VECTOR)
Lisp_Object startpos, endpos;
EMACS_INT start, end;
struct it it3;
+ int it3_moved;
/* Find the first and the last buffer positions
covered by the display string. */
begins. */
start_display (&it3, w, top);
move_it_to (&it3, -1, 0, top_y, -1, MOVE_TO_X | MOVE_TO_Y);
+ /* If it3_moved stays zero after the 'while' loop
+ below, that means we already were at a newline
+ before the loop (e.g., the display string begins
+ with a newline), so we don't need to (and cannot)
+ inspect the glyphs of it3.glyph_row, because
+ PRODUCE_GLYPHS will not produce anything for a
+ newline, and thus it3.glyph_row stays at its
+ stale content it got at top of the window. */
+ it3_moved = 0;
/* Finally, advance the iterator until we hit the
first display element whose character position is
CHARPOS, or until the first newline from the
if (IT_CHARPOS (it3) == charpos
|| ITERATOR_AT_END_OF_LINE_P (&it3))
break;
+ it3_moved = 1;
set_iterator_to_next (&it3, 0);
}
top_x = it3.current_x - it3.pixel_width;
display string, move back over the glyphs
produced from the string, until we find the
rightmost glyph not from the string. */
- if (IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
+ if (it3_moved
+ && IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
{
struct glyph *g = it3.glyph_row->glyphs[TEXT_AREA]
+ it3.glyph_row->used[TEXT_AREA];
overlays even if the actual buffer text is replaced. */
if (!handle_overlay_change_p
|| it->sp > 1
- || !get_overlay_strings_1 (it, 0, 0))
+ /* Don't call get_overlay_strings_1 if we already
+ have overlay strings loaded, because doing so
+ will load them again and push the iterator state
+ onto the stack one more time, which is not
+ expected by the rest of the code that processes
+ overlay strings. */
+ || (it->current.overlay_string_index < 0
+ ? !get_overlay_strings_1 (it, 0, 0)
+ : 0))
{
if (it->ellipsis_p)
setup_for_ellipsis (it, 0);
if (!FRAME_WINDOW_P (it->f))
/* If we return here, POSITION has been advanced
across the text with this property. */
- return 0;
+ {
+ /* Synchronize the bidi iterator with POSITION. This is
+ needed because we are not going to push the iterator
+ on behalf of this display property, so there will be
+ no pop_it call to do this synchronization for us. */
+ if (it->bidi_p)
+ {
+ it->position = *position;
+ iterate_out_of_display_property (it);
+ *position = it->position;
+ }
+ return 1;
+ }
}
else if (!frame_window_p)
- return 0;
+ return 1;
#ifdef HAVE_WINDOW_SYSTEM
value = XCAR (XCDR (spec));
|| !(fringe_bitmap = lookup_fringe_bitmap (value)))
/* If we return here, POSITION has been advanced
across the text with this property. */
- return 0;
+ {
+ if (it && it->bidi_p)
+ {
+ it->position = *position;
+ iterate_out_of_display_property (it);
+ *position = it->position;
+ }
+ return 1;
+ }
if (it)
{
static void
iterate_out_of_display_property (struct it *it)
{
- int buffer_p = BUFFERP (it->object);
+ int buffer_p = !STRINGP (it->string);
ptrdiff_t eob = (buffer_p ? ZV : it->end_charpos);
ptrdiff_t bob = (buffer_p ? BEGV : 0);
&& FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX);
}
}
+ /* If we reached the end of the object we've been iterating (e.g., a
+ display string or an overlay string), and there's something on
+ IT->stack, proceed with what's on the stack. It doesn't make
+ sense to return zero if there's unprocessed stuff on the stack,
+ because otherwise that stuff will never be displayed. */
+ if (!success_p && it->sp > 0)
+ {
+ set_iterator_to_next (it, 0);
+ success_p = get_next_display_element (it);
+ }
/* Value is 0 if end of buffer or string reached. */
return success_p;
display vector entry (these entries may contain faces). */
it->face_id = it->saved_face_id;
- if (it->dpvec + it->current.dpvec_index == it->dpend)
+ if (it->dpvec + it->current.dpvec_index >= it->dpend)
{
int recheck_faces = it->ellipsis_p;
case GET_FROM_STRING:
/* Current display element is a character from a Lisp string. */
xassert (it->s == NULL && STRINGP (it->string));
+ /* Don't advance past string end. These conditions are true
+ when set_iterator_to_next is called at the end of
+ get_next_display_element, in which case the Lisp string is
+ already exhausted, and all we want is pop the iterator
+ stack. */
+ if (it->current.overlay_string_index >= 0)
+ {
+ /* This is an overlay string, so there's no padding with
+ spaces, and the number of characters in the string is
+ where the string ends. */
+ if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
+ goto consider_string_end;
+ }
+ else
+ {
+ /* Not an overlay string. There could be padding, so test
+ against it->end_charpos . */
+ if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
+ goto consider_string_end;
+ }
if (it->cmp_it.id >= 0)
{
int i;
{
/* If TO_Y is in this line and TO_X was reached
above, we scanned too far. We have to restore
- IT's settings to the ones before skipping. */
+ IT's settings to the ones before skipping. But
+ keep the more accurate values of max_ascent and
+ max_descent we've found while skipping the rest
+ of the line, for the sake of callers, such as
+ pos_visible_p, that need to know the line
+ height. */
+ int max_ascent = it->max_ascent;
+ int max_descent = it->max_descent;
+
RESTORE_IT (it, &it_backup, backup_data);
+ it->max_ascent = max_ascent;
+ it->max_descent = max_descent;
reached = 6;
}
else
|| 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;
}
frames. Zero means, only selected_window is considered. */
int consider_all_windows_p;
+ /* Non-zero means redisplay has to redisplay the miniwindow */
+ int update_miniwindow_p = 0;
+
TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
/* No redisplay if running in batch mode or frame is not yet fully
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);
&& !MINI_WINDOW_P (XWINDOW (selected_window))))
{
int window_height_changed_p = echo_area_display (0);
+
+ if (message_cleared_p)
+ update_miniwindow_p = 1;
+
must_finish = 1;
/* If we don't display the current message, don't clear the
/* FIXME: this causes all frames to be updated, which seems unnecessary
since only the current frame needs to be considered. This function needs
to be rewritten with two variables, consider_all_windows and
- consider_all_frames. */
+ consider_all_frames. */
consider_all_windows_p = 1;
++windows_or_buffers_changed;
++update_mode_lines;
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)
then we can't just move the cursor. */
else if (! (!NILP (Vtransient_mark_mode)
&& !NILP (BVAR (current_buffer, mark_active)))
- && (EQ (selected_window, BVAR (current_buffer, last_selected_window))
+ && (EQ (selected_window,
+ BVAR (current_buffer, last_selected_window))
|| highlight_nonselected_windows)
&& NILP (w->region_showing)
&& NILP (Vshow_trailing_whitespace)
}
else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
{
- Lisp_Object mini_window;
+ Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
struct frame *mini_frame;
displayed_buffer = XBUFFER (XWINDOW (selected_window)->buffer);
internal_condition_case_1 (redisplay_window_1, selected_window,
list_of_error,
redisplay_window_error);
+ if (update_miniwindow_p)
+ internal_condition_case_1 (redisplay_window_1, mini_window,
+ list_of_error,
+ redisplay_window_error);
/* Compare desired and current matrices, perform output. */
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;
}
}
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
compute_line_metrics (&it);
}
+#ifdef HAVE_MENUS
+/* Display one menu item on a TTY, by overwriting the glyphs in the
+ desired glyph matrix with glyphs produced from the menu item text.
+ Called from term.c to display TTY drop-down menus one item at a
+ time.
+
+ ITEM_TEXT is the menu item text as a C string.
+
+ FACE_ID is the face ID to be used for this menu item. FACE_ID
+ could specify one of 3 faces: a face for an enabled item, a face
+ for a disabled item, or a face for a selected item.
+
+ X and Y are coordinates of the first glyph in the desired matrix to
+ be overwritten by the menu item. Since this is a TTY, Y is the
+ glyph row and X is the glyph number in the row, where to start
+ displaying the item.
+
+ SUBMENU non-zero means this menu item drops down a submenu, which
+ should be indicated by displaying a proper visual cue after the
+ item text. */
+
+void
+display_tty_menu_item (const char *item_text, int face_id, int x, int y,
+ int submenu)
+{
+ struct it it;
+ struct frame *f = SELECTED_FRAME ();
+ int saved_used, saved_truncated;
+ struct glyph_row *row;
+
+ xassert (FRAME_TERMCAP_P (f));
+
+ init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
+ it.first_visible_x = 0;
+ it.last_visible_x = FRAME_COLS (f);
+ row = it.glyph_row;
+ row->full_width_p = 1;
+
+ /* Arrange for the menu item glyphs to start at X and have the
+ desired face. */
+ it.current_x = it.hpos = x;
+ saved_used = row->used[TEXT_AREA];
+ saved_truncated = row->truncated_on_right_p;
+ row->used[TEXT_AREA] = x - row->used[LEFT_MARGIN_AREA];
+ it.face_id = face_id;
+ /* FIXME: This should be controlled by a user option. See the
+ comments in redisplay_tool_bar and display_mode_line about this.
+ Also, if paragraph_embedding could ever be R2L, changes will be
+ needed to avoid shifting to the right the row characters in
+ term.c:append_glyph. */
+ it.paragraph_embedding = L2R;
+
+ if (submenu)
+ {
+ /* Indicate with ">" that there's a submenu. */
+ display_string (item_text, Qnil, Qnil, 0, 0, &it,
+ strlen (item_text), 0, FRAME_COLS (f) - 2, -1);
+ display_string (">", Qnil, Qnil, 0, 0, &it, 1, 0, 0, -1);
+ }
+ else
+ {
+ /* Display the menu item, pad with one space. */
+ display_string (item_text, Qnil, Qnil, 0, 0, &it,
+ strlen (item_text) + 1, 0, 0, -1);
+ }
+
+ row->used[TEXT_AREA] = saved_used;
+ row->truncated_on_right_p = saved_truncated;
+ row->hash - row_hash (row);
+}
+#endif /* HAVE_MENUS */
\f
/***********************************************************************
Mode Line
return;
}
#endif
-#if defined (HAVE_GPM) || defined (MSDOS)
+#if defined (HAVE_GPM) || defined (MSDOS) || defined (WINDOWSNT)
tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
#endif
}
/* Platform-independent portion of hourglass implementation. */
-/* Return non-zero if hourglass timer has been started or hourglass is
- shown. */
-int
-hourglass_started (void)
-{
- return hourglass_shown_p || hourglass_atimer != NULL;
-}
-
/* Cancel a currently active hourglass timer, and start a new one. */
void
start_hourglass (void)