diff options
| author | Gerd Möllmann | 2024-10-05 18:55:18 +0200 |
|---|---|---|
| committer | Gerd Möllmann | 2024-10-05 18:55:18 +0200 |
| commit | beb5b77123619758c1def6b9f227fa7568516775 (patch) | |
| tree | 809e025df6a48b10f3022558f23840a8def6cbec /src/dispnew.c | |
| parent | 069ecc9c4c3709246a6ff50d09af418444d427c3 (diff) | |
| download | emacs-tty-child-frames.tar.gz emacs-tty-child-frames.zip | |
Preview from my branch on githubtty-child-frames
Diffstat (limited to 'src/dispnew.c')
| -rw-r--r-- | src/dispnew.c | 979 |
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 | ||
| 74 | static void update_frame_line (struct frame *, int, bool); | 74 | static void write_row (struct frame *f, int vpos, bool updating_menu_p); |
| 75 | static int required_matrix_height (struct window *); | 75 | static int required_matrix_height (struct window *); |
| 76 | static int required_matrix_width (struct window *); | 76 | static int required_matrix_width (struct window *); |
| 77 | static void increment_row_positions (struct glyph_row *, ptrdiff_t, ptrdiff_t); | 77 | static 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 *, | |||
| 80 | static void build_frame_matrix_from_leaf_window (struct glyph_matrix *, | 80 | static void build_frame_matrix_from_leaf_window (struct glyph_matrix *, |
| 81 | struct window *); | 81 | struct window *); |
| 82 | static void adjust_decode_mode_spec_buffer (struct frame *); | 82 | static void adjust_decode_mode_spec_buffer (struct frame *); |
| 83 | static void fill_up_glyph_row_with_spaces (struct glyph_row *); | 83 | static void fill_up_glyph_row_with_spaces (struct frame *, struct glyph_row *); |
| 84 | static void clear_window_matrices (struct window *, bool); | 84 | static void clear_window_matrices (struct window *, bool); |
| 85 | static void fill_up_glyph_row_area_with_spaces (struct glyph_row *, int); | 85 | static void fill_up_glyph_row_area_with_spaces (struct frame *, struct glyph_row *, int); |
| 86 | static int scrolling_window (struct window *, int); | 86 | static int scrolling_window (struct window *, int); |
| 87 | static bool update_window_line (struct window *, int, bool *); | 87 | static bool update_window_line (struct window *, int, bool *); |
| 88 | static void mirror_make_current (struct window *, int); | 88 | static void mirror_make_current (struct window *, int); |
| @@ -93,7 +93,7 @@ static void check_matrix_pointers (struct glyph_matrix *, | |||
| 93 | static void mirror_line_dance (struct window *, int, int, int *, char *); | 93 | static void mirror_line_dance (struct window *, int, int, int *, char *); |
| 94 | static bool update_window_tree (struct window *, bool); | 94 | static bool update_window_tree (struct window *, bool); |
| 95 | static bool update_window (struct window *, bool); | 95 | static bool update_window (struct window *, bool); |
| 96 | static bool update_frame_1 (struct frame *, bool, bool, bool, bool); | 96 | static bool write_matrix (struct frame *, bool, bool, bool, bool); |
| 97 | static bool scrolling (struct frame *); | 97 | static bool scrolling (struct frame *); |
| 98 | static void set_window_cursor_after_update (struct window *); | 98 | static void set_window_cursor_after_update (struct window *); |
| 99 | static void adjust_frame_glyphs_for_window_redisplay (struct frame *); | 99 | static 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 | |||
| 128 | static 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 | ||
| 2703 | static void | 2704 | static void |
| 2704 | fill_up_glyph_row_with_spaces (struct glyph_row *row) | 2705 | fill_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 | ||
| 2715 | static void | 2716 | static void |
| 2716 | fill_up_glyph_row_area_with_spaces (struct glyph_row *row, int area) | 2717 | fill_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 | ||
| 2733 | void | 2738 | void |
| 2734 | fill_up_frame_row_with_spaces (struct glyph_row *row, int upto) | 2739 | fill_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 | |||
| 2755 | static void | ||
| 2756 | set_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 | ||
| 2770 | static void | 2767 | static void |
| 2771 | make_current (struct glyph_matrix *desired_matrix, | 2768 | make_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 | ||
| 2864 | void | 2862 | void |
| 2865 | mirrored_line_dance (struct glyph_matrix *matrix, int unchanged_at_top, int nlines, | 2863 | mirrored_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 | ||
| 3245 | bool | 3251 | - building the desired matrix of the root frame itself which is |
| 3246 | update_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 | |||
| 3263 | struct 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; | 3269 | static bool |
| 3254 | else if (!force_p && detect_input_pending_ignore_squeezables ()) | 3270 | is_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 | |||
| 3283 | bool | ||
| 3284 | is_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 | |||
| 3292 | bool | ||
| 3293 | is_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 | |||
| 3303 | static bool | ||
| 3304 | rect_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 | |||
| 3320 | static struct rect | ||
| 3321 | frame_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 | |||
| 3332 | struct frame * | ||
| 3333 | root_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 | |||
| 3342 | static bool | ||
| 3343 | is_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 | |||
| 3353 | Lisp_Object | ||
| 3354 | frames_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 | 3369 | static bool |
| 3269 | when pending input is detected. */ | 3370 | frame_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 | 3379 | DEFUN ("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 | |||
| 3394 | Lisp_Object | ||
| 3395 | frames_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 | |||
| 3405 | void | ||
| 3406 | tty_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 | 3440 | bool |
| 3294 | reuse strings. */ | 3441 | is_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 | |||
| 3448 | bool | ||
| 3449 | is_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 | |||
| 3456 | bool | ||
| 3457 | is_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 | |||
| 3465 | static int | ||
| 3466 | first_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 | |||
| 3477 | static void | ||
| 3478 | make_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 | |||
| 3489 | static void | ||
| 3490 | copy_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 | |||
| 3549 | static void | ||
| 3550 | update_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. */ | 3559 | static void |
| 3304 | if (WINDOWP (f->tool_bar_window)) | 3560 | update_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); | 3582 | static void |
| 3314 | w->must_be_updated_p = false; | 3583 | update_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 | 3591 | static void |
| 3317 | reuse strings. */ | 3592 | update_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. */ | 3600 | static bool |
| 3326 | paused_p = update_window_tree (root_window, force_p); | 3601 | update_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 | |||
| 3615 | static bool | ||
| 3616 | update_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 | |||
| 3624 | static void | ||
| 3625 | flush_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 | |||
| 3632 | static bool | ||
| 3633 | update_tty_frame (struct frame *f, bool force_p) | ||
| 3634 | { | ||
| 3635 | build_frame_matrix (f); | ||
| 3636 | return false; | ||
| 3637 | } | ||
| 3638 | |||
| 3639 | bool | ||
| 3640 | combine_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 | |||
| 3679 | bool | ||
| 3680 | combine_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 | |||
| 3703 | bool | ||
| 3704 | update_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 | |||
| 3384 | update_frame_with_menu (struct frame *f, int row, int col) | 3742 | update_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. | 5287 | static void |
| 5288 | tty_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 | ||
| 4942 | static bool | 5380 | static bool |
| 4943 | update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p, | 5381 | write_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 | ||
| 5106 | static bool | 5435 | static bool |
| @@ -5209,12 +5538,12 @@ scrolling (struct frame *frame) | |||
| 5209 | which is LEN glyphs long. */ | 5538 | which is LEN glyphs long. */ |
| 5210 | 5539 | ||
| 5211 | static int | 5540 | static int |
| 5212 | count_blanks (struct glyph *r, int len) | 5541 | count_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 | ||
| 5252 | static void | 5581 | static void |
| 5253 | update_frame_line (struct frame *f, int vpos, bool updating_menu_p) | 5582 | write_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). | |||
| 6921 | This option affects only builds where the tool bar is not external. */); | 7238 | This 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 | ||
| 6926 | static void | 7245 | static void |