/* Display generation from window structure and buffer text.
Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006 Free Software Foundation, Inc.
+ 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
EMACS_INT tool_bar_button_relief;
-/* Non-zero means automatically resize tool-bars so that all tool-bar
- items are visible, and no blank lines remain. */
+/* Non-nil means automatically resize tool-bars so that all tool-bar
+ items are visible, and no blank lines remain.
-int auto_resize_tool_bars_p;
+ If value is `grow-only', only make tool-bar bigger. */
+
+Lisp_Object Vauto_resize_tool_bars;
/* Non-zero means draw block and hollow cursor as wide as the glyph
under it. For example, if a block cursor is over a tab, it will be
it->c = *p, it->len = 1;
/* Record what we have and where it came from. */
- it->what = IT_CHARACTER;;
+ it->what = IT_CHARACTER;
it->object = it->w->buffer;
it->position = it->current.pos;
{
struct position pos;
- if (!FRAME_WINDOW_P (it->f))
+ /* The commented-out optimization uses vmotion on terminals. This
+ gives bad results, because elements like it->what, on which
+ callers such as pos_visible_p rely, aren't updated. */
+ /* if (!FRAME_WINDOW_P (it->f))
{
struct text_pos textpos;
- /* We can use vmotion on frames without proportional fonts. */
pos = *vmotion (IT_CHARPOS (*it), dvpos, it->w);
SET_TEXT_POS (textpos, pos.bufpos, pos.bytepos);
reseat (it, textpos, 1);
it->vpos += pos.vpos;
it->current_y += pos.vpos;
}
- else if (dvpos == 0)
+ else */
+
+ if (dvpos == 0)
{
/* DVPOS == 0 means move to the start of the screen line. */
move_it_vertically_backward (it, 0);
struct frame *f;
int save_match_data;
{
-#ifdef USE_GTK
+#if defined (USE_GTK) || USE_MAC_TOOLBAR
int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
#else
int do_update = WINDOWP (f->tool_bar_window)
out:;
row->displays_text_p = row->used[TEXT_AREA] != 0;
- /* Use default face for the border below the tool bar. */
- if (!row->displays_text_p)
+
+ /* Use default face for the border below the tool bar.
+
+ FIXME: When auto-resize-tool-bars is grow-only, there is
+ no additional border below the possibly empty tool-bar lines.
+ So to make the extra empty lines look "normal", we have to
+ use the tool-bar face for the border too. */
+ if (!row->displays_text_p && !EQ (Vauto_resize_tool_bars, Qgrow_only))
it->face_id = DEFAULT_FACE_ID;
+
extend_face_to_end_of_line (it);
last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
last->right_box_line_p = 1;
if (!row->displays_text_p)
{
row->height = row->phys_height = it->last_visible_y - row->y;
+ row->visible_height = row->height;
row->ascent = row->phys_ascent = 0;
row->extra_line_spacing = 0;
}
struct window *w;
struct it it;
struct glyph_row *row;
- int change_height_p = 0;
-#ifdef USE_GTK
+#if defined (USE_GTK) || USE_MAC_TOOLBAR
if (FRAME_EXTERNAL_TOOL_BAR (f))
update_frame_tool_bar (f);
return 0;
w->desired_matrix->no_scrolling_p = 1;
w->must_be_updated_p = 1;
- if (auto_resize_tool_bars_p)
+ if (!NILP (Vauto_resize_tool_bars))
{
- int nlines, nrows;
int max_tool_bar_height = MAX_FRAME_TOOL_BAR_HEIGHT (f);
+ int change_height_p = 0;
/* If we couldn't display everything, change the tool-bar's
height if there is room for more. */
/* Resize windows as needed by changing the `tool-bar-lines'
frame parameter. */
- if (change_height_p
- && (nlines = tool_bar_lines_needed (f, &nrows),
- nlines != WINDOW_TOTAL_LINES (w)))
+ if (change_height_p)
{
extern Lisp_Object Qtool_bar_lines;
Lisp_Object frame;
int old_height = WINDOW_TOTAL_LINES (w);
+ int nrows;
+ int nlines = tool_bar_lines_needed (f, &nrows);
- XSETFRAME (frame, f);
- Fmodify_frame_parameters (frame,
- Fcons (Fcons (Qtool_bar_lines,
- make_number (nlines)),
- Qnil));
- if (WINDOW_TOTAL_LINES (w) != old_height)
+ change_height_p = ((EQ (Vauto_resize_tool_bars, Qgrow_only)
+ && !f->minimize_tool_bar_window_p)
+ ? (nlines > old_height)
+ : (nlines != old_height));
+ f->minimize_tool_bar_window_p = 0;
+
+ if (change_height_p)
{
- clear_glyph_matrix (w->desired_matrix);
- f->n_tool_bar_rows = nrows;
- fonts_changed_p = 1;
+ XSETFRAME (frame, f);
+ 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);
+ f->n_tool_bar_rows = nrows;
+ fonts_changed_p = 1;
+ return 1;
+ }
}
}
}
- return change_height_p;
+ f->minimize_tool_bar_window_p = 0;
+ return 0;
}
int must_finish = 0;
struct text_pos tlbufpos, tlendpos;
int number_of_visible_frames;
- int count;
+ int count, count1;
struct frame *sf;
int polling_stopped_here = 0;
return;
}
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (MAC_OS)
if (popup_activated ())
return;
#endif
update_mode_lines++;
}
+ /* Avoid invocation of point motion hooks by `current_column' below. */
+ count1 = SPECPDL_INDEX ();
+ specbind (Qinhibit_point_motion_hooks, Qt);
+
/* If %c is in the mode line, update it if needed. */
if (!NILP (w->column_number_displayed)
/* This alternative quickly identifies a common case
!= (int) current_column ())) /* iftc */
w->update_mode_line = Qt;
+ unbind_to (count1, Qnil);
+
FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
/* The variable buffer_shared is set in redisplay_window and
int rc;
int centering_position = -1;
int last_line_misfit = 0;
+ int beg_unchanged, end_unchanged;
SET_TEXT_POS (lpoint, PT, PT_BYTE);
opoint = lpoint;
set_buffer_internal_1 (XBUFFER (w->buffer));
SET_TEXT_POS (opoint, PT, PT_BYTE);
+ beg_unchanged = BEG_UNCHANGED;
+ end_unchanged = END_UNCHANGED;
+
current_matrix_up_to_date_p
= (!NILP (w->window_end_valid)
&& !current_buffer->clip_changed
w->force_start = Qt;
}
+ 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)
/* If first window line is a continuation line, and window start
is inside the modified region, but the first change is before
- current window start, we must select a new window start.*/
- if (NILP (w->start_at_line_beg)
- && CHARPOS (startp) > BEGV)
- {
- /* Make sure beg_unchanged and end_unchanged are up to date.
- Do it only if buffer has really changed. This may or may
- not have been done by try_window_id (see which) already. */
- if (MODIFF > SAVE_MODIFF
- /* This seems to happen sometimes after saving a buffer. */
- || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
- {
- if (GPT - BEG < BEG_UNCHANGED)
- BEG_UNCHANGED = GPT - BEG;
- if (Z - GPT < END_UNCHANGED)
- END_UNCHANGED = Z - GPT;
- }
+ current window start, we must select a new window start.
- if (CHARPOS (startp) > BEG + BEG_UNCHANGED
- && CHARPOS (startp) <= Z - END_UNCHANGED)
- {
- /* There doesn't seems to be a simple way to find a new
- window start that is near the old window start, so
- we just recenter. */
- goto recenter;
- }
- }
+ However, if this is the result of a down-mouse event (e.g. by
+ extending the mouse-drag-overlay), we don't want to select a
+ 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)
+ && NILP (do_mouse_tracking)
+ && CHARPOS (startp) > BEGV
+ && CHARPOS (startp) > BEG + beg_unchanged
+ && CHARPOS (startp) <= Z - end_unchanged)
+ {
+ 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;
+ }
#if GLYPH_DEBUG
debug_method_add (w, "same window start");
display_menu_bar (w);
#ifdef HAVE_WINDOW_SYSTEM
-#ifdef USE_GTK
+#if defined (USE_GTK) || USE_MAC_TOOLBAR
redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
#else
redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
&& (FRAME_TOOL_BAR_LINES (f) > 0
- || auto_resize_tool_bars_p);
+ || !NILP (Vauto_resize_tool_bars));
#endif
/* Restore current_buffer and value of point in it. */
TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
set_buffer_internal_1 (old);
- TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
+ /* Avoid an abort in TEMP_SET_PT_BOTH if the buffer has become
+ shorter. This can be caused by log truncation in *Messages*. */
+ if (CHARPOS (lpoint) <= ZV)
+ TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
unbind_to (count, Qnil);
}
struct window *w = XWINDOW (window);
struct it it;
struct glyph_row *last_text_row = NULL;
+ struct frame *f = XFRAME (w->frame);
/* Make POS the new window start. */
set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
nrows_scrolled);
/* Disable lines that must be updated. */
- for (i = 0; i < it.vpos; ++i)
+ for (i = 0; i < nrows_scrolled; ++i)
(start_row + i)->enabled_p = 0;
/* Re-compute Y positions. */
sync_frame_with_window_matrix_rows (w);
/* Adjust buffer positions in reused rows. */
- if (delta)
+ if (delta || delta_bytes)
increment_matrix_positions (current_matrix,
first_unchanged_at_end_vpos + dvpos,
bottom_vpos, delta, delta_bytes);
if (PT == MATRIX_ROW_END_CHARPOS (row))
{
- /* If the row ends with a newline from a string, we don't want
- the cursor there, but we still want it at the start of the
- string if the string starts in this row.
- If the row is continued it doesn't end in a newline. */
+ /* Suppose the row ends on a string.
+ Unless the row is continued, that means it ends on a newline
+ in the string. If it's anything other than a display string
+ (e.g. a before-string from an overlay), we don't want the
+ cursor there. (This heuristic seems to give the optimal
+ behavior for the various types of multi-line strings.) */
if (CHARPOS (row->end.string_pos) >= 0)
- cursor_row_p = (row->continued_p
- || PT >= MATRIX_ROW_START_CHARPOS (row));
+ {
+ if (row->continued_p)
+ cursor_row_p = 1;
+ else
+ {
+ /* Check for `display' property. */
+ struct glyph *beg = row->glyphs[TEXT_AREA];
+ struct glyph *end = beg + row->used[TEXT_AREA] - 1;
+ struct glyph *glyph;
+
+ cursor_row_p = 0;
+ for (glyph = end; glyph >= beg; --glyph)
+ if (STRINGP (glyph->object))
+ {
+ Lisp_Object prop
+ = Fget_char_property (make_number (PT),
+ Qdisplay, Qnil);
+ cursor_row_p =
+ (!NILP (prop)
+ && display_prop_string_p (prop, glyph->object));
+ break;
+ }
+ }
+ }
else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
{
/* If the row ends in middle of a real character,
CHECK_BUFFER (buffer);
if (NILP (format))
- return build_string ("");
+ return empty_unibyte_string;
if (no_props)
face = Qnil;
{
mode_line_string_list = Fnreverse (mode_line_string_list);
str = Fmapconcat (intern ("identity"), mode_line_string_list,
- make_string ("", 0));
+ empty_unibyte_string);
}
unbind_to (count, Qnil);
#endif
break;
+ case '@':
+ {
+ Lisp_Object val;
+ val = call1 (intern ("file-remote-p"), current_buffer->directory);
+ if (NILP (val))
+ return "-";
+ else
+ return "@";
+ }
+
case 't': /* indicate TEXT or BINARY */
#ifdef MODE_LINE_BINARY_TEXT
return MODE_LINE_BINARY_TEXT (b);
return 0;
}
+DEFUN ("invisible-p", Finvisible_p, Sinvisible_p, 1, 1, 0,
+ doc: /* Non-nil if the property makes the text invisible.
+POS-OR-PROP can be a marker or number, in which case it is taken to be
+a position in the current buffer and the value of the `invisible' property
+is checked; or it can be some other value, which is then presumed to be the
+value of the `invisible' property of the text of interest.
+The non-nil value returned can be t for truly invisible text or something
+else if the text is replaced by an ellipsis. */)
+ (pos_or_prop)
+ Lisp_Object pos_or_prop;
+{
+ Lisp_Object prop
+ = (NATNUMP (pos_or_prop) || MARKERP (pos_or_prop)
+ ? Fget_char_property (pos_or_prop, Qinvisible, Qnil)
+ : pos_or_prop);
+ int invis = TEXT_PROP_MEANS_INVISIBLE (prop);
+ return (invis == 0 ? Qnil
+ : invis == 1 ? Qt
+ : make_number (invis));
+}
+
/* Calculate a width or height in pixels from a specification using
the following elements:
Lisp_Object mouse_face;
int original_x_pixel = x;
- struct glyph * glyph = NULL;
+ struct glyph * glyph = NULL, * row_start_glyph = NULL;
struct glyph_row *row;
if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
/* Find glyph */
if (row->mode_line_p && row->enabled_p)
{
- glyph = row->glyphs[TEXT_AREA];
+ glyph = row_start_glyph = row->glyphs[TEXT_AREA];
end = glyph + row->used[TEXT_AREA];
for (x0 = original_x_pixel;
is converted to a flatten by emacs lisp interpreter.
The internal string is an element of the structures.
The displayed string is the flatten string. */
- for (tmp_glyph = glyph - 1, gpos = 0;
- tmp_glyph->charpos >= XINT (b);
- tmp_glyph--, gpos++)
+ gpos = 0;
+ if (glyph > row_start_glyph)
{
- if (!EQ (tmp_glyph->object, glyph->object))
- break;
+ tmp_glyph = glyph - 1;
+ while (tmp_glyph >= row_start_glyph
+ && tmp_glyph->charpos >= XINT (b)
+ && EQ (tmp_glyph->object, glyph->object))
+ {
+ tmp_glyph--;
+ gpos++;
+ }
}
/* Calculate the lenght(glyph sequence length: GSEQ_LENGTH) of
struct buffer *b;
/* When a menu is active, don't highlight because this looks odd. */
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (MAC_OS)
if (popup_activated ())
return;
#endif
defsubr (&Slookup_image_map);
#endif
defsubr (&Sformat_mode_line);
+ defsubr (&Sinvisible_p);
staticpro (&Qmenu_bar_update_hook);
Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
= Vframe_title_format
= Fcons (intern ("multiple-frames"),
Fcons (build_string ("%b"),
- Fcons (Fcons (empty_string,
+ Fcons (Fcons (empty_unibyte_string,
Fcons (intern ("invocation-name"),
Fcons (build_string ("@"),
Fcons (intern ("system-name"),
doc: /* Maximum number of lines to keep in the message log buffer.
If nil, disable message logging. If t, log messages but don't truncate
the buffer when it becomes large. */);
- Vmessage_log_max = make_number (50);
+ Vmessage_log_max = make_number (100);
DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
doc: /* Functions called before redisplay, if window sizes have changed.
unselects the minibuffer if it is active. */);
Vmouse_autoselect_window = Qnil;
- DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
+ DEFVAR_LISP ("auto-resize-tool-bars", &Vauto_resize_tool_bars,
doc: /* *Non-nil means automatically resize tool-bars.
-This increases a tool-bar's height if not all tool-bar items are visible.
-It decreases a tool-bar's height when it would display blank lines
-otherwise. */);
- auto_resize_tool_bars_p = 1;
+This dynamically changes the tool-bar's height to the minimum height
+that is needed to make all tool-bar items visible.
+If value is `grow-only', the tool-bar's height is only increased
+automatically; to decrease the tool-bar height, use \\[recenter]. */);
+ Vauto_resize_tool_bars = Qt;
DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p,
doc: /* *Non-nil means raise tool-bar buttons when the mouse moves over them. */);