comparison src/popupmnu.c @ 13369:244ff1b6d2ad v8.0.1558

patch 8.0.1558: no right-click menu in a terminal commit https://github.com/vim/vim/commit/aef8c3da2ba59285b7cfde559ae21cdce6ba6919 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Mar 3 18:59:16 2018 +0100 patch 8.0.1558: no right-click menu in a terminal Problem: No right-click menu in a terminal. Solution: Implement the right click menu for the terminal.
author Christian Brabandt <cb@256bit.org>
date Sat, 03 Mar 2018 19:00:06 +0100
parents 1ba4f926247c
children d5347779fb20
comparison
equal deleted inserted replaced
13368:a68814ee7449 13369:244ff1b6d2ad
420 /* Display the text that fits or comes before a Tab. 420 /* Display the text that fits or comes before a Tab.
421 * First convert it to printable characters. */ 421 * First convert it to printable characters. */
422 char_u *st; 422 char_u *st;
423 int saved = *p; 423 int saved = *p;
424 424
425 *p = NUL; 425 if (saved != NUL)
426 *p = NUL;
426 st = transstr(s); 427 st = transstr(s);
427 *p = saved; 428 if (saved != NUL)
429 *p = saved;
428 #ifdef FEAT_RIGHTLEFT 430 #ifdef FEAT_RIGHTLEFT
429 if (curwin->w_p_rl) 431 if (curwin->w_p_rl)
430 { 432 {
431 if (st != NULL) 433 if (st != NULL)
432 { 434 {
828 pum_get_height(void) 830 pum_get_height(void)
829 { 831 {
830 return pum_height; 832 return pum_height;
831 } 833 }
832 834
835 # if defined(FEAT_BEVAL_TERM) || defined(FEAT_TERM_POPUP_MENU) || defined(PROTO)
836 static void
837 pum_position_at_mouse(int min_width)
838 {
839 if (Rows - mouse_row > pum_size)
840 {
841 /* Enough space below the mouse row. */
842 pum_row = mouse_row + 1;
843 if (pum_height > Rows - pum_row)
844 pum_height = Rows - pum_row;
845 }
846 else
847 {
848 /* Show above the mouse row, reduce height if it does not fit. */
849 pum_row = mouse_row - pum_size;
850 if (pum_row < 0)
851 {
852 pum_height += pum_row;
853 pum_row = 0;
854 }
855 }
856 if (Columns - mouse_col >= pum_base_width
857 || Columns - mouse_col > min_width)
858 /* Enough space to show at mouse column. */
859 pum_col = mouse_col;
860 else
861 /* Not enough space, right align with window. */
862 pum_col = Columns - (pum_base_width > min_width
863 ? min_width : pum_base_width);
864
865 pum_width = Columns - pum_col;
866 if (pum_width > pum_base_width + 1)
867 pum_width = pum_base_width + 1;
868 }
869
870 # endif
871
833 # if defined(FEAT_BEVAL_TERM) || defined(PROTO) 872 # if defined(FEAT_BEVAL_TERM) || defined(PROTO)
834 static pumitem_T *balloon_array = NULL; 873 static pumitem_T *balloon_array = NULL;
835 static int balloon_arraysize; 874 static int balloon_arraysize;
836 static int balloon_mouse_row = 0; 875 static int balloon_mouse_row = 0;
837 static int balloon_mouse_col = 0; 876 static int balloon_mouse_col = 0;
1026 pum_size = balloon_arraysize; 1065 pum_size = balloon_arraysize;
1027 pum_compute_size(); 1066 pum_compute_size();
1028 pum_scrollbar = 0; 1067 pum_scrollbar = 0;
1029 pum_height = balloon_arraysize; 1068 pum_height = balloon_arraysize;
1030 1069
1031 if (Rows - mouse_row > pum_size) 1070 pum_position_at_mouse(BALLOON_MIN_WIDTH);
1032 {
1033 /* Enough space below the mouse row. */
1034 pum_row = mouse_row + 1;
1035 if (pum_height > Rows - pum_row)
1036 pum_height = Rows - pum_row;
1037 }
1038 else
1039 {
1040 /* Show above the mouse row, reduce height if it does not fit. */
1041 pum_row = mouse_row - pum_size;
1042 if (pum_row < 0)
1043 {
1044 pum_height += pum_row;
1045 pum_row = 0;
1046 }
1047 }
1048 if (Columns - mouse_col >= pum_base_width
1049 || Columns - mouse_col > BALLOON_MIN_WIDTH)
1050 /* Enough space to show at mouse column. */
1051 pum_col = mouse_col;
1052 else
1053 /* Not enough space, right align with window. */
1054 pum_col = Columns - (pum_base_width > BALLOON_MIN_WIDTH
1055 ? BALLOON_MIN_WIDTH : pum_base_width);
1056
1057 pum_width = Columns - pum_col;
1058 if (pum_width > pum_base_width + 1)
1059 pum_width = pum_base_width + 1;
1060
1061 pum_selected = -1; 1071 pum_selected = -1;
1062 pum_first = 0; 1072 pum_first = 0;
1063 pum_redraw(); 1073 pum_redraw();
1064 } 1074 }
1065 } 1075 }
1073 if (mouse_row != balloon_mouse_row || mouse_col != balloon_mouse_col) 1083 if (mouse_row != balloon_mouse_row || mouse_col != balloon_mouse_col)
1074 ui_remove_balloon(); 1084 ui_remove_balloon();
1075 } 1085 }
1076 # endif 1086 # endif
1077 1087
1078 #endif 1088 # if defined(FEAT_TERM_POPUP_MENU) || defined(PROTO)
1089 /*
1090 * Select the pum entry at the mouse position.
1091 */
1092 static void
1093 pum_select_mouse_pos(void)
1094 {
1095 int idx = mouse_row - pum_row;
1096
1097 if (idx < 0 || idx >= pum_size)
1098 pum_selected = -1;
1099 else if (*pum_array[idx].pum_text != NUL)
1100 pum_selected = idx;
1101 }
1102
1103 /*
1104 * Execute the currently selected popup menu item.
1105 */
1106 static void
1107 pum_execute_menu(vimmenu_T *menu)
1108 {
1109 vimmenu_T *mp;
1110 int idx = 0;
1111 exarg_T ea;
1112
1113 for (mp = menu->children; mp != NULL; mp = mp->next)
1114 if (idx++ == pum_selected)
1115 {
1116 vim_memset(&ea, 0, sizeof(ea));
1117 execute_menu(&ea, mp);
1118 break;
1119 }
1120 }
1121
1122 /*
1123 * Open the terminal version of the popup menu and don't return until it is
1124 * closed.
1125 */
1126 void
1127 pum_show_popupmenu(vimmenu_T *menu)
1128 {
1129 vimmenu_T *mp;
1130 int idx = 0;
1131 pumitem_T *array;
1132 #ifdef FEAT_BEVAL_TERM
1133 int save_bevalterm = p_bevalterm;
1134 #endif
1135
1136 pum_undisplay();
1137 pum_size = 0;
1138
1139 for (mp = menu->children; mp != NULL; mp = mp->next)
1140 ++pum_size;
1141
1142 array = (pumitem_T *)alloc_clear((unsigned)sizeof(pumitem_T) * pum_size);
1143 if (array == NULL)
1144 return;
1145
1146 for (mp = menu->children; mp != NULL; mp = mp->next)
1147 if (menu_is_separator(mp->dname))
1148 array[idx++].pum_text = (char_u *)"";
1149 else
1150 array[idx++].pum_text = mp->dname;
1151
1152 pum_array = array;
1153 pum_compute_size();
1154 pum_scrollbar = 0;
1155 pum_height = pum_size;
1156 pum_position_at_mouse(20);
1157
1158 pum_selected = -1;
1159 pum_first = 0;
1160 # ifdef FEAT_BEVAL_TERM
1161 p_bevalterm = TRUE; /* track mouse movement */
1162 mch_setmouse(TRUE);
1163 # endif
1164
1165 for (;;)
1166 {
1167 int c;
1168
1169 pum_redraw();
1170 setcursor();
1171 out_flush();
1172
1173 c = vgetc();
1174 if (c == ESC)
1175 break;
1176 else if (c == CAR || c == NL)
1177 {
1178 /* enter: select current item, if any, and close */
1179 pum_execute_menu(menu);
1180 break;
1181 }
1182 else if (c == 'k' || c == K_UP || c == K_MOUSEUP)
1183 {
1184 /* cursor up: select previous item */
1185 while (pum_selected > 0)
1186 {
1187 --pum_selected;
1188 if (*array[pum_selected].pum_text != NUL)
1189 break;
1190 }
1191 }
1192 else if (c == 'j' || c == K_DOWN || c == K_MOUSEDOWN)
1193 {
1194 /* cursor down: select next item */
1195 while (pum_selected < pum_size - 1)
1196 {
1197 ++pum_selected;
1198 if (*array[pum_selected].pum_text != NUL)
1199 break;
1200 }
1201 }
1202 else if (c == K_RIGHTMOUSE)
1203 {
1204 /* Right mouse down: reposition the menu. */
1205 vungetc(c);
1206 break;
1207 }
1208 else if (c == K_LEFTDRAG || c == K_RIGHTDRAG || c == K_MOUSEMOVE)
1209 {
1210 /* mouse moved: selec item in the mouse row */
1211 pum_select_mouse_pos();
1212 }
1213 else if (c == K_LEFTMOUSE || c == K_LEFTMOUSE_NM || c == K_RIGHTRELEASE)
1214 {
1215 /* left mouse click: select clicked item, if any, and close;
1216 * right mouse release: select clicked item, close if any */
1217 pum_select_mouse_pos();
1218 if (pum_selected >= 0)
1219 {
1220 pum_execute_menu(menu);
1221 break;
1222 }
1223 if (c == K_LEFTMOUSE || c == K_LEFTMOUSE_NM)
1224 break;
1225 }
1226 }
1227
1228 vim_free(array);
1229 pum_undisplay();
1230 # ifdef FEAT_BEVAL_TERM
1231 p_bevalterm = save_bevalterm;
1232 mch_setmouse(TRUE);
1233 # endif
1234 }
1235 # endif
1236
1237 #endif