comparison src/screen.c @ 17055:f4de7ccdfd8c v8.1.1527

patch 8.1.1527: when moving popup window over the cmdline it is not redrawn commit https://github.com/vim/vim/commit/a540f8aa3b2570f1d903b63413301ec3d48b27d5 Author: Bram Moolenaar <Bram@vim.org> Date: Fri Jun 14 19:23:57 2019 +0200 patch 8.1.1527: when moving popup window over the cmdline it is not redrawn Problem: When moving a popup window over the command line it is not redrawn. Solution: Redraw the command line. Move popup redrawing code to the popupwin file.
author Bram Moolenaar <Bram@vim.org>
date Fri, 14 Jun 2019 19:30:05 +0200
parents 5ed4965ebc7b
children 7ef5283ace3c
comparison
equal deleted inserted replaced
17054:aebfdd4e9ac5 17055:f4de7ccdfd8c
119 /* 119 /*
120 * Buffer for one screen line (characters and attributes). 120 * Buffer for one screen line (characters and attributes).
121 */ 121 */
122 static schar_T *current_ScreenLine; 122 static schar_T *current_ScreenLine;
123 123
124 #ifdef FEAT_TEXT_PROP
125 static void may_update_popup_mask(int type);
126 static void update_popups(void);
127 #endif
128 static void win_update(win_T *wp); 124 static void win_update(win_T *wp);
129 static void win_redr_status(win_T *wp, int ignore_pum); 125 static void win_redr_status(win_T *wp, int ignore_pum);
130 static void win_draw_end(win_T *wp, int c1, int c2, int draw_margin, int row, int endrow, hlf_T hl); 126 static void win_draw_end(win_T *wp, int c1, int c2, int draw_margin, int row, int endrow, hlf_T hl);
131 #ifdef FEAT_FOLDING 127 #ifdef FEAT_FOLDING
132 static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T lnum, int row); 128 static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T lnum, int row);
824 maybe_intro_message(); 820 maybe_intro_message();
825 did_intro = TRUE; 821 did_intro = TRUE;
826 822
827 #ifdef FEAT_TEXT_PROP 823 #ifdef FEAT_TEXT_PROP
828 // Display popup windows on top of the windows. 824 // Display popup windows on top of the windows.
829 update_popups(); 825 update_popups(win_update);
830 #endif 826 #endif
831 827
832 #ifdef FEAT_GUI 828 #ifdef FEAT_GUI
833 /* Redraw the cursor and update the scrollbars when all screen updating is 829 /* Redraw the cursor and update the scrollbars when all screen updating is
834 * done. */ 830 * done. */
999 995
1000 /* 996 /*
1001 * Get 'wincolor' attribute for window "wp". If not set and "wp" is a popup 997 * Get 'wincolor' attribute for window "wp". If not set and "wp" is a popup
1002 * window then get the "Pmenu" highlight attribute. 998 * window then get the "Pmenu" highlight attribute.
1003 */ 999 */
1004 static int 1000 int
1005 get_wcr_attr(win_T *wp) 1001 get_wcr_attr(win_T *wp)
1006 { 1002 {
1007 int wcr_attr = 0; 1003 int wcr_attr = 0;
1008 1004
1009 if (*wp->w_p_wcr != NUL) 1005 if (*wp->w_p_wcr != NUL)
1012 if (bt_popup(wp->w_buffer) && wcr_attr == 0) 1008 if (bt_popup(wp->w_buffer) && wcr_attr == 0)
1013 wcr_attr = HL_ATTR(HLF_PNI); 1009 wcr_attr = HL_ATTR(HLF_PNI);
1014 #endif 1010 #endif
1015 return wcr_attr; 1011 return wcr_attr;
1016 } 1012 }
1017
1018 #ifdef FEAT_TEXT_PROP
1019
1020 /*
1021 * Update "popup_mask" if needed.
1022 * Also recomputes the popup size and positions.
1023 * Also updates "popup_visible".
1024 * Also marks window lines for redrawing.
1025 */
1026 static void
1027 may_update_popup_mask(int type)
1028 {
1029 win_T *wp;
1030 short *mask;
1031 int line, col;
1032 int redraw_all = FALSE;
1033
1034 // Need to recompute when switching tabs.
1035 // Also recompute when the type is CLEAR or NOT_VALID, something basic
1036 // (such as the screen size) must have changed.
1037 if (popup_mask_tab != curtab || type >= NOT_VALID)
1038 {
1039 popup_mask_refresh = TRUE;
1040 redraw_all = TRUE;
1041 }
1042 if (!popup_mask_refresh)
1043 {
1044 // Check if any buffer has changed.
1045 for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
1046 if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer))
1047 popup_mask_refresh = TRUE;
1048 for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next)
1049 if (wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer))
1050 popup_mask_refresh = TRUE;
1051 if (!popup_mask_refresh)
1052 return;
1053 }
1054
1055 // Need to update the mask, something has changed.
1056 popup_mask_refresh = FALSE;
1057 popup_mask_tab = curtab;
1058 popup_visible = FALSE;
1059
1060 // If redrawing everything, just update "popup_mask".
1061 // If redrawing only what is needed, update "popup_mask_next" and then
1062 // compare with "popup_mask" to see what changed.
1063 if (type >= SOME_VALID)
1064 mask = popup_mask;
1065 else
1066 mask = popup_mask_next;
1067 vim_memset(mask, 0, screen_Rows * screen_Columns * sizeof(short));
1068
1069 // Find the window with the lowest zindex that hasn't been handled yet,
1070 // so that the window with a higher zindex overwrites the value in
1071 // popup_mask.
1072 popup_reset_handled();
1073 while ((wp = find_next_popup(TRUE)) != NULL)
1074 {
1075 popup_visible = TRUE;
1076
1077 // Recompute the position if the text changed.
1078 if (redraw_all
1079 || wp->w_popup_last_changedtick != CHANGEDTICK(wp->w_buffer))
1080 popup_adjust_position(wp);
1081
1082 for (line = wp->w_winrow;
1083 line < wp->w_winrow + popup_height(wp)
1084 && line < screen_Rows; ++line)
1085 for (col = wp->w_wincol;
1086 col < wp->w_wincol + popup_width(wp)
1087 && col < screen_Columns; ++col)
1088 mask[line * screen_Columns + col] = wp->w_zindex;
1089 }
1090
1091 // Only check which lines are to be updated if not already
1092 // updating all lines.
1093 if (mask == popup_mask_next)
1094 for (line = 0; line < screen_Rows; ++line)
1095 {
1096 int col_done = 0;
1097
1098 for (col = 0; col < screen_Columns; ++col)
1099 {
1100 int off = line * screen_Columns + col;
1101
1102 if (popup_mask[off] != popup_mask_next[off])
1103 {
1104 popup_mask[off] = popup_mask_next[off];
1105
1106 // The screen position "line" / "col" needs to be redrawn.
1107 // Figure out what window that is and update w_redraw_top
1108 // and w_redr_bot. Only needs to be done for each window
1109 // line.
1110 if (col >= col_done)
1111 {
1112 linenr_T lnum;
1113 int line_cp = line;
1114 int col_cp = col;
1115
1116 // find the window where the row is in
1117 wp = mouse_find_win(&line_cp, &col_cp, IGNORE_POPUP);
1118 if (wp != NULL)
1119 {
1120 if (line_cp >= wp->w_height)
1121 // In (or below) status line
1122 wp->w_redr_status = TRUE;
1123 // compute the position in the buffer line from the
1124 // position on the screen
1125 else if (mouse_comp_pos(wp, &line_cp, &col_cp,
1126 &lnum))
1127 // past bottom
1128 wp->w_redr_status = TRUE;
1129 else
1130 redrawWinline(wp, lnum);
1131
1132 // This line is going to be redrawn, no need to
1133 // check until the right side of the window.
1134 col_done = wp->w_wincol + wp->w_width - 1;
1135 }
1136 }
1137 }
1138 }
1139 }
1140 }
1141
1142 /*
1143 * Return a string of "len" spaces in IObuff.
1144 */
1145 static char_u *
1146 get_spaces(int len)
1147 {
1148 vim_memset(IObuff, ' ', (size_t)len);
1149 IObuff[len] = NUL;
1150 return IObuff;
1151 }
1152
1153 static void
1154 update_popups(void)
1155 {
1156 win_T *wp;
1157 int top_off;
1158 int left_off;
1159 int total_width;
1160 int total_height;
1161 int popup_attr;
1162 int border_attr[4];
1163 int border_char[8];
1164 char_u buf[MB_MAXBYTES];
1165 int row;
1166 int i;
1167
1168 // Find the window with the lowest zindex that hasn't been updated yet,
1169 // so that the window with a higher zindex is drawn later, thus goes on
1170 // top.
1171 popup_reset_handled();
1172 while ((wp = find_next_popup(TRUE)) != NULL)
1173 {
1174 // This drawing uses the zindex of the popup window, so that it's on
1175 // top of the text but doesn't draw when another popup with higher
1176 // zindex is on top of the character.
1177 screen_zindex = wp->w_zindex;
1178
1179 // adjust w_winrow and w_wincol for border and padding, since
1180 // win_update() doesn't handle them.
1181 top_off = wp->w_popup_padding[0] + wp->w_popup_border[0];
1182 left_off = wp->w_popup_padding[3] + wp->w_popup_border[3];
1183 wp->w_winrow += top_off;
1184 wp->w_wincol += left_off;
1185
1186 // Draw the popup text.
1187 win_update(wp);
1188
1189 wp->w_winrow -= top_off;
1190 wp->w_wincol -= left_off;
1191
1192 total_width = wp->w_popup_border[3] + wp->w_popup_padding[3]
1193 + wp->w_width + wp->w_popup_padding[1] + wp->w_popup_border[1];
1194 total_height = wp->w_popup_border[0] + wp->w_popup_padding[0]
1195 + wp->w_height + wp->w_popup_padding[2] + wp->w_popup_border[2];
1196 popup_attr = get_wcr_attr(wp);
1197
1198 // We can only use these line drawing characters when 'encoding' is
1199 // "utf-8" and 'ambiwidth' is "single".
1200 if (enc_utf8 && *p_ambw == 's')
1201 {
1202 border_char[0] = border_char[2] = 0x2550;
1203 border_char[1] = border_char[3] = 0x2551;
1204 border_char[4] = 0x2554;
1205 border_char[5] = 0x2557;
1206 border_char[6] = 0x255d;
1207 border_char[7] = 0x255a;
1208 }
1209 else
1210 {
1211 border_char[0] = border_char[2] = '-';
1212 border_char[1] = border_char[3] = '|';
1213 for (i = 4; i < 8; ++i)
1214 border_char[i] = '+';
1215 }
1216 for (i = 0; i < 8; ++i)
1217 if (wp->w_border_char[i] != 0)
1218 border_char[i] = wp->w_border_char[i];
1219
1220 for (i = 0; i < 4; ++i)
1221 {
1222 border_attr[i] = popup_attr;
1223 if (wp->w_border_highlight[i] != NULL)
1224 border_attr[i] = syn_name2attr(wp->w_border_highlight[i]);
1225 }
1226
1227 if (wp->w_popup_border[0] > 0)
1228 {
1229 // top border
1230 screen_fill(wp->w_winrow, wp->w_winrow + 1,
1231 wp->w_wincol,
1232 wp->w_wincol + total_width,
1233 wp->w_popup_border[3] != 0
1234 ? border_char[4] : border_char[0],
1235 border_char[0], border_attr[0]);
1236 if (wp->w_popup_border[1] > 0)
1237 {
1238 buf[mb_char2bytes(border_char[5], buf)] = NUL;
1239 screen_puts(buf, wp->w_winrow,
1240 wp->w_wincol + total_width - 1, border_attr[1]);
1241 }
1242 }
1243
1244 if (wp->w_popup_padding[0] > 0)
1245 {
1246 // top padding
1247 row = wp->w_winrow + wp->w_popup_border[0];
1248 screen_fill(row, row + wp->w_popup_padding[0],
1249 wp->w_wincol + wp->w_popup_border[3],
1250 wp->w_wincol + total_width - wp->w_popup_border[1],
1251 ' ', ' ', popup_attr);
1252 }
1253
1254 for (row = wp->w_winrow + wp->w_popup_border[0];
1255 row < wp->w_winrow + total_height - wp->w_popup_border[2];
1256 ++row)
1257 {
1258 // left border
1259 if (wp->w_popup_border[3] > 0)
1260 {
1261 buf[mb_char2bytes(border_char[3], buf)] = NUL;
1262 screen_puts(buf, row, wp->w_wincol, border_attr[3]);
1263 }
1264 // left padding
1265 if (wp->w_popup_padding[3] > 0)
1266 screen_puts(get_spaces(wp->w_popup_padding[3]), row,
1267 wp->w_wincol + wp->w_popup_border[3], popup_attr);
1268 // right border
1269 if (wp->w_popup_border[1] > 0)
1270 {
1271 buf[mb_char2bytes(border_char[1], buf)] = NUL;
1272 screen_puts(buf, row,
1273 wp->w_wincol + total_width - 1, border_attr[1]);
1274 }
1275 // right padding
1276 if (wp->w_popup_padding[1] > 0)
1277 screen_puts(get_spaces(wp->w_popup_padding[1]), row,
1278 wp->w_wincol + wp->w_popup_border[3]
1279 + wp->w_popup_padding[3] + wp->w_width, popup_attr);
1280 }
1281
1282 if (wp->w_popup_padding[2] > 0)
1283 {
1284 // bottom padding
1285 row = wp->w_winrow + wp->w_popup_border[0]
1286 + wp->w_popup_padding[0] + wp->w_height;
1287 screen_fill(row, row + wp->w_popup_padding[2],
1288 wp->w_wincol + wp->w_popup_border[3],
1289 wp->w_wincol + total_width - wp->w_popup_border[1],
1290 ' ', ' ', popup_attr);
1291 }
1292
1293 if (wp->w_popup_border[2] > 0)
1294 {
1295 // bottom border
1296 row = wp->w_winrow + total_height - 1;
1297 screen_fill(row , row + 1,
1298 wp->w_wincol,
1299 wp->w_wincol + total_width,
1300 wp->w_popup_border[3] != 0
1301 ? border_char[7] : border_char[2],
1302 border_char[2], border_attr[2]);
1303 if (wp->w_popup_border[1] > 0)
1304 {
1305 buf[mb_char2bytes(border_char[6], buf)] = NUL;
1306 screen_puts(buf, row,
1307 wp->w_wincol + total_width - 1, border_attr[2]);
1308 }
1309 }
1310
1311 // Back to the normal zindex.
1312 screen_zindex = 0;
1313 }
1314 }
1315 #endif
1316 1013
1317 #if defined(FEAT_GUI) || defined(PROTO) 1014 #if defined(FEAT_GUI) || defined(PROTO)
1318 /* 1015 /*
1319 * Update a single window, its status line and maybe the command line msg. 1016 * Update a single window, its status line and maybe the command line msg.
1320 * Used for the GUI scrollbar. 1017 * Used for the GUI scrollbar.
1352 ) 1049 )
1353 win_redr_status(wp, FALSE); 1050 win_redr_status(wp, FALSE);
1354 1051
1355 #ifdef FEAT_TEXT_PROP 1052 #ifdef FEAT_TEXT_PROP
1356 // Display popup windows on top of everything. 1053 // Display popup windows on top of everything.
1357 update_popups(); 1054 update_popups(win_update);
1358 #endif 1055 #endif
1359 1056
1360 update_finish(); 1057 update_finish();
1361 } 1058 }
1362 #endif 1059 #endif