diff options
| author | YAMAMOTO Mitsuharu | 2008-04-06 01:58:19 +0000 |
|---|---|---|
| committer | YAMAMOTO Mitsuharu | 2008-04-06 01:58:19 +0000 |
| commit | 5aa4098ee2f374fadf0bab8a4382b19a4da4cad6 (patch) | |
| tree | 4ed0bede9d425db85be261e1e7551453a29ef165 /src/macmenu.c | |
| parent | f3821d294580e2e7285d8cbd28b2a2dc773e31f5 (diff) | |
| download | emacs-5aa4098ee2f374fadf0bab8a4382b19a4da4cad6.tar.gz emacs-5aa4098ee2f374fadf0bab8a4382b19a4da4cad6.zip | |
[!TARGET_API_MAC_CARBON]: Move includes to mactoolbox.c.
(enum mac_menu_kind): Move enum to mactoolbox.c.
(min_menu_id): Move variable to mactoolbox.c.
(quit_dialog_event_loop) [TARGET_API_MAC_CARBON]: Likewise.
(DIALOG_WINDOW_RESOURCE): Move define to mactoolbox.c.
(DIALOG_BUTTON_COMMAND_ID_OFFSET, DIALOG_BUTTON_COMMAND_ID_P)
(DIALOG_BUTTON_COMMAND_ID_VALUE, DIALOG_BUTTON_MAKE_COMMAND_ID)
[TARGET_API_MAC_CARBON]: Likewise.
(XtPointer): Move typedef to macgui.h.
(enum button_type): Move enum to macgui.h.
(widget_value): Move typedef to macgui.h.
(DIALOG_LEFT_MARGIN, DIALOG_TOP_MARGIN, DIALOG_RIGHT_MARGIN)
(DIALOG_BOTTOM_MARGIN, DIALOG_MIN_INNER_WIDTH, DIALOG_MAX_INNER_WIDTH)
(DIALOG_BUTTON_BUTTON_HORIZONTAL_SPACE)
(DIALOG_BUTTON_BUTTON_VERTICAL_SPACE, DIALOG_BUTTON_MIN_WIDTH)
(DIALOG_TEXT_MIN_HEIGHT, DIALOG_TEXT_BUTTONS_VERTICAL_SPACE)
(DIALOG_ICON_WIDTH, DIALOG_ICON_HEIGHT, DIALOG_ICON_LEFT_MARGIN)
(DIALOG_ICON_TOP_MARGIN): Move defines to macgui.h.
(popup_activated_flag): Make variable non-static.
(x_activate_menubar, install_menu_quit_handler, pop_down_menu)
(add_menu_item, fill_menu, dispose_menus):
Move functions to mactoolbox.c.
(restore_show_help_function, menu_target_item_handler)
(install_menu_target_item_handler, mac_handle_dialog_event)
(install_dialog_event_handler, pop_down_dialog, create_and_show_dialog)
[TARGET_API_MAC_CARBON]: Likewise.
(menu_quit_handler) [MAC_OS_X_VERSION_MAX_ALLOWED >= 1030]: Likewise.
(mac_dialog) [!TARGET_API_MAC_CARBON]: Likewise.
(find_and_call_menu_selection, name_is_separator): Make function
non-static.
(Vshow_help_function, timer_check) [TARGET_API_MAC_CARBON]: Move extern
to mactoolbox.c.
(set_frame_menubar): Don't call install_menu_quit_handler.
(menu_item_selection): New variable.
(mac_menu_show): Use create_and_show_popup_menu.
(create_and_show_dialog) [TARGET_API_MAC_CARBON]: Don't return
selection but set variable menu_item_selection. All uses changed.
(mac_fill_menubar): Rename from fill_menubar. All uses changed.
Call install_menu_quit_handler. Move to mactoolbox.c.
Diffstat (limited to 'src/macmenu.c')
| -rw-r--r-- | src/macmenu.c | 1323 |
1 files changed, 14 insertions, 1309 deletions
diff --git a/src/macmenu.c b/src/macmenu.c index 591010a4d65..153969f7efd 100644 --- a/src/macmenu.c +++ b/src/macmenu.c | |||
| @@ -36,20 +36,6 @@ Boston, MA 02110-1301, USA. */ | |||
| 36 | #include "charset.h" | 36 | #include "charset.h" |
| 37 | #include "coding.h" | 37 | #include "coding.h" |
| 38 | 38 | ||
| 39 | #if !TARGET_API_MAC_CARBON | ||
| 40 | #include <MacTypes.h> | ||
| 41 | #include <Menus.h> | ||
| 42 | #include <Quickdraw.h> | ||
| 43 | #include <ToolUtils.h> | ||
| 44 | #include <Fonts.h> | ||
| 45 | #include <Controls.h> | ||
| 46 | #include <Windows.h> | ||
| 47 | #include <Events.h> | ||
| 48 | #if defined (__MRC__) || (__MSL__ >= 0x6000) | ||
| 49 | #include <ControlDefinitions.h> | ||
| 50 | #endif | ||
| 51 | #endif /* not TARGET_API_MAC_CARBON */ | ||
| 52 | |||
| 53 | /* This may include sys/types.h, and that somehow loses | 39 | /* This may include sys/types.h, and that somehow loses |
| 54 | if this is not done before the other system files. */ | 40 | if this is not done before the other system files. */ |
| 55 | #include "macterm.h" | 41 | #include "macterm.h" |
| @@ -62,21 +48,6 @@ Boston, MA 02110-1301, USA. */ | |||
| 62 | 48 | ||
| 63 | #include "dispextern.h" | 49 | #include "dispextern.h" |
| 64 | 50 | ||
| 65 | enum mac_menu_kind { /* Menu ID range */ | ||
| 66 | MAC_MENU_APPLE, /* 0 (Reserved by Apple) */ | ||
| 67 | MAC_MENU_MENU_BAR, /* 1 .. 233 */ | ||
| 68 | MAC_MENU_M_APPLE, /* 234 (== M_APPLE) */ | ||
| 69 | MAC_MENU_POPUP, /* 235 */ | ||
| 70 | MAC_MENU_DRIVER, /* 236 .. 255 (Reserved) */ | ||
| 71 | MAC_MENU_MENU_BAR_SUB, /* 256 .. 16383 */ | ||
| 72 | MAC_MENU_POPUP_SUB, /* 16384 .. 32767 */ | ||
| 73 | MAC_MENU_END /* 32768 */ | ||
| 74 | }; | ||
| 75 | |||
| 76 | static const int min_menu_id[] = {0, 1, 234, 235, 236, 256, 16384, 32768}; | ||
| 77 | |||
| 78 | #define DIALOG_WINDOW_RESOURCE 130 | ||
| 79 | |||
| 80 | #if TARGET_API_MAC_CARBON | 51 | #if TARGET_API_MAC_CARBON |
| 81 | #define HAVE_DIALOGS 1 | 52 | #define HAVE_DIALOGS 1 |
| 82 | #endif | 53 | #endif |
| @@ -84,69 +55,6 @@ static const int min_menu_id[] = {0, 1, 234, 235, 236, 256, 16384, 32768}; | |||
| 84 | #undef HAVE_MULTILINGUAL_MENU | 55 | #undef HAVE_MULTILINGUAL_MENU |
| 85 | 56 | ||
| 86 | /******************************************************************/ | 57 | /******************************************************************/ |
| 87 | /* Definitions copied from lwlib.h */ | ||
| 88 | |||
| 89 | typedef void * XtPointer; | ||
| 90 | |||
| 91 | enum button_type | ||
| 92 | { | ||
| 93 | BUTTON_TYPE_NONE, | ||
| 94 | BUTTON_TYPE_TOGGLE, | ||
| 95 | BUTTON_TYPE_RADIO | ||
| 96 | }; | ||
| 97 | |||
| 98 | /* This structure is based on the one in ../lwlib/lwlib.h, modified | ||
| 99 | for Mac OS. */ | ||
| 100 | typedef struct _widget_value | ||
| 101 | { | ||
| 102 | /* name of widget */ | ||
| 103 | Lisp_Object lname; | ||
| 104 | char* name; | ||
| 105 | /* value (meaning depend on widget type) */ | ||
| 106 | char* value; | ||
| 107 | /* keyboard equivalent. no implications for XtTranslations */ | ||
| 108 | Lisp_Object lkey; | ||
| 109 | char* key; | ||
| 110 | /* Help string or nil if none. | ||
| 111 | GC finds this string through the frame's menu_bar_vector | ||
| 112 | or through menu_items. */ | ||
| 113 | Lisp_Object help; | ||
| 114 | /* true if enabled */ | ||
| 115 | Boolean enabled; | ||
| 116 | /* true if selected */ | ||
| 117 | Boolean selected; | ||
| 118 | /* The type of a button. */ | ||
| 119 | enum button_type button_type; | ||
| 120 | /* true if menu title */ | ||
| 121 | Boolean title; | ||
| 122 | #if 0 | ||
| 123 | /* true if was edited (maintained by get_value) */ | ||
| 124 | Boolean edited; | ||
| 125 | /* true if has changed (maintained by lw library) */ | ||
| 126 | change_type change; | ||
| 127 | /* true if this widget itself has changed, | ||
| 128 | but not counting the other widgets found in the `next' field. */ | ||
| 129 | change_type this_one_change; | ||
| 130 | #endif | ||
| 131 | /* Contents of the sub-widgets, also selected slot for checkbox */ | ||
| 132 | struct _widget_value* contents; | ||
| 133 | /* data passed to callback */ | ||
| 134 | XtPointer call_data; | ||
| 135 | /* next one in the list */ | ||
| 136 | struct _widget_value* next; | ||
| 137 | #if 0 | ||
| 138 | /* slot for the toolkit dependent part. Always initialize to NULL. */ | ||
| 139 | void* toolkit_data; | ||
| 140 | /* tell us if we should free the toolkit data slot when freeing the | ||
| 141 | widget_value itself. */ | ||
| 142 | Boolean free_toolkit_data; | ||
| 143 | |||
| 144 | /* we resource the widget_value structures; this points to the next | ||
| 145 | one on the free list if this one has been deallocated. | ||
| 146 | */ | ||
| 147 | struct _widget_value *free_list; | ||
| 148 | #endif | ||
| 149 | } widget_value; | ||
| 150 | 58 | ||
| 151 | /* Assumed by other routines to zero area returned. */ | 59 | /* Assumed by other routines to zero area returned. */ |
| 152 | #define malloc_widget_value() (void *)memset (xmalloc (sizeof (widget_value)),\ | 60 | #define malloc_widget_value() (void *)memset (xmalloc (sizeof (widget_value)),\ |
| @@ -198,12 +106,6 @@ static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object, | |||
| 198 | static void list_of_panes P_ ((Lisp_Object)); | 106 | static void list_of_panes P_ ((Lisp_Object)); |
| 199 | static void list_of_items P_ ((Lisp_Object)); | 107 | static void list_of_items P_ ((Lisp_Object)); |
| 200 | 108 | ||
| 201 | static void find_and_call_menu_selection P_ ((FRAME_PTR, int, Lisp_Object, | ||
| 202 | void *)); | ||
| 203 | static int fill_menu P_ ((MenuRef, widget_value *, enum mac_menu_kind, int)); | ||
| 204 | static void fill_menubar P_ ((widget_value *, int)); | ||
| 205 | static void dispose_menus P_ ((enum mac_menu_kind, int)); | ||
| 206 | |||
| 207 | 109 | ||
| 208 | /* This holds a Lisp vector that holds the results of decoding | 110 | /* This holds a Lisp vector that holds the results of decoding |
| 209 | the keymaps or alist-of-alists that specify a menu. | 111 | the keymaps or alist-of-alists that specify a menu. |
| @@ -260,7 +162,7 @@ static int menu_items_n_panes; | |||
| 260 | static int menu_items_submenu_depth; | 162 | static int menu_items_submenu_depth; |
| 261 | 163 | ||
| 262 | /* Nonzero means a menu is currently active. */ | 164 | /* Nonzero means a menu is currently active. */ |
| 263 | static int popup_activated_flag; | 165 | int popup_activated_flag; |
| 264 | 166 | ||
| 265 | /* This is set nonzero after the user activates the menu bar, and set | 167 | /* This is set nonzero after the user activates the menu bar, and set |
| 266 | to zero again after the menu bars are redisplayed by prepare_menu_bar. | 168 | to zero again after the menu bars are redisplayed by prepare_menu_bar. |
| @@ -880,32 +782,6 @@ no quit occurs and `x-popup-menu' returns nil. */) | |||
| 880 | 782 | ||
| 881 | #ifdef HAVE_MENUS | 783 | #ifdef HAVE_MENUS |
| 882 | 784 | ||
| 883 | /* Regard ESC and C-g as Cancel even without the Cancel button. */ | ||
| 884 | |||
| 885 | #if 0 /* defined (MAC_OSX) */ | ||
| 886 | static Boolean | ||
| 887 | mac_dialog_modal_filter (dialog, event, item_hit) | ||
| 888 | DialogRef dialog; | ||
| 889 | EventRecord *event; | ||
| 890 | DialogItemIndex *item_hit; | ||
| 891 | { | ||
| 892 | Boolean result; | ||
| 893 | |||
| 894 | result = StdFilterProc (dialog, event, item_hit); | ||
| 895 | if (result == false | ||
| 896 | && (event->what == keyDown || event->what == autoKey) | ||
| 897 | && ((event->message & charCodeMask) == kEscapeCharCode | ||
| 898 | || mac_quit_char_key_p (event->modifiers, | ||
| 899 | (event->message & keyCodeMask) >> 8))) | ||
| 900 | { | ||
| 901 | *item_hit = kStdCancelItemIndex; | ||
| 902 | return true; | ||
| 903 | } | ||
| 904 | |||
| 905 | return result; | ||
| 906 | } | ||
| 907 | #endif | ||
| 908 | |||
| 909 | DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0, | 785 | DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0, |
| 910 | doc: /* Pop up a dialog box and return user's selection. | 786 | doc: /* Pop up a dialog box and return user's selection. |
| 911 | POSITION specifies which frame to use. | 787 | POSITION specifies which frame to use. |
| @@ -991,101 +867,6 @@ for instance using the window manager, then this produces a quit and | |||
| 991 | but I don't want to make one now. */ | 867 | but I don't want to make one now. */ |
| 992 | CHECK_WINDOW (window); | 868 | CHECK_WINDOW (window); |
| 993 | 869 | ||
| 994 | #if 0 /* defined (MAC_OSX) */ | ||
| 995 | /* Special treatment for Fmessage_box, Fyes_or_no_p, and Fy_or_n_p. */ | ||
| 996 | if (EQ (position, Qt) | ||
| 997 | && STRINGP (Fcar (contents)) | ||
| 998 | && ((!NILP (Fequal (XCDR (contents), | ||
| 999 | Fcons (Fcons (build_string ("OK"), Qt), Qnil))) | ||
| 1000 | && EQ (header, Qt)) | ||
| 1001 | || (!NILP (Fequal (XCDR (contents), | ||
| 1002 | Fcons (Fcons (build_string ("Yes"), Qt), | ||
| 1003 | Fcons (Fcons (build_string ("No"), Qnil), | ||
| 1004 | Qnil)))) | ||
| 1005 | && NILP (header)))) | ||
| 1006 | { | ||
| 1007 | OSStatus err = noErr; | ||
| 1008 | AlertStdCFStringAlertParamRec param; | ||
| 1009 | CFStringRef error_string, explanation_string; | ||
| 1010 | DialogRef alert; | ||
| 1011 | DialogItemIndex item_hit; | ||
| 1012 | Lisp_Object tem; | ||
| 1013 | |||
| 1014 | /* Force a redisplay before showing the dialog. If a frame is | ||
| 1015 | created just before showing the dialog, its contents may not | ||
| 1016 | have been fully drawn. */ | ||
| 1017 | Fredisplay (Qt); | ||
| 1018 | |||
| 1019 | tem = Fstring_match (concat3 (build_string ("\\("), | ||
| 1020 | call0 (intern ("sentence-end")), | ||
| 1021 | build_string ("\\)\n")), | ||
| 1022 | XCAR (contents), Qnil); | ||
| 1023 | BLOCK_INPUT; | ||
| 1024 | if (NILP (tem)) | ||
| 1025 | { | ||
| 1026 | error_string = cfstring_create_with_string (XCAR (contents)); | ||
| 1027 | if (error_string == NULL) | ||
| 1028 | err = memFullErr; | ||
| 1029 | explanation_string = NULL; | ||
| 1030 | } | ||
| 1031 | else | ||
| 1032 | { | ||
| 1033 | tem = Fmatch_end (make_number (1)); | ||
| 1034 | error_string = | ||
| 1035 | cfstring_create_with_string (Fsubstring (XCAR (contents), | ||
| 1036 | make_number (0), tem)); | ||
| 1037 | if (error_string == NULL) | ||
| 1038 | err = memFullErr; | ||
| 1039 | else | ||
| 1040 | { | ||
| 1041 | XSETINT (tem, XINT (tem) + 1); | ||
| 1042 | explanation_string = | ||
| 1043 | cfstring_create_with_string (Fsubstring (XCAR (contents), | ||
| 1044 | tem, Qnil)); | ||
| 1045 | if (explanation_string == NULL) | ||
| 1046 | { | ||
| 1047 | CFRelease (error_string); | ||
| 1048 | err = memFullErr; | ||
| 1049 | } | ||
| 1050 | } | ||
| 1051 | } | ||
| 1052 | if (err == noErr) | ||
| 1053 | err = GetStandardAlertDefaultParams (¶m, | ||
| 1054 | kStdCFStringAlertVersionOne); | ||
| 1055 | if (err == noErr) | ||
| 1056 | { | ||
| 1057 | param.movable = true; | ||
| 1058 | param.position = kWindowAlertPositionParentWindow; | ||
| 1059 | if (NILP (header)) | ||
| 1060 | { | ||
| 1061 | param.defaultText = CFSTR ("Yes"); | ||
| 1062 | param.otherText = CFSTR ("No"); | ||
| 1063 | #if 0 | ||
| 1064 | param.cancelText = CFSTR ("Cancel"); | ||
| 1065 | param.cancelButton = kAlertStdAlertCancelButton; | ||
| 1066 | #endif | ||
| 1067 | } | ||
| 1068 | err = CreateStandardAlert (kAlertNoteAlert, error_string, | ||
| 1069 | explanation_string, ¶m, &alert); | ||
| 1070 | CFRelease (error_string); | ||
| 1071 | if (explanation_string) | ||
| 1072 | CFRelease (explanation_string); | ||
| 1073 | } | ||
| 1074 | if (err == noErr) | ||
| 1075 | err = RunStandardAlert (alert, mac_dialog_modal_filter, &item_hit); | ||
| 1076 | UNBLOCK_INPUT; | ||
| 1077 | |||
| 1078 | if (err == noErr) | ||
| 1079 | { | ||
| 1080 | if (item_hit == kStdCancelItemIndex) | ||
| 1081 | Fsignal (Qquit, Qnil); | ||
| 1082 | else if (item_hit == kStdOkItemIndex) | ||
| 1083 | return Qt; | ||
| 1084 | else | ||
| 1085 | return Qnil; | ||
| 1086 | } | ||
| 1087 | } | ||
| 1088 | #endif | ||
| 1089 | #ifndef HAVE_DIALOGS | 870 | #ifndef HAVE_DIALOGS |
| 1090 | /* Display a menu with these alternatives | 871 | /* Display a menu with these alternatives |
| 1091 | in the middle of frame F. */ | 872 | in the middle of frame F. */ |
| @@ -1125,66 +906,12 @@ for instance using the window manager, then this produces a quit and | |||
| 1125 | #endif /* HAVE_DIALOGS */ | 906 | #endif /* HAVE_DIALOGS */ |
| 1126 | } | 907 | } |
| 1127 | 908 | ||
| 1128 | /* Activate the menu bar of frame F. | ||
| 1129 | This is called from keyboard.c when it gets the | ||
| 1130 | MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue. | ||
| 1131 | |||
| 1132 | To activate the menu bar, we use the button-press event location | ||
| 1133 | that was saved in saved_menu_event_location. | ||
| 1134 | |||
| 1135 | But first we recompute the menu bar contents (the whole tree). | ||
| 1136 | |||
| 1137 | The reason for saving the button event until here, instead of | ||
| 1138 | passing it to the toolkit right away, is that we can safely | ||
| 1139 | execute Lisp code. */ | ||
| 1140 | |||
| 1141 | void | ||
| 1142 | x_activate_menubar (f) | ||
| 1143 | FRAME_PTR f; | ||
| 1144 | { | ||
| 1145 | SInt32 menu_choice; | ||
| 1146 | SInt16 menu_id, menu_item; | ||
| 1147 | extern Point saved_menu_event_location; | ||
| 1148 | |||
| 1149 | set_frame_menubar (f, 0, 1); | ||
| 1150 | BLOCK_INPUT; | ||
| 1151 | |||
| 1152 | popup_activated_flag = 1; | ||
| 1153 | menu_choice = MenuSelect (saved_menu_event_location); | ||
| 1154 | popup_activated_flag = 0; | ||
| 1155 | menu_id = HiWord (menu_choice); | ||
| 1156 | menu_item = LoWord (menu_choice); | ||
| 1157 | |||
| 1158 | #if !TARGET_API_MAC_CARBON | ||
| 1159 | if (menu_id == min_menu_id[MAC_MENU_M_APPLE]) | ||
| 1160 | do_apple_menu (menu_item); | ||
| 1161 | else | ||
| 1162 | #endif | ||
| 1163 | if (menu_id) | ||
| 1164 | { | ||
| 1165 | MenuRef menu = GetMenuRef (menu_id); | ||
| 1166 | |||
| 1167 | if (menu) | ||
| 1168 | { | ||
| 1169 | UInt32 refcon; | ||
| 1170 | |||
| 1171 | GetMenuItemRefCon (menu, menu_item, &refcon); | ||
| 1172 | find_and_call_menu_selection (f, f->menu_bar_items_used, | ||
| 1173 | f->menu_bar_vector, (void *) refcon); | ||
| 1174 | } | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | HiliteMenu (0); | ||
| 1178 | |||
| 1179 | UNBLOCK_INPUT; | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | /* Find the menu selection and store it in the keyboard buffer. | 909 | /* Find the menu selection and store it in the keyboard buffer. |
| 1183 | F is the frame the menu is on. | 910 | F is the frame the menu is on. |
| 1184 | MENU_BAR_ITEMS_USED is the length of VECTOR. | 911 | MENU_BAR_ITEMS_USED is the length of VECTOR. |
| 1185 | VECTOR is an array of menu events for the whole menu. */ | 912 | VECTOR is an array of menu events for the whole menu. */ |
| 1186 | 913 | ||
| 1187 | static void | 914 | void |
| 1188 | find_and_call_menu_selection (f, menu_bar_items_used, vector, client_data) | 915 | find_and_call_menu_selection (f, menu_bar_items_used, vector, client_data) |
| 1189 | FRAME_PTR f; | 916 | FRAME_PTR f; |
| 1190 | int menu_bar_items_used; | 917 | int menu_bar_items_used; |
| @@ -1577,141 +1304,6 @@ update_submenu_strings (first_wv) | |||
| 1577 | } | 1304 | } |
| 1578 | 1305 | ||
| 1579 | 1306 | ||
| 1580 | #if TARGET_API_MAC_CARBON | ||
| 1581 | extern Lisp_Object Vshow_help_function; | ||
| 1582 | |||
| 1583 | static Lisp_Object | ||
| 1584 | restore_show_help_function (old_show_help_function) | ||
| 1585 | Lisp_Object old_show_help_function; | ||
| 1586 | { | ||
| 1587 | Vshow_help_function = old_show_help_function; | ||
| 1588 | |||
| 1589 | return Qnil; | ||
| 1590 | } | ||
| 1591 | |||
| 1592 | static pascal OSStatus | ||
| 1593 | menu_target_item_handler (next_handler, event, data) | ||
| 1594 | EventHandlerCallRef next_handler; | ||
| 1595 | EventRef event; | ||
| 1596 | void *data; | ||
| 1597 | { | ||
| 1598 | OSStatus err; | ||
| 1599 | MenuRef menu; | ||
| 1600 | MenuItemIndex menu_item; | ||
| 1601 | Lisp_Object help; | ||
| 1602 | GrafPtr port; | ||
| 1603 | int specpdl_count = SPECPDL_INDEX (); | ||
| 1604 | |||
| 1605 | /* Don't be bothered with the overflowed toolbar items menu. */ | ||
| 1606 | if (!popup_activated ()) | ||
| 1607 | return eventNotHandledErr; | ||
| 1608 | |||
| 1609 | err = GetEventParameter (event, kEventParamDirectObject, typeMenuRef, | ||
| 1610 | NULL, sizeof (MenuRef), NULL, &menu); | ||
| 1611 | if (err == noErr) | ||
| 1612 | err = GetEventParameter (event, kEventParamMenuItemIndex, | ||
| 1613 | typeMenuItemIndex, NULL, | ||
| 1614 | sizeof (MenuItemIndex), NULL, &menu_item); | ||
| 1615 | if (err == noErr) | ||
| 1616 | err = GetMenuItemProperty (menu, menu_item, | ||
| 1617 | MAC_EMACS_CREATOR_CODE, 'help', | ||
| 1618 | sizeof (Lisp_Object), NULL, &help); | ||
| 1619 | if (err != noErr) | ||
| 1620 | help = Qnil; | ||
| 1621 | |||
| 1622 | /* Temporarily bind Vshow_help_function to Qnil because we don't | ||
| 1623 | want tooltips during menu tracking. */ | ||
| 1624 | record_unwind_protect (restore_show_help_function, Vshow_help_function); | ||
| 1625 | Vshow_help_function = Qnil; | ||
| 1626 | GetPort (&port); | ||
| 1627 | show_help_echo (help, Qnil, Qnil, Qnil, 1); | ||
| 1628 | SetPort (port); | ||
| 1629 | unbind_to (specpdl_count, Qnil); | ||
| 1630 | |||
| 1631 | return err == noErr ? noErr : eventNotHandledErr; | ||
| 1632 | } | ||
| 1633 | |||
| 1634 | OSStatus | ||
| 1635 | install_menu_target_item_handler () | ||
| 1636 | { | ||
| 1637 | static const EventTypeSpec specs[] = | ||
| 1638 | {{kEventClassMenu, kEventMenuTargetItem}}; | ||
| 1639 | |||
| 1640 | return InstallApplicationEventHandler (NewEventHandlerUPP | ||
| 1641 | (menu_target_item_handler), | ||
| 1642 | GetEventTypeCount (specs), | ||
| 1643 | specs, NULL, NULL); | ||
| 1644 | } | ||
| 1645 | #endif /* TARGET_API_MAC_CARBON */ | ||
| 1646 | |||
| 1647 | /* Event handler function that pops down a menu on C-g. We can only pop | ||
| 1648 | down menus if CancelMenuTracking is present (OSX 10.3 or later). */ | ||
| 1649 | |||
| 1650 | #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 | ||
| 1651 | static pascal OSStatus | ||
| 1652 | menu_quit_handler (nextHandler, theEvent, userData) | ||
| 1653 | EventHandlerCallRef nextHandler; | ||
| 1654 | EventRef theEvent; | ||
| 1655 | void* userData; | ||
| 1656 | { | ||
| 1657 | OSStatus err; | ||
| 1658 | UInt32 keyCode; | ||
| 1659 | UInt32 keyModifiers; | ||
| 1660 | |||
| 1661 | err = GetEventParameter (theEvent, kEventParamKeyCode, | ||
| 1662 | typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode); | ||
| 1663 | |||
| 1664 | if (err == noErr) | ||
| 1665 | err = GetEventParameter (theEvent, kEventParamKeyModifiers, | ||
| 1666 | typeUInt32, NULL, sizeof(UInt32), | ||
| 1667 | NULL, &keyModifiers); | ||
| 1668 | |||
| 1669 | if (err == noErr && mac_quit_char_key_p (keyModifiers, keyCode)) | ||
| 1670 | { | ||
| 1671 | MenuRef menu = userData != 0 | ||
| 1672 | ? (MenuRef)userData : AcquireRootMenu (); | ||
| 1673 | |||
| 1674 | CancelMenuTracking (menu, true, 0); | ||
| 1675 | if (!userData) ReleaseMenu (menu); | ||
| 1676 | return noErr; | ||
| 1677 | } | ||
| 1678 | |||
| 1679 | return CallNextEventHandler (nextHandler, theEvent); | ||
| 1680 | } | ||
| 1681 | #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */ | ||
| 1682 | |||
| 1683 | /* Add event handler to all menus that belong to KIND so we can detect | ||
| 1684 | C-g. ROOT_MENU is the root menu of the tracking session to dismiss | ||
| 1685 | when C-g is detected. NULL means the menu bar. If | ||
| 1686 | CancelMenuTracking isn't available, do nothing. */ | ||
| 1687 | |||
| 1688 | static void | ||
| 1689 | install_menu_quit_handler (kind, root_menu) | ||
| 1690 | enum mac_menu_kind kind; | ||
| 1691 | MenuRef root_menu; | ||
| 1692 | { | ||
| 1693 | #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 | ||
| 1694 | static const EventTypeSpec typesList[] = | ||
| 1695 | {{kEventClassKeyboard, kEventRawKeyDown}}; | ||
| 1696 | int id; | ||
| 1697 | |||
| 1698 | #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020 | ||
| 1699 | if (CancelMenuTracking == NULL) | ||
| 1700 | return; | ||
| 1701 | #endif | ||
| 1702 | for (id = min_menu_id[kind]; id < min_menu_id[kind + 1]; id++) | ||
| 1703 | { | ||
| 1704 | MenuRef menu = GetMenuRef (id); | ||
| 1705 | |||
| 1706 | if (menu == NULL) | ||
| 1707 | break; | ||
| 1708 | InstallMenuEventHandler (menu, menu_quit_handler, | ||
| 1709 | GetEventTypeCount (typesList), | ||
| 1710 | typesList, root_menu, NULL); | ||
| 1711 | } | ||
| 1712 | #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */ | ||
| 1713 | } | ||
| 1714 | |||
| 1715 | /* Set the contents of the menubar widgets of frame F. | 1307 | /* Set the contents of the menubar widgets of frame F. |
| 1716 | The argument FIRST_TIME is currently ignored; | 1308 | The argument FIRST_TIME is currently ignored; |
| 1717 | it is set the first time this is called, from initialize_frame_menubar. */ | 1309 | it is set the first time this is called, from initialize_frame_menubar. */ |
| @@ -1947,11 +1539,8 @@ set_frame_menubar (f, first_time, deep_p) | |||
| 1947 | /* Non-null value to indicate menubar has already been "created". */ | 1539 | /* Non-null value to indicate menubar has already been "created". */ |
| 1948 | f->output_data.mac->menubar_widget = 1; | 1540 | f->output_data.mac->menubar_widget = 1; |
| 1949 | 1541 | ||
| 1950 | fill_menubar (first_wv->contents, deep_p); | 1542 | mac_fill_menubar (first_wv->contents, deep_p); |
| 1951 | 1543 | ||
| 1952 | /* Add event handler so we can detect C-g. */ | ||
| 1953 | install_menu_quit_handler (MAC_MENU_MENU_BAR, NULL); | ||
| 1954 | install_menu_quit_handler (MAC_MENU_MENU_BAR_SUB, NULL); | ||
| 1955 | free_menubar_widget_value_tree (first_wv); | 1544 | free_menubar_widget_value_tree (first_wv); |
| 1956 | 1545 | ||
| 1957 | UNBLOCK_INPUT; | 1546 | UNBLOCK_INPUT; |
| @@ -1968,29 +1557,8 @@ free_frame_menubar (f) | |||
| 1968 | } | 1557 | } |
| 1969 | 1558 | ||
| 1970 | 1559 | ||
| 1971 | static Lisp_Object | 1560 | /* The item selected in the popup menu. */ |
| 1972 | pop_down_menu (arg) | 1561 | int menu_item_selection; |
| 1973 | Lisp_Object arg; | ||
| 1974 | { | ||
| 1975 | struct Lisp_Save_Value *p = XSAVE_VALUE (arg); | ||
| 1976 | FRAME_PTR f = p->pointer; | ||
| 1977 | MenuRef menu = GetMenuRef (min_menu_id[MAC_MENU_POPUP]); | ||
| 1978 | |||
| 1979 | BLOCK_INPUT; | ||
| 1980 | |||
| 1981 | /* Must reset this manually because the button release event is not | ||
| 1982 | passed to Emacs event loop. */ | ||
| 1983 | FRAME_MAC_DISPLAY_INFO (f)->grabbed = 0; | ||
| 1984 | |||
| 1985 | /* delete all menus */ | ||
| 1986 | dispose_menus (MAC_MENU_POPUP_SUB, 0); | ||
| 1987 | DeleteMenu (min_menu_id[MAC_MENU_POPUP]); | ||
| 1988 | DisposeMenu (menu); | ||
| 1989 | |||
| 1990 | UNBLOCK_INPUT; | ||
| 1991 | |||
| 1992 | return Qnil; | ||
| 1993 | } | ||
| 1994 | 1562 | ||
| 1995 | /* Mac_menu_show actually displays a menu using the panes and items in | 1563 | /* Mac_menu_show actually displays a menu using the panes and items in |
| 1996 | menu_items and returns the value selected from it; we assume input | 1564 | menu_items and returns the value selected from it; we assume input |
| @@ -2018,9 +1586,6 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) | |||
| 2018 | char **error; | 1586 | char **error; |
| 2019 | { | 1587 | { |
| 2020 | int i; | 1588 | int i; |
| 2021 | int menu_item_choice; | ||
| 2022 | UInt32 menu_item_selection; | ||
| 2023 | MenuRef menu; | ||
| 2024 | widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; | 1589 | widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; |
| 2025 | widget_value **submenu_stack | 1590 | widget_value **submenu_stack |
| 2026 | = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); | 1591 | = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); |
| @@ -2029,7 +1594,6 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) | |||
| 2029 | int submenu_depth = 0; | 1594 | int submenu_depth = 0; |
| 2030 | 1595 | ||
| 2031 | int first_pane; | 1596 | int first_pane; |
| 2032 | int specpdl_count = SPECPDL_INDEX (); | ||
| 2033 | 1597 | ||
| 2034 | *error = NULL; | 1598 | *error = NULL; |
| 2035 | 1599 | ||
| @@ -2215,45 +1779,14 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) | |||
| 2215 | first_wv->contents = wv_title; | 1779 | first_wv->contents = wv_title; |
| 2216 | } | 1780 | } |
| 2217 | 1781 | ||
| 2218 | /* Actually create the menu. */ | ||
| 2219 | menu = NewMenu (min_menu_id[MAC_MENU_POPUP], "\p"); | ||
| 2220 | InsertMenu (menu, -1); | ||
| 2221 | fill_menu (menu, first_wv->contents, MAC_MENU_POPUP_SUB, | ||
| 2222 | min_menu_id[MAC_MENU_POPUP_SUB]); | ||
| 2223 | |||
| 2224 | /* Free the widget_value objects we used to specify the | ||
| 2225 | contents. */ | ||
| 2226 | free_menubar_widget_value_tree (first_wv); | ||
| 2227 | |||
| 2228 | /* Adjust coordinates to be root-window-relative. */ | ||
| 2229 | x += f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f); | ||
| 2230 | y += f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f); | ||
| 2231 | |||
| 2232 | /* No selection has been chosen yet. */ | 1782 | /* No selection has been chosen yet. */ |
| 2233 | menu_item_selection = 0; | 1783 | menu_item_selection = 0; |
| 2234 | 1784 | ||
| 2235 | record_unwind_protect (pop_down_menu, make_save_value (f, 0)); | 1785 | /* Actually create and show the menu until popped down. */ |
| 1786 | create_and_show_popup_menu (f, first_wv, x, y, for_click); | ||
| 2236 | 1787 | ||
| 2237 | /* Add event handler so we can detect C-g. */ | 1788 | /* Free the widget_value objects we used to specify the contents. */ |
| 2238 | install_menu_quit_handler (MAC_MENU_POPUP, menu); | 1789 | free_menubar_widget_value_tree (first_wv); |
| 2239 | install_menu_quit_handler (MAC_MENU_POPUP_SUB, menu); | ||
| 2240 | |||
| 2241 | /* Display the menu. */ | ||
| 2242 | popup_activated_flag = 1; | ||
| 2243 | menu_item_choice = PopUpMenuSelect (menu, y, x, 0); | ||
| 2244 | popup_activated_flag = 0; | ||
| 2245 | |||
| 2246 | /* Get the refcon to find the correct item */ | ||
| 2247 | if (menu_item_choice) | ||
| 2248 | { | ||
| 2249 | MenuRef sel_menu = GetMenuRef (HiWord (menu_item_choice)); | ||
| 2250 | |||
| 2251 | if (sel_menu) | ||
| 2252 | GetMenuItemRefCon (sel_menu, LoWord (menu_item_choice), | ||
| 2253 | &menu_item_selection); | ||
| 2254 | } | ||
| 2255 | |||
| 2256 | unbind_to (specpdl_count, Qnil); | ||
| 2257 | 1790 | ||
| 2258 | /* Find the selected item, and its pane, to return | 1791 | /* Find the selected item, and its pane, to return |
| 2259 | the proper value. */ | 1792 | the proper value. */ |
| @@ -2320,582 +1853,6 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error) | |||
| 2320 | #ifdef HAVE_DIALOGS | 1853 | #ifdef HAVE_DIALOGS |
| 2321 | /* Construct native Mac OS dialog based on widget_value tree. */ | 1854 | /* Construct native Mac OS dialog based on widget_value tree. */ |
| 2322 | 1855 | ||
| 2323 | #if TARGET_API_MAC_CARBON | ||
| 2324 | |||
| 2325 | #define DIALOG_BUTTON_COMMAND_ID_OFFSET 'Bt\0\0' | ||
| 2326 | #define DIALOG_BUTTON_COMMAND_ID_P(id) \ | ||
| 2327 | (((id) & ~0xffff) == DIALOG_BUTTON_COMMAND_ID_OFFSET) | ||
| 2328 | #define DIALOG_BUTTON_COMMAND_ID_VALUE(id) \ | ||
| 2329 | ((id) - DIALOG_BUTTON_COMMAND_ID_OFFSET) | ||
| 2330 | #define DIALOG_BUTTON_MAKE_COMMAND_ID(value) \ | ||
| 2331 | ((value) + DIALOG_BUTTON_COMMAND_ID_OFFSET) | ||
| 2332 | |||
| 2333 | extern EMACS_TIME timer_check P_ ((int)); | ||
| 2334 | static int quit_dialog_event_loop; | ||
| 2335 | |||
| 2336 | static pascal OSStatus | ||
| 2337 | mac_handle_dialog_event (next_handler, event, data) | ||
| 2338 | EventHandlerCallRef next_handler; | ||
| 2339 | EventRef event; | ||
| 2340 | void *data; | ||
| 2341 | { | ||
| 2342 | OSStatus err, result = eventNotHandledErr; | ||
| 2343 | WindowRef window = (WindowRef) data; | ||
| 2344 | |||
| 2345 | switch (GetEventClass (event)) | ||
| 2346 | { | ||
| 2347 | case kEventClassCommand: | ||
| 2348 | { | ||
| 2349 | HICommand command; | ||
| 2350 | |||
| 2351 | err = GetEventParameter (event, kEventParamDirectObject, | ||
| 2352 | typeHICommand, NULL, sizeof (HICommand), | ||
| 2353 | NULL, &command); | ||
| 2354 | if (err == noErr) | ||
| 2355 | if (DIALOG_BUTTON_COMMAND_ID_P (command.commandID)) | ||
| 2356 | { | ||
| 2357 | SetWRefCon (window, command.commandID); | ||
| 2358 | quit_dialog_event_loop = 1; | ||
| 2359 | break; | ||
| 2360 | } | ||
| 2361 | |||
| 2362 | result = CallNextEventHandler (next_handler, event); | ||
| 2363 | } | ||
| 2364 | break; | ||
| 2365 | |||
| 2366 | case kEventClassKeyboard: | ||
| 2367 | { | ||
| 2368 | OSStatus result; | ||
| 2369 | char char_code; | ||
| 2370 | |||
| 2371 | result = CallNextEventHandler (next_handler, event); | ||
| 2372 | if (result != eventNotHandledErr) | ||
| 2373 | break; | ||
| 2374 | |||
| 2375 | err = GetEventParameter (event, kEventParamKeyMacCharCodes, | ||
| 2376 | typeChar, NULL, sizeof (char), | ||
| 2377 | NULL, &char_code); | ||
| 2378 | if (err == noErr) | ||
| 2379 | switch (char_code) | ||
| 2380 | { | ||
| 2381 | case kEscapeCharCode: | ||
| 2382 | quit_dialog_event_loop = 1; | ||
| 2383 | break; | ||
| 2384 | |||
| 2385 | default: | ||
| 2386 | { | ||
| 2387 | UInt32 modifiers, key_code; | ||
| 2388 | |||
| 2389 | err = GetEventParameter (event, kEventParamKeyModifiers, | ||
| 2390 | typeUInt32, NULL, sizeof (UInt32), | ||
| 2391 | NULL, &modifiers); | ||
| 2392 | if (err == noErr) | ||
| 2393 | err = GetEventParameter (event, kEventParamKeyCode, | ||
| 2394 | typeUInt32, NULL, sizeof (UInt32), | ||
| 2395 | NULL, &key_code); | ||
| 2396 | if (err == noErr) | ||
| 2397 | if (mac_quit_char_key_p (modifiers, key_code)) | ||
| 2398 | quit_dialog_event_loop = 1; | ||
| 2399 | } | ||
| 2400 | break; | ||
| 2401 | } | ||
| 2402 | } | ||
| 2403 | break; | ||
| 2404 | |||
| 2405 | default: | ||
| 2406 | abort (); | ||
| 2407 | } | ||
| 2408 | |||
| 2409 | if (quit_dialog_event_loop) | ||
| 2410 | { | ||
| 2411 | err = QuitEventLoop (GetCurrentEventLoop ()); | ||
| 2412 | if (err == noErr) | ||
| 2413 | result = noErr; | ||
| 2414 | } | ||
| 2415 | |||
| 2416 | return result; | ||
| 2417 | } | ||
| 2418 | |||
| 2419 | static OSStatus | ||
| 2420 | install_dialog_event_handler (window) | ||
| 2421 | WindowRef window; | ||
| 2422 | { | ||
| 2423 | static const EventTypeSpec specs[] = | ||
| 2424 | {{kEventClassCommand, kEventCommandProcess}, | ||
| 2425 | {kEventClassKeyboard, kEventRawKeyDown}}; | ||
| 2426 | static EventHandlerUPP handle_dialog_eventUPP = NULL; | ||
| 2427 | |||
| 2428 | if (handle_dialog_eventUPP == NULL) | ||
| 2429 | handle_dialog_eventUPP = NewEventHandlerUPP (mac_handle_dialog_event); | ||
| 2430 | return InstallWindowEventHandler (window, handle_dialog_eventUPP, | ||
| 2431 | GetEventTypeCount (specs), specs, | ||
| 2432 | window, NULL); | ||
| 2433 | } | ||
| 2434 | |||
| 2435 | #define DIALOG_LEFT_MARGIN (112) | ||
| 2436 | #define DIALOG_TOP_MARGIN (24) | ||
| 2437 | #define DIALOG_RIGHT_MARGIN (24) | ||
| 2438 | #define DIALOG_BOTTOM_MARGIN (20) | ||
| 2439 | #define DIALOG_MIN_INNER_WIDTH (338) | ||
| 2440 | #define DIALOG_MAX_INNER_WIDTH (564) | ||
| 2441 | #define DIALOG_BUTTON_BUTTON_HORIZONTAL_SPACE (12) | ||
| 2442 | #define DIALOG_BUTTON_BUTTON_VERTICAL_SPACE (12) | ||
| 2443 | #define DIALOG_BUTTON_MIN_WIDTH (68) | ||
| 2444 | #define DIALOG_TEXT_MIN_HEIGHT (50) | ||
| 2445 | #define DIALOG_TEXT_BUTTONS_VERTICAL_SPACE (10) | ||
| 2446 | #define DIALOG_ICON_WIDTH (64) | ||
| 2447 | #define DIALOG_ICON_HEIGHT (64) | ||
| 2448 | #define DIALOG_ICON_LEFT_MARGIN (24) | ||
| 2449 | #define DIALOG_ICON_TOP_MARGIN (15) | ||
| 2450 | |||
| 2451 | static Lisp_Object | ||
| 2452 | pop_down_dialog (arg) | ||
| 2453 | Lisp_Object arg; | ||
| 2454 | { | ||
| 2455 | struct Lisp_Save_Value *p = XSAVE_VALUE (arg); | ||
| 2456 | WindowRef window = p->pointer; | ||
| 2457 | |||
| 2458 | BLOCK_INPUT; | ||
| 2459 | |||
| 2460 | if (popup_activated_flag) | ||
| 2461 | EndAppModalStateForWindow (window); | ||
| 2462 | DisposeWindow (window); | ||
| 2463 | popup_activated_flag = 0; | ||
| 2464 | |||
| 2465 | UNBLOCK_INPUT; | ||
| 2466 | |||
| 2467 | return Qnil; | ||
| 2468 | } | ||
| 2469 | |||
| 2470 | static int | ||
| 2471 | create_and_show_dialog (f, first_wv) | ||
| 2472 | FRAME_PTR f; | ||
| 2473 | widget_value *first_wv; | ||
| 2474 | { | ||
| 2475 | OSStatus err; | ||
| 2476 | char *dialog_name, *message; | ||
| 2477 | int nb_buttons, first_group_count, i, result = 0; | ||
| 2478 | widget_value *wv; | ||
| 2479 | short buttons_height, text_height, inner_width, inner_height; | ||
| 2480 | Rect empty_rect, *rects; | ||
| 2481 | WindowRef window = NULL; | ||
| 2482 | ControlRef *buttons, default_button = NULL, text; | ||
| 2483 | int specpdl_count = SPECPDL_INDEX (); | ||
| 2484 | |||
| 2485 | dialog_name = first_wv->name; | ||
| 2486 | nb_buttons = dialog_name[1] - '0'; | ||
| 2487 | first_group_count = nb_buttons - (dialog_name[4] - '0'); | ||
| 2488 | |||
| 2489 | wv = first_wv->contents; | ||
| 2490 | message = wv->value; | ||
| 2491 | |||
| 2492 | wv = wv->next; | ||
| 2493 | SetRect (&empty_rect, 0, 0, 0, 0); | ||
| 2494 | |||
| 2495 | /* Create dialog window. */ | ||
| 2496 | err = CreateNewWindow (kMovableModalWindowClass, | ||
| 2497 | kWindowStandardHandlerAttribute, | ||
| 2498 | &empty_rect, &window); | ||
| 2499 | if (err == noErr) | ||
| 2500 | { | ||
| 2501 | record_unwind_protect (pop_down_dialog, make_save_value (window, 0)); | ||
| 2502 | err = SetThemeWindowBackground (window, kThemeBrushMovableModalBackground, | ||
| 2503 | true); | ||
| 2504 | } | ||
| 2505 | if (err == noErr) | ||
| 2506 | err = SetWindowTitleWithCFString (window, (dialog_name[0] == 'Q' | ||
| 2507 | ? CFSTR ("Question") | ||
| 2508 | : CFSTR ("Information"))); | ||
| 2509 | |||
| 2510 | /* Create button controls and measure their optimal bounds. */ | ||
| 2511 | if (err == noErr) | ||
| 2512 | { | ||
| 2513 | buttons = alloca (sizeof (ControlRef) * nb_buttons); | ||
| 2514 | rects = alloca (sizeof (Rect) * nb_buttons); | ||
| 2515 | for (i = 0; i < nb_buttons; i++) | ||
| 2516 | { | ||
| 2517 | CFStringRef label = cfstring_create_with_utf8_cstring (wv->value); | ||
| 2518 | |||
| 2519 | if (label == NULL) | ||
| 2520 | err = memFullErr; | ||
| 2521 | else | ||
| 2522 | { | ||
| 2523 | err = CreatePushButtonControl (window, &empty_rect, | ||
| 2524 | label, &buttons[i]); | ||
| 2525 | CFRelease (label); | ||
| 2526 | } | ||
| 2527 | if (err == noErr) | ||
| 2528 | { | ||
| 2529 | if (!wv->enabled) | ||
| 2530 | { | ||
| 2531 | #ifdef MAC_OSX | ||
| 2532 | err = DisableControl (buttons[i]); | ||
| 2533 | #else | ||
| 2534 | err = DeactivateControl (buttons[i]); | ||
| 2535 | #endif | ||
| 2536 | } | ||
| 2537 | else if (default_button == NULL) | ||
| 2538 | default_button = buttons[i]; | ||
| 2539 | } | ||
| 2540 | if (err == noErr) | ||
| 2541 | { | ||
| 2542 | SInt16 unused; | ||
| 2543 | |||
| 2544 | rects[i] = empty_rect; | ||
| 2545 | err = GetBestControlRect (buttons[i], &rects[i], &unused); | ||
| 2546 | } | ||
| 2547 | if (err == noErr) | ||
| 2548 | { | ||
| 2549 | UInt32 command_id; | ||
| 2550 | |||
| 2551 | OffsetRect (&rects[i], -rects[i].left, -rects[i].top); | ||
| 2552 | if (rects[i].right < DIALOG_BUTTON_MIN_WIDTH) | ||
| 2553 | rects[i].right = DIALOG_BUTTON_MIN_WIDTH; | ||
| 2554 | else if (rects[i].right > DIALOG_MAX_INNER_WIDTH) | ||
| 2555 | rects[i].right = DIALOG_MAX_INNER_WIDTH; | ||
| 2556 | |||
| 2557 | command_id = DIALOG_BUTTON_MAKE_COMMAND_ID ((int) wv->call_data); | ||
| 2558 | err = SetControlCommandID (buttons[i], command_id); | ||
| 2559 | } | ||
| 2560 | if (err != noErr) | ||
| 2561 | break; | ||
| 2562 | wv = wv->next; | ||
| 2563 | } | ||
| 2564 | } | ||
| 2565 | |||
| 2566 | /* Layout buttons. rects[i] is set relative to the bottom-right | ||
| 2567 | corner of the inner box. */ | ||
| 2568 | if (err == noErr) | ||
| 2569 | { | ||
| 2570 | short bottom, right, max_height, left_align_shift; | ||
| 2571 | |||
| 2572 | inner_width = DIALOG_MIN_INNER_WIDTH; | ||
| 2573 | bottom = right = max_height = 0; | ||
| 2574 | for (i = 0; i < nb_buttons; i++) | ||
| 2575 | { | ||
| 2576 | if (right - rects[i].right < - inner_width) | ||
| 2577 | { | ||
| 2578 | if (i != first_group_count | ||
| 2579 | && right - rects[i].right >= - DIALOG_MAX_INNER_WIDTH) | ||
| 2580 | inner_width = - (right - rects[i].right); | ||
| 2581 | else | ||
| 2582 | { | ||
| 2583 | bottom -= max_height + DIALOG_BUTTON_BUTTON_VERTICAL_SPACE; | ||
| 2584 | right = max_height = 0; | ||
| 2585 | } | ||
| 2586 | } | ||
| 2587 | if (max_height < rects[i].bottom) | ||
| 2588 | max_height = rects[i].bottom; | ||
| 2589 | OffsetRect (&rects[i], right - rects[i].right, | ||
| 2590 | bottom - rects[i].bottom); | ||
| 2591 | right = rects[i].left - DIALOG_BUTTON_BUTTON_HORIZONTAL_SPACE; | ||
| 2592 | if (i == first_group_count - 1) | ||
| 2593 | right -= DIALOG_BUTTON_BUTTON_HORIZONTAL_SPACE; | ||
| 2594 | } | ||
| 2595 | buttons_height = - (bottom - max_height); | ||
| 2596 | |||
| 2597 | left_align_shift = - (inner_width + rects[nb_buttons - 1].left); | ||
| 2598 | for (i = nb_buttons - 1; i >= first_group_count; i--) | ||
| 2599 | { | ||
| 2600 | if (bottom != rects[i].bottom) | ||
| 2601 | { | ||
| 2602 | left_align_shift = - (inner_width + rects[i].left); | ||
| 2603 | bottom = rects[i].bottom; | ||
| 2604 | } | ||
| 2605 | OffsetRect (&rects[i], left_align_shift, 0); | ||
| 2606 | } | ||
| 2607 | } | ||
| 2608 | |||
| 2609 | /* Create a static text control and measure its bounds. */ | ||
| 2610 | if (err == noErr) | ||
| 2611 | { | ||
| 2612 | CFStringRef message_string; | ||
| 2613 | Rect bounds; | ||
| 2614 | |||
| 2615 | message_string = cfstring_create_with_utf8_cstring (message); | ||
| 2616 | if (message_string == NULL) | ||
| 2617 | err = memFullErr; | ||
| 2618 | else | ||
| 2619 | { | ||
| 2620 | ControlFontStyleRec text_style; | ||
| 2621 | |||
| 2622 | text_style.flags = 0; | ||
| 2623 | SetRect (&bounds, 0, 0, inner_width, 0); | ||
| 2624 | err = CreateStaticTextControl (window, &bounds, message_string, | ||
| 2625 | &text_style, &text); | ||
| 2626 | CFRelease (message_string); | ||
| 2627 | } | ||
| 2628 | if (err == noErr) | ||
| 2629 | { | ||
| 2630 | SInt16 unused; | ||
| 2631 | |||
| 2632 | bounds = empty_rect; | ||
| 2633 | err = GetBestControlRect (text, &bounds, &unused); | ||
| 2634 | } | ||
| 2635 | if (err == noErr) | ||
| 2636 | { | ||
| 2637 | text_height = bounds.bottom - bounds.top; | ||
| 2638 | if (text_height < DIALOG_TEXT_MIN_HEIGHT) | ||
| 2639 | text_height = DIALOG_TEXT_MIN_HEIGHT; | ||
| 2640 | } | ||
| 2641 | } | ||
| 2642 | |||
| 2643 | /* Place buttons. */ | ||
| 2644 | if (err == noErr) | ||
| 2645 | { | ||
| 2646 | inner_height = (text_height + DIALOG_TEXT_BUTTONS_VERTICAL_SPACE | ||
| 2647 | + buttons_height); | ||
| 2648 | |||
| 2649 | for (i = 0; i < nb_buttons; i++) | ||
| 2650 | { | ||
| 2651 | OffsetRect (&rects[i], DIALOG_LEFT_MARGIN + inner_width, | ||
| 2652 | DIALOG_TOP_MARGIN + inner_height); | ||
| 2653 | SetControlBounds (buttons[i], &rects[i]); | ||
| 2654 | } | ||
| 2655 | } | ||
| 2656 | |||
| 2657 | /* Place text. */ | ||
| 2658 | if (err == noErr) | ||
| 2659 | { | ||
| 2660 | Rect bounds; | ||
| 2661 | |||
| 2662 | SetRect (&bounds, DIALOG_LEFT_MARGIN, DIALOG_TOP_MARGIN, | ||
| 2663 | DIALOG_LEFT_MARGIN + inner_width, | ||
| 2664 | DIALOG_TOP_MARGIN + text_height); | ||
| 2665 | SetControlBounds (text, &bounds); | ||
| 2666 | } | ||
| 2667 | |||
| 2668 | /* Create the application icon at the upper-left corner. */ | ||
| 2669 | if (err == noErr) | ||
| 2670 | { | ||
| 2671 | ControlButtonContentInfo content; | ||
| 2672 | ControlRef icon; | ||
| 2673 | static const ProcessSerialNumber psn = {0, kCurrentProcess}; | ||
| 2674 | #ifdef MAC_OSX | ||
| 2675 | FSRef app_location; | ||
| 2676 | #else | ||
| 2677 | ProcessInfoRec pinfo; | ||
| 2678 | FSSpec app_spec; | ||
| 2679 | #endif | ||
| 2680 | SInt16 unused; | ||
| 2681 | |||
| 2682 | content.contentType = kControlContentIconRef; | ||
| 2683 | #ifdef MAC_OSX | ||
| 2684 | err = GetProcessBundleLocation (&psn, &app_location); | ||
| 2685 | if (err == noErr) | ||
| 2686 | err = GetIconRefFromFileInfo (&app_location, 0, NULL, 0, NULL, | ||
| 2687 | kIconServicesNormalUsageFlag, | ||
| 2688 | &content.u.iconRef, &unused); | ||
| 2689 | #else | ||
| 2690 | bzero (&pinfo, sizeof (ProcessInfoRec)); | ||
| 2691 | pinfo.processInfoLength = sizeof (ProcessInfoRec); | ||
| 2692 | pinfo.processAppSpec = &app_spec; | ||
| 2693 | err = GetProcessInformation (&psn, &pinfo); | ||
| 2694 | if (err == noErr) | ||
| 2695 | err = GetIconRefFromFile (&app_spec, &content.u.iconRef, &unused); | ||
| 2696 | #endif | ||
| 2697 | if (err == noErr) | ||
| 2698 | { | ||
| 2699 | Rect bounds; | ||
| 2700 | |||
| 2701 | SetRect (&bounds, DIALOG_ICON_LEFT_MARGIN, DIALOG_ICON_TOP_MARGIN, | ||
| 2702 | DIALOG_ICON_LEFT_MARGIN + DIALOG_ICON_WIDTH, | ||
| 2703 | DIALOG_ICON_TOP_MARGIN + DIALOG_ICON_HEIGHT); | ||
| 2704 | err = CreateIconControl (window, &bounds, &content, true, &icon); | ||
| 2705 | ReleaseIconRef (content.u.iconRef); | ||
| 2706 | } | ||
| 2707 | } | ||
| 2708 | |||
| 2709 | /* Show the dialog window and run event loop. */ | ||
| 2710 | if (err == noErr) | ||
| 2711 | if (default_button) | ||
| 2712 | err = SetWindowDefaultButton (window, default_button); | ||
| 2713 | if (err == noErr) | ||
| 2714 | err = install_dialog_event_handler (window); | ||
| 2715 | if (err == noErr) | ||
| 2716 | { | ||
| 2717 | SizeWindow (window, | ||
| 2718 | DIALOG_LEFT_MARGIN + inner_width + DIALOG_RIGHT_MARGIN, | ||
| 2719 | DIALOG_TOP_MARGIN + inner_height + DIALOG_BOTTOM_MARGIN, | ||
| 2720 | true); | ||
| 2721 | err = RepositionWindow (window, FRAME_MAC_WINDOW (f), | ||
| 2722 | kWindowAlertPositionOnParentWindow); | ||
| 2723 | } | ||
| 2724 | if (err == noErr) | ||
| 2725 | { | ||
| 2726 | SetWRefCon (window, 0); | ||
| 2727 | ShowWindow (window); | ||
| 2728 | BringToFront (window); | ||
| 2729 | popup_activated_flag = 1; | ||
| 2730 | err = BeginAppModalStateForWindow (window); | ||
| 2731 | } | ||
| 2732 | if (err == noErr) | ||
| 2733 | { | ||
| 2734 | EventTargetRef toolbox_dispatcher = GetEventDispatcherTarget (); | ||
| 2735 | |||
| 2736 | quit_dialog_event_loop = 0; | ||
| 2737 | while (1) | ||
| 2738 | { | ||
| 2739 | EMACS_TIME next_time = timer_check (1); | ||
| 2740 | long secs = EMACS_SECS (next_time); | ||
| 2741 | long usecs = EMACS_USECS (next_time); | ||
| 2742 | EventTimeout timeout; | ||
| 2743 | EventRef event; | ||
| 2744 | |||
| 2745 | if (secs < 0 || (secs == 0 && usecs == 0)) | ||
| 2746 | { | ||
| 2747 | /* Sometimes timer_check returns -1 (no timers) even if | ||
| 2748 | there are timers. So do a timeout anyway. */ | ||
| 2749 | secs = 1; | ||
| 2750 | usecs = 0; | ||
| 2751 | } | ||
| 2752 | |||
| 2753 | timeout = (secs * kEventDurationSecond | ||
| 2754 | + usecs * kEventDurationMicrosecond); | ||
| 2755 | err = ReceiveNextEvent (0, NULL, timeout, kEventRemoveFromQueue, | ||
| 2756 | &event); | ||
| 2757 | if (err == noErr) | ||
| 2758 | { | ||
| 2759 | SendEventToEventTarget (event, toolbox_dispatcher); | ||
| 2760 | ReleaseEvent (event); | ||
| 2761 | } | ||
| 2762 | #if 0 /* defined (MAC_OSX) */ | ||
| 2763 | else if (err != eventLoopTimedOutErr) | ||
| 2764 | { | ||
| 2765 | if (err == eventLoopQuitErr) | ||
| 2766 | err = noErr; | ||
| 2767 | break; | ||
| 2768 | } | ||
| 2769 | #else | ||
| 2770 | /* The return value of ReceiveNextEvent seems to be | ||
| 2771 | unreliable. Use our own global variable instead. */ | ||
| 2772 | if (quit_dialog_event_loop) | ||
| 2773 | { | ||
| 2774 | err = noErr; | ||
| 2775 | break; | ||
| 2776 | } | ||
| 2777 | #endif | ||
| 2778 | } | ||
| 2779 | } | ||
| 2780 | if (err == noErr) | ||
| 2781 | { | ||
| 2782 | UInt32 command_id = GetWRefCon (window); | ||
| 2783 | |||
| 2784 | if (DIALOG_BUTTON_COMMAND_ID_P (command_id)) | ||
| 2785 | result = DIALOG_BUTTON_COMMAND_ID_VALUE (command_id); | ||
| 2786 | } | ||
| 2787 | |||
| 2788 | unbind_to (specpdl_count, Qnil); | ||
| 2789 | |||
| 2790 | return result; | ||
| 2791 | } | ||
| 2792 | #else /* not TARGET_API_MAC_CARBON */ | ||
| 2793 | static int | ||
| 2794 | mac_dialog (widget_value *wv) | ||
| 2795 | { | ||
| 2796 | char *dialog_name; | ||
| 2797 | char *prompt; | ||
| 2798 | char **button_labels; | ||
| 2799 | UInt32 *ref_cons; | ||
| 2800 | int nb_buttons; | ||
| 2801 | int left_count; | ||
| 2802 | int i; | ||
| 2803 | int dialog_width; | ||
| 2804 | Rect rect; | ||
| 2805 | WindowRef window_ptr; | ||
| 2806 | ControlRef ch; | ||
| 2807 | int left; | ||
| 2808 | EventRecord event_record; | ||
| 2809 | SInt16 part_code; | ||
| 2810 | int control_part_code; | ||
| 2811 | Point mouse; | ||
| 2812 | |||
| 2813 | dialog_name = wv->name; | ||
| 2814 | nb_buttons = dialog_name[1] - '0'; | ||
| 2815 | left_count = nb_buttons - (dialog_name[4] - '0'); | ||
| 2816 | button_labels = (char **) alloca (sizeof (char *) * nb_buttons); | ||
| 2817 | ref_cons = (UInt32 *) alloca (sizeof (UInt32) * nb_buttons); | ||
| 2818 | |||
| 2819 | wv = wv->contents; | ||
| 2820 | prompt = (char *) alloca (strlen (wv->value) + 1); | ||
| 2821 | strcpy (prompt, wv->value); | ||
| 2822 | c2pstr (prompt); | ||
| 2823 | |||
| 2824 | wv = wv->next; | ||
| 2825 | for (i = 0; i < nb_buttons; i++) | ||
| 2826 | { | ||
| 2827 | button_labels[i] = wv->value; | ||
| 2828 | button_labels[i] = (char *) alloca (strlen (wv->value) + 1); | ||
| 2829 | strcpy (button_labels[i], wv->value); | ||
| 2830 | c2pstr (button_labels[i]); | ||
| 2831 | ref_cons[i] = (UInt32) wv->call_data; | ||
| 2832 | wv = wv->next; | ||
| 2833 | } | ||
| 2834 | |||
| 2835 | window_ptr = GetNewCWindow (DIALOG_WINDOW_RESOURCE, NULL, (WindowRef) -1); | ||
| 2836 | |||
| 2837 | SetPortWindowPort (window_ptr); | ||
| 2838 | |||
| 2839 | TextFont (0); | ||
| 2840 | /* Left and right margins in the dialog are 13 pixels each.*/ | ||
| 2841 | dialog_width = 14; | ||
| 2842 | /* Calculate width of dialog box: 8 pixels on each side of the text | ||
| 2843 | label in each button, 12 pixels between buttons. */ | ||
| 2844 | for (i = 0; i < nb_buttons; i++) | ||
| 2845 | dialog_width += StringWidth (button_labels[i]) + 16 + 12; | ||
| 2846 | |||
| 2847 | if (left_count != 0 && nb_buttons - left_count != 0) | ||
| 2848 | dialog_width += 12; | ||
| 2849 | |||
| 2850 | dialog_width = max (dialog_width, StringWidth (prompt) + 26); | ||
| 2851 | |||
| 2852 | SizeWindow (window_ptr, dialog_width, 78, 0); | ||
| 2853 | ShowWindow (window_ptr); | ||
| 2854 | |||
| 2855 | SetPortWindowPort (window_ptr); | ||
| 2856 | |||
| 2857 | TextFont (0); | ||
| 2858 | |||
| 2859 | MoveTo (13, 29); | ||
| 2860 | DrawString (prompt); | ||
| 2861 | |||
| 2862 | left = 13; | ||
| 2863 | for (i = 0; i < nb_buttons; i++) | ||
| 2864 | { | ||
| 2865 | int button_width = StringWidth (button_labels[i]) + 16; | ||
| 2866 | SetRect (&rect, left, 45, left + button_width, 65); | ||
| 2867 | ch = NewControl (window_ptr, &rect, button_labels[i], 1, 0, 0, 0, | ||
| 2868 | kControlPushButtonProc, ref_cons[i]); | ||
| 2869 | left += button_width + 12; | ||
| 2870 | if (i == left_count - 1) | ||
| 2871 | left += 12; | ||
| 2872 | } | ||
| 2873 | |||
| 2874 | i = 0; | ||
| 2875 | while (!i) | ||
| 2876 | { | ||
| 2877 | if (WaitNextEvent (mDownMask, &event_record, 10, NULL)) | ||
| 2878 | if (event_record.what == mouseDown) | ||
| 2879 | { | ||
| 2880 | part_code = FindWindow (event_record.where, &window_ptr); | ||
| 2881 | if (part_code == inContent) | ||
| 2882 | { | ||
| 2883 | mouse = event_record.where; | ||
| 2884 | GlobalToLocal (&mouse); | ||
| 2885 | control_part_code = FindControl (mouse, window_ptr, &ch); | ||
| 2886 | if (control_part_code == kControlButtonPart) | ||
| 2887 | if (TrackControl (ch, mouse, NULL)) | ||
| 2888 | i = GetControlReference (ch); | ||
| 2889 | } | ||
| 2890 | } | ||
| 2891 | } | ||
| 2892 | |||
| 2893 | DisposeWindow (window_ptr); | ||
| 2894 | |||
| 2895 | return i; | ||
| 2896 | } | ||
| 2897 | #endif /* not TARGET_API_MAC_CARBON */ | ||
| 2898 | |||
| 2899 | static char * button_names [] = { | 1856 | static char * button_names [] = { |
| 2900 | "button1", "button2", "button3", "button4", "button5", | 1857 | "button1", "button2", "button3", "button4", "button5", |
| 2901 | "button6", "button7", "button8", "button9", "button10" }; | 1858 | "button6", "button7", "button8", "button9", "button10" }; |
| @@ -2909,7 +1866,6 @@ mac_dialog_show (f, keymaps, title, header, error_name) | |||
| 2909 | { | 1866 | { |
| 2910 | int i, nb_buttons=0; | 1867 | int i, nb_buttons=0; |
| 2911 | char dialog_name[6]; | 1868 | char dialog_name[6]; |
| 2912 | int menu_item_selection; | ||
| 2913 | 1869 | ||
| 2914 | widget_value *wv, *first_wv = 0, *prev_wv = 0; | 1870 | widget_value *wv, *first_wv = 0, *prev_wv = 0; |
| 2915 | 1871 | ||
| @@ -3026,6 +1982,9 @@ mac_dialog_show (f, keymaps, title, header, error_name) | |||
| 3026 | first_wv = wv; | 1982 | first_wv = wv; |
| 3027 | } | 1983 | } |
| 3028 | 1984 | ||
| 1985 | /* No selection has been chosen yet. */ | ||
| 1986 | menu_item_selection = 0; | ||
| 1987 | |||
| 3029 | /* Force a redisplay before showing the dialog. If a frame is created | 1988 | /* Force a redisplay before showing the dialog. If a frame is created |
| 3030 | just before showing the dialog, its contents may not have been fully | 1989 | just before showing the dialog, its contents may not have been fully |
| 3031 | drawn. */ | 1990 | drawn. */ |
| @@ -3033,7 +1992,7 @@ mac_dialog_show (f, keymaps, title, header, error_name) | |||
| 3033 | 1992 | ||
| 3034 | /* Actually create the dialog. */ | 1993 | /* Actually create the dialog. */ |
| 3035 | #if TARGET_API_MAC_CARBON | 1994 | #if TARGET_API_MAC_CARBON |
| 3036 | menu_item_selection = create_and_show_dialog (f, first_wv); | 1995 | create_and_show_dialog (f, first_wv); |
| 3037 | #else | 1996 | #else |
| 3038 | menu_item_selection = mac_dialog (first_wv); | 1997 | menu_item_selection = mac_dialog (first_wv); |
| 3039 | #endif | 1998 | #endif |
| @@ -3093,7 +2052,7 @@ mac_dialog_show (f, keymaps, title, header, error_name) | |||
| 3093 | 2052 | ||
| 3094 | 2053 | ||
| 3095 | /* Is this item a separator? */ | 2054 | /* Is this item a separator? */ |
| 3096 | static int | 2055 | int |
| 3097 | name_is_separator (name) | 2056 | name_is_separator (name) |
| 3098 | const char *name; | 2057 | const char *name; |
| 3099 | { | 2058 | { |
| @@ -3106,260 +2065,6 @@ name_is_separator (name) | |||
| 3106 | them like normal separators. */ | 2065 | them like normal separators. */ |
| 3107 | return (*name == '\0' || start + 2 == name); | 2066 | return (*name == '\0' || start + 2 == name); |
| 3108 | } | 2067 | } |
| 3109 | |||
| 3110 | static void | ||
| 3111 | add_menu_item (menu, pos, wv) | ||
| 3112 | MenuRef menu; | ||
| 3113 | int pos; | ||
| 3114 | widget_value *wv; | ||
| 3115 | { | ||
| 3116 | #if TARGET_API_MAC_CARBON | ||
| 3117 | CFStringRef item_name; | ||
| 3118 | #else | ||
| 3119 | Str255 item_name; | ||
| 3120 | #endif | ||
| 3121 | |||
| 3122 | if (name_is_separator (wv->name)) | ||
| 3123 | AppendMenu (menu, "\p-"); | ||
| 3124 | else | ||
| 3125 | { | ||
| 3126 | AppendMenu (menu, "\pX"); | ||
| 3127 | |||
| 3128 | #if TARGET_API_MAC_CARBON | ||
| 3129 | item_name = cfstring_create_with_utf8_cstring (wv->name); | ||
| 3130 | |||
| 3131 | if (wv->key != NULL) | ||
| 3132 | { | ||
| 3133 | CFStringRef name, key; | ||
| 3134 | |||
| 3135 | name = item_name; | ||
| 3136 | key = cfstring_create_with_utf8_cstring (wv->key); | ||
| 3137 | item_name = CFStringCreateWithFormat (NULL, NULL, CFSTR ("%@ %@"), | ||
| 3138 | name, key); | ||
| 3139 | CFRelease (name); | ||
| 3140 | CFRelease (key); | ||
| 3141 | } | ||
| 3142 | |||
| 3143 | SetMenuItemTextWithCFString (menu, pos, item_name); | ||
| 3144 | CFRelease (item_name); | ||
| 3145 | |||
| 3146 | if (wv->enabled) | ||
| 3147 | EnableMenuItem (menu, pos); | ||
| 3148 | else | ||
| 3149 | DisableMenuItem (menu, pos); | ||
| 3150 | |||
| 3151 | if (STRINGP (wv->help)) | ||
| 3152 | SetMenuItemProperty (menu, pos, MAC_EMACS_CREATOR_CODE, 'help', | ||
| 3153 | sizeof (Lisp_Object), &wv->help); | ||
| 3154 | #else /* ! TARGET_API_MAC_CARBON */ | ||
| 3155 | item_name[sizeof (item_name) - 1] = '\0'; | ||
| 3156 | strncpy (item_name, wv->name, sizeof (item_name) - 1); | ||
| 3157 | if (wv->key != NULL) | ||
| 3158 | { | ||
| 3159 | int len = strlen (item_name); | ||
| 3160 | |||
| 3161 | strncpy (item_name + len, " ", sizeof (item_name) - 1 - len); | ||
| 3162 | len = strlen (item_name); | ||
| 3163 | strncpy (item_name + len, wv->key, sizeof (item_name) - 1 - len); | ||
| 3164 | } | ||
| 3165 | c2pstr (item_name); | ||
| 3166 | SetMenuItemText (menu, pos, item_name); | ||
| 3167 | |||
| 3168 | if (wv->enabled) | ||
| 3169 | EnableItem (menu, pos); | ||
| 3170 | else | ||
| 3171 | DisableItem (menu, pos); | ||
| 3172 | #endif /* ! TARGET_API_MAC_CARBON */ | ||
| 3173 | |||
| 3174 | /* Draw radio buttons and tickboxes. */ | ||
| 3175 | if (wv->selected && (wv->button_type == BUTTON_TYPE_TOGGLE || | ||
| 3176 | wv->button_type == BUTTON_TYPE_RADIO)) | ||
| 3177 | SetItemMark (menu, pos, checkMark); | ||
| 3178 | else | ||
| 3179 | SetItemMark (menu, pos, noMark); | ||
| 3180 | |||
| 3181 | SetMenuItemRefCon (menu, pos, (UInt32) wv->call_data); | ||
| 3182 | } | ||
| 3183 | } | ||
| 3184 | |||
| 3185 | /* Construct native Mac OS menu based on widget_value tree. */ | ||
| 3186 | |||
| 3187 | static int | ||
| 3188 | fill_menu (menu, wv, kind, submenu_id) | ||
| 3189 | MenuRef menu; | ||
| 3190 | widget_value *wv; | ||
| 3191 | enum mac_menu_kind kind; | ||
| 3192 | int submenu_id; | ||
| 3193 | { | ||
| 3194 | int pos; | ||
| 3195 | |||
| 3196 | for (pos = 1; wv != NULL; wv = wv->next, pos++) | ||
| 3197 | { | ||
| 3198 | add_menu_item (menu, pos, wv); | ||
| 3199 | if (wv->contents && submenu_id < min_menu_id[kind + 1]) | ||
| 3200 | { | ||
| 3201 | MenuRef submenu = NewMenu (submenu_id, "\pX"); | ||
| 3202 | |||
| 3203 | InsertMenu (submenu, -1); | ||
| 3204 | #if TARGET_API_MAC_CARBON | ||
| 3205 | SetMenuItemHierarchicalMenu (menu, pos, submenu); | ||
| 3206 | #else | ||
| 3207 | SetMenuItemHierarchicalID (menu, pos, submenu_id); | ||
| 3208 | #endif | ||
| 3209 | submenu_id = fill_menu (submenu, wv->contents, kind, submenu_id + 1); | ||
| 3210 | } | ||
| 3211 | } | ||
| 3212 | |||
| 3213 | return submenu_id; | ||
| 3214 | } | ||
| 3215 | |||
| 3216 | /* Construct native Mac OS menubar based on widget_value tree. */ | ||
| 3217 | |||
| 3218 | static void | ||
| 3219 | fill_menubar (wv, deep_p) | ||
| 3220 | widget_value *wv; | ||
| 3221 | int deep_p; | ||
| 3222 | { | ||
| 3223 | int id, submenu_id; | ||
| 3224 | #if !TARGET_API_MAC_CARBON | ||
| 3225 | int title_changed_p = 0; | ||
| 3226 | #endif | ||
| 3227 | |||
| 3228 | /* Clean up the menu bar when filled by the entire menu trees. */ | ||
| 3229 | if (deep_p) | ||
| 3230 | { | ||
| 3231 | dispose_menus (MAC_MENU_MENU_BAR, 0); | ||
| 3232 | dispose_menus (MAC_MENU_MENU_BAR_SUB, 0); | ||
| 3233 | #if !TARGET_API_MAC_CARBON | ||
| 3234 | title_changed_p = 1; | ||
| 3235 | #endif | ||
| 3236 | } | ||
| 3237 | |||
| 3238 | /* Fill menu bar titles and submenus. Reuse the existing menu bar | ||
| 3239 | titles as much as possible to minimize redraw (if !deep_p). */ | ||
| 3240 | submenu_id = min_menu_id[MAC_MENU_MENU_BAR_SUB]; | ||
| 3241 | for (id = min_menu_id[MAC_MENU_MENU_BAR]; | ||
| 3242 | wv != NULL && id < min_menu_id[MAC_MENU_MENU_BAR + 1]; | ||
| 3243 | wv = wv->next, id++) | ||
| 3244 | { | ||
| 3245 | OSStatus err = noErr; | ||
| 3246 | MenuRef menu; | ||
| 3247 | #if TARGET_API_MAC_CARBON | ||
| 3248 | CFStringRef title; | ||
| 3249 | |||
| 3250 | title = CFStringCreateWithCString (NULL, wv->name, | ||
| 3251 | kCFStringEncodingMacRoman); | ||
| 3252 | #else | ||
| 3253 | Str255 title; | ||
| 3254 | |||
| 3255 | strncpy (title, wv->name, 255); | ||
| 3256 | title[255] = '\0'; | ||
| 3257 | c2pstr (title); | ||
| 3258 | #endif | ||
| 3259 | |||
| 3260 | menu = GetMenuRef (id); | ||
| 3261 | if (menu) | ||
| 3262 | { | ||
| 3263 | #if TARGET_API_MAC_CARBON | ||
| 3264 | CFStringRef old_title; | ||
| 3265 | |||
| 3266 | err = CopyMenuTitleAsCFString (menu, &old_title); | ||
| 3267 | if (err == noErr) | ||
| 3268 | { | ||
| 3269 | if (CFStringCompare (title, old_title, 0) != kCFCompareEqualTo) | ||
| 3270 | { | ||
| 3271 | #ifdef MAC_OSX | ||
| 3272 | if (id + 1 == min_menu_id[MAC_MENU_MENU_BAR + 1] | ||
| 3273 | || GetMenuRef (id + 1) == NULL) | ||
| 3274 | { | ||
| 3275 | /* This is a workaround for Mac OS X 10.5 where | ||
| 3276 | just calling SetMenuTitleWithCFString fails | ||
| 3277 | to change the title of the last (Help) menu | ||
| 3278 | in the menu bar. */ | ||
| 3279 | DeleteMenu (id); | ||
| 3280 | DisposeMenu (menu); | ||
| 3281 | menu = NULL; | ||
| 3282 | } | ||
| 3283 | else | ||
| 3284 | #endif /* MAC_OSX */ | ||
| 3285 | err = SetMenuTitleWithCFString (menu, title); | ||
| 3286 | } | ||
| 3287 | CFRelease (old_title); | ||
| 3288 | } | ||
| 3289 | else | ||
| 3290 | err = SetMenuTitleWithCFString (menu, title); | ||
| 3291 | #else /* !TARGET_API_MAC_CARBON */ | ||
| 3292 | if (!EqualString (title, (*menu)->menuData, false, false)) | ||
| 3293 | { | ||
| 3294 | DeleteMenu (id); | ||
| 3295 | DisposeMenu (menu); | ||
| 3296 | menu = NewMenu (id, title); | ||
| 3297 | InsertMenu (menu, GetMenuRef (id + 1) ? id + 1 : 0); | ||
| 3298 | title_changed_p = 1; | ||
| 3299 | } | ||
| 3300 | #endif /* !TARGET_API_MAC_CARBON */ | ||
| 3301 | } | ||
| 3302 | |||
| 3303 | if (!menu) | ||
| 3304 | { | ||
| 3305 | #if TARGET_API_MAC_CARBON | ||
| 3306 | err = CreateNewMenu (id, 0, &menu); | ||
| 3307 | if (err == noErr) | ||
| 3308 | err = SetMenuTitleWithCFString (menu, title); | ||
| 3309 | #else | ||
| 3310 | menu = NewMenu (id, title); | ||
| 3311 | #endif | ||
| 3312 | if (err == noErr) | ||
| 3313 | { | ||
| 3314 | InsertMenu (menu, 0); | ||
| 3315 | #if !TARGET_API_MAC_CARBON | ||
| 3316 | title_changed_p = 1; | ||
| 3317 | #endif | ||
| 3318 | } | ||
| 3319 | } | ||
| 3320 | #if TARGET_API_MAC_CARBON | ||
| 3321 | CFRelease (title); | ||
| 3322 | #endif | ||
| 3323 | |||
| 3324 | if (err == noErr) | ||
| 3325 | if (wv->contents) | ||
| 3326 | submenu_id = fill_menu (menu, wv->contents, MAC_MENU_MENU_BAR_SUB, | ||
| 3327 | submenu_id); | ||
| 3328 | } | ||
| 3329 | |||
| 3330 | if (id < min_menu_id[MAC_MENU_MENU_BAR + 1] && GetMenuRef (id)) | ||
| 3331 | { | ||
| 3332 | dispose_menus (MAC_MENU_MENU_BAR, id); | ||
| 3333 | #if !TARGET_API_MAC_CARBON | ||
| 3334 | title_changed_p = 1; | ||
| 3335 | #endif | ||
| 3336 | } | ||
| 3337 | |||
| 3338 | #if !TARGET_API_MAC_CARBON | ||
| 3339 | if (title_changed_p) | ||
| 3340 | InvalMenuBar (); | ||
| 3341 | #endif | ||
| 3342 | } | ||
| 3343 | |||
| 3344 | /* Dispose of menus that belong to KIND, and remove them from the menu | ||
| 3345 | list. ID is the lower bound of menu IDs that will be processed. */ | ||
| 3346 | |||
| 3347 | static void | ||
| 3348 | dispose_menus (kind, id) | ||
| 3349 | enum mac_menu_kind kind; | ||
| 3350 | int id; | ||
| 3351 | { | ||
| 3352 | for (id = max (id, min_menu_id[kind]); id < min_menu_id[kind + 1]; id++) | ||
| 3353 | { | ||
| 3354 | MenuRef menu = GetMenuRef (id); | ||
| 3355 | |||
| 3356 | if (menu == NULL) | ||
| 3357 | break; | ||
| 3358 | DeleteMenu (id); | ||
| 3359 | DisposeMenu (menu); | ||
| 3360 | } | ||
| 3361 | } | ||
| 3362 | |||
| 3363 | #endif /* HAVE_MENUS */ | 2068 | #endif /* HAVE_MENUS */ |
| 3364 | 2069 | ||
| 3365 | /* Detect if a menu is currently active. */ | 2070 | /* Detect if a menu is currently active. */ |