Mercurial > vim
comparison src/popupwin.c @ 17117:7ef5283ace3c v8.1.1558
patch 8.1.1558: popup_menu() and popup_filter_menu() are not implemented yet
commit https://github.com/vim/vim/commit/a730e55cc2d3045a79a340a5af1ad4a749058a32
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Jun 16 19:05:31 2019 +0200
patch 8.1.1558: popup_menu() and popup_filter_menu() are not implemented yet
Problem: Popup_menu() and popup_filter_menu() are not implemented yet.
Solution: Implement the functions. Fix that centering didn't take the border
and padding into account.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 16 Jun 2019 19:15:05 +0200 |
parents | af861fccc309 |
children | b439e096a011 |
comparison
equal
deleted
inserted
replaced
17116:3cc7132b7a5c | 17117:7ef5283ace3c |
---|---|
649 if (wp->w_minwidth > 0 && wp->w_width < wp->w_minwidth) | 649 if (wp->w_minwidth > 0 && wp->w_width < wp->w_minwidth) |
650 wp->w_width = wp->w_minwidth; | 650 wp->w_width = wp->w_minwidth; |
651 if (wp->w_width > maxwidth) | 651 if (wp->w_width > maxwidth) |
652 wp->w_width = maxwidth; | 652 wp->w_width = maxwidth; |
653 if (center_hor) | 653 if (center_hor) |
654 wp->w_wincol = (Columns - wp->w_width) / 2; | 654 { |
655 wp->w_wincol = (Columns - wp->w_width - extra_width) / 2; | |
656 if (wp->w_wincol < 0) | |
657 wp->w_wincol = 0; | |
658 } | |
655 else if (wp->w_popup_pos == POPPOS_BOTRIGHT | 659 else if (wp->w_popup_pos == POPPOS_BOTRIGHT |
656 || wp->w_popup_pos == POPPOS_TOPRIGHT) | 660 || wp->w_popup_pos == POPPOS_TOPRIGHT) |
657 { | 661 { |
658 // Right aligned: move to the right if needed. | 662 // Right aligned: move to the right if needed. |
659 // No truncation, because that would change the height. | 663 // No truncation, because that would change the height. |
669 wp->w_height = wp->w_maxheight; | 673 wp->w_height = wp->w_maxheight; |
670 if (wp->w_height > Rows - wp->w_winrow) | 674 if (wp->w_height > Rows - wp->w_winrow) |
671 wp->w_height = Rows - wp->w_winrow; | 675 wp->w_height = Rows - wp->w_winrow; |
672 | 676 |
673 if (center_vert) | 677 if (center_vert) |
674 wp->w_winrow = (Rows - wp->w_height) / 2; | 678 { |
679 wp->w_winrow = (Rows - wp->w_height - extra_height) / 2; | |
680 if (wp->w_winrow < 0) | |
681 wp->w_winrow = 0; | |
682 } | |
675 else if (wp->w_popup_pos == POPPOS_BOTRIGHT | 683 else if (wp->w_popup_pos == POPPOS_BOTRIGHT |
676 || wp->w_popup_pos == POPPOS_BOTLEFT) | 684 || wp->w_popup_pos == POPPOS_BOTLEFT) |
677 { | 685 { |
678 if ((wp->w_height + extra_height) <= wp->w_wantline) | 686 if ((wp->w_height + extra_height) <= wp->w_wantline) |
679 // bottom aligned: may move down | 687 // bottom aligned: may move down |
700 typedef enum | 708 typedef enum |
701 { | 709 { |
702 TYPE_NORMAL, | 710 TYPE_NORMAL, |
703 TYPE_ATCURSOR, | 711 TYPE_ATCURSOR, |
704 TYPE_NOTIFICATION, | 712 TYPE_NOTIFICATION, |
705 TYPE_DIALOG | 713 TYPE_DIALOG, |
714 TYPE_MENU | |
706 } create_type_T; | 715 } create_type_T; |
707 | 716 |
708 /* | 717 /* |
709 * Make "buf" empty and set the contents to "text". | 718 * Make "buf" empty and set the contents to "text". |
710 * Used by popup_create() and popup_settext(). | 719 * Used by popup_create() and popup_settext(). |
749 | 758 |
750 /* | 759 /* |
751 * popup_create({text}, {options}) | 760 * popup_create({text}, {options}) |
752 * popup_atcursor({text}, {options}) | 761 * popup_atcursor({text}, {options}) |
753 */ | 762 */ |
754 static void | 763 static win_T * |
755 popup_create(typval_T *argvars, typval_T *rettv, create_type_T type) | 764 popup_create(typval_T *argvars, typval_T *rettv, create_type_T type) |
756 { | 765 { |
757 win_T *wp; | 766 win_T *wp; |
758 buf_T *buf; | 767 buf_T *buf; |
759 dict_T *d; | 768 dict_T *d; |
762 // Check arguments look OK. | 771 // Check arguments look OK. |
763 if (!(argvars[0].v_type == VAR_STRING && argvars[0].vval.v_string != NULL) | 772 if (!(argvars[0].v_type == VAR_STRING && argvars[0].vval.v_string != NULL) |
764 && !(argvars[0].v_type == VAR_LIST && argvars[0].vval.v_list != NULL)) | 773 && !(argvars[0].v_type == VAR_LIST && argvars[0].vval.v_list != NULL)) |
765 { | 774 { |
766 emsg(_(e_listreq)); | 775 emsg(_(e_listreq)); |
767 return; | 776 return NULL; |
768 } | 777 } |
769 if (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL) | 778 if (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL) |
770 { | 779 { |
771 emsg(_(e_dictreq)); | 780 emsg(_(e_dictreq)); |
772 return; | 781 return NULL; |
773 } | 782 } |
774 d = argvars[1].vval.v_dict; | 783 d = argvars[1].vval.v_dict; |
775 | 784 |
776 // Create the window and buffer. | 785 // Create the window and buffer. |
777 wp = win_alloc_popup_win(); | 786 wp = win_alloc_popup_win(); |
778 if (wp == NULL) | 787 if (wp == NULL) |
779 return; | 788 return NULL; |
780 rettv->vval.v_number = wp->w_id; | 789 rettv->vval.v_number = wp->w_id; |
781 wp->w_popup_pos = POPPOS_TOPLEFT; | 790 wp->w_popup_pos = POPPOS_TOPLEFT; |
782 | 791 |
783 buf = buflist_new(NULL, NULL, (linenr_T)0, BLN_NEW|BLN_LISTED|BLN_DUMMY); | 792 buf = buflist_new(NULL, NULL, (linenr_T)0, BLN_NEW|BLN_LISTED|BLN_DUMMY); |
784 if (buf == NULL) | 793 if (buf == NULL) |
785 return; | 794 return NULL; |
786 ml_open(buf); | 795 ml_open(buf); |
787 | 796 |
788 win_init_popup_win(wp, buf); | 797 win_init_popup_win(wp, buf); |
789 | 798 |
790 set_local_options_default(wp); | 799 set_local_options_default(wp); |
896 set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1, | 905 set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1, |
897 (char_u *)(nr == 0 ? "WarningMsg" : "PopupNotification"), | 906 (char_u *)(nr == 0 ? "WarningMsg" : "PopupNotification"), |
898 OPT_FREE|OPT_LOCAL, 0); | 907 OPT_FREE|OPT_LOCAL, 0); |
899 } | 908 } |
900 | 909 |
901 if (type == TYPE_DIALOG) | 910 if (type == TYPE_DIALOG || type == TYPE_MENU) |
902 { | 911 { |
903 int i; | 912 int i; |
904 | 913 |
905 wp->w_popup_pos = POPPOS_CENTER; | 914 wp->w_popup_pos = POPPOS_CENTER; |
906 wp->w_zindex = POPUPWIN_DIALOG_ZINDEX; | 915 wp->w_zindex = POPUPWIN_DIALOG_ZINDEX; |
910 wp->w_popup_border[i] = 1; | 919 wp->w_popup_border[i] = 1; |
911 wp->w_popup_padding[i] = 1; | 920 wp->w_popup_padding[i] = 1; |
912 } | 921 } |
913 } | 922 } |
914 | 923 |
924 if (type == TYPE_MENU) | |
925 { | |
926 typval_T tv; | |
927 callback_T callback; | |
928 | |
929 tv.v_type = VAR_STRING; | |
930 tv.vval.v_string = (char_u *)"popup_filter_menu"; | |
931 callback = get_callback(&tv); | |
932 if (callback.cb_name != NULL) | |
933 set_callback(&wp->w_filter_cb, &callback); | |
934 | |
935 wp->w_p_wrap = 0; | |
936 } | |
937 | |
915 // Deal with options. | 938 // Deal with options. |
916 apply_options(wp, buf, argvars[1].vval.v_dict); | 939 apply_options(wp, buf, argvars[1].vval.v_dict); |
917 | 940 |
918 if (type == TYPE_NOTIFICATION && wp->w_popup_timer == NULL) | 941 if (type == TYPE_NOTIFICATION && wp->w_popup_timer == NULL) |
919 popup_add_timeout(wp, 3000); | 942 popup_add_timeout(wp, 3000); |
922 | 945 |
923 wp->w_vsep_width = 0; | 946 wp->w_vsep_width = 0; |
924 | 947 |
925 redraw_all_later(NOT_VALID); | 948 redraw_all_later(NOT_VALID); |
926 popup_mask_refresh = TRUE; | 949 popup_mask_refresh = TRUE; |
950 | |
951 return wp; | |
927 } | 952 } |
928 | 953 |
929 /* | 954 /* |
930 * popup_clear() | 955 * popup_clear() |
931 */ | 956 */ |
998 | 1023 |
999 popup_close(id); | 1024 popup_close(id); |
1000 } | 1025 } |
1001 | 1026 |
1002 /* | 1027 /* |
1003 * popup_filter_yesno({text}, {options}) | 1028 * In a filter: check if the typed key is a mouse event that is used for |
1004 */ | 1029 * dragging the popup. |
1005 void | 1030 */ |
1006 f_popup_filter_yesno(typval_T *argvars, typval_T *rettv) | 1031 static void |
1032 filter_handle_drag(win_T *wp, int c, typval_T *rettv) | |
1033 { | |
1034 int row = mouse_row; | |
1035 int col = mouse_col; | |
1036 | |
1037 if (wp->w_popup_drag | |
1038 && is_mouse_key(c) | |
1039 && (wp == popup_dragwin | |
1040 || wp == mouse_find_win(&row, &col, FIND_POPUP))) | |
1041 // do not consume the key, allow for dragging the popup | |
1042 rettv->vval.v_number = 0; | |
1043 } | |
1044 | |
1045 static void | |
1046 popup_highlight_curline(win_T *wp) | |
1047 { | |
1048 int id; | |
1049 char buf[100]; | |
1050 | |
1051 match_delete(wp, 1, FALSE); | |
1052 | |
1053 id = syn_name2id((char_u *)"PopupSelected"); | |
1054 vim_snprintf(buf, sizeof(buf), "\\%%%dl.*", (int)wp->w_cursor.lnum); | |
1055 match_add(wp, (char_u *)(id == 0 ? "PmenuSel" : "PopupSelected"), | |
1056 (char_u *)buf, 10, 1, NULL, NULL); | |
1057 } | |
1058 | |
1059 /* | |
1060 * popup_filter_menu({text}, {options}) | |
1061 */ | |
1062 void | |
1063 f_popup_filter_menu(typval_T *argvars, typval_T *rettv) | |
1007 { | 1064 { |
1008 int id = tv_get_number(&argvars[0]); | 1065 int id = tv_get_number(&argvars[0]); |
1009 win_T *wp = win_id2wp(id); | 1066 win_T *wp = win_id2wp(id); |
1010 char_u *key = tv_get_string(&argvars[1]); | 1067 char_u *key = tv_get_string(&argvars[1]); |
1011 typval_T res; | 1068 typval_T res; |
1069 int c; | |
1070 linenr_T old_lnum; | |
1071 | |
1072 // If the popup has been closed do not consume the key. | |
1073 if (wp == NULL) | |
1074 return; | |
1075 | |
1076 c = *key; | |
1077 if (c == K_SPECIAL && key[1] != NUL) | |
1078 c = TO_SPECIAL(key[1], key[2]); | |
1079 | |
1080 // consume all keys until done | |
1081 rettv->vval.v_number = 1; | |
1082 res.v_type = VAR_NUMBER; | |
1083 | |
1084 old_lnum = wp->w_cursor.lnum; | |
1085 if ((c == 'k' || c == 'K' || c == K_UP) && wp->w_cursor.lnum > 1) | |
1086 --wp->w_cursor.lnum; | |
1087 if ((c == 'j' || c == 'J' || c == K_DOWN) | |
1088 && wp->w_cursor.lnum < wp->w_buffer->b_ml.ml_line_count) | |
1089 ++wp->w_cursor.lnum; | |
1090 if (old_lnum != wp->w_cursor.lnum) | |
1091 { | |
1092 popup_highlight_curline(wp); | |
1093 return; | |
1094 } | |
1095 | |
1096 if (c == 'x' || c == 'X' || c == ESC || c == Ctrl_C) | |
1097 { | |
1098 // Cancelled, invoke callback with -1 | |
1099 res.vval.v_number = -1; | |
1100 popup_close_and_callback(wp, &res); | |
1101 return; | |
1102 } | |
1103 if (c == ' ' || c == K_KENTER || c == CAR || c == NL) | |
1104 { | |
1105 // Invoke callback with current index. | |
1106 res.vval.v_number = wp->w_cursor.lnum; | |
1107 popup_close_and_callback(wp, &res); | |
1108 return; | |
1109 } | |
1110 | |
1111 filter_handle_drag(wp, c, rettv); | |
1112 } | |
1113 | |
1114 /* | |
1115 * popup_filter_yesno({text}, {options}) | |
1116 */ | |
1117 void | |
1118 f_popup_filter_yesno(typval_T *argvars, typval_T *rettv) | |
1119 { | |
1120 int id = tv_get_number(&argvars[0]); | |
1121 win_T *wp = win_id2wp(id); | |
1122 char_u *key = tv_get_string(&argvars[1]); | |
1123 typval_T res; | |
1124 int c; | |
1012 | 1125 |
1013 // If the popup has been closed don't consume the key. | 1126 // If the popup has been closed don't consume the key. |
1014 if (wp == NULL) | 1127 if (wp == NULL) |
1015 return; | 1128 return; |
1016 | 1129 |
1130 c = *key; | |
1131 if (c == K_SPECIAL && key[1] != NUL) | |
1132 c = TO_SPECIAL(key[1], key[2]); | |
1133 | |
1017 // consume all keys until done | 1134 // consume all keys until done |
1018 rettv->vval.v_number = 1; | 1135 rettv->vval.v_number = 1; |
1019 | 1136 |
1020 if (STRCMP(key, "y") == 0 || STRCMP(key, "Y") == 0) | 1137 if (c == 'y' || c == 'Y') |
1021 res.vval.v_number = 1; | 1138 res.vval.v_number = 1; |
1022 else if (STRCMP(key, "n") == 0 || STRCMP(key, "N") == 0 | 1139 else if (c == 'n' || c == 'N' || c == 'x' || c == 'X' || c == ESC) |
1023 || STRCMP(key, "x") == 0 || STRCMP(key, "X") == 0 | |
1024 || STRCMP(key, "\x1b") == 0) | |
1025 res.vval.v_number = 0; | 1140 res.vval.v_number = 0; |
1026 else | 1141 else |
1027 { | 1142 { |
1028 int c = *key; | 1143 filter_handle_drag(wp, c, rettv); |
1029 int row = mouse_row; | |
1030 int col = mouse_col; | |
1031 | |
1032 if (c == K_SPECIAL && key[1] != NUL) | |
1033 c = TO_SPECIAL(key[1], key[2]); | |
1034 if (wp->w_popup_drag | |
1035 && is_mouse_key(c) | |
1036 && (wp == popup_dragwin | |
1037 || wp == mouse_find_win(&row, &col, FIND_POPUP))) | |
1038 // allow for dragging the popup | |
1039 rettv->vval.v_number = 0; | |
1040 | |
1041 // ignore this key | |
1042 return; | 1144 return; |
1043 } | 1145 } |
1044 | 1146 |
1045 // Invoke callback | 1147 // Invoke callback |
1046 res.v_type = VAR_NUMBER; | 1148 res.v_type = VAR_NUMBER; |
1052 */ | 1154 */ |
1053 void | 1155 void |
1054 f_popup_dialog(typval_T *argvars, typval_T *rettv) | 1156 f_popup_dialog(typval_T *argvars, typval_T *rettv) |
1055 { | 1157 { |
1056 popup_create(argvars, rettv, TYPE_DIALOG); | 1158 popup_create(argvars, rettv, TYPE_DIALOG); |
1159 } | |
1160 | |
1161 /* | |
1162 * popup_menu({text}, {options}) | |
1163 */ | |
1164 void | |
1165 f_popup_menu(typval_T *argvars, typval_T *rettv) | |
1166 { | |
1167 win_T *wp = popup_create(argvars, rettv, TYPE_MENU); | |
1168 | |
1169 if (wp != NULL) | |
1170 popup_highlight_curline(wp); | |
1057 } | 1171 } |
1058 | 1172 |
1059 /* | 1173 /* |
1060 * popup_notification({text}, {options}) | 1174 * popup_notification({text}, {options}) |
1061 */ | 1175 */ |