/* Updating of data structures for redisplay.
- Copyright (C) 1985, 1986, 1987, 1988, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <signal.h>
-#include "config.h"
+#include <config.h>
+
#include <stdio.h>
#include <ctype.h>
+#include "lisp.h"
#include "termchar.h"
#include "termopts.h"
#include "termhooks.h"
#include "cm.h"
-#include "lisp.h"
#include "dispextern.h"
#include "buffer.h"
#include "frame.h"
#include "commands.h"
#include "disptab.h"
#include "indent.h"
+#include "intervals.h"
#include "systty.h"
-#include "systime.h"
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#endif /* HAVE_X_WINDOWS */
+/* Include systime.h after xterm.h to avoid double inclusion of time.h. */
+#include "systime.h"
+
+#include <errno.h>
+
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
-#ifndef PENDING_OUTPUT_COUNT
/* Get number of chars of output now in the buffer of a stdio stream.
This ought to be built in in stdio, but it isn't.
Some s- files override this because their stdio internals differ. */
+#ifdef __GNU_LIBRARY__
+/* The s- file might have overridden the definition with one that works for
+ the system's C library. But we are using the GNU C library, so this is
+ the right definition for every system. */
+#ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT
+#define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT
+#else
+#undef PENDING_OUTPUT_COUNT
+#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
+#endif
+#else /* not __GNU_LIBRARY__ */
+#ifndef PENDING_OUTPUT_COUNT
#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
#endif
+#endif
+
+static void change_frame_size_1 ();
/* Nonzero upon entry to redisplay means do not assume anything about
current contents of actual terminal frame; clear and redraw it. */
int cursor_in_echo_area;
\f
/* The currently selected frame.
- In a single-frame version, this variable always remains 0. */
+ In a single-frame version, this variable always holds the address of
+ the_only_frame. */
FRAME_PTR selected_frame;
/* A frame which is not just a minibuffer, or 0 if there are no such
frames. This is usually the most recent such frame that was
- selected. In a single-frame version, this variable always remains 0. */
+ selected. In a single-frame version, this variable always holds
+ the address of the_only_frame. */
FRAME_PTR last_nonminibuf_frame;
/* In a single-frame version, the information that would otherwise
exist inside frame objects lives in the following structure instead.
NOTE: the_only_frame is not checked for garbage collection; don't
- store collectable objects in any of its fields!
+ store collectible objects in any of its fields!
You're not/The only frame in town/... */
FRAME_PTR f;
{
Lisp_Object frame;
- XSET (frame, Lisp_Frame, f);
+ XSETFRAME (frame, f);
Fredraw_frame (frame);
}
#else
-DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, "",
- "Clear frame FRAME and output again what is supposed to appear on it.")
+DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
+ /* Don't confuse make-docfile by having two doc strings for this function.
+ make-docfile does not pay attention to #if, for good reason! */
+ 0)
(frame)
Lisp_Object frame;
{
Lisp_Object tail, frame;
FOR_EACH_FRAME (tail, frame)
- /* If we simply redrew all visible frames, whether or not they
- were garbaged, then this would make all frames clear and
- nredraw whenever a new frame is created or an existing frame
- is de-iconified; those events set the global frame_garbaged
- flag, to which redisplay responds by calling this function.
-
- This used to redraw all visible frames; the only advantage of
- that approach is that if a frame changes from invisible to
- visible without setting its garbaged flag, it still gets
- redisplayed. But that should never happen; since invisible
- frames are not updated, they should always be marked as
- garbaged when they become visible again. If that doesn't
- happen, it's a bug in the visibility code, not a bug here. */
- if (FRAME_VISIBLE_P (XFRAME (frame))
- && FRAME_GARBAGED_P (XFRAME (frame)))
+ if (FRAME_VISIBLE_P (XFRAME (frame)))
Fredraw_frame (frame);
return Qnil;
}
+/* This is used when frame_garbaged is set.
+ Redraw the individual frames marked as garbaged. */
+
+void
+redraw_garbaged_frames ()
+{
+ Lisp_Object tail, frame;
+
+ FOR_EACH_FRAME (tail, frame)
+ if (FRAME_VISIBLE_P (XFRAME (frame))
+ && FRAME_GARBAGED_P (XFRAME (frame)))
+ Fredraw_frame (frame);
+}
+
\f
static struct frame_glyphs *
make_frame_glyphs (frame, empty)
register int i;
register width = FRAME_WIDTH (frame);
register height = FRAME_HEIGHT (frame);
- register struct frame_glyphs *new =
- (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs));
+ register struct frame_glyphs *new
+ = (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs));
SET_GLYPHS_FRAME (new, frame);
new->height = height;
new->width = width;
new->used = (int *) xmalloc (height * sizeof (int));
new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *));
+ new->charstarts = (int **) xmalloc (height * sizeof (int *));
new->highlight = (char *) xmalloc (height * sizeof (char));
new->enable = (char *) xmalloc (height * sizeof (char));
bzero (new->enable, height * sizeof (char));
/* Make the buffer used by decode_mode_spec. This buffer is also
used as temporary storage when updating the frame. See scroll.c. */
unsigned int total_glyphs = (width + 2) * sizeof (GLYPH);
+ unsigned int total_charstarts = (width + 2) * sizeof (int);
new->total_contents = (GLYPH *) xmalloc (total_glyphs);
bzero (new->total_contents, total_glyphs);
+
+ new->total_charstarts = (int *) xmalloc (total_charstarts);
+ bzero (new->total_charstarts, total_glyphs);
}
else
{
bzero (new->total_contents, total_glyphs);
for (i = 0; i < height; i++)
new->glyphs[i] = new->total_contents + i * (width + 2) + 1;
+
+ if (!FRAME_TERMCAP_P (frame))
+ {
+ unsigned int total_charstarts = height * (width + 2) * sizeof (int);
+
+ new->total_charstarts = (int *) xmalloc (total_charstarts);
+ bzero (new->total_charstarts, total_charstarts);
+ for (i = 0; i < height; i++)
+ new->charstarts[i] = new->total_charstarts + i * (width + 2) + 1;
+ }
+ else
+ {
+ /* Without a window system, we don't really need charstarts.
+ So use a small amount of space to make enough data structure
+ to prevent crashes in display_text_line. */
+ new->total_charstarts = (int *) xmalloc ((width + 2) * sizeof (int));
+ for (i = 0; i < height; i++)
+ new->charstarts[i] = new->total_charstarts;
+ }
}
return new;
}
-static void
+void
free_frame_glyphs (frame, glyphs)
FRAME_PTR frame;
struct frame_glyphs *glyphs;
{
if (glyphs->total_contents)
xfree (glyphs->total_contents);
+ if (glyphs->total_charstarts)
+ xfree (glyphs->total_charstarts);
xfree (glyphs->used);
xfree (glyphs->glyphs);
xfree (glyphs->highlight);
xfree (glyphs->enable);
xfree (glyphs->bufp);
+ if (glyphs->charstarts)
+ xfree (glyphs->charstarts);
#ifdef HAVE_X_WINDOWS
if (FRAME_X_P (frame))
xfree (glyphs);
}
-static void
+void
remake_frame_glyphs (frame)
FRAME_PTR frame;
{
FRAME_CURRENT_GLYPHS (frame) = make_frame_glyphs (frame, 0);
FRAME_DESIRED_GLYPHS (frame) = make_frame_glyphs (frame, 0);
FRAME_TEMP_GLYPHS (frame) = make_frame_glyphs (frame, 1);
- SET_FRAME_GARBAGED (frame);
+ if (! FRAME_TERMCAP_P (frame) || frame == selected_frame)
+ SET_FRAME_GARBAGED (frame);
}
\f
/* Return the hash code of contents of line VPOS in frame-matrix M. */
bzero (FRAME_CURRENT_GLYPHS (frame)->enable, FRAME_HEIGHT (frame));
}
+/* Clear out all display lines for a coming redisplay. */
+
+void
+init_desired_glyphs (frame)
+ register FRAME_PTR frame;
+{
+ register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
+ int vpos;
+ int height = FRAME_HEIGHT (frame);
+
+ for (vpos = 0; vpos < height; vpos++)
+ desired_glyphs->enable[vpos] = 0;
+}
+
/* Prepare to display on line VPOS starting at HPOS within it. */
void
Returns nonzero if done, zero if terminal cannot scroll them. */
int
-scroll_frame_lines (frame, from, end, amount)
+scroll_frame_lines (frame, from, end, amount, newpos)
register FRAME_PTR frame;
- int from, end, amount;
+ int from, end, amount, newpos;
{
register int i;
register struct frame_glyphs *current_frame
= FRAME_CURRENT_GLYPHS (frame);
+ int pos_adjust;
+ int width = FRAME_WIDTH (frame);
if (!line_ins_del_ok)
return 0;
sizeof (GLYPH *) * (end + amount - from),
amount * sizeof (GLYPH *));
+ rotate_vector (current_frame->charstarts + from,
+ sizeof (int *) * (end + amount - from),
+ amount * sizeof (int *));
+
safe_bcopy (current_frame->used + from,
current_frame->used + from + amount,
(end - from) * sizeof current_frame->used[0]);
current_frame->enable + from + amount,
(end - from) * sizeof current_frame->enable[0]);
+ /* Adjust the lines by an amount
+ that puts the first of them at NEWPOS. */
+ pos_adjust = newpos - current_frame->charstarts[from + amount][0];
+
+ /* Offset each char position in the charstarts lines we moved
+ by pos_adjust. */
+ for (i = from + amount; i < end + amount; i++)
+ {
+ int *line = current_frame->charstarts[i];
+ int col;
+ for (col = 0; col < width; col++)
+ if (line[col] > 0)
+ line[col] += pos_adjust;
+ }
+ for (i = from; i < from + amount; i++)
+ {
+ int *line = current_frame->charstarts[i];
+ int col;
+ line[0] = -1;
+ for (col = 0; col < width; col++)
+ line[col] = 0;
+ }
+
/* Mark the lines made empty by scrolling as enabled, empty and
normal video. */
bzero (current_frame->used + from,
for (i = from; i < from + amount; i++)
{
current_frame->glyphs[i][0] = '\0';
+ current_frame->charstarts[i][0] = -1;
current_frame->enable[i] = 1;
}
sizeof (GLYPH *) * (end - from - amount),
amount * sizeof (GLYPH *));
+ rotate_vector (current_frame->charstarts + from + amount,
+ sizeof (int *) * (end - from - amount),
+ amount * sizeof (int *));
+
safe_bcopy (current_frame->used + from,
current_frame->used + from + amount,
(end - from) * sizeof current_frame->used[0]);
current_frame->enable + from + amount,
(end - from) * sizeof current_frame->enable[0]);
+ /* Adjust the lines by an amount
+ that puts the first of them at NEWPOS. */
+ pos_adjust = newpos - current_frame->charstarts[from + amount][0];
+
+ /* Offset each char position in the charstarts lines we moved
+ by pos_adjust. */
+ for (i = from + amount; i < end + amount; i++)
+ {
+ int *line = current_frame->charstarts[i];
+ int col;
+ for (col = 0; col < width; col++)
+ if (line[col] > 0)
+ line[col] += pos_adjust;
+ }
+ for (i = end + amount; i < end; i++)
+ {
+ int *line = current_frame->charstarts[i];
+ int col;
+ line[0] = -1;
+ for (col = 0; col < width; col++)
+ line[col] = 0;
+ }
+
/* Mark the lines made empty by scrolling as enabled, empty and
normal video. */
bzero (current_frame->used + end + amount,
for (i = end + amount; i < end; i++)
{
current_frame->glyphs[i][0] = '\0';
+ current_frame->charstarts[i][0] = 0;
current_frame->enable[i] = 1;
}
bcopy (current_frame->glyphs[vpos],
desired_frame->glyphs[vpos],
- start * sizeof (current_frame->glyphs[vpos]));
+ start * sizeof (current_frame->glyphs[vpos][0]));
+ bcopy (current_frame->charstarts[vpos],
+ desired_frame->charstarts[vpos],
+ start * sizeof (current_frame->charstarts[vpos][0]));
len = min (start, current_frame->used[vpos]);
if (desired_frame->used[vpos] < len)
desired_frame->used[vpos] = len;
&& desired_frame->used[vpos] < current_frame->used[vpos])
{
while (desired_frame->used[vpos] < end)
- desired_frame->glyphs[vpos][desired_frame->used[vpos]++]
- = SPACEGLYPH;
+ {
+ int used = desired_frame->used[vpos]++;
+ desired_frame->glyphs[vpos][used] = SPACEGLYPH;
+ desired_frame->glyphs[vpos][used] = 0;
+ }
bcopy (current_frame->glyphs[vpos] + end,
desired_frame->glyphs[vpos] + end,
((current_frame->used[vpos] - end)
- * sizeof (current_frame->glyphs[vpos])));
+ * sizeof (current_frame->glyphs[vpos][0])));
+ bcopy (current_frame->charstarts[vpos] + end,
+ desired_frame->charstarts[vpos] + end,
+ ((current_frame->used[vpos] - end)
+ * sizeof (current_frame->charstarts[vpos][0])));
desired_frame->used[vpos] = current_frame->used[vpos];
}
}
#endif
\f
+/* Adjust by ADJUST the charstart values in window W
+ after vpos VPOS, which counts relative to the frame
+ (not relative to W itself). */
+
+void
+adjust_window_charstarts (w, vpos, adjust)
+ struct window *w;
+ int vpos;
+ int adjust;
+{
+ int left = XFASTINT (w->left);
+ int top = XFASTINT (w->top);
+ int right = left + window_internal_width (w);
+ int bottom = top + window_internal_height (w);
+ int i;
+
+ for (i = vpos + 1; i < bottom; i++)
+ {
+ int *charstart
+ = FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i];
+ int j;
+ for (j = left; j < right; j++)
+ if (charstart[j] > 0)
+ charstart[j] += adjust;
+ }
+}
+
+/* Check the charstarts values in the area of window W
+ for internal consistency. We cannot check that they are "right";
+ we can only look for something nonsensical. */
+
+verify_charstarts (w)
+ struct window *w;
+{
+ FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
+ int i;
+ int top = XFASTINT (w->top);
+ int bottom = top + window_internal_height (w);
+ int left = XFASTINT (w->left);
+ int right = left + window_internal_width (w);
+ int next_line;
+ int truncate = (XINT (w->hscroll)
+ || (truncate_partial_width_windows
+ && (XFASTINT (w->width) < FRAME_WIDTH (f)))
+ || !NILP (XBUFFER (w->buffer)->truncate_lines));
+
+ for (i = top; i < bottom; i++)
+ {
+ int j;
+ int last;
+ int *charstart = FRAME_CURRENT_GLYPHS (f)->charstarts[i];
+
+ if (i != top)
+ {
+ if (truncate)
+ {
+ /* If we are truncating lines, allow a jump
+ in charstarts from one line to the next. */
+ if (charstart[left] < next_line)
+ abort ();
+ }
+ else
+ {
+ if (charstart[left] != next_line)
+ abort ();
+ }
+ }
+
+ for (j = left; j < right; j++)
+ if (charstart[j] > 0)
+ last = charstart[j];
+ /* Record where the next line should start. */
+ next_line = last;
+ if (BUF_ZV (XBUFFER (w->buffer)) != last)
+ {
+ /* If there's a newline between the two lines, count that. */
+ int endchar = *BUF_CHAR_ADDRESS (XBUFFER (w->buffer), last);
+ if (endchar == '\n')
+ next_line++;
+ }
+ }
+}
+\f
/* On discovering that the redisplay for a window was no good,
cancel the columns of that window, so that when the window is
displayed over again get_display_line will not complain. */
struct window *w;
{
register int vpos;
- register struct frame_glyphs *desired_glyphs =
- FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
+ register struct frame_glyphs *desired_glyphs
+ = FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
register int start = XFASTINT (w->left);
register int bot = XFASTINT (w->top) + XFASTINT (w->height);
/* Give up if buffer appears in two places. */
|| buffer_shared > 1
+#ifdef USE_TEXT_PROPERTIES
+ /* Intervals have already been adjusted, point is after the
+ character that was just inserted. */
+ /* Give up if character is invisible. */
+ /* Give up if character has a face property.
+ At the moment we only lose at end of line or end of buffer
+ and only with faces that have some background */
+ /* Instead of wasting time, give up if character has any text properties */
+ || ! NILP (Ftext_properties_at (make_number (point - 1), Qnil))
+#endif
+
/* Give up if w is minibuffer and a message is being displayed there */
|| (MINI_WINDOW_P (w) && echo_area_glyphs))
return 0;
{
-#ifdef HAVE_X_WINDOWS
- int dummy;
- int face = compute_char_face (frame, w, point, -1, -1, &dummy);
-#else
int face = 0;
+#ifdef HAVE_FACES
+ int dummy;
+
+ if (FRAME_X_P (frame))
+ face = compute_char_face (frame, w, point - 1, -1, -1, &dummy, point, 0);
#endif
-
- current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (g, face);
+ current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face);
+ current_frame->charstarts[vpos][hpos] = point - 1;
+ /* Record the entry for after the newly inserted character. */
+ current_frame->charstarts[vpos][hpos + 1] = point;
+ adjust_window_charstarts (w, vpos, 1);
}
unchanged_modified = MODIFF;
beg_unchanged = GPT - BEG;
- XFASTINT (w->last_point) = point;
- XFASTINT (w->last_point_x) = hpos;
- XFASTINT (w->last_modified) = MODIFF;
+ XSETFASTINT (w->last_point, point);
+ XSETFASTINT (w->last_point_x, hpos);
+ XSETFASTINT (w->last_modified, MODIFF);
reassert_line_highlight (0, vpos);
write_glyphs (¤t_frame->glyphs[vpos][hpos], 1);
{
register FRAME_PTR frame = selected_frame;
register struct window *w = XWINDOW (selected_window);
+ Lisp_Object position;
+ int hpos = FRAME_CURSOR_X (frame);
+
+ /* Give up if in truncated text at end of line. */
+ if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1)
+ return 0;
/* Avoid losing if cursor is in invisible text off left margin
or about to go off either side of window. */
if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
return 0;
+ /* Can't use direct output at an overlay boundary; it might have
+ before-string or after-string properties. */
+ if (overlay_touches_p (PT) || overlay_touches_p (PT - n))
+ return 0;
+
+#ifdef USE_TEXT_PROPERTIES
+ /* Don't use direct output next to an invisible character
+ since we might need to do something special. */
+
+ XSETFASTINT (position, point);
+ if (XFASTINT (position) < ZV
+ && ! NILP (Fget_char_property (position,
+ Qinvisible,
+ selected_window)))
+ return 0;
+
+ XSETFASTINT (position, point - 1);
+ if (XFASTINT (position) >= BEGV
+ && ! NILP (Fget_char_property (position,
+ Qinvisible,
+ selected_window)))
+ return 0;
+#endif
+
FRAME_CURSOR_X (frame) += n;
- XFASTINT (w->last_point_x) = FRAME_CURSOR_X (frame);
- XFASTINT (w->last_point) = point;
+ XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (frame));
+ XSETFASTINT (w->last_point, point);
cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
fflush (stdout);
+
return 1;
}
\f
int force;
int inhibit_hairy_id;
{
- register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (f);
- register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (f);
+ register struct frame_glyphs *current_frame;
+ register struct frame_glyphs *desired_frame = 0;
register int i;
int pause;
int preempt_count = baud_rate / 2400 + 1;
register int downto, leftmost;
#endif
+ if (baud_rate != FRAME_COST_BAUD_RATE (f))
+ calculate_costs (f);
+
if (preempt_count <= 0)
preempt_count = 1;
if (!line_ins_del_ok)
inhibit_hairy_id = 1;
+ /* These are separate to avoid a possible bug in the AIX C compiler. */
+ current_frame = FRAME_CURRENT_GLYPHS (f);
+ desired_frame = FRAME_DESIRED_GLYPHS (f);
+
/* See if any of the desired lines are enabled; don't compute for
i/d line if just want cursor motion. */
for (i = 0; i < FRAME_HEIGHT (f); i++)
outq = PENDING_OUTPUT_COUNT (stdout);
#endif
outq *= 10;
- if (baud_rate > 0)
+ if (baud_rate <= outq && baud_rate > 0)
sleep (outq / baud_rate);
}
}
if (!pause)
{
if (cursor_in_echo_area
- && FRAME_HAS_MINIBUF_P (f))
+ && FRAME_HAS_MINIBUF_P (f)
+ && EQ (FRAME_MINIBUF_WINDOW (f), minibuf_window))
{
int top = XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
int row, col;
if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
display_completed = !pause;
- bzero (desired_frame->enable, FRAME_HEIGHT (f));
+ bzero (FRAME_DESIRED_GLYPHS (f)->enable, FRAME_HEIGHT (f));
return pause;
}
int *old_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
int *new_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
int *draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
+ int *old_draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
register int i;
int free_at_end_vpos = FRAME_HEIGHT (frame);
register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (frame);
else if (i == unchanged_at_top)
unchanged_at_top++;
draw_cost[i] = line_draw_cost (desired_frame, i);
+ old_draw_cost[i] = line_draw_cost (current_frame, i);
}
/* If changed lines are few, don't allow preemption, don't scroll. */
- if (changed_lines < baud_rate / 2400
+ if (!scroll_region_ok && changed_lines < baud_rate / 2400
|| unchanged_at_bottom == FRAME_HEIGHT (frame))
return 1;
/* If large window, fast terminal and few lines in common between
current frame and desired frame, don't bother with i/d calc. */
- if (window_size >= 18 && baud_rate > 2400
+ if (!scroll_region_ok && window_size >= 18 && baud_rate > 2400
&& (window_size >=
10 * scrolling_max_lines_saved (unchanged_at_top,
FRAME_HEIGHT (frame) - unchanged_at_bottom,
scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
draw_cost + unchanged_at_top - 1,
+ old_draw_cost + unchanged_at_top - 1,
old_hash + unchanged_at_top - 1,
new_hash + unchanged_at_top - 1,
free_at_end_vpos - unchanged_at_top);
struct window *window;
int col, line;
{
+ int hscroll = XINT (window->hscroll);
int window_left = XFASTINT (window->left);
/* The actual width of the window is window->width less one for the
current_buffer = XBUFFER (window->buffer);
+ /* We can't get a correct result in this case,
+ but at least prevent compute_motion from crashing. */
+ if (startp < BEGV)
+ startp = BEGV;
+
/* It would be nice if we could use FRAME_CURRENT_GLYPHS (XFRAME
(window->frame))->bufp to avoid scanning from the very top of
the window, but it isn't maintained correctly, and I'm not even
sure I will keep it. */
posn = compute_motion (startp, 0,
- (window == XWINDOW (minibuf_window) && startp == 1
- ? minibuf_prompt_width : 0),
+ ((window == XWINDOW (minibuf_window) && startp == BEG
+ ? minibuf_prompt_width : 0)
+ + (hscroll ? 1 - hscroll : 0)),
+ 0,
ZV, line, col,
- window_width, XINT (window->hscroll), 0);
+ window_width, hscroll, 0, window);
current_buffer = old_current_buffer;
int vpos;
{
register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp;
+ int *temp1;
int tem;
int osp, nsp, begmatch, endmatch, olen, nlen;
int save;
= current_frame->used[vpos]
* FONT_WIDTH (frame->display.x->font);
current_frame->pix_height[vpos]
- = FONT_HEIGHT (frame->display.x->font);
+ = frame->display.x->line_height;
}
#endif /* HAVE_X_WINDOWS */
{
int i,j;
+#if 0
+ if (FRAME_X_P (frame))
+ {
+ /* Under X, erase everything we are going to rewrite,
+ and rewrite everything from the first char that's changed.
+ This is part of supporting fonts like Courier
+ whose chars can overlap outside the char width. */
+ for (i = 0; i < nlen; i++)
+ if (i >= olen || nbody[i] != obody[i])
+ break;
+
+ cursor_to (vpos, i);
+ if (i != olen)
+ clear_end_of_line (olen);
+ write_glyphs (nbody + i, nlen - i);
+ }
+ else
+ {}
+#endif /* 0 */
for (i = 0; i < nlen; i++)
{
if (i >= olen || nbody[i] != obody[i]) /* A non-matching char. */
desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
current_frame->glyphs[vpos] = temp;
+ /* Exchange charstarts between current_frame and new_frame. */
+ temp1 = desired_frame->charstarts[vpos];
+ desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
+ current_frame->charstarts[vpos] = temp1;
+
return;
}
desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
current_frame->glyphs[vpos] = temp;
+ /* Exchange charstarts between current_frame and new_frame. */
+ temp1 = desired_frame->charstarts[vpos];
+ desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
+ current_frame->charstarts[vpos] = temp1;
+
return;
}
temp = desired_frame->glyphs[vpos];
desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
current_frame->glyphs[vpos] = temp;
+
+ /* Exchange charstarts between current_frame and new_frame. */
+ temp1 = desired_frame->charstarts[vpos];
+ desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
+ current_frame->charstarts[vpos] = temp1;
+}
+\f
+/* A vector of size >= 2 * NFRAMES + 3 * NBUFFERS + 1, containing the
+ session's frames, frame names, buffers, buffer-read-only flags, and
+ buffer-modified-flags, and a trailing sentinel (so we don't need to
+ add length checks). */
+static Lisp_Object frame_and_buffer_state;
+
+DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
+ Sframe_or_buffer_changed_p, 0, 0, 0,
+ "Return non-nil if the frame and buffer state appears to have changed.\n\
+The state variable is an internal vector containing all frames and buffers,\n\
+aside from buffers whose names start with space,\n\
+along with the buffers' read-only and modified flags, which allows a fast\n\
+check to see whether the menu bars might need to be recomputed.\n\
+If this function returns non-nil, it updates the internal vector to reflect\n\
+the current state.\n")
+ ()
+{
+ Lisp_Object tail, frame, buf;
+ Lisp_Object *vecp;
+ int n;
+
+ vecp = XVECTOR (frame_and_buffer_state)->contents;
+ FOR_EACH_FRAME (tail, frame)
+ {
+ if (!EQ (*vecp++, frame))
+ goto changed;
+ if (!EQ (*vecp++, XFRAME (frame)->name))
+ goto changed;
+ }
+ /* Check that the buffer info matches.
+ No need to test for the end of the vector
+ because the last element of the vector is lambda
+ and that will always cause a mismatch. */
+ for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ buf = XCONS (XCONS (tail)->car)->cdr;
+ /* Ignore buffers that aren't included in buffer lists. */
+ if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
+ continue;
+ if (!EQ (*vecp++, buf))
+ goto changed;
+ if (!EQ (*vecp++, XBUFFER (buf)->read_only))
+ goto changed;
+ if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
+ goto changed;
+ }
+ /* Detect deletion of a buffer at the end of the list. */
+ if (*vecp == Qlambda)
+ return Qnil;
+ changed:
+ /* Start with 1 so there is room for at least one lambda at the end. */
+ n = 1;
+ FOR_EACH_FRAME (tail, frame)
+ n += 2;
+ for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+ n += 3;
+ /* Reallocate the vector if it's grown, or if it's shrunk a lot. */
+ if (n > XVECTOR (frame_and_buffer_state)->size
+ || n + 20 < XVECTOR (frame_and_buffer_state)->size / 2)
+ /* Add 20 extra so we grow it less often. */
+ frame_and_buffer_state = Fmake_vector (make_number (n + 20), Qlambda);
+ vecp = XVECTOR (frame_and_buffer_state)->contents;
+ FOR_EACH_FRAME (tail, frame)
+ {
+ *vecp++ = frame;
+ *vecp++ = XFRAME (frame)->name;
+ }
+ for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ buf = XCONS (XCONS (tail)->car)->cdr;
+ /* Ignore buffers that aren't included in buffer lists. */
+ if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
+ continue;
+ *vecp++ = buf;
+ *vecp++ = XBUFFER (buf)->read_only;
+ *vecp++ = Fbuffer_modified_p (buf);
+ }
+ /* Fill up the vector with lambdas (always at least one). */
+ *vecp++ = Qlambda;
+ while (vecp - XVECTOR (frame_and_buffer_state)->contents
+ < XVECTOR (frame_and_buffer_state)->size)
+ *vecp++ = Qlambda;
+ /* Make sure we didn't overflow the vector. */
+ if (vecp - XVECTOR (frame_and_buffer_state)->contents
+ > XVECTOR (frame_and_buffer_state)->size)
+ abort ();
+ return Qt;
}
\f
DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
#ifdef SIGWINCH
SIGTYPE
-window_change_signal ()
+window_change_signal (signalnum) /* If we don't have an argument, */
+ int signalnum; /* some compilers complain in signal calls. */
{
int width, height;
extern int errno;
redisplay. Since this tries to resize windows, we can't call it
from a signal handler. */
-change_frame_size (frame, newheight, newwidth, pretend, delay)
- register FRAME_PTR frame;
+change_frame_size (f, newheight, newwidth, pretend, delay)
+ register FRAME_PTR f;
int newheight, newwidth, pretend;
+{
+ Lisp_Object tail, frame;
+ if (FRAME_TERMCAP_P (f))
+ {
+ /* When using termcap, all frames use the same screen,
+ so a change in size affects all termcap frames. */
+ FOR_EACH_FRAME (tail, frame)
+ if (FRAME_TERMCAP_P (XFRAME (frame)))
+ change_frame_size_1 (XFRAME (frame), newheight, newwidth,
+ pretend, delay);
+ }
+ else
+ change_frame_size_1 (f, newheight, newwidth, pretend, delay);
+}
+
+static void
+change_frame_size_1 (frame, newheight, newwidth, pretend, delay)
+ register FRAME_PTR frame;
+ int newheight, newwidth, pretend, delay;
{
/* If we can't deal with the change now, queue it for later. */
if (delay)
/* Frame has both root and minibuffer. */
set_window_height (FRAME_ROOT_WINDOW (frame),
newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
- XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top)
- = newheight - 1;
+ XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top,
+ newheight - 1);
set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
}
else
FRAME_HEIGHT (frame) = newheight;
FRAME_WIDTH (frame) = newwidth;
-
+
+ if (FRAME_CURSOR_X (frame) >= FRAME_WIDTH (frame))
+ FRAME_CURSOR_X (frame) = FRAME_WIDTH (frame) - 1;
+ if (FRAME_CURSOR_Y (frame) >= FRAME_HEIGHT (frame))
+ FRAME_CURSOR_Y (frame) = FRAME_HEIGHT (frame) - 1;
+
remake_frame_glyphs (frame);
calculate_costs (frame);
}
int sec, usec;
if (NILP (milliseconds))
- XSET (milliseconds, Lisp_Int, 0);
+ XSETINT (milliseconds, 0);
else
CHECK_NUMBER (milliseconds, 1);
usec = XINT (milliseconds) * 1000;
else
sec += usec / 1000000, usec %= 1000000;
- if (sec < 0)
+ if (sec <= 0)
return Qnil;
{
Lisp_Object zero;
- XFASTINT (zero) = 0;
+ XSETFASTINT (zero, 0);
wait_reading_process_input (sec, usec, zero, 0);
}
/* This is just like wait_reading_process_input, except that
it does the redisplay.
- It's also just like Fsit_for, except that it can be used for
+ It's also much like Fsit_for, except that it can be used for
waiting for input as well. */
Lisp_Object
gobble_input (0);
#endif
- XSET (read_kbd, Lisp_Int, reading ? -1 : 1);
+ XSETINT (read_kbd, reading ? -1 : 1);
wait_reading_process_input (sec, usec, read_kbd, display);
int sec, usec;
if (NILP (milliseconds))
- XSET (milliseconds, Lisp_Int, 0);
+ XSETINT (milliseconds, 0);
else
CHECK_NUMBER (milliseconds, 1);
usec = XINT (milliseconds) * 1000;
error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
#endif
+ if (NILP (nodisp))
+ prepare_menu_bars ();
return sit_for (sec, usec, 0, NILP (nodisp));
}
\f
defsubr (&Sredraw_frame);
#endif
defsubr (&Sredraw_display);
+ defsubr (&Sframe_or_buffer_changed_p);
defsubr (&Sopen_termscript);
defsubr (&Sding);
defsubr (&Ssit_for);
defsubr (&Ssleep_for);
defsubr (&Ssend_string_to_terminal);
+ frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
+ staticpro (&frame_and_buffer_state);
+
DEFVAR_INT ("baud-rate", &baud_rate,
- "The output baud rate of the terminal.\n\
+ "*The output baud rate of the terminal.\n\
On most systems, changing this value will affect the amount of padding\n\
and the other strategic decisions made during redisplay.");
DEFVAR_BOOL ("inverse-video", &inverse_video,
integer: a glyph code which this glyph is an alias for.\n\
string: output this glyph using that string (not impl. in X windows).\n\
nil: this glyph mod 256 is char code to output,\n\
- and this glyph / 256 is face code for X windows (see `x-set-face').");
+ and this glyph / 256 is face code for X windows (see `face-id').");
Vglyph_table = Qnil;
DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
Vwindow_system_version = Qnil;
}
}
-