#include <config.h>
#include <stdio.h>
+#include <limits.h>
#include "lisp.h"
#include "keyboard.h"
#ifdef WINDOWSNT
#include "w32term.h"
#endif
-#ifdef MAC_OS
-#include "macterm.h"
-#endif
#ifdef HAVE_NS
#include "nsterm.h"
#endif
+#ifdef USE_GTK
+#include "gtkutil.h"
+#endif
#include "font.h"
#define INFINITY 10000000
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
|| defined(HAVE_NS) || defined (USE_GTK)
extern void set_frame_menubar P_ ((struct frame *f, int, int));
extern int pending_menu_activation;
static void handle_line_prefix P_ ((struct it *));
-#if 0
-static int invisible_text_between_p P_ ((struct it *, int, int));
-#endif
-
static void pint2str P_ ((char *, int, int));
static void pint2hrstr P_ ((char *, int, int));
static struct text_pos run_window_scroll_functions P_ ((Lisp_Object,
text, or we can't tell because W's current matrix is not up to
date. */
-#ifndef HAVE_CARBON
static
-#endif
struct glyph *
x_y_to_hpos_vpos (w, x, y, hpos, vpos, dx, dy, area)
struct window *w;
rectangle as wide as the glyph, but use a canonical character
width instead. */
wd = glyph->pixel_width - 1;
-#ifdef HAVE_NTGUI
+#if defined(HAVE_NTGUI) || defined(HAVE_NS)
wd++; /* Why? */
#endif
it->current.dpvec_index = -1;
handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p;
it->ignore_overlay_strings_at_pos_p = 0;
+ it->ellipsis_p = 0;
/* Use face of preceding text for ellipsis (if invisible) */
if (it->selective_display_ellipsis_p)
{
/* We still want to show before and after strings from
overlays even if the actual buffer text is replaced. */
- if (!handle_overlay_change_p || it->sp > 1)
- return;
- if (!get_overlay_strings_1 (it, 0, 0))
- return;
+ if (!handle_overlay_change_p
+ || it->sp > 1
+ || !get_overlay_strings_1 (it, 0, 0))
+ {
+ if (it->ellipsis_p)
+ setup_for_ellipsis (it, 0);
+ return;
+ }
it->ignore_overlay_strings_at_pos_p = 1;
it->string_from_display_prop_p = 0;
handle_overlay_change_p = 0;
if (handle_overlay_change_p)
handled = handle_overlay_change (it);
}
+
+ if (it->ellipsis_p)
+ {
+ setup_for_ellipsis (it, 0);
+ break;
+ }
}
while (handled == HANDLED_RECOMPUTE_PROPS);
it->position.charpos = IT_CHARPOS (*it) - 1;
it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
}
- setup_for_ellipsis (it, 0);
+ it->ellipsis_p = 1;
/* Let the ellipsis display before
considering any properties of the following char.
Fixes jasonr@gnu.org 01 Oct 07 bug. */
/* No more overlay strings. Restore IT's settings to what
they were before overlay strings were processed, and
continue to deliver from current_buffer. */
- int display_ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
+ it->ellipsis_p = (it->stack[it->sp - 1].display_ellipsis_p != 0);
pop_it (it);
xassert (it->sp > 0
|| it->method == GET_FROM_COMPOSITION
next_element_from_buffer doesn't try it again. */
if (NILP (it->string) && IT_CHARPOS (*it) >= it->end_charpos)
it->overlay_strings_at_end_processed_p = 1;
-
- /* If we have to display `...' for invisible text, set
- the iterator up for that. */
- if (display_ellipsis_p)
- setup_for_ellipsis (it, 0);
}
else
{
/* IT->string is an overlay string. Advance to the
next, if there is one. */
if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
- next_overlay_string (it);
+ {
+ it->ellipsis_p = 0;
+ next_overlay_string (it);
+ if (it->ellipsis_p)
+ setup_for_ellipsis (it, 0);
+ }
}
else
{
out:
+ /* On text terminals, we may stop at the end of a line in the middle
+ of a multi-character glyph. If the glyph itself is continued,
+ i.e. it is actually displayed on the next line, don't treat this
+ stopping point as valid; move to the next line instead (unless
+ that brings us offscreen). */
+ if (!FRAME_WINDOW_P (it->f)
+ && op & MOVE_TO_POS
+ && IT_CHARPOS (*it) == to_charpos
+ && it->what == IT_CHARACTER
+ && it->nglyphs > 1
+ && it->line_wrap == WINDOW_WRAP
+ && it->current_x == it->last_visible_x - 1
+ && it->c != '\n'
+ && it->c != '\t'
+ && it->vpos < XFASTINT (it->w->window_end_vpos))
+ {
+ it->continuation_lines_width += it->current_x;
+ it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
+ it->current_y += it->max_ascent + it->max_descent;
+ ++it->vpos;
+ last_height = it->max_ascent + it->max_descent;
+ last_max_ascent = it->max_ascent;
+ }
+
TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
}
}
-#if 0 /* Currently not used. */
-
-/* Return non-zero if some text between buffer positions START_CHARPOS
- and END_CHARPOS is invisible. IT->window is the window for text
- property lookup. */
-
-static int
-invisible_text_between_p (it, start_charpos, end_charpos)
- struct it *it;
- int start_charpos, end_charpos;
-{
- Lisp_Object prop, limit;
- int invisible_found_p;
-
- xassert (it != NULL && start_charpos <= end_charpos);
-
- /* Is text at START invisible? */
- prop = Fget_char_property (make_number (start_charpos), Qinvisible,
- it->window);
- if (TEXT_PROP_MEANS_INVISIBLE (prop))
- invisible_found_p = 1;
- else
- {
- limit = Fnext_single_char_property_change (make_number (start_charpos),
- Qinvisible, Qnil,
- make_number (end_charpos));
- invisible_found_p = XFASTINT (limit) < end_charpos;
- }
-
- return invisible_found_p;
-}
-
-#endif /* 0 */
-
-
/* Move IT by a specified number DVPOS of screen lines down. DVPOS
negative means move up. DVPOS == 0 means move to the start of the
screen line. NEED_Y_P non-zero means calculate IT->current_y. If
sprintf (name, " *Echo Area %d*", i);
echo_buffer[i] = Fget_buffer_create (build_string (name));
XBUFFER (echo_buffer[i])->truncate_lines = Qnil;
+ /* to force word wrap in echo area -
+ it was decided to postpone this*/
+ /* XBUFFER (echo_buffer[i])->word_wrap = Qt; */
for (j = 0; j < 2; ++j)
if (EQ (old_buffer, echo_area_buffer[j]))
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
- mac_update_title_bar (f, 0);
-#endif
#endif
UNGCPRO;
}
update_menu_bar (sf, 1, 0);
#ifdef HAVE_WINDOW_SYSTEM
update_tool_bar (sf, 1);
-#ifdef MAC_OS
- mac_update_title_bar (sf, 1);
-#endif
#endif
}
window = FRAME_SELECTED_WINDOW (f);
w = XWINDOW (window);
-#if 0 /* The if statement below this if statement used to include the
- condition !NILP (w->update_mode_line), rather than using
- update_mode_lines directly, and this if statement may have
- been added to make that condition work. Now the if
- statement below matches its comment, this isn't needed. */
- if (update_mode_lines)
- w->update_mode_line = Qt;
-#endif
-
if (FRAME_WINDOW_P (f)
?
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
|| defined (HAVE_NS) || defined (USE_GTK)
FRAME_EXTERNAL_MENU_BAR (f)
#else
FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
/* Redisplay the menu bar in case we changed it. */
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
|| defined (HAVE_NS) || defined (USE_GTK)
if (FRAME_WINDOW_P (f))
{
-#if defined (MAC_OS) || defined (HAVE_NS)
+#if defined (HAVE_NS)
/* All frames on Mac OS share the same menubar. So only
the selected frame should be allowed to set it. */
if (f == SELECTED_FRAME ())
/* On a terminal screen, the menu bar is an ordinary screen
line, and this makes it get updated. */
w->update_mode_line = Qt;
-#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || HAVE_NS || USE_GTK) */
+#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;
-#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || HAVE_NS || USE_GTK) */
+#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || HAVE_NS || USE_GTK) */
unbind_to (count, Qnil);
set_buffer_internal_1 (prev);
return;
}
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (MAC_OS)
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
if (popup_activated ())
return;
#endif
the whole thing. */
windows_or_buffers_changed++;
SET_FRAME_GARBAGED (sf);
-#ifndef WINDOWSNT
+#ifndef DOS_NT
set_tty_color_mode (FRAME_TTY (sf), sf);
#endif
FRAME_TTY (sf)->previous_frame = sf;
/* Update the display. */
set_window_update_flags (XWINDOW (f->root_window), 1);
pause |= update_frame (f, 0, 0);
-#if 0 /* Exiting the loop can leave the wrong value for buffer_shared. */
- if (pause)
- break;
-#endif
-
f->updated_p = 1;
}
}
if (accurate_p)
{
w->window_end_valid = w->buffer;
-#if 0 /* This is incorrect with variable-height lines. */
- xassert (XINT (w->window_end_vpos)
- < (WINDOW_TOTAL_LINES (w)
- - (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0)));
-#endif
w->update_mode_line = Qnil;
}
}
{
struct window *w = XWINDOW (window);
struct frame *f = XFRAME (w->frame);
- struct text_pos scroll_margin_pos;
- struct text_pos pos;
- struct text_pos startp;
+ struct text_pos pos, startp;
struct it it;
- Lisp_Object window_end;
- int this_scroll_margin;
- int dy = 0;
- int scroll_max;
- int rc;
- int amount_to_scroll = 0;
- Lisp_Object aggressive;
- int height;
+ int this_scroll_margin, scroll_max, rc, height;
+ int dy = 0, amount_to_scroll = 0, scroll_down_p = 0;
int extra_scroll_margin_lines = last_line_misfit ? 1 : 0;
+ Lisp_Object aggressive;
+ int scroll_limit = INT_MAX / FRAME_LINE_HEIGHT (f);
#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)
- scroll_max = max (scroll_step,
- max (scroll_conservatively, temp_scroll_step));
+ /* Force scroll_conservatively to have a reasonable value, to avoid
+ overflow while computing how much to scroll. Note that it's
+ fairly common for users to supply scroll-conservatively equal to
+ `most-positive-fixnum', which can be larger than INT_MAX. */
+ if (scroll_conservatively > scroll_limit)
+ {
+ scroll_conservatively = scroll_limit;
+ scroll_max = INT_MAX;
+ }
+ else if (scroll_step || scroll_conservatively || temp_scroll_step)
+ /* Compute how much we should try to scroll maximally to bring
+ point into view. */
+ scroll_max = (max (scroll_step,
+ max (scroll_conservatively, temp_scroll_step))
+ * FRAME_LINE_HEIGHT (f));
else if (NUMBERP (current_buffer->scroll_down_aggressively)
|| NUMBERP (current_buffer->scroll_up_aggressively))
- /* We're trying to scroll because of aggressive scrolling
- but no scroll_step is set. Choose an arbitrary one. Maybe
- there should be a variable for this. */
- scroll_max = 10;
+ /* We're trying to scroll because of aggressive scrolling but no
+ scroll_step is set. Choose an arbitrary one. */
+ scroll_max = 10 * FRAME_LINE_HEIGHT (f);
else
scroll_max = 0;
- scroll_max *= FRAME_LINE_HEIGHT (f);
-
- /* Decide whether we have to scroll down. Start at the window end
- and move this_scroll_margin up to find the position of the scroll
- margin. */
- window_end = Fwindow_end (window, Qt);
too_near_end:
- CHARPOS (scroll_margin_pos) = XINT (window_end);
- BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
-
- if (this_scroll_margin || extra_scroll_margin_lines)
+ /* Decide whether we have to scroll down. */
+ if (PT > CHARPOS (startp))
{
- start_display (&it, w, scroll_margin_pos);
- 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;
- }
+ int scroll_margin_y;
- if (PT >= CHARPOS (scroll_margin_pos))
- {
- int y0;
+ /* Compute the pixel ypos of the scroll margin, then move it to
+ either that ypos or PT, whichever comes first. */
+ start_display (&it, w, startp);
+ scroll_margin_y = it.last_visible_y - this_scroll_margin
+ - FRAME_LINE_HEIGHT (f) * extra_scroll_margin_lines;
+ move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
+ (MOVE_TO_POS | MOVE_TO_Y));
- /* Point is in the scroll margin at the bottom of the window, or
- below. Compute a new window start that makes point visible. */
+ if (PT > CHARPOS (it.current.pos))
+ {
+ /* Point is in the scroll margin at the bottom of the
+ window, or below. Compute the distance from the scroll
+ margin to PT, and give up if the distance is greater than
+ scroll_max. */
+ move_it_to (&it, PT, -1, it.last_visible_y - 1, -1,
+ MOVE_TO_POS | MOVE_TO_Y);
- /* Compute the distance from the scroll margin to PT.
- Give up if the distance is greater than scroll_max. */
- start_display (&it, w, scroll_margin_pos);
- y0 = it.current_y;
- move_it_to (&it, PT, 0, it.last_visible_y, -1,
- MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+ /* To make point visible, we must move the window start down
+ so that the cursor line is visible, which means we have
+ to add in the height of the cursor line. */
+ dy = line_bottom_y (&it) - scroll_margin_y;
- /* To make point visible, we have to move the window start
- down so that the line the cursor is in is visible, which
- means we have to add in the height of the cursor line. */
- dy = line_bottom_y (&it) - y0;
+ if (dy > scroll_max)
+ return SCROLLING_FAILED;
- if (dy > scroll_max)
- return SCROLLING_FAILED;
+ scroll_down_p = 1;
+ }
+ }
+ if (scroll_down_p)
+ {
/* Move the window start down. If scrolling conservatively,
move it just enough down to make point visible. If
scroll_step is set, move it down by scroll_step. */
}
else
{
+ struct text_pos scroll_margin_pos = startp;
+
/* See if point is inside the scroll margin at the top of the
window. */
- scroll_margin_pos = startp;
if (this_scroll_margin)
{
start_display (&it, w, startp);
/* Scroll if point within this distance from the top or bottom
of the window. This is a pixel value. */
- this_scroll_margin = max (0, scroll_margin);
- this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
- this_scroll_margin *= FRAME_LINE_HEIGHT (f);
+ if (scroll_margin > 0)
+ {
+ this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+ this_scroll_margin *= FRAME_LINE_HEIGHT (f);
+ }
+ else
+ this_scroll_margin = 0;
top_scroll_margin = this_scroll_margin;
if (WINDOW_WANTS_HEADER_LINE_P (w))
{
/* We set this later on if we have to adjust point. */
int new_vpos = -1;
- int val;
w->force_start = Qnil;
w->vscroll = 0;
/* Redisplay, then check if cursor has been set during the
redisplay. Give up if new fonts were loaded. */
- val = try_window (window, startp, 1);
- if (!val)
+ /* We used to issue a CHECK_MARGINS argument to try_window here,
+ but this causes scrolling to fail when point begins inside
+ the scroll margin (bug#148) -- cyd */
+ if (!try_window (window, startp, 0))
{
w->force_start = Qt;
clear_glyph_matrix (w->desired_matrix);
goto need_larger_matrices;
}
- /* Point was outside the scroll margins. */
- if (val < 0)
- new_vpos = window_box_height (w) / 2;
if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
{
&& NILP (do_mouse_tracking)
&& CHARPOS (startp) > BEGV
&& CHARPOS (startp) > BEG + beg_unchanged
- && CHARPOS (startp) <= Z - end_unchanged)
+ && CHARPOS (startp) <= Z - end_unchanged
+ /* Even if w->start_at_line_beg is nil, a new window may
+ start at a line_beg, since that's how set_buffer_window
+ sets it. So, we need to check the return value of
+ compute_window_start_on_continuation_line. (See also
+ bug#197). */
+ && XMARKER (w->start)->buffer == current_buffer
+ && compute_window_start_on_continuation_line (w))
{
w->force_start = Qt;
- if (XMARKER (w->start)->buffer == current_buffer)
- compute_window_start_on_continuation_line (w);
SET_TEXT_POS_FROM_MARKER (startp, w->start);
goto force_start;
}
{
init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
move_it_vertically_backward (&it, 0);
-#if 0
- /* I think this assert is bogus if buffer contains
- invisible text or images. KFS. */
- xassert (IT_CHARPOS (it) <= PT);
-#endif
it.current_y = 0;
}
if (FRAME_WINDOW_P (f))
{
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
|| defined (HAVE_NS) || defined (USE_GTK)
redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
#else
{
int this_scroll_margin;
- this_scroll_margin = max (0, scroll_margin);
- this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
- this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
+ if (scroll_margin > 0)
+ {
+ this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+ this_scroll_margin *= FRAME_LINE_HEIGHT (f);
+ }
+ else
+ this_scroll_margin = 0;
if ((w->cursor.y >= 0 /* not vscrolled */
&& w->cursor.y < this_scroll_margin
seems to give wrong results. We don't want to recenter
when the last line is partly visible, we want to allow
that case to be handled in the usual way. */
- || (w->cursor.y + 1) > it.last_visible_y)
+ || w->cursor.y > it.last_visible_y - this_scroll_margin - 1)
{
w->cursor.vpos = -1;
clear_glyph_matrix (w->desired_matrix);
if (FRAME_X_P (f))
return;
#endif
-#ifdef MAC_OS
- if (FRAME_MAC_P (f))
- return;
-#endif
#ifdef HAVE_NS
if (FRAME_NS_P (f))
/* Return the index of the last glyph following glyph string S that is
- not overwritten by S because of S's right overhang. Value is -1 if
+ overwritten by S because of S's right overhang. Value is -1 if
no such glyph is found. */
static int
}
else if (it->char_to_display == '\t')
{
- int tab_width = it->tab_width * font->space_width;
- int x = it->current_x + it->continuation_lines_width;
- int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
-
- /* If the distance from the current position to the next tab
- stop is less than a space character width, use the
- tab stop after that. */
- if (next_tab_x - x < font->space_width)
- next_tab_x += tab_width;
-
- it->pixel_width = next_tab_x - x;
- it->nglyphs = 1;
- it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
- it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
-
- if (it->glyph_row)
+ if (font->space_width > 0)
+ {
+ int tab_width = it->tab_width * font->space_width;
+ int x = it->current_x + it->continuation_lines_width;
+ int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
+
+ /* If the distance from the current position to the next tab
+ stop is less than a space character width, use the
+ tab stop after that. */
+ if (next_tab_x - x < font->space_width)
+ next_tab_x += tab_width;
+
+ it->pixel_width = next_tab_x - x;
+ it->nglyphs = 1;
+ it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
+ it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
+
+ if (it->glyph_row)
+ {
+ append_stretch_glyph (it, it->object, it->pixel_width,
+ it->ascent + it->descent, it->ascent);
+ }
+ }
+ else
{
- append_stretch_glyph (it, it->object, it->pixel_width,
- it->ascent + it->descent, it->ascent);
+ it->pixel_width = 0;
+ it->nglyphs = 1;
}
}
else
in 20.x as well, and I think it's too risky to install
so near the release of 21.1. 2001-09-25 gerd. */
-#ifndef HAVE_CARBON
static
-#endif
int
fast_find_position (w, charpos, hpos, vpos, x, y, stop)
struct window *w;
struct buffer *b;
/* When a menu is active, don't highlight because this looks odd. */
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (MAC_OS)
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
if (popup_activated ())
return;
#endif