@@ -122,6 +122,7 @@ static int redrawing_for_callback = 0;
122122static schar_T * current_ScreenLine ;
123123
124124#ifdef FEAT_TEXT_PROP
125+ static void may_update_popup_mask (int type );
125126static void update_popups (void );
126127#endif
127128static void win_update (win_T * wp );
@@ -612,8 +613,9 @@ update_screen(int type_arg)
612613 }
613614
614615#ifdef FEAT_TEXT_PROP
615- // Update popup_mask if needed.
616- type = may_update_popup_mask (type );
616+ // Update popup_mask if needed. This may set w_redraw_top and w_redraw_bot
617+ // in some windows.
618+ may_update_popup_mask (type );
617619#endif
618620
619621 updating_screen = TRUE;
@@ -1014,17 +1016,19 @@ get_wcr_attr(win_T *wp)
10141016}
10151017
10161018#ifdef FEAT_TEXT_PROP
1019+
10171020/*
10181021 * Update "popup_mask" if needed.
10191022 * Also recomputes the popup size and positions.
10201023 * Also updates "popup_visible".
1021- * If more redrawing is needed than "type_arg" a higher value is returned .
1024+ * Also marks window lines for redrawing .
10221025 */
1023- int
1024- may_update_popup_mask (int type_arg )
1026+ static void
1027+ may_update_popup_mask (int type )
10251028{
1026- int type = type_arg ;
10271029 win_T * wp ;
1030+ short * mask ;
1031+ int line , col ;
10281032
10291033 if (popup_mask_tab != curtab )
10301034 popup_mask_refresh = TRUE;
@@ -1038,56 +1042,102 @@ may_update_popup_mask(int type_arg)
10381042 if (wp -> w_popup_last_changedtick != CHANGEDTICK (wp -> w_buffer ))
10391043 popup_mask_refresh = TRUE;
10401044 if (!popup_mask_refresh )
1041- return type ;
1045+ return ;
10421046 }
10431047
1048+ // Need to update the mask, something has changed.
10441049 popup_mask_refresh = FALSE;
10451050 popup_mask_tab = curtab ;
1046-
10471051 popup_visible = FALSE;
1048- vim_memset (popup_mask , 0 , screen_Rows * screen_Columns * sizeof (short ));
1052+
1053+ // If redrawing everything, just update "popup_mask".
1054+ // If redrawing only what is needed, update "popup_mask_next" and then
1055+ // compare with "popup_mask" to see what changed.
1056+ if (type >= SOME_VALID )
1057+ mask = popup_mask ;
1058+ else
1059+ mask = popup_mask_next ;
1060+ vim_memset (mask , 0 , screen_Rows * screen_Columns * sizeof (short ));
10491061
10501062 // Find the window with the lowest zindex that hasn't been handled yet,
10511063 // so that the window with a higher zindex overwrites the value in
10521064 // popup_mask.
10531065 popup_reset_handled ();
10541066 while ((wp = find_next_popup (TRUE)) != NULL )
10551067 {
1056- int top_off , bot_off ;
1057- int left_off , right_off ;
1058- short * p ;
1059- int line , col ;
1068+ int height_extra , width_extra ;
10601069
10611070 popup_visible = TRUE;
10621071
10631072 // Recompute the position if the text changed.
10641073 if (wp -> w_popup_last_changedtick != CHANGEDTICK (wp -> w_buffer ))
10651074 popup_adjust_position (wp );
10661075
1067- // the position and size are for the inside, add the padding and
1076+ // the width and height are for the inside, add the padding and
10681077 // border
1069- top_off = wp -> w_popup_padding [0 ] + wp -> w_popup_border [0 ];
1070- bot_off = wp -> w_popup_padding [2 ] + wp -> w_popup_border [2 ];
1071- left_off = wp -> w_popup_padding [3 ] + wp -> w_popup_border [3 ];
1072- right_off = wp -> w_popup_padding [1 ] + wp -> w_popup_border [1 ];
1078+ height_extra = wp -> w_popup_padding [0 ] + wp -> w_popup_border [0 ]
1079+ + wp -> w_popup_padding [2 ] + wp -> w_popup_border [2 ];
1080+ width_extra = wp -> w_popup_padding [3 ] + wp -> w_popup_border [3 ]
1081+ + wp -> w_popup_padding [1 ] + wp -> w_popup_border [1 ];
10731082
1074- for (line = wp -> w_winrow + top_off ;
1075- line < wp -> w_winrow + wp -> w_height + bot_off
1083+ for (line = wp -> w_winrow ;
1084+ line < wp -> w_winrow + wp -> w_height + height_extra
10761085 && line < screen_Rows ; ++ line )
1077- for (col = wp -> w_wincol + left_off ;
1078- col < wp -> w_wincol + wp -> w_width + right_off
1086+ for (col = wp -> w_wincol ;
1087+ col < wp -> w_wincol + wp -> w_width + width_extra
10791088 && col < screen_Columns ; ++ col )
1089+ mask [line * screen_Columns + col ] = wp -> w_zindex ;
1090+ }
1091+
1092+ // Only check which lines are to be updated if not already
1093+ // updating all lines.
1094+ if (mask == popup_mask_next )
1095+ for (line = 0 ; line < screen_Rows ; ++ line )
1096+ {
1097+ int col_done = 0 ;
1098+
1099+ for (col = 0 ; col < screen_Columns ; ++ col )
10801100 {
1081- p = popup_mask + line * screen_Columns + col ;
1082- if (* p != wp -> w_zindex )
1101+ int off = line * screen_Columns + col ;
1102+
1103+ if (popup_mask [off ] != popup_mask_next [off ])
10831104 {
1084- * p = wp -> w_zindex ;
1085- type = NOT_VALID ;
1105+ popup_mask [off ] = popup_mask_next [off ];
1106+
1107+ // The screen position "line" / "col" needs to be redrawn.
1108+ // Figure out what window that is and update w_redraw_top
1109+ // and w_redr_bot. Only needs to be done for each window
1110+ // line.
1111+ if (col >= col_done )
1112+ {
1113+ linenr_T lnum ;
1114+ int line_cp = line ;
1115+ int col_cp = col ;
1116+
1117+ // find the window where the row is in
1118+ wp = mouse_find_win (& line_cp , & col_cp );
1119+ if (wp != NULL )
1120+ {
1121+ if (line_cp >= wp -> w_height )
1122+ // In (or below) status line
1123+ wp -> w_redr_status = TRUE;
1124+ // compute the position in the buffer line from the
1125+ // position on the screen
1126+ else if (mouse_comp_pos (wp , & line_cp , & col_cp ,
1127+ & lnum ))
1128+ // past bottom
1129+ wp -> w_redr_status = TRUE;
1130+ else
1131+ redrawWinline (wp , lnum );
1132+
1133+ // This line is going to be redrawn, no need to
1134+ // check until the right side of the window.
1135+ col_done = wp -> w_wincol + wp -> w_width - 1 ;
1136+ }
1137+ }
10861138 }
10871139 }
1088- }
1089-
1090- return type ;
1140+ }
10911141}
10921142
10931143/*
@@ -9112,6 +9162,7 @@ screenalloc(int doclear)
91129162 short * new_TabPageIdxs ;
91139163#ifdef FEAT_TEXT_PROP
91149164 short * new_popup_mask ;
9165+ short * new_popup_mask_next ;
91159166#endif
91169167 tabpage_T * tp ;
91179168 static int entered = FALSE; /* avoid recursiveness */
@@ -9196,6 +9247,7 @@ screenalloc(int doclear)
91969247 new_TabPageIdxs = LALLOC_MULT (short , Columns );
91979248#ifdef FEAT_TEXT_PROP
91989249 new_popup_mask = LALLOC_MULT (short , Rows * Columns );
9250+ new_popup_mask_next = LALLOC_MULT (short , Rows * Columns );
91999251#endif
92009252
92019253 FOR_ALL_TAB_WINDOWS (tp , wp )
@@ -9241,6 +9293,7 @@ screenalloc(int doclear)
92419293 || new_TabPageIdxs == NULL
92429294#ifdef FEAT_TEXT_PROP
92439295 || new_popup_mask == NULL
9296+ || new_popup_mask_next == NULL
92449297#endif
92459298 || outofmem )
92469299 {
@@ -9264,6 +9317,7 @@ screenalloc(int doclear)
92649317 VIM_CLEAR (new_TabPageIdxs );
92659318#ifdef FEAT_TEXT_PROP
92669319 VIM_CLEAR (new_popup_mask );
9320+ VIM_CLEAR (new_popup_mask_next );
92679321#endif
92689322 }
92699323 else
@@ -9353,6 +9407,7 @@ screenalloc(int doclear)
93539407 TabPageIdxs = new_TabPageIdxs ;
93549408#ifdef FEAT_TEXT_PROP
93559409 popup_mask = new_popup_mask ;
9410+ popup_mask_next = new_popup_mask_next ;
93569411 vim_memset (popup_mask , 0 , Rows * Columns * sizeof (short ));
93579412 popup_mask_refresh = TRUE;
93589413#endif
@@ -9421,6 +9476,7 @@ free_screenlines(void)
94219476 VIM_CLEAR (TabPageIdxs );
94229477#ifdef FEAT_TEXT_PROP
94239478 VIM_CLEAR (popup_mask );
9479+ VIM_CLEAR (popup_mask_next );
94249480#endif
94259481}
94269482
@@ -10027,7 +10083,7 @@ win_do_lines(
1002710083 }
1002810084
1002910085#ifdef FEAT_TEXT_PROP
10030- // this doesn't work when tere are popups visible
10086+ // this doesn't work when there are popups visible
1003110087 if (popup_visible )
1003210088 return FAIL ;
1003310089#endif
0 commit comments