aboutsummaryrefslogtreecommitdiffstats
path: root/src/dispnew.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dispnew.c')
-rw-r--r--src/dispnew.c979
1 files changed, 649 insertions, 330 deletions
diff --git a/src/dispnew.c b/src/dispnew.c
index 1a243079e46..1089ab4c4f8 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -71,7 +71,7 @@ struct dim
71 71
72/* Function prototypes. */ 72/* Function prototypes. */
73 73
74static void update_frame_line (struct frame *, int, bool); 74static void write_row (struct frame *f, int vpos, bool updating_menu_p);
75static int required_matrix_height (struct window *); 75static int required_matrix_height (struct window *);
76static int required_matrix_width (struct window *); 76static int required_matrix_width (struct window *);
77static void increment_row_positions (struct glyph_row *, ptrdiff_t, ptrdiff_t); 77static void increment_row_positions (struct glyph_row *, ptrdiff_t, ptrdiff_t);
@@ -80,9 +80,9 @@ static void build_frame_matrix_from_window_tree (struct glyph_matrix *,
80static void build_frame_matrix_from_leaf_window (struct glyph_matrix *, 80static void build_frame_matrix_from_leaf_window (struct glyph_matrix *,
81 struct window *); 81 struct window *);
82static void adjust_decode_mode_spec_buffer (struct frame *); 82static void adjust_decode_mode_spec_buffer (struct frame *);
83static void fill_up_glyph_row_with_spaces (struct glyph_row *); 83static void fill_up_glyph_row_with_spaces (struct frame *, struct glyph_row *);
84static void clear_window_matrices (struct window *, bool); 84static void clear_window_matrices (struct window *, bool);
85static void fill_up_glyph_row_area_with_spaces (struct glyph_row *, int); 85static void fill_up_glyph_row_area_with_spaces (struct frame *, struct glyph_row *, int);
86static int scrolling_window (struct window *, int); 86static int scrolling_window (struct window *, int);
87static bool update_window_line (struct window *, int, bool *); 87static bool update_window_line (struct window *, int, bool *);
88static void mirror_make_current (struct window *, int); 88static void mirror_make_current (struct window *, int);
@@ -93,7 +93,7 @@ static void check_matrix_pointers (struct glyph_matrix *,
93static void mirror_line_dance (struct window *, int, int, int *, char *); 93static void mirror_line_dance (struct window *, int, int, int *, char *);
94static bool update_window_tree (struct window *, bool); 94static bool update_window_tree (struct window *, bool);
95static bool update_window (struct window *, bool); 95static bool update_window (struct window *, bool);
96static bool update_frame_1 (struct frame *, bool, bool, bool, bool); 96static bool write_matrix (struct frame *, bool, bool, bool, bool);
97static bool scrolling (struct frame *); 97static bool scrolling (struct frame *);
98static void set_window_cursor_after_update (struct window *); 98static void set_window_cursor_after_update (struct window *);
99static void adjust_frame_glyphs_for_window_redisplay (struct frame *); 99static void adjust_frame_glyphs_for_window_redisplay (struct frame *);
@@ -122,11 +122,6 @@ static int glyph_pool_count;
122 122
123#endif /* GLYPH_DEBUG and ENABLE_CHECKING */ 123#endif /* GLYPH_DEBUG and ENABLE_CHECKING */
124 124
125/* If non-null, the frame whose frame matrices are manipulated. If
126 null, window matrices are worked on. */
127
128static struct frame *frame_matrix_frame;
129
130/* Convert vpos and hpos from frame to window and vice versa. 125/* Convert vpos and hpos from frame to window and vice versa.
131 This may only be used for terminal frames. */ 126 This may only be used for terminal frames. */
132 127
@@ -1178,7 +1173,12 @@ line_hash_code (struct frame *f, struct glyph_row *row)
1178 while (glyph < end) 1173 while (glyph < end)
1179 { 1174 {
1180 int c = glyph->u.ch; 1175 int c = glyph->u.ch;
1176 /* FIXME/tty: struct frame can move with igc, and so on.
1177 But we need something that takes different frames
1178 into account. */
1181 int face_id = glyph->face_id; 1179 int face_id = glyph->face_id;
1180 if (glyph->frame != f)
1181 face_id += (ptrdiff_t) glyph->frame;
1182 if (FRAME_MUST_WRITE_SPACES (f)) 1182 if (FRAME_MUST_WRITE_SPACES (f))
1183 c -= SPACEGLYPH; 1183 c -= SPACEGLYPH;
1184 hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c; 1184 hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c;
@@ -1213,7 +1213,7 @@ line_draw_cost (struct frame *f, struct glyph_matrix *matrix, int vpos)
1213 if (!FRAME_MUST_WRITE_SPACES (f)) 1213 if (!FRAME_MUST_WRITE_SPACES (f))
1214 { 1214 {
1215 /* Skip from the end over trailing spaces. */ 1215 /* Skip from the end over trailing spaces. */
1216 while (end > beg && CHAR_GLYPH_SPACE_P (*(end - 1))) 1216 while (end > beg && CHAR_GLYPH_SPACE_P (f, *(end - 1)))
1217 --end; 1217 --end;
1218 1218
1219 /* All blank line. */ 1219 /* All blank line. */
@@ -1221,7 +1221,7 @@ line_draw_cost (struct frame *f, struct glyph_matrix *matrix, int vpos)
1221 return 0; 1221 return 0;
1222 1222
1223 /* Skip over leading spaces. */ 1223 /* Skip over leading spaces. */
1224 while (CHAR_GLYPH_SPACE_P (*beg)) 1224 while (CHAR_GLYPH_SPACE_P (f, *beg))
1225 ++beg; 1225 ++beg;
1226 } 1226 }
1227 1227
@@ -2558,6 +2558,7 @@ build_frame_matrix_from_leaf_window (struct glyph_matrix *frame_matrix, struct w
2558 int window_y, frame_y; 2558 int window_y, frame_y;
2559 /* If non-zero, a glyph to insert at the right border of W. */ 2559 /* If non-zero, a glyph to insert at the right border of W. */
2560 GLYPH right_border_glyph; 2560 GLYPH right_border_glyph;
2561 struct frame *f = XFRAME (w->frame);
2561 2562
2562 SET_GLYPH_FROM_CHAR (right_border_glyph, 0); 2563 SET_GLYPH_FROM_CHAR (right_border_glyph, 0);
2563 2564
@@ -2599,10 +2600,10 @@ build_frame_matrix_from_leaf_window (struct glyph_matrix *frame_matrix, struct w
2599 2600
2600 /* Fill up the frame row with spaces up to the left margin of the 2601 /* Fill up the frame row with spaces up to the left margin of the
2601 window row. */ 2602 window row. */
2602 fill_up_frame_row_with_spaces (frame_row, window_matrix->matrix_x); 2603 fill_up_frame_row_with_spaces (f, frame_row, window_matrix->matrix_x);
2603 2604
2604 /* Fill up areas in the window matrix row with spaces. */ 2605 /* Fill up areas in the window matrix row with spaces. */
2605 fill_up_glyph_row_with_spaces (window_row); 2606 fill_up_glyph_row_with_spaces (f, window_row);
2606 2607
2607 /* If only part of W's desired matrix has been built, and 2608 /* If only part of W's desired matrix has been built, and
2608 window_row wasn't displayed, use the corresponding current 2609 window_row wasn't displayed, use the corresponding current
@@ -2638,7 +2639,7 @@ build_frame_matrix_from_leaf_window (struct glyph_matrix *frame_matrix, struct w
2638 glyph with the vertical border glyph. */ 2639 glyph with the vertical border glyph. */
2639 eassert (border->type == CHAR_GLYPH); 2640 eassert (border->type == CHAR_GLYPH);
2640 border->type = CHAR_GLYPH; 2641 border->type = CHAR_GLYPH;
2641 SET_CHAR_GLYPH_FROM_GLYPH (*border, right_border_glyph); 2642 SET_CHAR_GLYPH_FROM_GLYPH (f, *border, right_border_glyph);
2642 } 2643 }
2643 2644
2644#ifdef GLYPH_DEBUG 2645#ifdef GLYPH_DEBUG
@@ -2701,11 +2702,11 @@ spec_glyph_lookup_face (struct window *w, GLYPH *glyph)
2701 To be called for frame-based redisplay, only. */ 2702 To be called for frame-based redisplay, only. */
2702 2703
2703static void 2704static void
2704fill_up_glyph_row_with_spaces (struct glyph_row *row) 2705fill_up_glyph_row_with_spaces (struct frame *f, struct glyph_row *row)
2705{ 2706{
2706 fill_up_glyph_row_area_with_spaces (row, LEFT_MARGIN_AREA); 2707 fill_up_glyph_row_area_with_spaces (f, row, LEFT_MARGIN_AREA);
2707 fill_up_glyph_row_area_with_spaces (row, TEXT_AREA); 2708 fill_up_glyph_row_area_with_spaces (f, row, TEXT_AREA);
2708 fill_up_glyph_row_area_with_spaces (row, RIGHT_MARGIN_AREA); 2709 fill_up_glyph_row_area_with_spaces (f, row, RIGHT_MARGIN_AREA);
2709} 2710}
2710 2711
2711 2712
@@ -2713,15 +2714,19 @@ fill_up_glyph_row_with_spaces (struct glyph_row *row)
2713 frame-based redisplay only. */ 2714 frame-based redisplay only. */
2714 2715
2715static void 2716static void
2716fill_up_glyph_row_area_with_spaces (struct glyph_row *row, int area) 2717fill_up_glyph_row_area_with_spaces (struct frame *f, struct glyph_row *row,
2718 int area)
2717{ 2719{
2718 if (row->glyphs[area] < row->glyphs[area + 1]) 2720 if (row->glyphs[area] < row->glyphs[area + 1])
2719 { 2721 {
2720 struct glyph *end = row->glyphs[area + 1]; 2722 struct glyph *end = row->glyphs[area + 1];
2721 struct glyph *text = row->glyphs[area] + row->used[area]; 2723 struct glyph *text = row->glyphs[area] + row->used[area];
2722 2724
2723 while (text < end) 2725 for (; text < end; ++text)
2724 *text++ = space_glyph; 2726 {
2727 *text = space_glyph;
2728 text->frame = f;
2729 }
2725 row->used[area] = text - row->glyphs[area]; 2730 row->used[area] = text - row->glyphs[area];
2726 } 2731 }
2727} 2732}
@@ -2731,13 +2736,16 @@ fill_up_glyph_row_area_with_spaces (struct glyph_row *row, int area)
2731 reached. In frame matrices only one area, TEXT_AREA, is used. */ 2736 reached. In frame matrices only one area, TEXT_AREA, is used. */
2732 2737
2733void 2738void
2734fill_up_frame_row_with_spaces (struct glyph_row *row, int upto) 2739fill_up_frame_row_with_spaces (struct frame *f, struct glyph_row *row, int upto)
2735{ 2740{
2736 int i = row->used[TEXT_AREA]; 2741 int i = row->used[TEXT_AREA];
2737 struct glyph *glyph = row->glyphs[TEXT_AREA]; 2742 struct glyph *glyph = row->glyphs[TEXT_AREA];
2738 2743
2739 while (i < upto) 2744 for (; i < upto; ++i)
2740 glyph[i++] = space_glyph; 2745 {
2746 glyph[i] = space_glyph;
2747 glyph[i].frame = f;
2748 }
2741 2749
2742 row->used[TEXT_AREA] = i; 2750 row->used[TEXT_AREA] = i;
2743} 2751}
@@ -2748,17 +2756,6 @@ fill_up_frame_row_with_spaces (struct glyph_row *row, int upto)
2748 Mirroring operations on frame matrices in window matrices 2756 Mirroring operations on frame matrices in window matrices
2749 **********************************************************************/ 2757 **********************************************************************/
2750 2758
2751/* Set frame being updated via frame-based redisplay to F. This
2752 function must be called before updates to make explicit that we are
2753 working on frame matrices or not. */
2754
2755static void
2756set_frame_matrix_frame (struct frame *f)
2757{
2758 frame_matrix_frame = f;
2759}
2760
2761
2762/* Make sure glyph row ROW in CURRENT_MATRIX is up to date. 2759/* Make sure glyph row ROW in CURRENT_MATRIX is up to date.
2763 DESIRED_MATRIX is the desired matrix corresponding to 2760 DESIRED_MATRIX is the desired matrix corresponding to
2764 CURRENT_MATRIX. The update is done by exchanging glyph pointers 2761 CURRENT_MATRIX. The update is done by exchanging glyph pointers
@@ -2768,9 +2765,10 @@ set_frame_matrix_frame (struct frame *f)
2768 operations in window matrices of frame_matrix_frame. */ 2765 operations in window matrices of frame_matrix_frame. */
2769 2766
2770static void 2767static void
2771make_current (struct glyph_matrix *desired_matrix, 2768make_current (struct frame *f, struct window *w, int row)
2772 struct glyph_matrix *current_matrix, int row)
2773{ 2769{
2770 struct glyph_matrix *desired_matrix = f ? f->desired_matrix : w->desired_matrix;
2771 struct glyph_matrix *current_matrix = f ? f->current_matrix : w->current_matrix;
2774 struct glyph_row *current_row = MATRIX_ROW (current_matrix, row); 2772 struct glyph_row *current_row = MATRIX_ROW (current_matrix, row);
2775 struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row); 2773 struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row);
2776 bool mouse_face_p = current_row->mouse_face_p; 2774 bool mouse_face_p = current_row->mouse_face_p;
@@ -2797,8 +2795,8 @@ make_current (struct glyph_matrix *desired_matrix,
2797 2795
2798 /* If we are called on frame matrices, perform analogous operations 2796 /* If we are called on frame matrices, perform analogous operations
2799 for window matrices. */ 2797 for window matrices. */
2800 if (frame_matrix_frame) 2798 if (f)
2801 mirror_make_current (XWINDOW (frame_matrix_frame->root_window), row); 2799 mirror_make_current (XWINDOW (f->root_window), row);
2802} 2800}
2803 2801
2804 2802
@@ -2862,9 +2860,11 @@ mirror_make_current (struct window *w, int frame_row)
2862 This function is called from do_scrolling and do_direct_scrolling. */ 2860 This function is called from do_scrolling and do_direct_scrolling. */
2863 2861
2864void 2862void
2865mirrored_line_dance (struct glyph_matrix *matrix, int unchanged_at_top, int nlines, 2863mirrored_line_dance (struct frame *f, int unchanged_at_top, int nlines,
2866 int *copy_from, char *retained_p) 2864 int *copy_from, char *retained_p)
2867{ 2865{
2866 struct glyph_matrix *matrix = f->current_matrix;
2867
2868 /* A copy of original rows. */ 2868 /* A copy of original rows. */
2869 struct glyph_row *old_rows; 2869 struct glyph_row *old_rows;
2870 2870
@@ -2894,9 +2894,8 @@ mirrored_line_dance (struct glyph_matrix *matrix, int unchanged_at_top, int nlin
2894 } 2894 }
2895 2895
2896 /* Do the same for window matrices, if MATRIX is a frame matrix. */ 2896 /* Do the same for window matrices, if MATRIX is a frame matrix. */
2897 if (frame_matrix_frame) 2897 mirror_line_dance (XWINDOW (f->root_window),
2898 mirror_line_dance (XWINDOW (frame_matrix_frame->root_window), 2898 unchanged_at_top, nlines, copy_from, retained_p);
2899 unchanged_at_top, nlines, copy_from, retained_p);
2900 2899
2901 SAFE_FREE (); 2900 SAFE_FREE ();
2902} 2901}
@@ -3194,7 +3193,10 @@ redraw_frame (struct frame *f)
3194 future. */ 3193 future. */
3195 SET_FRAME_GARBAGED (f); 3194 SET_FRAME_GARBAGED (f);
3196 3195
3197 clear_frame (f); 3196 /* FIXME/tty: clear_frame is actually a "clear_terminal", i.e.
3197 is clears the entire screen. */
3198 if (!FRAME_PARENT_FRAME (f))
3199 clear_frame (f);
3198 clear_current_matrices (f); 3200 clear_current_matrices (f);
3199 update_end (f); 3201 update_end (f);
3200 fset_redisplay (f); 3202 fset_redisplay (f);
@@ -3229,145 +3231,501 @@ DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
3229 return Qnil; 3231 return Qnil;
3230} 3232}
3231 3233
3232
3233 3234
3234/*********************************************************************** 3235/**********************************************************************
3235 Frame Update 3236 TTY Child Frames
3236 ***********************************************************************/ 3237 **********************************************************************/
3237 3238
3238/* Update frame F based on the data in desired matrices. 3239/* The new thing that child frames on ttys provide is that frames on a
3240 tty no longer always occupy the whole terminal. They can overlap
3241 instead.
3239 3242
3240 If FORCE_P, don't let redisplay be stopped by detecting pending input. 3243 Let a "root" frame be a frame that has no parent frame. Such root
3241 If INHIBIT_HAIRY_ID_P, don't try scrolling. 3244 frames we require to be the size of the terminal screen. The current
3245 glyph matrix of a root frame of a termimnal represents what is on the
3246 screen. The desired matrix of a root frame represents what should be
3247 one the screen.
3242 3248
3243 Value is true if redisplay was stopped due to pending input. */ 3249 Building the desired matrix of root frame proceeds by
3244 3250
3245bool 3251 - building the desired matrix of the root frame itself which is
3246update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p) 3252 the bottommost frame in z-order,
3253 - building desired matrices of child frames in z-order, topmost last,
3254 - copying the desired glyphs from child frames to the desired glyphs
3255 of the root frame
3256
3257 Updating the screen is then done using root frame matrices as it was
3258 before child frames were introduced. Child frame current matrices are
3259 updated by copying glyph contents of the current matrix of the root
3260 frames to the current matrices of child frames. This imnplicitly
3261 also updates the glyph contents of their windows' current matrices. */
3262
3263struct rect
3247{ 3264{
3248 /* True means display has been paused because of pending input. */ 3265 int x, y, w, h;
3249 bool paused_p; 3266};
3250 struct window *root_window = XWINDOW (f->root_window);
3251 3267
3252 if (redisplay_dont_pause) 3268#ifdef GLYPH_DEBUG
3253 force_p = true; 3269static bool
3254 else if (!force_p && detect_input_pending_ignore_squeezables ()) 3270is_glyph_in_matrix (struct glyph_matrix *m, struct glyph *g)
3271{
3272 for (int y = 0; y < m->matrix_h; ++y)
3255 { 3273 {
3256 paused_p = true; 3274 struct glyph_row *r = MATRIX_ROW (m, y);
3257 goto do_pause; 3275 if (g >= r->glyphs[0] && g < r->glyphs[0] + m->matrix_w)
3276 return true;
3258 } 3277 }
3278 return false;
3279}
3259 3280
3260 if (FRAME_WINDOW_P (f)) 3281/* Return true if GLYPH is part of the desired matrix of F. */
3282
3283bool
3284is_tty_desired_glyph (struct frame *f, struct glyph *g)
3285{
3286 eassert (is_tty_frame (f));
3287 return is_glyph_in_matrix (f->desired_matrix, g);
3288}
3289
3290/* Return true if GLYPH is part of the desired matrix of F. */
3291
3292bool
3293is_tty_current_glyph (struct frame *f, struct glyph *g)
3294{
3295 eassert (is_tty_frame (f));
3296 return is_glyph_in_matrix (f->current_matrix, g);
3297}
3298#endif // GLYPH_DEBUG
3299
3300/* Compute the intersection of R1 and R2 in R. Value is true if R1 and
3301 R2 intersect, false otherwise. */
3302
3303static bool
3304rect_intersect (struct rect *r, struct rect r1, struct rect r2)
3305{
3306 int x1 = max (r1.x, r2.x);
3307 int x2 = min (r1.x + r1.w, r2.x + r2.w);
3308 if (x2 < x1)
3309 return false;
3310 int y1 = max (r1.y, r2.y);
3311 int y2 = min (r1.y + r1.h, r2.y + r2.h);
3312 if (y2 < y1)
3313 return false;
3314 *r = (struct rect) { .x = x1, .y = y1, .w = x2 - x1, .h = y2 - y1 };
3315 return true;
3316}
3317
3318/* Return the rectanlge frame F occupies. */
3319
3320static struct rect
3321frame_rect (struct frame *f)
3322{
3323 return (struct rect) {
3324 .x = f->left_pos, .y = f->top_pos, .w = f->total_cols, .h = f->total_lines
3325 };
3326}
3327
3328/* Return the root frame of frame F. Follow the parent_frame chain until
3329 we reach a frame that has no parent. That is the root frame. Note
3330 that the root of a root frame is itself. */
3331
3332struct frame *
3333root_frame (struct frame *f)
3334{
3335 while (FRAME_PARENT_FRAME (f))
3336 f = FRAME_PARENT_FRAME (f);
3337 return f;
3338}
3339
3340/* Return true if F1 is an ancestor of F2. */
3341
3342static bool
3343is_frame_ancestor (struct frame *f1, struct frame *f2)
3344{
3345 for (struct frame *f = FRAME_PARENT_FRAME (f2); f; f = FRAME_PARENT_FRAME (f))
3346 if (f == f1)
3347 return true;
3348 return false;
3349}
3350
3351/* Return a list of all frames having root frame ROOT. */
3352
3353Lisp_Object
3354frames_with_root (struct frame *root, bool visible)
3355{
3356 Lisp_Object list = Qnil;
3357 Lisp_Object tail, frame;
3358 FOR_EACH_FRAME (tail, frame)
3261 { 3359 {
3262 /* We are working on window matrix basis. All windows whose 3360 struct frame *f = XFRAME (frame);
3263 flag must_be_updated_p is set have to be updated. */ 3361 if (FRAME_VISIBLE_P (f) && root_frame (f) == root)
3362 list = Fcons (frame, list);
3363 }
3364 return list;
3365}
3264 3366
3265 /* Record that we are not working on frame matrices. */ 3367/* Compare frames F1 and F2 for z-order. Value is like strcmp. */
3266 set_frame_matrix_frame (NULL);
3267 3368
3268 /* Update all windows in the window tree of F, maybe stopping 3369static bool
3269 when pending input is detected. */ 3370frame_z_order_cmp (struct frame *f1, struct frame *f2)
3270 update_begin (f); 3371{
3372 if (f1 == f2)
3373 return 0;
3374 if (is_frame_ancestor (f1, f2))
3375 return -1;
3376 return f1->z_order - f2->z_order;
3377}
3271 3378
3272#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR 3379DEFUN ("frame--z-order-sort-predicate",
3273 /* Update the menu bar on X frames that don't have toolkit 3380 Fframe__z_order_sort_predicate,
3274 support. */ 3381 Sframe__z_order_sort_predicate,
3275 if (WINDOWP (f->menu_bar_window)) 3382 2, 2, 0,
3276 update_window (XWINDOW (f->menu_bar_window), true); 3383 doc: /* Internal frame sorting function A < B. */)
3277#endif 3384 (Lisp_Object a, Lisp_Object b)
3385{
3386 CHECK_FRAME (a); CHECK_FRAME (b);
3387 return frame_z_order_cmp (XFRAME (a), XFRAME (b)) < 0 ? Qt : Qnil;
3388}
3278 3389
3279#if defined (HAVE_WINDOW_SYSTEM) 3390/* Return a z-order list of frames on the same terminal as F. The list
3280 /* Update the tab-bar window, if present. */ 3391 is ordered topmost frame last. Note that this list may contain
3281 if (WINDOWP (f->tab_bar_window)) 3392 more than one root frame plus their children. */
3393
3394Lisp_Object
3395frames_in_reverse_z_order (struct frame *f, bool visible)
3396{
3397 struct frame *root = root_frame (f);
3398 Lisp_Object frames = frames_with_root (root, visible);
3399 frames = CALLN (Fsort, frames, Qframe__z_order_sort_predicate);
3400 eassert (FRAMEP (XCAR (frames)));
3401 eassert (XFRAME (XCAR (frames)) == root);
3402 return frames;
3403}
3404
3405void
3406tty_raise_lower_frame (struct frame *f, bool raise)
3407{
3408 struct frame *parent = FRAME_PARENT_FRAME (f);
3409 if (parent)
3410 {
3411 Lisp_Object children = frames_in_reverse_z_order (root_frame (f), false);
3412 Lisp_Object siblings = Qnil;
3413 for (Lisp_Object tail = children; CONSP (tail); tail = XCDR (tail))
3282 { 3414 {
3283 struct window *w = XWINDOW (f->tab_bar_window); 3415 struct frame *child = XFRAME (XCAR (tail));
3416 if (FRAME_PARENT_FRAME (child) == parent)
3417 siblings = Fcons (XCAR (tail), siblings);
3418 }
3284 3419
3285 /* Update tab-bar window. */ 3420 int n = list_length (siblings);
3286 if (w->must_be_updated_p) 3421 if (n > 1)
3422 {
3423 int i;
3424 if (raise)
3425 f->z_order = 0, i = 1;
3426 else
3427 f->z_order = n - 1, i = 0;
3428 for (Lisp_Object tail = siblings; CONSP (tail); tail = XCDR (tail))
3287 { 3429 {
3288 Lisp_Object tem; 3430 struct frame *child = XFRAME (XCAR (tail));
3431 if (f != child)
3432 child->z_order = i++;
3433 }
3434 }
3435 }
3436}
3289 3437
3290 update_window (w, true); 3438/* Return true if frame F is a tty frame. */
3291 w->must_be_updated_p = false;
3292 3439
3293 /* Swap tab-bar strings. We swap because we want to 3440bool
3294 reuse strings. */ 3441is_tty_frame (struct frame *f)
3295 tem = f->current_tab_bar_string; 3442{
3296 fset_current_tab_bar_string (f, f->desired_tab_bar_string); 3443 return FRAME_TERMCAP_P (f);
3297 fset_desired_tab_bar_string (f, tem); 3444}
3298 } 3445
3446/* Return true if frame F is a tty child frame. */
3447
3448bool
3449is_tty_child_frame (struct frame *f)
3450{
3451 return FRAME_PARENT_FRAME (f) && is_tty_frame (f);
3452}
3453
3454/* Return true if frame F is a tty root frame. */
3455
3456bool
3457is_tty_root_frame (struct frame *f)
3458{
3459 return !FRAME_PARENT_FRAME (f) && is_tty_frame (f);
3460}
3461
3462/* Return the index of the first enabled row in MATRIX, or -1 if there
3463 is none. */
3464
3465static int
3466first_enabled_row (struct glyph_matrix *matrix)
3467{
3468 for (int i = 0; i < matrix->nrows; ++i)
3469 if (MATRIX_ROW_ENABLED_P (matrix, i))
3470 return i;
3471 return -1;
3472}
3473
3474/* On tty frame F, make desired matrix current, without writing
3475 to the terminal. */
3476
3477static void
3478make_matrix_current (struct frame *f)
3479{
3480 int first_row = first_enabled_row (f->desired_matrix);
3481 if (first_row >= 0)
3482 for (int i = first_row; i < f->desired_matrix->nrows; ++i)
3483 if (MATRIX_ROW_ENABLED_P (f->desired_matrix, i))
3484 make_current (f, NULL, i);
3485}
3486
3487/* Copy to ROOT's desired matrix what we need from CHILD's current frame matrix. */
3488
3489static void
3490copy_child_glyphs (struct frame *root, struct frame *child)
3491{
3492 eassert (!FRAME_PARENT_FRAME (root));
3493 eassert (is_frame_ancestor (root, child));
3494
3495 /* Determine the intersection of the child frame rectangle with
3496 the root frame. This is basically clipping the child frame to
3497 the root frame rectangle. */
3498 struct rect r;
3499 if (!rect_intersect (&r, frame_rect (root), frame_rect (child)))
3500 return;
3501
3502 /* Build CHILD's current matrix which we need to copy from it. */
3503 make_matrix_current (child);
3504
3505 /* The first row of the child's matrix that is visible in the parent
3506 depends on how many child rows are above the parent, which is
3507 abs (child->top_pos) if top_pos is negative. */
3508 int child_y = child->top_pos < 0 ? abs (child->top_pos) : 0;
3509
3510 /* The first column of the child's matrix that is visible in the
3511 parent depends on how many child columns are to the left of the
3512 parent, which is abs (child->left_pos) if left_pos is negative. */
3513 int child_x = child->left_pos < 0 ? abs (child->left_pos) : 0;
3514
3515 /* For all rows in the intersection, copy glyphs from the child's
3516 current matrix to the root's desired matrix, enabling those
3517 rows. */
3518 for (int y = r.y; y < r.y + r.h; ++y, ++child_y)
3519 {
3520 /* Start with the root's desired matrix row. If that hasn't
3521 been redisplayed, copy from the root's current matrix. */
3522 struct glyph_row *root_row = MATRIX_ROW (root->desired_matrix, y);
3523 if (!root_row->enabled_p)
3524 {
3525 struct glyph_row *from = MATRIX_ROW (root->current_matrix, y);
3526 memcpy (root_row->glyphs[0], from->glyphs[0],
3527 root->current_matrix->matrix_w * sizeof (struct glyph));
3528 root_row->enabled_p = true;
3299 } 3529 }
3530
3531 /* Copy the child's current row contents over it. */
3532 struct glyph_row *child_row = MATRIX_ROW (child->current_matrix, child_y);
3533 memcpy (root_row->glyphs[0] + r.x,
3534 child_row->glyphs[0] + child_x,
3535 r.w * sizeof (struct glyph));
3536
3537 /* Compute a new hash since we changed glyphs. */
3538 root_row->hash = row_hash (root_row);
3539 }
3540}
3541
3542/***********************************************************************
3543 Frame Update
3544 ***********************************************************************/
3545
3546/* Update the menu bar on X frames that don't have toolkit
3547 support. */
3548
3549static void
3550update_menu_bar (struct frame *f)
3551{
3552#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
3553 if (WINDOWP (f->menu_bar_window))
3554 update_window (XWINDOW (f->menu_bar_window), true);
3300#endif 3555#endif
3556}
3301 3557
3302#if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR) 3558#ifdef HAVE_WINDOW_SYSTEM
3303 /* Update the tool-bar window, if present. */ 3559static void
3304 if (WINDOWP (f->tool_bar_window)) 3560update_bar_window (Lisp_Object window, Lisp_Object *current,
3561 Lisp_Object *desired)
3562{
3563 if (WINDOWP (window))
3564 {
3565 struct window *w = XWINDOW (window);
3566 if (w->must_be_updated_p)
3305 { 3567 {
3306 struct window *w = XWINDOW (f->tool_bar_window); 3568 update_window (w, true);
3569 w->must_be_updated_p = false;
3570 Lisp_Object tem = *current;
3571 *current = *desired;
3572 *desired = tem;
3573 }
3574 }
3575}
3576#endif
3307 3577
3308 /* Update tool-bar window. */ 3578/* Update the tab-bar window of frame F, if present.
3309 if (w->must_be_updated_p) 3579 FIXME/tty: This is almost identical to the updating
3310 { 3580 of the tab bar. */
3311 Lisp_Object tem;
3312 3581
3313 update_window (w, true); 3582static void
3314 w->must_be_updated_p = false; 3583update_tab_bar (struct frame *f)
3584{
3585#if defined(HAVE_WINDOW_SYSTEM)
3586 update_bar_window (f->tab_bar_window, &f->current_tab_bar_string,
3587 &f->desired_tab_bar_string);
3588#endif
3589}
3315 3590
3316 /* Swap tool-bar strings. We swap because we want to 3591static void
3317 reuse strings. */ 3592update_tool_bar (struct frame *f)
3318 tem = f->current_tool_bar_string; 3593{
3319 fset_current_tool_bar_string (f, f->desired_tool_bar_string); 3594#if defined(HAVE_WINDOW_SYSTEM) && !defined(HAVE_EXT_TOOL_BAR)
3320 fset_desired_tool_bar_string (f, tem); 3595 update_bar_window (f->tool_bar_window, &f->current_tool_bar_string,
3321 } 3596 &f->desired_tool_bar_string);
3322 }
3323#endif 3597#endif
3598}
3324 3599
3325 /* Update windows. */ 3600static bool
3326 paused_p = update_window_tree (root_window, force_p); 3601update_window_frame (struct frame *f, bool force_p)
3327 update_end (f); 3602{
3328 } 3603 eassert (FRAME_WINDOW_P (f));
3329 else 3604 update_begin (f);
3605 update_menu_bar (f);
3606 update_tab_bar (f);
3607 update_tool_bar (f);
3608 struct window *root_window = XWINDOW (f->root_window);
3609 bool paused_p = update_window_tree (root_window, force_p);
3610 update_end (f);
3611 set_window_update_flags (root_window, false);
3612 return paused_p;
3613}
3614
3615static bool
3616update_initial_frame (struct frame *f, bool force_p)
3617{
3618 build_frame_matrix (f);
3619 struct window *root_window = XWINDOW (f->root_window);
3620 set_window_update_flags (root_window, false);
3621 return false;
3622}
3623
3624static void
3625flush_terminal (struct frame *f)
3626{
3627 if (FRAME_TTY (f)->termscript)
3628 fflush (FRAME_TTY (f)->termscript);
3629 fflush (FRAME_TTY (f)->output);
3630}
3631
3632static bool
3633update_tty_frame (struct frame *f, bool force_p)
3634{
3635 build_frame_matrix (f);
3636 return false;
3637}
3638
3639bool
3640combine_updates_for_frame (struct frame *f, bool force_p, bool inhibit_scrolling)
3641{
3642 struct frame *root = root_frame (f);
3643 eassert (FRAME_VISIBLE_P (root));
3644
3645 /* Process child frames in reverse z-order, topmost last. For each
3646 child, copy what we need to the root's desired matrix. */
3647 Lisp_Object z_order = frames_in_reverse_z_order (root, true);
3648 for (Lisp_Object tail = XCDR (z_order); CONSP (tail); tail = XCDR (tail))
3330 { 3649 {
3331 /* We are working on frame matrix basis. Set the frame on whose 3650 struct frame *child = XFRAME (XCAR (tail));
3332 frame matrix we operate. */ 3651 copy_child_glyphs (root, child);
3333 set_frame_matrix_frame (f); 3652 }
3334 3653
3335 /* Build F's desired matrix from window matrices. */ 3654 update_begin (root);
3336 build_frame_matrix (f); 3655 bool paused = write_matrix (root, force_p, inhibit_scrolling, 1, false);
3656 if (!paused)
3657 make_matrix_current (root);
3658 update_end (root);
3659 flush_terminal (root);
3337 3660
3338 /* Update the display. */ 3661 for (Lisp_Object tail = z_order; CONSP (tail); tail = XCDR (tail))
3339 if (FRAME_INITIAL_P (f)) 3662 {
3340 /* No actual display to update so the "update" is a nop and 3663 struct frame *f = XFRAME (XCAR (tail));
3341 obviously isn't interrupted by pending input. */ 3664 struct window *root_window = XWINDOW (f->root_window);
3342 paused_p = false; 3665 set_window_update_flags (root_window, false);
3343 else 3666 clear_desired_matrices (f);
3344 {
3345 update_begin (f);
3346 paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p, 1, false);
3347 update_end (f);
3348 }
3349
3350 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
3351 {
3352 if (FRAME_TTY (f)->termscript)
3353 fflush (FRAME_TTY (f)->termscript);
3354 if (FRAME_TERMCAP_P (f))
3355 fflush (FRAME_TTY (f)->output);
3356 }
3357
3358 /* Check window matrices for lost pointers. */
3359#ifdef GLYPH_DEBUG 3667#ifdef GLYPH_DEBUG
3360 check_window_matrix_pointers (root_window); 3668 check_window_matrix_pointers (root_window);
3361 add_frame_display_history (f, paused_p); 3669 add_frame_display_history (f, false);
3362#endif 3670#endif
3363 } 3671 }
3364 3672
3365 do_pause: 3673 return paused;
3366 /* Reset flags indicating that a window should be updated. */ 3674}
3367 set_window_update_flags (root_window, false);
3368 3675
3369 display_completed = !paused_p; 3676/* Update on the screen all root frames ROOTS. Called from
3370 return paused_p; 3677 redisplay_internal as the last step of redisplaying. */
3678
3679bool
3680combine_updates (Lisp_Object roots, bool force_p, bool inhibit_scrolling)
3681{
3682 for (; CONSP (roots); roots = XCDR (roots))
3683 {
3684 struct frame *root = XFRAME (XCAR (roots));
3685 if (combine_updates_for_frame (root, force_p, inhibit_scrolling))
3686 {
3687 display_completed = false;
3688 return true;
3689 }
3690 }
3691
3692 display_completed = true;
3693 return false;
3694}
3695
3696/* Update frame F based on the data in desired matrices.
3697
3698 If FORCE_P, don't let redisplay be stopped by detecting pending input.
3699 If INHIBIT_SCROLLING, don't try scrolling.
3700
3701 Value is true if redisplay was stopped due to pending input. */
3702
3703bool
3704update_frame (struct frame *f, bool force_p, bool inhibit_scrolling)
3705{
3706 struct window *root_window = XWINDOW (f->root_window);
3707
3708 if (redisplay_dont_pause)
3709 force_p = true;
3710 else if (!force_p && detect_input_pending_ignore_squeezables ())
3711 {
3712 /* Reset flags indicating that a window should be updated. */
3713 set_window_update_flags (root_window, false);
3714 display_completed = false;
3715 return true;
3716 }
3717
3718 bool paused;
3719 if (FRAME_WINDOW_P (f))
3720 paused = update_window_frame (f, force_p);
3721 else if (FRAME_INITIAL_P (f))
3722 paused = update_initial_frame (f, force_p);
3723 else
3724 paused = update_tty_frame (f, force_p);
3725
3726 if (paused)
3727 display_completed = false;
3728 return paused;
3371} 3729}
3372 3730
3373/* Update a TTY frame F that has a menu dropped down over some of its 3731/* Update a TTY frame F that has a menu dropped down over some of its
@@ -3384,29 +3742,25 @@ void
3384update_frame_with_menu (struct frame *f, int row, int col) 3742update_frame_with_menu (struct frame *f, int row, int col)
3385{ 3743{
3386 struct window *root_window = XWINDOW (f->root_window); 3744 struct window *root_window = XWINDOW (f->root_window);
3387 bool paused_p, cursor_at_point_p; 3745 bool cursor_at_point_p;
3388 3746
3389 eassert (FRAME_TERMCAP_P (f)); 3747 eassert (FRAME_TERMCAP_P (f));
3390 3748
3391 /* We are working on frame matrix basis. Set the frame on whose
3392 frame matrix we operate. */
3393 set_frame_matrix_frame (f);
3394
3395 /* Update the display. */ 3749 /* Update the display. */
3396 update_begin (f); 3750 update_begin (f);
3397 cursor_at_point_p = !(row >= 0 && col >= 0); 3751 cursor_at_point_p = !(row >= 0 && col >= 0);
3398 /* Force update_frame_1 not to stop due to pending input, and not 3752 /* Do not stop due to pending input, and do not try scrolling. This
3399 try scrolling. */ 3753 means that write_glyphs will always return false. */
3400 paused_p = update_frame_1 (f, 1, 1, cursor_at_point_p, true); 3754 write_matrix (f, 1, 1, cursor_at_point_p, true);
3755 make_matrix_current (f);
3756 clear_desired_matrices (f);
3401 /* ROW and COL tell us where in the menu to position the cursor, so 3757 /* ROW and COL tell us where in the menu to position the cursor, so
3402 that screen readers know the active region on the screen. */ 3758 that screen readers know the active region on the screen. */
3403 if (!cursor_at_point_p) 3759 if (!cursor_at_point_p)
3404 cursor_to (f, row, col); 3760 cursor_to (f, row, col);
3405 update_end (f); 3761 update_end (f);
3762 flush_terminal (f);
3406 3763
3407 if (FRAME_TTY (f)->termscript)
3408 fflush (FRAME_TTY (f)->termscript);
3409 fflush (FRAME_TTY (f)->output);
3410 /* Check window matrices for lost pointers. */ 3764 /* Check window matrices for lost pointers. */
3411#if GLYPH_DEBUG 3765#if GLYPH_DEBUG
3412#if 0 3766#if 0
@@ -3415,12 +3769,12 @@ update_frame_with_menu (struct frame *f, int row, int col)
3415 making any updates to the window matrices. */ 3769 making any updates to the window matrices. */
3416 check_window_matrix_pointers (root_window); 3770 check_window_matrix_pointers (root_window);
3417#endif 3771#endif
3418 add_frame_display_history (f, paused_p); 3772 add_frame_display_history (f, false);
3419#endif 3773#endif
3420 3774
3421 /* Reset flags indicating that a window should be updated. */ 3775 /* Reset flags indicating that a window should be updated. */
3422 set_window_update_flags (root_window, false); 3776 set_window_update_flags (root_window, false);
3423 display_completed = !paused_p; 3777 display_completed = true;
3424} 3778}
3425 3779
3426/* Update the mouse position for a frame F. This handles both 3780/* Update the mouse position for a frame F. This handles both
@@ -3507,9 +3861,6 @@ update_single_window (struct window *w)
3507 { 3861 {
3508 struct frame *f = XFRAME (WINDOW_FRAME (w)); 3862 struct frame *f = XFRAME (WINDOW_FRAME (w));
3509 3863
3510 /* Record that this is not a frame-based redisplay. */
3511 set_frame_matrix_frame (NULL);
3512
3513 /* Update W. */ 3864 /* Update W. */
3514 update_begin (f); 3865 update_begin (f);
3515 update_window (w, true); 3866 update_window (w, true);
@@ -3688,6 +4039,8 @@ update_window (struct window *w, bool force_p)
3688 4039
3689#ifdef HAVE_WINDOW_SYSTEM 4040#ifdef HAVE_WINDOW_SYSTEM
3690 gui_update_window_begin (w); 4041 gui_update_window_begin (w);
4042#else
4043 (void) changed_p;
3691#endif 4044#endif
3692 yb = window_text_bottom_y (w); 4045 yb = window_text_bottom_y (w);
3693 row = MATRIX_ROW (desired_matrix, 0); 4046 row = MATRIX_ROW (desired_matrix, 0);
@@ -4321,7 +4674,7 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
4321 4674
4322 /* Update current_row from desired_row. */ 4675 /* Update current_row from desired_row. */
4323 was_stipple = current_row->stipple_p; 4676 was_stipple = current_row->stipple_p;
4324 make_current (w->desired_matrix, w->current_matrix, vpos); 4677 make_current (NULL, w, vpos);
4325 4678
4326 /* If only a partial update was performed, any stipple already 4679 /* If only a partial update was performed, any stipple already
4327 displayed in MATRIX_ROW (w->current_matrix, vpos) might still be 4680 displayed in MATRIX_ROW (w->current_matrix, vpos) might still be
@@ -4931,7 +5284,92 @@ scrolling_window (struct window *w, int tab_line_p)
4931 Frame-Based Updates 5284 Frame-Based Updates
4932 ************************************************************************/ 5285 ************************************************************************/
4933 5286
4934/* Update the desired frame matrix of frame F. 5287static void
5288tty_set_cursor (void)
5289{
5290 struct frame *f = SELECTED_FRAME ();
5291
5292 if ((cursor_in_echo_area
5293 /* If we are showing a message instead of the mini-buffer,
5294 show the cursor for the message instead of for the
5295 (now hidden) mini-buffer contents. */
5296 || (BASE_EQ (minibuf_window, selected_window)
5297 && BASE_EQ (minibuf_window, echo_area_window)
5298 && !NILP (echo_area_buffer[0])))
5299 /* These cases apply only to the frame that contains
5300 the active mini-buffer window. */
5301 && FRAME_HAS_MINIBUF_P (f)
5302 && BASE_EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
5303 {
5304 int top = WINDOW_TOP_EDGE_LINE (XWINDOW (FRAME_MINIBUF_WINDOW (f)));
5305 int col;
5306
5307 /* Put cursor at the end of the prompt. If the mini-buffer
5308 is several lines high, find the last line that has
5309 any text on it. */
5310 int row = FRAME_TOTAL_LINES (f);
5311 do
5312 {
5313 row--;
5314 col = 0;
5315
5316 if (MATRIX_ROW_ENABLED_P (f->current_matrix, row))
5317 {
5318 /* Frame rows are filled up with spaces that
5319 must be ignored here. */
5320 struct glyph_row *r = MATRIX_ROW (f->current_matrix, row);
5321 struct glyph *start = r->glyphs[TEXT_AREA];
5322
5323 col = r->used[TEXT_AREA];
5324 while (0 < col && start[col - 1].charpos < 0)
5325 col--;
5326 }
5327 }
5328 while (row > top && col == 0);
5329
5330 /* We exit the loop with COL at the glyph _after_ the last one. */
5331 if (col > 0)
5332 col--;
5333
5334 /* Make sure COL is not out of range. */
5335 if (col >= FRAME_CURSOR_X_LIMIT (f))
5336 {
5337 /* If we have another row, advance cursor into it. */
5338 if (row < FRAME_TOTAL_LINES (f) - 1)
5339 {
5340 col = FRAME_LEFT_SCROLL_BAR_COLS (f);
5341 row++;
5342 }
5343 /* Otherwise move it back in range. */
5344 else
5345 col = FRAME_CURSOR_X_LIMIT (f) - 1;
5346 }
5347
5348 cursor_to (f, row, col);
5349 }
5350 else
5351 {
5352 /* We have only one cursor on terminal frames. Use it to
5353 display the cursor of the selected window. */
5354 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
5355 if (w->cursor.vpos >= 0
5356 /* The cursor vpos may be temporarily out of bounds
5357 in the following situation: There is one window,
5358 with the cursor in the lower half of it. The window
5359 is split, and a message causes a redisplay before
5360 a new cursor position has been computed. */
5361 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
5362 {
5363 int x = WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos);
5364 int y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos);
5365
5366 x += max (0, w->left_margin_cols);
5367 cursor_to (f, y, x);
5368 }
5369 }
5370}
5371
5372/* Write desired matix of tty frame F and make it current.
4935 5373
4936 FORCE_P means that the update should not be stopped by pending input. 5374 FORCE_P means that the update should not be stopped by pending input.
4937 INHIBIT_ID_P means that scrolling by insert/delete should not be tried. 5375 INHIBIT_ID_P means that scrolling by insert/delete should not be tried.
@@ -4940,167 +5378,58 @@ scrolling_window (struct window *w, int tab_line_p)
4940 Value is true if update was stopped due to pending input. */ 5378 Value is true if update was stopped due to pending input. */
4941 5379
4942static bool 5380static bool
4943update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p, 5381write_matrix (struct frame *f, bool force_p, bool inhibit_id_p,
4944 bool set_cursor_p, bool updating_menu_p) 5382 bool set_cursor_p, bool updating_menu_p)
4945{ 5383{
4946 /* Frame matrices to work on. */
4947 struct glyph_matrix *current_matrix = f->current_matrix;
4948 struct glyph_matrix *desired_matrix = f->desired_matrix;
4949 int i;
4950 bool pause_p;
4951 int preempt_count = clip_to_bounds (1, baud_rate / 2400 + 1, INT_MAX);
4952
4953 eassert (current_matrix && desired_matrix);
4954
4955 if (baud_rate != FRAME_COST_BAUD_RATE (f))
4956 calculate_costs (f);
4957
4958 if (!force_p && detect_input_pending_ignore_squeezables ()) 5384 if (!force_p && detect_input_pending_ignore_squeezables ())
4959 { 5385 return true;
4960 pause_p = 1;
4961 goto do_pause;
4962 }
4963 5386
4964 /* If we cannot insert/delete lines, it's no use trying it. */ 5387 /* If we cannot insert/delete lines, it's no use trying it. */
4965 if (!FRAME_LINE_INS_DEL_OK (f)) 5388 if (!FRAME_LINE_INS_DEL_OK (f))
4966 inhibit_id_p = 1; 5389 inhibit_id_p = true;
4967 5390
4968 /* See if any of the desired lines are enabled; don't compute for 5391 if (baud_rate != FRAME_COST_BAUD_RATE (f))
4969 i/d line if just want cursor motion. */ 5392 calculate_costs (f);
4970 for (i = 0; i < desired_matrix->nrows; i++)
4971 if (MATRIX_ROW_ENABLED_P (desired_matrix, i))
4972 break;
4973 5393
4974 /* Try doing i/d line, if not yet inhibited. */ 5394 /* See if any of the desired lines are enabled; don't compute for
4975 if (!inhibit_id_p && i < desired_matrix->nrows) 5395 i/d line if just want cursor motion. */
5396 int first_row = first_enabled_row (f->desired_matrix);
5397 if (!inhibit_id_p && first_row >= 0)
4976 force_p |= scrolling (f); 5398 force_p |= scrolling (f);
4977 5399
4978 /* Update the individual lines as needed. Do bottom line first. */ 5400 /* Update the individual lines as needed. Do bottom line first. This
4979 if (MATRIX_ROW_ENABLED_P (desired_matrix, desired_matrix->nrows - 1)) 5401 is done so that messages are made visible when pausing. */
4980 update_frame_line (f, desired_matrix->nrows - 1, updating_menu_p); 5402 int last_row = f->desired_matrix->nrows - 1;
5403 if (MATRIX_ROW_ENABLED_P (f->desired_matrix, last_row))
5404 write_row (f, last_row, updating_menu_p);
4981 5405
4982 /* Now update the rest of the lines. */ 5406 bool pause_p = false;
4983 for (i = 0; i < desired_matrix->nrows - 1 && (force_p || !input_pending); i++) 5407 if (first_row >= 0)
4984 { 5408 {
4985 if (MATRIX_ROW_ENABLED_P (desired_matrix, i)) 5409 const int preempt_count = clip_to_bounds (1, baud_rate / 2400 + 1, INT_MAX);
4986 {
4987 /* Note that output_buffer_size being 0 means that we want the
4988 old default behavior of flushing output every now and then. */
4989 if (FRAME_TERMCAP_P (f) && FRAME_TTY (f)->output_buffer_size == 0)
4990 {
4991 /* Flush out every so many lines.
4992 Also flush out if likely to have more than 1k buffered
4993 otherwise. I'm told that some telnet connections get
4994 really screwed by more than 1k output at once. */
4995 FILE *display_output = FRAME_TTY (f)->output;
4996 if (display_output)
4997 {
4998 ptrdiff_t outq = __fpending (display_output);
4999 if (outq > 900
5000 || (outq > 20 && ((i - 1) % preempt_count == 0)))
5001 fflush (display_output);
5002 }
5003 }
5004 5410
5005 if (!force_p && (i - 1) % preempt_count == 0) 5411 for (int i = first_row, n = 0; i < last_row; ++i)
5006 detect_input_pending_ignore_squeezables (); 5412 if (MATRIX_ROW_ENABLED_P (f->desired_matrix, i))
5413 {
5414 if (!force_p && n % preempt_count == 0
5415 && detect_input_pending_ignore_squeezables ())
5416 {
5417 pause_p = true;
5418 break;
5419 }
5007 5420
5008 update_frame_line (f, i, updating_menu_p); 5421 write_row (f, i, updating_menu_p);
5009 } 5422 ++n;
5423 }
5010 } 5424 }
5011 5425
5012 pause_p = 0 < i && i < FRAME_TOTAL_LINES (f) - 1;
5013
5014 /* Now just clean up termcap drivers and set cursor, etc. */ 5426 /* Now just clean up termcap drivers and set cursor, etc. */
5015 if (!pause_p && set_cursor_p) 5427 if (!pause_p && set_cursor_p)
5016 { 5428 tty_set_cursor ();
5017 if ((cursor_in_echo_area
5018 /* If we are showing a message instead of the mini-buffer,
5019 show the cursor for the message instead of for the
5020 (now hidden) mini-buffer contents. */
5021 || (BASE_EQ (minibuf_window, selected_window)
5022 && BASE_EQ (minibuf_window, echo_area_window)
5023 && !NILP (echo_area_buffer[0])))
5024 /* These cases apply only to the frame that contains
5025 the active mini-buffer window. */
5026 && FRAME_HAS_MINIBUF_P (f)
5027 && BASE_EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
5028 {
5029 int top = WINDOW_TOP_EDGE_LINE (XWINDOW (FRAME_MINIBUF_WINDOW (f)));
5030 int col;
5031
5032 /* Put cursor at the end of the prompt. If the mini-buffer
5033 is several lines high, find the last line that has
5034 any text on it. */
5035 int row = FRAME_TOTAL_LINES (f);
5036 do
5037 {
5038 row--;
5039 col = 0;
5040
5041 if (MATRIX_ROW_ENABLED_P (current_matrix, row))
5042 {
5043 /* Frame rows are filled up with spaces that
5044 must be ignored here. */
5045 struct glyph_row *r = MATRIX_ROW (current_matrix, row);
5046 struct glyph *start = r->glyphs[TEXT_AREA];
5047
5048 col = r->used[TEXT_AREA];
5049 while (0 < col && start[col - 1].charpos < 0)
5050 col--;
5051 }
5052 }
5053 while (row > top && col == 0);
5054
5055 /* We exit the loop with COL at the glyph _after_ the last one. */
5056 if (col > 0)
5057 col--;
5058
5059 /* Make sure COL is not out of range. */
5060 if (col >= FRAME_CURSOR_X_LIMIT (f))
5061 {
5062 /* If we have another row, advance cursor into it. */
5063 if (row < FRAME_TOTAL_LINES (f) - 1)
5064 {
5065 col = FRAME_LEFT_SCROLL_BAR_COLS (f);
5066 row++;
5067 }
5068 /* Otherwise move it back in range. */
5069 else
5070 col = FRAME_CURSOR_X_LIMIT (f) - 1;
5071 }
5072 5429
5073 cursor_to (f, row, col);
5074 }
5075 else
5076 {
5077 /* We have only one cursor on terminal frames. Use it to
5078 display the cursor of the selected window. */
5079 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
5080 if (w->cursor.vpos >= 0
5081 /* The cursor vpos may be temporarily out of bounds
5082 in the following situation: There is one window,
5083 with the cursor in the lower half of it. The window
5084 is split, and a message causes a redisplay before
5085 a new cursor position has been computed. */
5086 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
5087 {
5088 int x = WINDOW_TO_FRAME_HPOS (w, w->cursor.hpos);
5089 int y = WINDOW_TO_FRAME_VPOS (w, w->cursor.vpos);
5090
5091 x += max (0, w->left_margin_cols);
5092 cursor_to (f, y, x);
5093 }
5094 }
5095 }
5096
5097 do_pause:
5098
5099 clear_desired_matrices (f);
5100 return pause_p; 5430 return pause_p;
5101} 5431}
5102 5432
5103
5104/* Do line insertions/deletions on frame F for frame-based redisplay. */ 5433/* Do line insertions/deletions on frame F for frame-based redisplay. */
5105 5434
5106static bool 5435static bool
@@ -5209,12 +5538,12 @@ scrolling (struct frame *frame)
5209 which is LEN glyphs long. */ 5538 which is LEN glyphs long. */
5210 5539
5211static int 5540static int
5212count_blanks (struct glyph *r, int len) 5541count_blanks (struct frame *f, struct glyph *r, int len)
5213{ 5542{
5214 int i; 5543 int i;
5215 5544
5216 for (i = 0; i < len; ++i) 5545 for (i = 0; i < len; ++i)
5217 if (!CHAR_GLYPH_SPACE_P (r[i])) 5546 if (!CHAR_GLYPH_SPACE_P (f, r[i]))
5218 break; 5547 break;
5219 5548
5220 return i; 5549 return i;
@@ -5250,7 +5579,7 @@ count_match (struct glyph *str1, struct glyph *end1, struct glyph *str2, struct
5250/* Perform a frame-based update on line VPOS in frame FRAME. */ 5579/* Perform a frame-based update on line VPOS in frame FRAME. */
5251 5580
5252static void 5581static void
5253update_frame_line (struct frame *f, int vpos, bool updating_menu_p) 5582write_row (struct frame *f, int vpos, bool updating_menu_p)
5254{ 5583{
5255 struct glyph *obody, *nbody, *op1, *op2, *np1, *nend; 5584 struct glyph *obody, *nbody, *op1, *op2, *np1, *nend;
5256 int tem; 5585 int tem;
@@ -5264,11 +5593,6 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5264 bool colored_spaces_p = (FACE_FROM_ID (f, DEFAULT_FACE_ID)->background 5593 bool colored_spaces_p = (FACE_FROM_ID (f, DEFAULT_FACE_ID)->background
5265 != FACE_TTY_DEFAULT_BG_COLOR); 5594 != FACE_TTY_DEFAULT_BG_COLOR);
5266 5595
5267 /* This should never happen, but evidently sometimes does if one
5268 resizes the frame quickly enough. Prevent aborts in cmcheckmagic. */
5269 if (vpos >= FRAME_TOTAL_LINES (f))
5270 return;
5271
5272 if (colored_spaces_p) 5596 if (colored_spaces_p)
5273 write_spaces_p = 1; 5597 write_spaces_p = 1;
5274 5598
@@ -5287,7 +5611,7 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5287 5611
5288 /* Ignore trailing spaces, if we can. */ 5612 /* Ignore trailing spaces, if we can. */
5289 if (!write_spaces_p) 5613 if (!write_spaces_p)
5290 while (olen > 0 && CHAR_GLYPH_SPACE_P (obody[olen-1])) 5614 while (olen > 0 && CHAR_GLYPH_SPACE_P (f, obody[olen-1]))
5291 olen--; 5615 olen--;
5292 } 5616 }
5293 5617
@@ -5316,7 +5640,7 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5316 { 5640 {
5317 /* Ignore spaces at the end, if we can. */ 5641 /* Ignore spaces at the end, if we can. */
5318 if (!write_spaces_p) 5642 if (!write_spaces_p)
5319 while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1])) 5643 while (nlen > 0 && CHAR_GLYPH_SPACE_P (f, nbody[nlen - 1]))
5320 --nlen; 5644 --nlen;
5321 5645
5322 /* Write the contents of the desired line. */ 5646 /* Write the contents of the desired line. */
@@ -5338,15 +5662,13 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5338 /* Make sure we are in the right row, otherwise cursor movement 5662 /* Make sure we are in the right row, otherwise cursor movement
5339 with cmgoto might use `ch' in the wrong row. */ 5663 with cmgoto might use `ch' in the wrong row. */
5340 cursor_to (f, vpos, 0); 5664 cursor_to (f, vpos, 0);
5341
5342 make_current (desired_matrix, current_matrix, vpos);
5343 return; 5665 return;
5344 } 5666 }
5345 5667
5346 /* Pretend trailing spaces are not there at all, 5668 /* Pretend trailing spaces are not there at all,
5347 unless for one reason or another we must write all spaces. */ 5669 unless for one reason or another we must write all spaces. */
5348 if (!write_spaces_p) 5670 if (!write_spaces_p)
5349 while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1])) 5671 while (nlen > 0 && CHAR_GLYPH_SPACE_P (f, nbody[nlen - 1]))
5350 nlen--; 5672 nlen--;
5351 5673
5352 /* If there's no i/d char, quickly do the best we can without it. */ 5674 /* If there's no i/d char, quickly do the best we can without it. */
@@ -5383,9 +5705,6 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5383 cursor_to (f, vpos, nlen); 5705 cursor_to (f, vpos, nlen);
5384 clear_end_of_line (f, olen); 5706 clear_end_of_line (f, olen);
5385 } 5707 }
5386
5387 /* Make current row = desired row. */
5388 make_current (desired_matrix, current_matrix, vpos);
5389 return; 5708 return;
5390 } 5709 }
5391 5710
@@ -5399,7 +5718,7 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5399 if (write_spaces_p) 5718 if (write_spaces_p)
5400 nsp = 0; 5719 nsp = 0;
5401 else 5720 else
5402 nsp = count_blanks (nbody, nlen); 5721 nsp = count_blanks (f, nbody, nlen);
5403 5722
5404 if (nlen > nsp) 5723 if (nlen > nsp)
5405 { 5724 {
@@ -5407,14 +5726,12 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5407 write_glyphs (f, nbody + nsp, nlen - nsp); 5726 write_glyphs (f, nbody + nsp, nlen - nsp);
5408 } 5727 }
5409 5728
5410 /* Exchange contents between current_frame and new_frame. */
5411 make_current (desired_matrix, current_matrix, vpos);
5412 return; 5729 return;
5413 } 5730 }
5414 5731
5415 /* Compute number of leading blanks in old and new contents. */ 5732 /* Compute number of leading blanks in old and new contents. */
5416 osp = count_blanks (obody, olen); 5733 osp = count_blanks (f, obody, olen);
5417 nsp = (colored_spaces_p ? 0 : count_blanks (nbody, nlen)); 5734 nsp = (colored_spaces_p ? 0 : count_blanks (f, nbody, nlen));
5418 5735
5419 /* Compute number of matching chars starting with first non-blank. */ 5736 /* Compute number of matching chars starting with first non-blank. */
5420 begmatch = count_match (obody + osp, obody + olen, 5737 begmatch = count_match (obody + osp, obody + olen,
@@ -5425,7 +5742,7 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5425 if (!write_spaces_p && osp + begmatch == olen) 5742 if (!write_spaces_p && osp + begmatch == olen)
5426 { 5743 {
5427 np1 = nbody + nsp; 5744 np1 = nbody + nsp;
5428 while (np1 + begmatch < nend && CHAR_GLYPH_SPACE_P (np1[begmatch])) 5745 while (np1 + begmatch < nend && CHAR_GLYPH_SPACE_P (f, np1[begmatch]))
5429 ++begmatch; 5746 ++begmatch;
5430 } 5747 }
5431 5748
@@ -5566,9 +5883,6 @@ update_frame_line (struct frame *f, int vpos, bool updating_menu_p)
5566 cursor_to (f, vpos, nlen); 5883 cursor_to (f, vpos, nlen);
5567 clear_end_of_line (f, olen); 5884 clear_end_of_line (f, olen);
5568 } 5885 }
5569
5570 /* Exchange contents between current_frame and new_frame. */
5571 make_current (desired_matrix, current_matrix, vpos);
5572} 5886}
5573 5887
5574 5888
@@ -5967,7 +6281,8 @@ handle_window_change_signal (int sig)
5967 { 6281 {
5968 struct frame *f = XFRAME (frame); 6282 struct frame *f = XFRAME (frame);
5969 6283
5970 if (FRAME_TERMCAP_P (f) && FRAME_TTY (f) == tty) 6284 if (FRAME_TERMCAP_P (f) && FRAME_TTY (f) == tty
6285 && !FRAME_PARENT_FRAME (f))
5971 /* Record the new sizes, but don't reallocate the data 6286 /* Record the new sizes, but don't reallocate the data
5972 structures now. Let that be done later outside of the 6287 structures now. Let that be done later outside of the
5973 signal handler. */ 6288 signal handler. */
@@ -6534,7 +6849,7 @@ init_display_interactive (void)
6534 6849
6535 /* Construct the space glyph. */ 6850 /* Construct the space glyph. */
6536 space_glyph.type = CHAR_GLYPH; 6851 space_glyph.type = CHAR_GLYPH;
6537 SET_CHAR_GLYPH (space_glyph, ' ', DEFAULT_FACE_ID, 0); 6852 SET_CHAR_GLYPH (NULL, space_glyph, ' ', DEFAULT_FACE_ID, 0);
6538 space_glyph.charpos = -1; 6853 space_glyph.charpos = -1;
6539 6854
6540 inverse_video = 0; 6855 inverse_video = 0;
@@ -6808,6 +7123,7 @@ syms_of_display (void)
6808 defsubr (&Ssend_string_to_terminal); 7123 defsubr (&Ssend_string_to_terminal);
6809 defsubr (&Sinternal_show_cursor); 7124 defsubr (&Sinternal_show_cursor);
6810 defsubr (&Sinternal_show_cursor_p); 7125 defsubr (&Sinternal_show_cursor_p);
7126 defsubr (&Sframe__z_order_sort_predicate);
6811 7127
6812#ifdef GLYPH_DEBUG 7128#ifdef GLYPH_DEBUG
6813 defsubr (&Sdump_redisplay_history); 7129 defsubr (&Sdump_redisplay_history);
@@ -6818,6 +7134,7 @@ syms_of_display (void)
6818 7134
6819 /* This is the "purpose" slot of a display table. */ 7135 /* This is the "purpose" slot of a display table. */
6820 DEFSYM (Qdisplay_table, "display-table"); 7136 DEFSYM (Qdisplay_table, "display-table");
7137 DEFSYM (Qframe__z_order_sort_predicate, "frame--z-order-sort-predicate");
6821 7138
6822 DEFSYM (Qredisplay_dont_pause, "redisplay-dont-pause"); 7139 DEFSYM (Qredisplay_dont_pause, "redisplay-dont-pause");
6823 7140
@@ -6921,6 +7238,8 @@ Possible values are t (below the tool bar), nil (above the tool bar).
6921This option affects only builds where the tool bar is not external. */); 7238This option affects only builds where the tool bar is not external. */);
6922 7239
6923 pdumper_do_now_and_after_load (syms_of_display_for_pdumper); 7240 pdumper_do_now_and_after_load (syms_of_display_for_pdumper);
7241
7242 Fprovide (intern_c_string ("tty-child-frames"), Qnil);
6924} 7243}
6925 7244
6926static void 7245static void