diff options
| author | Juri Linkov | 2019-10-01 23:15:03 +0300 |
|---|---|---|
| committer | Juri Linkov | 2019-10-01 23:15:03 +0300 |
| commit | 2698d3dba2e9858b026ed127d4de3f86810a5ef3 (patch) | |
| tree | 8e9b8f194cfcad8af83a4174a0105bbc691f06d6 /src/keyboard.c | |
| parent | 25f45d710e91a7c1049f056ff27bc3e6968f5624 (diff) | |
| parent | 3f981a0a89bca47a207fb362485f07e7322bb145 (diff) | |
| download | emacs-2698d3dba2e9858b026ed127d4de3f86810a5ef3.tar.gz emacs-2698d3dba2e9858b026ed127d4de3f86810a5ef3.zip | |
Merge branch 'feature/tabs'
Diffstat (limited to 'src/keyboard.c')
| -rw-r--r-- | src/keyboard.c | 436 |
1 files changed, 425 insertions, 11 deletions
diff --git a/src/keyboard.c b/src/keyboard.c index a16d13cc7b8..40aaf496384 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -2385,7 +2385,8 @@ read_char (int commandflag, Lisp_Object map, | |||
| 2385 | if (used_mouse_menu | 2385 | if (used_mouse_menu |
| 2386 | /* Also check was_disabled so last-nonmenu-event won't return | 2386 | /* Also check was_disabled so last-nonmenu-event won't return |
| 2387 | a bad value when submenus are involved. (Bug#447) */ | 2387 | a bad value when submenus are involved. (Bug#447) */ |
| 2388 | && (EQ (c, Qtool_bar) || EQ (c, Qmenu_bar) || was_disabled)) | 2388 | && (EQ (c, Qtool_bar) || EQ (c, Qtab_bar) || EQ (c, Qmenu_bar) |
| 2389 | || was_disabled)) | ||
| 2389 | *used_mouse_menu = true; | 2390 | *used_mouse_menu = true; |
| 2390 | 2391 | ||
| 2391 | goto reread_for_input_method; | 2392 | goto reread_for_input_method; |
| @@ -2666,6 +2667,7 @@ read_char (int commandflag, Lisp_Object map, | |||
| 2666 | && !NILP (prev_event) | 2667 | && !NILP (prev_event) |
| 2667 | && EVENT_HAS_PARAMETERS (prev_event) | 2668 | && EVENT_HAS_PARAMETERS (prev_event) |
| 2668 | && !EQ (XCAR (prev_event), Qmenu_bar) | 2669 | && !EQ (XCAR (prev_event), Qmenu_bar) |
| 2670 | && !EQ (XCAR (prev_event), Qtab_bar) | ||
| 2669 | && !EQ (XCAR (prev_event), Qtool_bar) | 2671 | && !EQ (XCAR (prev_event), Qtool_bar) |
| 2670 | /* Don't bring up a menu if we already have another event. */ | 2672 | /* Don't bring up a menu if we already have another event. */ |
| 2671 | && !CONSP (Vunread_command_events)) | 2673 | && !CONSP (Vunread_command_events)) |
| @@ -2930,7 +2932,7 @@ read_char (int commandflag, Lisp_Object map, | |||
| 2930 | posn = POSN_POSN (xevent_start (c)); | 2932 | posn = POSN_POSN (xevent_start (c)); |
| 2931 | /* Handle menu-bar events: | 2933 | /* Handle menu-bar events: |
| 2932 | insert the dummy prefix event `menu-bar'. */ | 2934 | insert the dummy prefix event `menu-bar'. */ |
| 2933 | if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar)) | 2935 | if (EQ (posn, Qmenu_bar) || EQ (posn, Qtab_bar) || EQ (posn, Qtool_bar)) |
| 2934 | { | 2936 | { |
| 2935 | /* Change menu-bar to (menu-bar) as the event "position". */ | 2937 | /* Change menu-bar to (menu-bar) as the event "position". */ |
| 2936 | POSN_SET_POSN (xevent_start (c), list1 (posn)); | 2938 | POSN_SET_POSN (xevent_start (c), list1 (posn)); |
| @@ -3974,6 +3976,7 @@ kbd_buffer_get_event (KBOARD **kbp, | |||
| 3974 | if (used_mouse_menu | 3976 | if (used_mouse_menu |
| 3975 | && !EQ (event->ie.frame_or_window, event->ie.arg) | 3977 | && !EQ (event->ie.frame_or_window, event->ie.arg) |
| 3976 | && (event->kind == MENU_BAR_EVENT | 3978 | && (event->kind == MENU_BAR_EVENT |
| 3979 | || event->kind == TAB_BAR_EVENT | ||
| 3977 | || event->kind == TOOL_BAR_EVENT)) | 3980 | || event->kind == TOOL_BAR_EVENT)) |
| 3978 | *used_mouse_menu = true; | 3981 | *used_mouse_menu = true; |
| 3979 | #endif | 3982 | #endif |
| @@ -5012,7 +5015,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, | |||
| 5012 | int xret = 0, yret = 0; | 5015 | int xret = 0, yret = 0; |
| 5013 | /* The window or frame under frame pixel coordinates (x,y) */ | 5016 | /* The window or frame under frame pixel coordinates (x,y) */ |
| 5014 | Lisp_Object window_or_frame = f | 5017 | Lisp_Object window_or_frame = f |
| 5015 | ? window_from_coordinates (f, XFIXNUM (x), XFIXNUM (y), &part, 0) | 5018 | ? window_from_coordinates (f, XFIXNUM (x), XFIXNUM (y), &part, 0, 0) |
| 5016 | : Qnil; | 5019 | : Qnil; |
| 5017 | 5020 | ||
| 5018 | if (WINDOWP (window_or_frame)) | 5021 | if (WINDOWP (window_or_frame)) |
| @@ -5036,17 +5039,21 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, | |||
| 5036 | if (part == ON_TEXT) | 5039 | if (part == ON_TEXT) |
| 5037 | { | 5040 | { |
| 5038 | xret = XFIXNUM (x) - window_box_left (w, TEXT_AREA); | 5041 | xret = XFIXNUM (x) - window_box_left (w, TEXT_AREA); |
| 5039 | yret = wy - WINDOW_HEADER_LINE_HEIGHT (w); | 5042 | yret = wy - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w); |
| 5040 | } | 5043 | } |
| 5041 | /* For mode line and header line clicks, return X, Y relative to | 5044 | /* For mode line and header line clicks, return X, Y relative to |
| 5042 | the left window edge. Use mode_line_string to look for a | 5045 | the left window edge. Use mode_line_string to look for a |
| 5043 | string on the click position. */ | 5046 | string on the click position. */ |
| 5044 | else if (part == ON_MODE_LINE || part == ON_HEADER_LINE) | 5047 | else if (part == ON_MODE_LINE || part == ON_TAB_LINE |
| 5048 | || part == ON_HEADER_LINE) | ||
| 5045 | { | 5049 | { |
| 5046 | Lisp_Object string; | 5050 | Lisp_Object string; |
| 5047 | ptrdiff_t charpos; | 5051 | ptrdiff_t charpos; |
| 5048 | 5052 | ||
| 5049 | posn = (part == ON_MODE_LINE) ? Qmode_line : Qheader_line; | 5053 | posn = (part == ON_MODE_LINE ? Qmode_line |
| 5054 | : (part == ON_TAB_LINE ? Qtab_line | ||
| 5055 | : Qheader_line)); | ||
| 5056 | |||
| 5050 | /* Note that mode_line_string takes COL, ROW as pixels and | 5057 | /* Note that mode_line_string takes COL, ROW as pixels and |
| 5051 | converts them to characters. */ | 5058 | converts them to characters. */ |
| 5052 | col = wx; | 5059 | col = wx; |
| @@ -5075,7 +5082,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, | |||
| 5075 | if (STRINGP (string)) | 5082 | if (STRINGP (string)) |
| 5076 | string_info = Fcons (string, make_fixnum (charpos)); | 5083 | string_info = Fcons (string, make_fixnum (charpos)); |
| 5077 | xret = wx; | 5084 | xret = wx; |
| 5078 | yret = wy - WINDOW_HEADER_LINE_HEIGHT (w); | 5085 | yret = wy - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w); |
| 5079 | } | 5086 | } |
| 5080 | else if (part == ON_LEFT_FRINGE) | 5087 | else if (part == ON_LEFT_FRINGE) |
| 5081 | { | 5088 | { |
| @@ -5085,7 +5092,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, | |||
| 5085 | dx = wx | 5092 | dx = wx |
| 5086 | - (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) | 5093 | - (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) |
| 5087 | ? 0 : window_box_width (w, LEFT_MARGIN_AREA)); | 5094 | ? 0 : window_box_width (w, LEFT_MARGIN_AREA)); |
| 5088 | dy = yret = wy - WINDOW_HEADER_LINE_HEIGHT (w); | 5095 | dy = yret = wy - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w); |
| 5089 | } | 5096 | } |
| 5090 | else if (part == ON_RIGHT_FRINGE) | 5097 | else if (part == ON_RIGHT_FRINGE) |
| 5091 | { | 5098 | { |
| @@ -5098,7 +5105,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, | |||
| 5098 | - (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) | 5105 | - (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) |
| 5099 | ? window_box_width (w, RIGHT_MARGIN_AREA) | 5106 | ? window_box_width (w, RIGHT_MARGIN_AREA) |
| 5100 | : 0); | 5107 | : 0); |
| 5101 | dy = yret = wy - WINDOW_HEADER_LINE_HEIGHT (w); | 5108 | dy = yret = wy - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w); |
| 5102 | } | 5109 | } |
| 5103 | else if (part == ON_VERTICAL_BORDER) | 5110 | else if (part == ON_VERTICAL_BORDER) |
| 5104 | { | 5111 | { |
| @@ -5953,6 +5960,16 @@ make_lispy_event (struct input_event *event) | |||
| 5953 | /* Make an event (select-window (WINDOW)). */ | 5960 | /* Make an event (select-window (WINDOW)). */ |
| 5954 | return list2 (Qselect_window, list1 (event->frame_or_window)); | 5961 | return list2 (Qselect_window, list1 (event->frame_or_window)); |
| 5955 | 5962 | ||
| 5963 | case TAB_BAR_EVENT: | ||
| 5964 | if (EQ (event->arg, event->frame_or_window)) | ||
| 5965 | /* This is the prefix key. We translate this to | ||
| 5966 | `(tab_bar)' because the code in keyboard.c for tab bar | ||
| 5967 | events, which we use, relies on this. */ | ||
| 5968 | return list1 (Qtab_bar); | ||
| 5969 | else if (SYMBOLP (event->arg)) | ||
| 5970 | return apply_modifiers (event->modifiers, event->arg); | ||
| 5971 | return event->arg; | ||
| 5972 | |||
| 5956 | case TOOL_BAR_EVENT: | 5973 | case TOOL_BAR_EVENT: |
| 5957 | if (EQ (event->arg, event->frame_or_window)) | 5974 | if (EQ (event->arg, event->frame_or_window)) |
| 5958 | /* This is the prefix key. We translate this to | 5975 | /* This is the prefix key. We translate this to |
| @@ -6730,6 +6747,7 @@ lucid_event_type_list_p (Lisp_Object object) | |||
| 6730 | if (EQ (XCAR (object), Qhelp_echo) | 6747 | if (EQ (XCAR (object), Qhelp_echo) |
| 6731 | || EQ (XCAR (object), Qvertical_line) | 6748 | || EQ (XCAR (object), Qvertical_line) |
| 6732 | || EQ (XCAR (object), Qmode_line) | 6749 | || EQ (XCAR (object), Qmode_line) |
| 6750 | || EQ (XCAR (object), Qtab_line) | ||
| 6733 | || EQ (XCAR (object), Qheader_line)) | 6751 | || EQ (XCAR (object), Qheader_line)) |
| 6734 | return 0; | 6752 | return 0; |
| 6735 | 6753 | ||
| @@ -7891,6 +7909,389 @@ parse_menu_item (Lisp_Object item, int inmenubar) | |||
| 7891 | 7909 | ||
| 7892 | 7910 | ||
| 7893 | /*********************************************************************** | 7911 | /*********************************************************************** |
| 7912 | Tab-bars | ||
| 7913 | ***********************************************************************/ | ||
| 7914 | |||
| 7915 | /* A vector holding tab bar items while they are parsed in function | ||
| 7916 | tab_bar_items. Each item occupies TAB_BAR_ITEM_NSCLOTS elements | ||
| 7917 | in the vector. */ | ||
| 7918 | |||
| 7919 | static Lisp_Object tab_bar_items_vector; | ||
| 7920 | |||
| 7921 | /* A vector holding the result of parse_tab_bar_item. Layout is like | ||
| 7922 | the one for a single item in tab_bar_items_vector. */ | ||
| 7923 | |||
| 7924 | static Lisp_Object tab_bar_item_properties; | ||
| 7925 | |||
| 7926 | /* Next free index in tab_bar_items_vector. */ | ||
| 7927 | |||
| 7928 | static int ntab_bar_items; | ||
| 7929 | |||
| 7930 | /* Function prototypes. */ | ||
| 7931 | |||
| 7932 | static void init_tab_bar_items (Lisp_Object); | ||
| 7933 | static void process_tab_bar_item (Lisp_Object, Lisp_Object, Lisp_Object, | ||
| 7934 | void *); | ||
| 7935 | static bool parse_tab_bar_item (Lisp_Object, Lisp_Object); | ||
| 7936 | static void append_tab_bar_item (void); | ||
| 7937 | |||
| 7938 | |||
| 7939 | /* Return a vector of tab bar items for keymaps currently in effect. | ||
| 7940 | Reuse vector REUSE if non-nil. Return in *NITEMS the number of | ||
| 7941 | tab bar items found. */ | ||
| 7942 | |||
| 7943 | Lisp_Object | ||
| 7944 | tab_bar_items (Lisp_Object reuse, int *nitems) | ||
| 7945 | { | ||
| 7946 | Lisp_Object *maps; | ||
| 7947 | Lisp_Object mapsbuf[3]; | ||
| 7948 | ptrdiff_t nmaps, i; | ||
| 7949 | Lisp_Object oquit; | ||
| 7950 | Lisp_Object *tmaps; | ||
| 7951 | USE_SAFE_ALLOCA; | ||
| 7952 | |||
| 7953 | *nitems = 0; | ||
| 7954 | |||
| 7955 | /* In order to build the menus, we need to call the keymap | ||
| 7956 | accessors. They all call maybe_quit. But this function is called | ||
| 7957 | during redisplay, during which a quit is fatal. So inhibit | ||
| 7958 | quitting while building the menus. We do this instead of | ||
| 7959 | specbind because (1) errors will clear it anyway and (2) this | ||
| 7960 | avoids risk of specpdl overflow. */ | ||
| 7961 | oquit = Vinhibit_quit; | ||
| 7962 | Vinhibit_quit = Qt; | ||
| 7963 | |||
| 7964 | /* Initialize tab_bar_items_vector and protect it from GC. */ | ||
| 7965 | init_tab_bar_items (reuse); | ||
| 7966 | |||
| 7967 | /* Build list of keymaps in maps. Set nmaps to the number of maps | ||
| 7968 | to process. */ | ||
| 7969 | |||
| 7970 | /* Should overriding-terminal-local-map and overriding-local-map apply? */ | ||
| 7971 | if (!NILP (Voverriding_local_map_menu_flag) | ||
| 7972 | && !NILP (Voverriding_local_map)) | ||
| 7973 | { | ||
| 7974 | /* Yes, use them (if non-nil) as well as the global map. */ | ||
| 7975 | maps = mapsbuf; | ||
| 7976 | nmaps = 0; | ||
| 7977 | if (!NILP (KVAR (current_kboard, Voverriding_terminal_local_map))) | ||
| 7978 | maps[nmaps++] = KVAR (current_kboard, Voverriding_terminal_local_map); | ||
| 7979 | if (!NILP (Voverriding_local_map)) | ||
| 7980 | maps[nmaps++] = Voverriding_local_map; | ||
| 7981 | } | ||
| 7982 | else | ||
| 7983 | { | ||
| 7984 | /* No, so use major and minor mode keymaps and keymap property. | ||
| 7985 | Note that tab-bar bindings in the local-map and keymap | ||
| 7986 | properties may not work reliably, as they are only | ||
| 7987 | recognized when the tab-bar (or mode-line) is updated, | ||
| 7988 | which does not normally happen after every command. */ | ||
| 7989 | ptrdiff_t nminor = current_minor_maps (NULL, &tmaps); | ||
| 7990 | SAFE_NALLOCA (maps, 1, nminor + 4); | ||
| 7991 | nmaps = 0; | ||
| 7992 | Lisp_Object tem = KVAR (current_kboard, Voverriding_terminal_local_map); | ||
| 7993 | if (!NILP (tem) && !NILP (Voverriding_local_map_menu_flag)) | ||
| 7994 | maps[nmaps++] = tem; | ||
| 7995 | if (tem = get_local_map (PT, current_buffer, Qkeymap), !NILP (tem)) | ||
| 7996 | maps[nmaps++] = tem; | ||
| 7997 | if (nminor != 0) | ||
| 7998 | { | ||
| 7999 | memcpy (maps + nmaps, tmaps, nminor * sizeof (maps[0])); | ||
| 8000 | nmaps += nminor; | ||
| 8001 | } | ||
| 8002 | maps[nmaps++] = get_local_map (PT, current_buffer, Qlocal_map); | ||
| 8003 | } | ||
| 8004 | |||
| 8005 | /* Add global keymap at the end. */ | ||
| 8006 | maps[nmaps++] = current_global_map; | ||
| 8007 | |||
| 8008 | /* Process maps in reverse order and look up in each map the prefix | ||
| 8009 | key `tab-bar'. */ | ||
| 8010 | for (i = nmaps - 1; i >= 0; --i) | ||
| 8011 | if (!NILP (maps[i])) | ||
| 8012 | { | ||
| 8013 | Lisp_Object keymap; | ||
| 8014 | |||
| 8015 | keymap = get_keymap (access_keymap (maps[i], Qtab_bar, 1, 0, 1), 0, 1); | ||
| 8016 | if (CONSP (keymap)) | ||
| 8017 | map_keymap (keymap, process_tab_bar_item, Qnil, NULL, 1); | ||
| 8018 | } | ||
| 8019 | |||
| 8020 | Vinhibit_quit = oquit; | ||
| 8021 | *nitems = ntab_bar_items / TAB_BAR_ITEM_NSLOTS; | ||
| 8022 | SAFE_FREE (); | ||
| 8023 | return tab_bar_items_vector; | ||
| 8024 | } | ||
| 8025 | |||
| 8026 | |||
| 8027 | /* Process the definition of KEY which is DEF. */ | ||
| 8028 | |||
| 8029 | static void | ||
| 8030 | process_tab_bar_item (Lisp_Object key, Lisp_Object def, Lisp_Object data, void *args) | ||
| 8031 | { | ||
| 8032 | int i; | ||
| 8033 | |||
| 8034 | if (EQ (def, Qundefined)) | ||
| 8035 | { | ||
| 8036 | /* If a map has an explicit `undefined' as definition, | ||
| 8037 | discard any previously made item. */ | ||
| 8038 | for (i = 0; i < ntab_bar_items; i += TAB_BAR_ITEM_NSLOTS) | ||
| 8039 | { | ||
| 8040 | Lisp_Object *v = XVECTOR (tab_bar_items_vector)->contents + i; | ||
| 8041 | |||
| 8042 | if (EQ (key, v[TAB_BAR_ITEM_KEY])) | ||
| 8043 | { | ||
| 8044 | if (ntab_bar_items > i + TAB_BAR_ITEM_NSLOTS) | ||
| 8045 | memmove (v, v + TAB_BAR_ITEM_NSLOTS, | ||
| 8046 | ((ntab_bar_items - i - TAB_BAR_ITEM_NSLOTS) | ||
| 8047 | * word_size)); | ||
| 8048 | ntab_bar_items -= TAB_BAR_ITEM_NSLOTS; | ||
| 8049 | break; | ||
| 8050 | } | ||
| 8051 | } | ||
| 8052 | } | ||
| 8053 | else if (parse_tab_bar_item (key, def)) | ||
| 8054 | /* Append a new tab bar item to tab_bar_items_vector. Accept | ||
| 8055 | more than one definition for the same key. */ | ||
| 8056 | append_tab_bar_item (); | ||
| 8057 | } | ||
| 8058 | |||
| 8059 | /* Access slot with index IDX of vector tab_bar_item_properties. */ | ||
| 8060 | #define PROP(IDX) AREF (tab_bar_item_properties, (IDX)) | ||
| 8061 | static void | ||
| 8062 | set_prop_tab_bar (ptrdiff_t idx, Lisp_Object val) | ||
| 8063 | { | ||
| 8064 | ASET (tab_bar_item_properties, idx, val); | ||
| 8065 | } | ||
| 8066 | |||
| 8067 | |||
| 8068 | /* Parse a tab bar item specification ITEM for key KEY and return the | ||
| 8069 | result in tab_bar_item_properties. Value is false if ITEM is | ||
| 8070 | invalid. | ||
| 8071 | |||
| 8072 | ITEM is a list `(menu-item CAPTION BINDING PROPS...)'. | ||
| 8073 | |||
| 8074 | CAPTION is the caption of the item, If it's not a string, it is | ||
| 8075 | evaluated to get a string. | ||
| 8076 | |||
| 8077 | BINDING is the tab bar item's binding. Tab-bar items with keymaps | ||
| 8078 | as binding are currently ignored. | ||
| 8079 | |||
| 8080 | The following properties are recognized: | ||
| 8081 | |||
| 8082 | - `:enable FORM'. | ||
| 8083 | |||
| 8084 | FORM is evaluated and specifies whether the tab bar item is | ||
| 8085 | enabled or disabled. | ||
| 8086 | |||
| 8087 | - `:visible FORM' | ||
| 8088 | |||
| 8089 | FORM is evaluated and specifies whether the tab bar item is visible. | ||
| 8090 | |||
| 8091 | - `:filter FUNCTION' | ||
| 8092 | |||
| 8093 | FUNCTION is invoked with one parameter `(quote BINDING)'. Its | ||
| 8094 | result is stored as the new binding. | ||
| 8095 | |||
| 8096 | - `:button (TYPE SELECTED)' | ||
| 8097 | |||
| 8098 | TYPE must be one of `:radio' or `:toggle'. SELECTED is evaluated | ||
| 8099 | and specifies whether the button is selected (pressed) or not. | ||
| 8100 | |||
| 8101 | - `:image IMAGES' | ||
| 8102 | |||
| 8103 | IMAGES is either a single image specification or a vector of four | ||
| 8104 | image specifications. See enum tab_bar_item_images. | ||
| 8105 | |||
| 8106 | - `:help HELP-STRING'. | ||
| 8107 | |||
| 8108 | Gives a help string to display for the tab bar item. | ||
| 8109 | |||
| 8110 | - `:label LABEL-STRING'. | ||
| 8111 | |||
| 8112 | A text label to show with the tab bar button if labels are enabled. */ | ||
| 8113 | |||
| 8114 | static bool | ||
| 8115 | parse_tab_bar_item (Lisp_Object key, Lisp_Object item) | ||
| 8116 | { | ||
| 8117 | Lisp_Object filter = Qnil; | ||
| 8118 | Lisp_Object caption; | ||
| 8119 | int i; | ||
| 8120 | |||
| 8121 | /* Definition looks like `(menu-item CAPTION BINDING PROPS...)'. | ||
| 8122 | Rule out items that aren't lists, don't start with | ||
| 8123 | `menu-item' or whose rest following `tab-bar-item' is not a | ||
| 8124 | list. */ | ||
| 8125 | if (!CONSP (item)) | ||
| 8126 | return 0; | ||
| 8127 | |||
| 8128 | /* As an exception, allow old-style menu separators. */ | ||
| 8129 | if (STRINGP (XCAR (item))) | ||
| 8130 | item = list1 (XCAR (item)); | ||
| 8131 | else if (!EQ (XCAR (item), Qmenu_item) | ||
| 8132 | || (item = XCDR (item), !CONSP (item))) | ||
| 8133 | return 0; | ||
| 8134 | |||
| 8135 | /* Create tab_bar_item_properties vector if necessary. Reset it to | ||
| 8136 | defaults. */ | ||
| 8137 | if (VECTORP (tab_bar_item_properties)) | ||
| 8138 | { | ||
| 8139 | for (i = 0; i < TAB_BAR_ITEM_NSLOTS; ++i) | ||
| 8140 | set_prop_tab_bar (i, Qnil); | ||
| 8141 | } | ||
| 8142 | else | ||
| 8143 | tab_bar_item_properties = make_nil_vector (TAB_BAR_ITEM_NSLOTS); | ||
| 8144 | |||
| 8145 | /* Set defaults. */ | ||
| 8146 | set_prop_tab_bar (TAB_BAR_ITEM_KEY, key); | ||
| 8147 | set_prop_tab_bar (TAB_BAR_ITEM_ENABLED_P, Qt); | ||
| 8148 | |||
| 8149 | /* Get the caption of the item. If the caption is not a string, | ||
| 8150 | evaluate it to get a string. If we don't get a string, skip this | ||
| 8151 | item. */ | ||
| 8152 | caption = XCAR (item); | ||
| 8153 | if (!STRINGP (caption)) | ||
| 8154 | { | ||
| 8155 | caption = menu_item_eval_property (caption); | ||
| 8156 | if (!STRINGP (caption)) | ||
| 8157 | return 0; | ||
| 8158 | } | ||
| 8159 | set_prop_tab_bar (TAB_BAR_ITEM_CAPTION, caption); | ||
| 8160 | |||
| 8161 | /* If the rest following the caption is not a list, the menu item is | ||
| 8162 | either a separator, or invalid. */ | ||
| 8163 | item = XCDR (item); | ||
| 8164 | if (!CONSP (item)) | ||
| 8165 | { | ||
| 8166 | if (menu_separator_name_p (SSDATA (caption))) | ||
| 8167 | { | ||
| 8168 | set_prop_tab_bar (TAB_BAR_ITEM_ENABLED_P, Qnil); | ||
| 8169 | set_prop_tab_bar (TAB_BAR_ITEM_SELECTED_P, Qnil); | ||
| 8170 | set_prop_tab_bar (TAB_BAR_ITEM_CAPTION, Qnil); | ||
| 8171 | return 1; | ||
| 8172 | } | ||
| 8173 | return 0; | ||
| 8174 | } | ||
| 8175 | |||
| 8176 | /* Store the binding. */ | ||
| 8177 | set_prop_tab_bar (TAB_BAR_ITEM_BINDING, XCAR (item)); | ||
| 8178 | item = XCDR (item); | ||
| 8179 | |||
| 8180 | /* Ignore cached key binding, if any. */ | ||
| 8181 | if (CONSP (item) && CONSP (XCAR (item))) | ||
| 8182 | item = XCDR (item); | ||
| 8183 | |||
| 8184 | /* Process the rest of the properties. */ | ||
| 8185 | for (; CONSP (item) && CONSP (XCDR (item)); item = XCDR (XCDR (item))) | ||
| 8186 | { | ||
| 8187 | Lisp_Object ikey, value; | ||
| 8188 | |||
| 8189 | ikey = XCAR (item); | ||
| 8190 | value = XCAR (XCDR (item)); | ||
| 8191 | |||
| 8192 | if (EQ (ikey, QCenable)) | ||
| 8193 | { | ||
| 8194 | /* `:enable FORM'. */ | ||
| 8195 | if (!NILP (Venable_disabled_menus_and_buttons)) | ||
| 8196 | set_prop_tab_bar (TAB_BAR_ITEM_ENABLED_P, Qt); | ||
| 8197 | else | ||
| 8198 | set_prop_tab_bar (TAB_BAR_ITEM_ENABLED_P, value); | ||
| 8199 | } | ||
| 8200 | else if (EQ (ikey, QCvisible)) | ||
| 8201 | { | ||
| 8202 | /* `:visible FORM'. If got a visible property and that | ||
| 8203 | evaluates to nil then ignore this item. */ | ||
| 8204 | if (NILP (menu_item_eval_property (value))) | ||
| 8205 | return 0; | ||
| 8206 | } | ||
| 8207 | else if (EQ (ikey, QChelp)) | ||
| 8208 | /* `:help HELP-STRING'. */ | ||
| 8209 | set_prop_tab_bar (TAB_BAR_ITEM_HELP, value); | ||
| 8210 | else if (EQ (ikey, QCfilter)) | ||
| 8211 | /* ':filter FORM'. */ | ||
| 8212 | filter = value; | ||
| 8213 | else if (EQ (ikey, QCbutton) && CONSP (value)) | ||
| 8214 | { | ||
| 8215 | /* `:button (TYPE . SELECTED)'. */ | ||
| 8216 | Lisp_Object type, selected; | ||
| 8217 | |||
| 8218 | type = XCAR (value); | ||
| 8219 | selected = XCDR (value); | ||
| 8220 | if (EQ (type, QCtoggle) || EQ (type, QCradio)) | ||
| 8221 | { | ||
| 8222 | set_prop_tab_bar (TAB_BAR_ITEM_SELECTED_P, selected); | ||
| 8223 | } | ||
| 8224 | } | ||
| 8225 | } | ||
| 8226 | |||
| 8227 | /* If got a filter apply it on binding. */ | ||
| 8228 | if (!NILP (filter)) | ||
| 8229 | set_prop_tab_bar (TAB_BAR_ITEM_BINDING, | ||
| 8230 | (menu_item_eval_property | ||
| 8231 | (list2 (filter, | ||
| 8232 | list2 (Qquote, | ||
| 8233 | PROP (TAB_BAR_ITEM_BINDING)))))); | ||
| 8234 | |||
| 8235 | /* See if the binding is a keymap. Give up if it is. */ | ||
| 8236 | if (CONSP (get_keymap (PROP (TAB_BAR_ITEM_BINDING), 0, 1))) | ||
| 8237 | return 0; | ||
| 8238 | |||
| 8239 | /* Enable or disable selection of item. */ | ||
| 8240 | if (!EQ (PROP (TAB_BAR_ITEM_ENABLED_P), Qt)) | ||
| 8241 | set_prop_tab_bar (TAB_BAR_ITEM_ENABLED_P, | ||
| 8242 | menu_item_eval_property (PROP (TAB_BAR_ITEM_ENABLED_P))); | ||
| 8243 | |||
| 8244 | /* Handle radio buttons or toggle boxes. */ | ||
| 8245 | if (!NILP (PROP (TAB_BAR_ITEM_SELECTED_P))) | ||
| 8246 | set_prop_tab_bar (TAB_BAR_ITEM_SELECTED_P, | ||
| 8247 | menu_item_eval_property (PROP (TAB_BAR_ITEM_SELECTED_P))); | ||
| 8248 | |||
| 8249 | return 1; | ||
| 8250 | |||
| 8251 | #undef PROP | ||
| 8252 | } | ||
| 8253 | |||
| 8254 | |||
| 8255 | /* Initialize tab_bar_items_vector. REUSE, if non-nil, is a vector | ||
| 8256 | that can be reused. */ | ||
| 8257 | |||
| 8258 | static void | ||
| 8259 | init_tab_bar_items (Lisp_Object reuse) | ||
| 8260 | { | ||
| 8261 | if (VECTORP (reuse)) | ||
| 8262 | tab_bar_items_vector = reuse; | ||
| 8263 | else | ||
| 8264 | tab_bar_items_vector = make_nil_vector (64); | ||
| 8265 | ntab_bar_items = 0; | ||
| 8266 | } | ||
| 8267 | |||
| 8268 | |||
| 8269 | /* Append parsed tab bar item properties from | ||
| 8270 | tab_bar_item_properties */ | ||
| 8271 | |||
| 8272 | static void | ||
| 8273 | append_tab_bar_item (void) | ||
| 8274 | { | ||
| 8275 | ptrdiff_t incr | ||
| 8276 | = (ntab_bar_items | ||
| 8277 | - (ASIZE (tab_bar_items_vector) - TAB_BAR_ITEM_NSLOTS)); | ||
| 8278 | |||
| 8279 | /* Enlarge tab_bar_items_vector if necessary. */ | ||
| 8280 | if (incr > 0) | ||
| 8281 | tab_bar_items_vector = larger_vector (tab_bar_items_vector, incr, -1); | ||
| 8282 | |||
| 8283 | /* Append entries from tab_bar_item_properties to the end of | ||
| 8284 | tab_bar_items_vector. */ | ||
| 8285 | vcopy (tab_bar_items_vector, ntab_bar_items, | ||
| 8286 | XVECTOR (tab_bar_item_properties)->contents, TAB_BAR_ITEM_NSLOTS); | ||
| 8287 | ntab_bar_items += TAB_BAR_ITEM_NSLOTS; | ||
| 8288 | } | ||
| 8289 | |||
| 8290 | |||
| 8291 | |||
| 8292 | |||
| 8293 | |||
| 8294 | /*********************************************************************** | ||
| 7894 | Tool-bars | 8295 | Tool-bars |
| 7895 | ***********************************************************************/ | 8296 | ***********************************************************************/ |
| 7896 | 8297 | ||
| @@ -8402,6 +8803,7 @@ read_char_x_menu_prompt (Lisp_Object map, | |||
| 8402 | use a real menu for mouse selection. */ | 8803 | use a real menu for mouse selection. */ |
| 8403 | if (EVENT_HAS_PARAMETERS (prev_event) | 8804 | if (EVENT_HAS_PARAMETERS (prev_event) |
| 8404 | && !EQ (XCAR (prev_event), Qmenu_bar) | 8805 | && !EQ (XCAR (prev_event), Qmenu_bar) |
| 8806 | && !EQ (XCAR (prev_event), Qtab_bar) | ||
| 8405 | && !EQ (XCAR (prev_event), Qtool_bar)) | 8807 | && !EQ (XCAR (prev_event), Qtool_bar)) |
| 8406 | { | 8808 | { |
| 8407 | /* Display the menu and get the selection. */ | 8809 | /* Display the menu and get the selection. */ |
| @@ -9377,7 +9779,7 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt, | |||
| 9377 | posn = POSN_POSN (xevent_start (key)); | 9779 | posn = POSN_POSN (xevent_start (key)); |
| 9378 | /* Handle menu-bar events: | 9780 | /* Handle menu-bar events: |
| 9379 | insert the dummy prefix event `menu-bar'. */ | 9781 | insert the dummy prefix event `menu-bar'. */ |
| 9380 | if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar)) | 9782 | if (EQ (posn, Qmenu_bar) || EQ (posn, Qtab_bar) || EQ (posn, Qtool_bar)) |
| 9381 | { | 9783 | { |
| 9382 | if (READ_KEY_ELTS - t <= 1) | 9784 | if (READ_KEY_ELTS - t <= 1) |
| 9383 | error ("Key sequence too long"); | 9785 | error ("Key sequence too long"); |
| @@ -10237,7 +10639,8 @@ On such systems, Emacs starts a subshell instead of suspending. */) | |||
| 10237 | get_tty_size (fileno (CURTTY ()->input), &width, &height); | 10639 | get_tty_size (fileno (CURTTY ()->input), &width, &height); |
| 10238 | if (width != old_width || height != old_height) | 10640 | if (width != old_width || height != old_height) |
| 10239 | change_frame_size (SELECTED_FRAME (), width, | 10641 | change_frame_size (SELECTED_FRAME (), width, |
| 10240 | height - FRAME_MENU_BAR_LINES (SELECTED_FRAME ()), | 10642 | height - FRAME_MENU_BAR_LINES (SELECTED_FRAME ()) |
| 10643 | - FRAME_TAB_BAR_LINES (SELECTED_FRAME ()), | ||
| 10241 | 0, 0, 0, 0); | 10644 | 0, 0, 0, 0); |
| 10242 | 10645 | ||
| 10243 | run_hook (intern ("suspend-resume-hook")); | 10646 | run_hook (intern ("suspend-resume-hook")); |
| @@ -11057,6 +11460,11 @@ syms_of_keyboard (void) | |||
| 11057 | staticpro (&item_properties); | 11460 | staticpro (&item_properties); |
| 11058 | item_properties = Qnil; | 11461 | item_properties = Qnil; |
| 11059 | 11462 | ||
| 11463 | staticpro (&tab_bar_item_properties); | ||
| 11464 | tab_bar_item_properties = Qnil; | ||
| 11465 | staticpro (&tab_bar_items_vector); | ||
| 11466 | tab_bar_items_vector = Qnil; | ||
| 11467 | |||
| 11060 | staticpro (&tool_bar_item_properties); | 11468 | staticpro (&tool_bar_item_properties); |
| 11061 | tool_bar_item_properties = Qnil; | 11469 | tool_bar_item_properties = Qnil; |
| 11062 | staticpro (&tool_bar_items_vector); | 11470 | staticpro (&tool_bar_items_vector); |
| @@ -11610,6 +12018,12 @@ See also `pre-command-hook'. */); | |||
| 11610 | The elements of the list are event types that may have menu bar bindings. */); | 12018 | The elements of the list are event types that may have menu bar bindings. */); |
| 11611 | Vmenu_bar_final_items = Qnil; | 12019 | Vmenu_bar_final_items = Qnil; |
| 11612 | 12020 | ||
| 12021 | DEFVAR_LISP ("tab-bar-separator-image-expression", Vtab_bar_separator_image_expression, | ||
| 12022 | doc: /* Expression evaluating to the image spec for a tab-bar separator. | ||
| 12023 | This is used internally by graphical displays that do not render | ||
| 12024 | tab-bar separators natively. Otherwise it is unused (e.g. on GTK). */); | ||
| 12025 | Vtab_bar_separator_image_expression = Qnil; | ||
| 12026 | |||
| 11613 | DEFVAR_LISP ("tool-bar-separator-image-expression", Vtool_bar_separator_image_expression, | 12027 | DEFVAR_LISP ("tool-bar-separator-image-expression", Vtool_bar_separator_image_expression, |
| 11614 | doc: /* Expression evaluating to the image spec for a tool-bar separator. | 12028 | doc: /* Expression evaluating to the image spec for a tool-bar separator. |
| 11615 | This is used internally by graphical displays that do not render | 12029 | This is used internally by graphical displays that do not render |