X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/c6c5df7f76ab65b485bf110a8c5fcbdbd56d36af..254277e15d6906634686a682bfc7a163b20d7be5:/src/dispnew.c diff --git a/src/dispnew.c b/src/dispnew.c index 1766561515..0faabda929 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -1,5 +1,5 @@ /* 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 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -20,15 +20,16 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include -#include "config.h" +#include + #include #include +#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" @@ -36,23 +37,40 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #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 + #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. */ @@ -116,7 +134,7 @@ FRAME_PTR last_nonminibuf_frame; 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/... */ @@ -174,7 +192,7 @@ redraw_frame (f) #else -DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, "", +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; @@ -201,26 +219,26 @@ DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "", 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); +} + static struct frame_glyphs * make_frame_glyphs (frame, empty) @@ -230,14 +248,15 @@ 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)); @@ -259,9 +278,13 @@ make_frame_glyphs (frame, 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 { @@ -271,24 +294,47 @@ make_frame_glyphs (frame, empty) 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)) @@ -566,13 +612,15 @@ rotate_vector (vector, size, distance) 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; @@ -593,6 +641,10 @@ scroll_frame_lines (frame, from, end, amount) 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]); @@ -605,6 +657,29 @@ scroll_frame_lines (frame, from, end, 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, @@ -614,6 +689,7 @@ scroll_frame_lines (frame, from, end, amount) for (i = from; i < from + amount; i++) { current_frame->glyphs[i][0] = '\0'; + current_frame->charstarts[i][0] = -1; current_frame->enable[i] = 1; } @@ -661,6 +737,10 @@ scroll_frame_lines (frame, from, end, amount) 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]); @@ -673,6 +753,29 @@ scroll_frame_lines (frame, from, end, 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, @@ -682,6 +785,7 @@ scroll_frame_lines (frame, from, 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; } @@ -747,7 +851,10 @@ preserve_other_columns (w) 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; @@ -756,12 +863,19 @@ preserve_other_columns (w) && 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]; } } @@ -807,6 +921,89 @@ preserve_my_columns (w) #endif +/* 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++; + } + } +} + /* 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. */ @@ -815,8 +1012,8 @@ cancel_my_columns (w) 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); @@ -872,19 +1069,34 @@ direct_output_for_insert (g) /* 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; { + int face = 0; #ifdef HAVE_X_WINDOWS int dummy; - int face = compute_char_face (frame, w, point, -1, -1, &dummy); -#else - int face = 0; + + 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; @@ -911,6 +1123,12 @@ direct_output_forward_char (n) { 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. */ @@ -920,16 +1138,36 @@ direct_output_forward_char (n) && (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; } @@ -945,8 +1183,8 @@ update_frame (f, force, inhibit_hairy_id) 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; @@ -955,6 +1193,9 @@ update_frame (f, force, inhibit_hairy_id) 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 (); @@ -969,6 +1210,10 @@ update_frame (f, force, inhibit_hairy_id) 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++) @@ -1025,7 +1270,8 @@ update_frame (f, force, inhibit_hairy_id) 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) @@ -1105,7 +1351,7 @@ update_frame (f, force, inhibit_hairy_id) 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; } @@ -1208,6 +1454,7 @@ buffer_posn_from_coords (window, col, line) 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 @@ -1230,9 +1477,10 @@ buffer_posn_from_coords (window, col, line) 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; @@ -1276,6 +1524,7 @@ 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; @@ -1333,7 +1582,7 @@ update_line (frame, vpos) = 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 */ @@ -1370,6 +1619,25 @@ update_line (frame, vpos) { 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. */ @@ -1399,6 +1667,11 @@ update_line (frame, 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; + return; } @@ -1417,6 +1690,11 @@ update_line (frame, 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; + return; } @@ -1577,6 +1855,70 @@ update_line (frame, vpos) 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; +} + +/* 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; } DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript, @@ -1653,11 +1995,8 @@ do_pending_window_change () 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); } } @@ -1689,7 +2028,7 @@ change_frame_size (frame, newheight, newwidth, pretend, delay) 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)); @@ -1751,7 +2090,12 @@ change_frame_size (frame, newheight, newwidth, pretend, delay) 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); } @@ -1902,8 +2246,9 @@ Emacs was built without floating point support.\n\ /* 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) @@ -1994,6 +2339,8 @@ Value is t if waited the full time with no input arriving.") 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)); } @@ -2111,14 +2458,18 @@ syms_of_display () 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\ + "*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, @@ -2146,7 +2497,7 @@ Each element can be:\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, @@ -2163,4 +2514,3 @@ See `buffer-display-table' for more information."); Vwindow_system_version = Qnil; } } -