/* Updating of data structures for redisplay.
- Copyright (C) 1985, 86, 87, 88, 93, 94 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 <stdio.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"
+/* cm.h must come after dispextern.h on Windows. */
#include "dispextern.h"
+#include "cm.h"
#include "buffer.h"
#include "frame.h"
#include "window.h"
#include "intervals.h"
#include "systty.h"
-#include "systime.h"
+#include "syssignal.h"
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#endif /* HAVE_X_WINDOWS */
+#ifdef HAVE_NTGUI
+#include "w32term.h"
+#endif /* HAVE_NTGUI */
+
+/* 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__
-#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
+/* 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. */
positive means at end of text in echo area;
negative means at beginning of line. */
int cursor_in_echo_area;
+
+Lisp_Object Qdisplay_table;
\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
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, 0,
- "Clear frame FRAME and output again what is supposed to appear on it.")
+ /* 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;
{
bzero (new->enable, height * sizeof (char));
new->bufp = (int *) xmalloc (height * sizeof (int));
-#ifdef HAVE_X_WINDOWS
- if (FRAME_X_P (frame))
+#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_WINDOW_P (frame))
{
new->top_left_x = (short *) xmalloc (height * sizeof (short));
new->top_left_y = (short *) xmalloc (height * sizeof (short));
new->pix_height = (short *) xmalloc (height * sizeof (short));
new->max_ascent = (short *) xmalloc (height * sizeof (short));
}
-#endif
+#endif /* HAVE_WINDOW_SYSTEM */
if (empty)
{
/* 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
{
return new;
}
-static void
+void
free_frame_glyphs (frame, glyphs)
FRAME_PTR frame;
struct frame_glyphs *glyphs;
if (glyphs->charstarts)
xfree (glyphs->charstarts);
-#ifdef HAVE_X_WINDOWS
- if (FRAME_X_P (frame))
+#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_WINDOW_P (frame))
{
xfree (glyphs->top_left_x);
xfree (glyphs->top_left_y);
xfree (glyphs->pix_height);
xfree (glyphs->max_ascent);
}
-#endif
+#endif /* HAVE_WINDOW_SYSTEM */
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
if (vpos < 0)
abort ();
- if ((desired_glyphs->enable[vpos]) && desired_glyphs->used[vpos] > hpos)
- abort ();
-
if (! desired_glyphs->enable[vpos])
{
desired_glyphs->used[vpos] = 0;
Returns nonzero if done, zero if terminal cannot scroll them. */
int
-scroll_frame_lines (frame, from, end, amount, pos_adjust)
+scroll_frame_lines (frame, from, end, amount, newpos)
register FRAME_PTR frame;
- int from, end, amount, pos_adjust;
+ 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;
amount * sizeof (GLYPH *));
rotate_vector (current_frame->charstarts + from,
- sizeof (GLYPH *) * (end + amount - from),
- amount * sizeof (GLYPH *));
-
- /* Offset each char position in the charstarts lines we moved
- by pos_adjust. */
- for (i = from + amount; i < end; i++)
- {
- int *line = current_frame->charstarts[from];
- int col;
- for (col = 0; col < current_frame->used[from]; col++)
- line[col] += pos_adjust;
- }
- for (i = from; i <= from + amount; i++)
- {
- int *line = current_frame->charstarts[from];
- int col;
- line[0] = -1;
- for (col = 0; col < current_frame->used[from]; col++)
- line[col] = 0;
- }
+ sizeof (int *) * (end + amount - from),
+ amount * sizeof (int *));
safe_bcopy (current_frame->used + from,
current_frame->used + from + amount,
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,
current_frame->bufp + from + amount,
(end - from) * sizeof current_frame->bufp[0]);
-#ifdef HAVE_X_WINDOWS
- if (FRAME_X_P (frame))
+#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_WINDOW_P (frame))
{
safe_bcopy (current_frame->top_left_x + from,
current_frame->top_left_x + from + amount,
current_frame->max_ascent + from + amount,
(end - from) * sizeof current_frame->max_ascent[0]);
}
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
update_end (frame);
}
amount * sizeof (GLYPH *));
rotate_vector (current_frame->charstarts + from + amount,
- sizeof (GLYPH *) * (end - from - amount),
- amount * sizeof (GLYPH *));
-
- /* 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[from];
- int col;
- for (col = 0; col < current_frame->used[from]; col++)
- line[col] += pos_adjust;
- }
- for (i = end + amount; i <= end; i++)
- {
- int *line = current_frame->charstarts[from];
- int col;
- line[0] = -1;
- for (col = 0; col < current_frame->used[from]; col++)
- line[col] = 0;
- }
+ sizeof (int *) * (end - from - amount),
+ amount * sizeof (int *));
safe_bcopy (current_frame->used + from,
current_frame->used + from + amount,
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,
current_frame->bufp + from + amount,
(end - from) * sizeof current_frame->bufp[0]);
-#ifdef HAVE_X_WINDOWS
- if (FRAME_X_P (frame))
+#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_WINDOW_P (frame))
{
safe_bcopy (current_frame->top_left_x + from,
current_frame->top_left_x + from + amount,
current_frame->max_ascent + from + amount,
(end - from) * sizeof current_frame->max_ascent[0]);
}
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
update_end (frame);
}
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]));
+ 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;
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])));
+ * 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
- before vpos VPOS, which counts relative to the frame
+ after vpos VPOS, which counts relative to the frame
(not relative to W itself). */
void
{
int left = XFASTINT (w->left);
int top = XFASTINT (w->top);
- int right = left + window_internal_height (w);
- int height = window_internal_height (w);
+ int right = left + window_internal_width (w);
+ int bottom = top + window_internal_height (w);
int i;
- for (i = vpos + 1; i < top + height; i++)
+ for (i = vpos + 1; i < bottom; i++)
{
int *charstart
= FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i];
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
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 (XFASTINT (point - 1), Qnil))
+ || ! NILP (Ftext_properties_at (make_number (point - 1), Qnil))
#endif
/* Give up if w is minibuffer and a message is being displayed there */
return 0;
{
-#ifdef HAVE_X_WINDOWS
+ int face = 0;
+#ifdef HAVE_FACES
int dummy;
- int face = compute_char_face (frame, w, point - 1, -1, -1, &dummy, point);
+
+ if (FRAME_WINDOW_P (frame))
+ face = compute_char_face (frame, w, point - 1, -1, -1, &dummy, point, 0);
#endif
current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face);
- current_frame->charstarts[vpos][hpos] = point;
+ 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);
- int position;
+ Lisp_Object position;
int hpos = FRAME_CURSOR_X (frame);
/* Give up if in truncated text at end of line. */
&& (FRAME_CURSOR_X (frame) + 1 >= window_internal_width (w) - 1))
|| cursor_in_echo_area)
return 0;
-
+
/* Can't use direct output if highlighting a region. */
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. */
- XFASTINT (position) = point;
+ XSETFASTINT (position, point);
if (XFASTINT (position) < ZV
&& ! NILP (Fget_char_property (position,
Qinvisible,
selected_window)))
return 0;
- XFASTINT (position) = point - 1;
+ XSETFASTINT (position, point - 1);
if (XFASTINT (position) >= BEGV
&& ! NILP (Fget_char_property (position,
Qinvisible,
#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);
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;
extern input_pending;
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
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++)
if (desired_frame->enable[FRAME_HEIGHT (f) - 1])
update_line (f, FRAME_HEIGHT (f) - 1);
-#ifdef HAVE_X_WINDOWS
- if (FRAME_X_P (f))
+#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_WINDOW_P (f))
{
- leftmost = downto = f->display.x->internal_border_width;
+ leftmost = downto = FRAME_INTERNAL_BORDER_WIDTH (f);
if (desired_frame->enable[0])
{
current_frame->top_left_x[FRAME_HEIGHT (f) - 1] = leftmost;
current_frame->top_left_y[FRAME_HEIGHT (f) - 1]
- = PIXEL_HEIGHT (f) - f->display.x->internal_border_width
+ = PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f)
- current_frame->pix_height[FRAME_HEIGHT (f) - 1];
current_frame->top_left_x[0] = leftmost;
current_frame->top_left_y[0] = downto;
}
}
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
/* Now update the rest of the lines. */
for (i = 0; i < FRAME_HEIGHT (f) - 1 && (force || !input_pending); i++)
outq = PENDING_OUTPUT_COUNT (stdout);
#endif
outq *= 10;
- if (baud_rate >= outq)
+ if (baud_rate <= outq && baud_rate > 0)
sleep (outq / baud_rate);
}
}
}
update_line (f, i);
-#ifdef HAVE_X_WINDOWS
- if (FRAME_X_P (f))
+#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_WINDOW_P (f))
{
current_frame->top_left_y[i] = downto;
current_frame->top_left_x[i] = leftmost;
}
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
}
-#ifdef HAVE_X_WINDOWS
- if (FRAME_X_P (f))
+#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_WINDOW_P (f))
downto += current_frame->pix_height[i];
-#endif
+#endif /* HAVE_WINDOW_SYSTEM */
}
pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0;
/* Now just clean up termcap drivers and set cursor, etc. */
if (!pause)
{
- if (cursor_in_echo_area
- && FRAME_HAS_MINIBUF_P (f))
+ if ((cursor_in_echo_area
+ /* If we are showing a message instead of the minibuffer,
+ show the cursor for the message instead of for the
+ (now hidden) minibuffer contents. */
+ || (EQ (minibuf_window, selected_window)
+ && EQ (minibuf_window, echo_area_window)
+ && echo_area_glyphs != 0))
+ /* These cases apply only to the frame that contains
+ the active minibuffer window. */
+ && 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;
}
void
quit_error_check ()
{
+#if 0
if (FRAME_DESIRED_GLYPHS (selected_frame) == 0)
return;
if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[0])
abort ();
if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[FRAME_HEIGHT (selected_frame) - 1])
abort ();
+#endif
}
\f
/* Decide what insert/delete line to do, and do it */
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);
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)
- + (hscroll ? 1 - hscroll : 0),
+ ((window == XWINDOW (minibuf_window) && startp == BEG
+ ? minibuf_prompt_width : 0)
+ + (hscroll ? 1 - hscroll : 0)),
+ 0,
ZV, line, col,
- window_width, hscroll, 0);
+ window_width, hscroll, 0, window);
current_buffer = old_current_buffer;
if (! current_frame->highlight[vpos])
{
if (!must_write_spaces)
- while (obody[olen - 1] == SPACEGLYPH && olen > 0)
+ while (olen > 0 && obody[olen - 1] == SPACEGLYPH)
olen--;
}
else
current_frame->highlight[vpos] = desired_frame->highlight[vpos];
current_frame->bufp[vpos] = desired_frame->bufp[vpos];
-#ifdef HAVE_X_WINDOWS
- if (FRAME_X_P (frame))
+#ifdef HAVE_WINDOW_SYSTEM
+ if (FRAME_WINDOW_P (frame))
{
current_frame->pix_width[vpos]
= current_frame->used[vpos]
- * FONT_WIDTH (frame->display.x->font);
+ * FONT_WIDTH (FRAME_FONT (frame));
current_frame->pix_height[vpos]
- = FONT_HEIGHT (frame->display.x->font);
+ = FRAME_LINE_HEIGHT (frame);
}
-#endif /* HAVE_X_WINDOWS */
+#endif /* HAVE_WINDOW_SYSTEM */
if (!desired_frame->enable[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,
1, 1, "FOpen termscript file: ",
"Start writing all terminal output to FILE as well as the terminal.\n\
#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;
{
Lisp_Object zero;
- XFASTINT (zero) = 0;
+ XSETFASTINT (zero, 0);
wait_reading_process_input (sec, usec, zero, 0);
}
it does the redisplay.
It's also much like Fsit_for, except that it can be used for
- waiting for input as well. One differnce is that sit_for
- does not call prepare_menu_bars; Fsit_for does call that. */
+ waiting for input as well. */
Lisp_Object
sit_for (sec, usec, reading, display)
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
}
#endif /* HAVE_X_WINDOWS */
+#ifdef HAVE_NTGUI
+ if (!inhibit_window_system)
+ {
+ Vwindow_system = intern ("win32");
+ Vwindow_system_version = make_number (1);
+ return;
+ }
+#endif /* HAVE_NTGUI */
+
/* If no window system has been specified, try to use the terminal. */
if (! isatty (0))
{
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);
+
+ Qdisplay_table = intern ("display-table");
+ staticpro (&Qdisplay_table);
+
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,