/* Updating of data structures for redisplay.
- Copyright (C) 1985, 1986, 1987, 1988, 1990,
- 1992 Free Software Foundation, Inc.
+ Copyright (C) 1985, 86, 87, 88, 93, 94 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 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
#include <signal.h>
-
-#include "config.h"
#include <stdio.h>
+
+#include <config.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
/* Nonzero upon entry to redisplay means do not assume anything about
current contents of actual terminal frame; clear and redraw it. */
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/... */
return Qnil;
}
-DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
- "Redraw all frames marked as having their images garbled.")
- ()
-{
- Lisp_Object frame, tail;
-
- for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
- {
- frame = XCONS (tail)->car;
- if (XFRAME (frame)->garbaged && XFRAME (frame)->visible)
- Fredraw_frame (frame);
- }
- return Qnil;
-}
-
redraw_frame (f)
FRAME_PTR f;
{
Fredraw_frame (frame);
}
-#else /* not MULTI_FRAME */
+#else
-DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, 0,
- "Clear screen and output again what is supposed to appear on it.")
- ()
+DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
+ "Clear frame FRAME and output again what is supposed to appear on it.")
+ (frame)
+ Lisp_Object frame;
{
update_begin (0);
set_terminal_modes ();
windows_or_buffers_changed++;
/* Mark all windows as INaccurate,
so that every window will have its redisplay done. */
- mark_window_display_accurate (FRAME_ROOT_WINDOW (0));
+ mark_window_display_accurate (FRAME_ROOT_WINDOW (0), 0);
return Qnil;
}
-#endif /* not MULTI_FRAME */
+#endif
+
+DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
+ "Clear and redisplay all visible frames.")
+ ()
+{
+ Lisp_Object tail, frame;
+
+ FOR_EACH_FRAME (tail, 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;
struct frame_glyphs *glyphs;
{
if (glyphs->total_contents)
- free (glyphs->total_contents);
-
- free (glyphs->used);
- free (glyphs->glyphs);
- free (glyphs->highlight);
- free (glyphs->enable);
- free (glyphs->bufp);
+ 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))
{
- free (glyphs->top_left_x);
- free (glyphs->top_left_y);
- free (glyphs->pix_width);
- free (glyphs->pix_height);
- free (glyphs->max_ascent);
+ xfree (glyphs->top_left_x);
+ xfree (glyphs->top_left_y);
+ xfree (glyphs->pix_width);
+ xfree (glyphs->pix_height);
+ xfree (glyphs->max_ascent);
}
#endif
- free (glyphs);
+ xfree (glyphs);
}
static void
free_frame_glyphs (frame, FRAME_TEMP_GLYPHS (frame));
if (FRAME_MESSAGE_BUF (frame))
- FRAME_MESSAGE_BUF (frame)
- = (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
- FRAME_WIDTH (frame) + 1);
+ {
+ /* Reallocate the frame's message buffer; remember that
+ echo_area_glyphs may be pointing here. */
+ char *old_message_buf = FRAME_MESSAGE_BUF (frame);
+
+ FRAME_MESSAGE_BUF (frame)
+ = (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
+ FRAME_WIDTH (frame) + 1);
+
+ if (echo_area_glyphs == old_message_buf)
+ echo_area_glyphs = FRAME_MESSAGE_BUF (frame);
+ if (previous_echo_glyphs == old_message_buf)
+ previous_echo_glyphs = FRAME_MESSAGE_BUF (frame);
+ }
else
FRAME_MESSAGE_BUF (frame)
= (char *) xmalloc (FRAME_WIDTH (frame) + 1);
char *from, *to;
int size;
{
- register char *endf;
- register char *endt;
-
- if (size == 0)
+ if (size <= 0 || from == to)
return;
- /* If destination is higher in memory, and overlaps source zone,
- copy from the end. */
- if (from < to && from + size > to)
+ /* If the source and destination don't overlap, then bcopy can
+ handle it. If they do overlap, but the destination is lower in
+ memory than the source, we'll assume bcopy can handle that. */
+ if (to < from || from + size <= to)
+ bcopy (from, to, size);
+
+ /* Otherwise, we'll copy from the end. */
+ else
{
- endf = from + size;
- endt = to + size;
+ register char *endf = from + size;
+ register char *endt = to + size;
/* If TO - FROM is large, then we should break the copy into
nonoverlapping chunks of TO - FROM bytes each. However, if
TO - FROM is small, then the bcopy function call overhead
makes this not worth it. The crossover point could be about
- anywhere. Since I don't think the obvious copy loop is ever
- too bad, I'm trying to err in its favor. */
+ anywhere. Since I don't think the obvious copy loop is too
+ bad, I'm trying to err in its favor. */
if (to - from < 64)
{
do
}
else
{
- /* Since TO - FROM >= 64, the overlap is less than SIZE,
- so we can always safely do this loop once. */
- while (endt > to)
+ for (;;)
{
endt -= (to - from);
endf -= (to - from);
+ if (endt < to)
+ break;
+
bcopy (endf, endt, to - from);
}
-
- /* If TO - FROM wasn't a multiple of SIZE, there will be a
+
+ /* If SIZE wasn't a multiple of TO - FROM, there will be a
little left over. The amount left over is
(endt + (to - from)) - to, which is endt - from. */
bcopy (from, to, endt - from);
}
}
- else
- bcopy (from, to, size);
}
-#if 0
-void
-safe_bcopy (from, to, size)
- char *from, *to;
- int size;
-{
- register char *endf;
- register char *endt;
-
- if (size == 0)
- return;
-
- /* If destination is higher in memory, and overlaps source zone,
- copy from the end. */
- if (from < to && from + size > to)
- {
- endf = from + size;
- endt = to + size;
-
- do
- *--endt = *--endf;
- while (endf != from);
-
- return;
- }
-
- bcopy (from, to, size);
-}
-#endif
-
/* Rotate a vector of SIZE bytes right, by DISTANCE bytes.
DISTANCE may be negative. */
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;
}
int len;
bcopy (current_frame->glyphs[vpos],
- desired_frame->glyphs[vpos], start);
+ desired_frame->glyphs[vpos],
+ start * sizeof (current_frame->glyphs[vpos]));
+ bcopy (current_frame->charstarts[vpos],
+ desired_frame->charstarts[vpos],
+ start * sizeof (current_frame->charstarts[vpos]));
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);
+ ((current_frame->used[vpos] - end)
+ * sizeof (current_frame->glyphs[vpos])));
+ bcopy (current_frame->charstarts[vpos] + end,
+ desired_frame->charstarts[vpos] + end,
+ ((current_frame->used[vpos] - end)
+ * sizeof (current_frame->charstarts[vpos])));
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);
#endif /* COMPILER_REGISTER_BUG */
int vpos = FRAME_CURSOR_Y (frame);
- /* Give up if about to continue line */
- if (hpos - XFASTINT (w->left) + 1 + 1 >= XFASTINT (w->width)
-
+ /* Give up if about to continue line. */
+ if (hpos >= XFASTINT (w->left) + window_internal_width (w) - 1
+
/* Avoid losing if cursor is in invisible text off left margin */
|| (XINT (w->hscroll) && hpos == XFASTINT (w->left))
/* 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 (XFASTINT (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;
- current_frame->glyphs[vpos][hpos] = g;
+ {
+#ifdef HAVE_X_WINDOWS
+ int dummy;
+ int face = compute_char_face (frame, w, point - 1, -1, -1, &dummy, point);
+#endif
+ 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;
{
register FRAME_PTR frame = selected_frame;
register struct window *w = XWINDOW (selected_window);
+ int 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 ((FRAME_CURSOR_X (frame) == XFASTINT (w->left)
&& (XINT (w->hscroll) || n < 0))
|| (n > 0
- && (FRAME_CURSOR_X (frame) + 1
- >= (XFASTINT (w->left) + XFASTINT (w->width)
- - (XFASTINT (w->width) < FRAME_WIDTH (frame))
- - 1)))
+ && (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;
+
+#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;
+ if (XFASTINT (position) < ZV
+ && ! NILP (Fget_char_property (position,
+ Qinvisible,
+ selected_window)))
+ return 0;
+
+ XFASTINT (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;
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 (preempt_count <= 0)
+ preempt_count = 1;
+
if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
detect_input_pending ();
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;
- sleep (outq / baud_rate);
+ if (baud_rate <= outq && baud_rate > 0)
+ sleep (outq / baud_rate);
}
}
if ((i - 1) % preempt_count == 0)
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;
}
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
DISP_CONTINUE_GLYPH, and less one if it's not the rightmost
window. */
- int window_width = (XFASTINT (window->width) - 1
- - (XFASTINT (window->width) + window_left
- != FRAME_WIDTH (XFRAME (window->frame))));
+ int window_width = window_internal_width (window) - 1;
int startp = marker_position (window->start);
sure I will keep it. */
posn = compute_motion (startp, 0,
(window == XWINDOW (minibuf_window) && startp == 1
- ? minibuf_prompt_width : 0),
- ZV, line, col - window_left,
- window_width, XINT (window->hscroll), 0);
+ ? minibuf_prompt_width : 0)
+ + (hscroll ? 1 - hscroll : 0),
+ ZV, line, col,
+ window_width, hscroll, 0, window);
current_buffer = old_current_buffer;
/* Char insertion/deletion cost vector, from term.c */
extern int *char_ins_del_vector;
-#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_HEIGHT((f))])
+#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH((f))])
static void
update_line (frame, vpos)
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 >= NFRAMES + 3 * NBUFFERS + 1, containing the session's
+ frames, 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\
+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;
+ for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ buf = XCONS (XCONS (tail)->car)->cdr;
+ if (!EQ (*vecp++, buf))
+ goto changed;
+ if (!EQ (*vecp++, XBUFFER (buf)->read_only))
+ goto changed;
+ if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
+ goto changed;
+ }
+ return Qnil;
+ changed:
+ n = 1;
+ FOR_EACH_FRAME (tail, frame)
+ n++;
+ 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 < XVECTOR (frame_and_buffer_state)->size / 2)
+ frame_and_buffer_state = Fmake_vector (make_number (n), Qlambda);
+ vecp = XVECTOR (frame_and_buffer_state)->contents;
+ FOR_EACH_FRAME (tail, frame)
+ *vecp++ = frame;
+ for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
+ {
+ buf = XCONS (XCONS (tail)->car)->cdr;
+ *vecp++ = buf;
+ *vecp++ = XBUFFER (buf)->read_only;
+ *vecp++ = Fbuffer_modified_p (buf);
+ }
+ /* If we left any slack in the vector, fill it up now. */
+ for (; n < XVECTOR (frame_and_buffer_state)->size; ++n)
+ *vecp++ = Qlambda;
+ return Qt;
}
\f
DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
later outside of the signal handler. */
{
- Lisp_Object tail;
- FRAME_PTR f;
+ Lisp_Object tail, frame;
- FOR_EACH_FRAME (tail, f)
+ FOR_EACH_FRAME (tail, frame)
{
- if (FRAME_TERMCAP_P (f))
+ if (FRAME_TERMCAP_P (XFRAME (frame)))
{
- change_frame_size (f, height, width, 0, 1);
+ change_frame_size (XFRAME (frame), height, width, 0, 1);
break;
}
}
/* If window_change_signal should have run before, run it now. */
while (delayed_size_change)
{
- Lisp_Object tail;
- FRAME_PTR f;
+ Lisp_Object tail, frame;
delayed_size_change = 0;
- FOR_EACH_FRAME (tail, f)
+ FOR_EACH_FRAME (tail, frame)
{
+ FRAME_PTR f = XFRAME (frame);
+
int height = FRAME_NEW_HEIGHT (f);
int width = FRAME_NEW_WIDTH (f);
-
- FRAME_NEW_HEIGHT (f) = 0;
- FRAME_NEW_WIDTH (f) = 0;
- if (height != 0)
+ if (height != 0 || width != 0)
change_frame_size (f, height, width, 0, 0);
}
}
FRAME_NEW_HEIGHT (frame) = 0;
FRAME_NEW_WIDTH (frame) = 0;
- /* If an arguments is zero, set it to the current value. */
+ /* If an argument is zero, set it to the current value. */
newheight || (newheight = FRAME_HEIGHT (frame));
newwidth || (newwidth = FRAME_WIDTH (frame));
{
/* Frame has both root and minibuffer. */
set_window_height (FRAME_ROOT_WINDOW (frame),
- newheight - 1, 0);
+ newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top)
= newheight - 1;
set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
}
else
/* Frame has just one top-level window. */
- set_window_height (FRAME_ROOT_WINDOW (frame), newheight, 0);
+ set_window_height (FRAME_ROOT_WINDOW (frame),
+ newheight - FRAME_MENU_BAR_LINES (frame), 0);
if (FRAME_TERMCAP_P (frame) && !pretend)
FrameRows = newheight;
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);
}
}
DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
- "Pause, without updating display, for ARG seconds.\n\
-Optional second arg non-nil means ARG is measured in milliseconds.\n\
-\(Not all operating systems support milliseconds.)")
- (arg, millisec)
- Lisp_Object arg, millisec;
+ "Pause, without updating display, for SECONDS seconds.\n\
+SECONDS may be a floating-point value, meaning that you can wait for a\n\
+fraction of a second. Optional second arg MILLISECONDS specifies an\n\
+additional wait period, in milliseconds; this may be useful if your\n\
+Emacs was built without floating point support.\n\
+\(Not all operating systems support waiting for a fraction of a second.)")
+ (seconds, milliseconds)
+ Lisp_Object seconds, milliseconds;
{
- int usec = 0;
- int sec;
+ int sec, usec;
- CHECK_NUMBER (arg, 0);
- sec = XINT (arg);
- if (sec <= 0)
- return Qnil;
+ if (NILP (milliseconds))
+ XSET (milliseconds, Lisp_Int, 0);
+ else
+ CHECK_NUMBER (milliseconds, 1);
+ usec = XINT (milliseconds) * 1000;
- if (!NILP (millisec))
- {
-#ifndef EMACS_HAS_USECS
- error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
+#ifdef LISP_FLOAT_TYPE
+ {
+ double duration = extract_float (seconds);
+ sec = (int) duration;
+ usec += (duration - sec) * 1000000;
+ }
#else
- usec = sec % 1000 * 1000;
- sec /= 1000;
+ CHECK_NUMBER (seconds, 0);
+ sec = XINT (seconds);
#endif
+
+#ifndef EMACS_HAS_USECS
+ if (sec == 0 && usec != 0)
+ error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
+#endif
+
+ /* Assure that 0 <= usec < 1000000. */
+ if (usec < 0)
+ {
+ /* We can't rely on the rounding being correct if user is negative. */
+ if (-1000000 < usec)
+ sec--, usec += 1000000;
+ else
+ sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
}
+ else
+ sec += usec / 1000000, usec %= 1000000;
+
+ if (sec <= 0)
+ return Qnil;
{
Lisp_Object zero;
wait_reading_process_input (sec, usec, zero, 0);
}
-#if 0 /* No wait_reading_process_input */
+ /* We should always have wait_reading_process_input; we have a dummy
+ implementation for systems which don't support subprocesses. */
+#if 0
+ /* No wait_reading_process_input */
immediate_quit = 1;
QUIT;
/* 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
- waiting for input as well. */
+ 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. */
Lisp_Object
sit_for (sec, usec, reading, display)
return Qt;
#ifdef SIGIO
- gobble_input ();
+ gobble_input (0);
#endif
XSET (read_kbd, Lisp_Int, reading ? -1 : 1);
wait_reading_process_input (sec, usec, read_kbd, display);
-#if 0 /* No wait_reading_process_input available. */
+ /* wait_reading_process_input should always be available now; it is
+ simulated in a simple way on systems that don't support
+ subprocesses. */
+#if 0
+ /* No wait_reading_process_input available. */
immediate_quit = 1;
QUIT;
}
DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
- "Perform redisplay, then wait for ARG seconds or until input is available.\n\
-Optional second arg non-nil means ARG counts in milliseconds.\n\
+ "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
+SECONDS may be a floating-point value, meaning that you can wait for a\n\
+fraction of a second. Optional second arg MILLISECONDS specifies an\n\
+additional wait period, in milliseconds; this may be useful if your\n\
+Emacs was built without floating point support.\n\
+\(Not all operating systems support waiting for a fraction of a second.)\n\
Optional third arg non-nil means don't redisplay, just wait for input.\n\
Redisplay is preempted as always if input arrives, and does not happen\n\
if input is available before it starts.\n\
Value is t if waited the full time with no input arriving.")
- (arg, millisec, nodisp)
- Lisp_Object arg, millisec, nodisp;
+ (seconds, milliseconds, nodisp)
+ Lisp_Object seconds, milliseconds, nodisp;
{
- int usec = 0;
- int sec;
+ int sec, usec;
- CHECK_NUMBER (arg, 0);
- sec = XINT (arg);
+ if (NILP (milliseconds))
+ XSET (milliseconds, Lisp_Int, 0);
+ else
+ CHECK_NUMBER (milliseconds, 1);
+ usec = XINT (milliseconds) * 1000;
- if (!NILP (millisec))
- {
-#ifndef EMACS_HAS_USECS
- error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
+#ifdef LISP_FLOAT_TYPE
+ {
+ double duration = extract_float (seconds);
+ sec = (int) duration;
+ usec += (duration - sec) * 1000000;
+ }
#else
- usec = (sec % 1000) * 1000;
- sec /= 1000;
+ CHECK_NUMBER (seconds, 0);
+ sec = XINT (seconds);
#endif
- }
-
- return sit_for (sec, usec, 0, NILP (nodisp));
-}
-
-DEFUN ("sleep-for-millisecs", Fsleep_for_millisecs, Ssleep_for_millisecs,
- 1, 1, 0,
- "Pause, without updating display, for ARG milliseconds.")
- (arg)
- Lisp_Object arg;
-{
- Lisp_Object zero;
#ifndef EMACS_HAS_USECS
- error ("sleep-for-millisecs not supported on %s", SYSTEM_TYPE);
-#else
- CHECK_NUMBER (arg, 0);
+ if (usec != 0 && sec == 0)
+ error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
+#endif
- XFASTINT (zero) = 0;
- wait_reading_process_input (XINT (arg) / 1000, XINT (arg) % 1000 * 1000,
- zero, 0);
- return Qnil;
-#endif /* EMACS_HAS_USECS */
+ if (NILP (nodisp))
+ prepare_menu_bars ();
+ return sit_for (sec, usec, 0, NILP (nodisp));
}
\f
char *terminal_type;
cursor_in_echo_area = 0;
terminal_type = (char *) 0;
- /* If the DISPLAY environment variable is set, try to use X, and
- die with an error message if that doesn't work. */
+ /* Now is the time to initialize this; it's used by init_sys_modes
+ during startup. */
+ Vwindow_system = Qnil;
- /* Check if we're using a window system here before trying to
- initialize the terminal. If we check the terminal first,
+ /* If the user wants to use a window system, we shouldn't bother
+ initializing the terminal. This is especially important when the
+ terminal is so dumb that emacs gives up before and doesn't bother
+ using the window system.
- If someone has indicated that they want
- to use a window system, we shouldn't bother initializing the
- terminal. This is especially important when the terminal is so
- dumb that emacs gives up before and doesn't bother using the window
- system. */
+ If the DISPLAY environment variable is set, try to use X, and die
+ with an error message if that doesn't work. */
#ifdef HAVE_X_WINDOWS
- if (!inhibit_window_system && (display_arg || getenv ("DISPLAY")))
+ if (! display_arg)
+ {
+#ifdef VMS
+ display_arg = (getenv ("DECW$DISPLAY") != 0);
+#else
+ display_arg = (getenv ("DISPLAY") != 0);
+#endif
+ }
+
+ if (!inhibit_window_system && display_arg)
{
Vwindow_system = intern ("x");
#ifdef HAVE_X11
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 (1), Qlambda);
+ staticpro (&frame_and_buffer_state);
+
DEFVAR_INT ("baud-rate", &baud_rate,
"The output baud rate of the terminal.\n\
On most systems, changing this value will affect the amount of padding\n\
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;
}
}
-