# HG changeset patch # User YAMAMOTO Mitsuharu # Date 1207447099 0 # Node ID 07666d9ede234f67b9bfa40e50f0edeeca83877f # Parent 6d01fa145e93e3e940c421fafee817fb5abb31c8 [!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. diff -r 6d01fa145e93 -r 07666d9ede23 src/macmenu.c --- a/src/macmenu.c Sun Apr 06 01:58:05 2008 +0000 +++ b/src/macmenu.c Sun Apr 06 01:58:19 2008 +0000 @@ -36,20 +36,6 @@ #include "charset.h" #include "coding.h" -#if !TARGET_API_MAC_CARBON -#include -#include -#include -#include -#include -#include -#include -#include -#if defined (__MRC__) || (__MSL__ >= 0x6000) -#include -#endif -#endif /* not TARGET_API_MAC_CARBON */ - /* This may include sys/types.h, and that somehow loses if this is not done before the other system files. */ #include "macterm.h" @@ -62,21 +48,6 @@ #include "dispextern.h" -enum mac_menu_kind { /* Menu ID range */ - MAC_MENU_APPLE, /* 0 (Reserved by Apple) */ - MAC_MENU_MENU_BAR, /* 1 .. 233 */ - MAC_MENU_M_APPLE, /* 234 (== M_APPLE) */ - MAC_MENU_POPUP, /* 235 */ - MAC_MENU_DRIVER, /* 236 .. 255 (Reserved) */ - MAC_MENU_MENU_BAR_SUB, /* 256 .. 16383 */ - MAC_MENU_POPUP_SUB, /* 16384 .. 32767 */ - MAC_MENU_END /* 32768 */ -}; - -static const int min_menu_id[] = {0, 1, 234, 235, 236, 256, 16384, 32768}; - -#define DIALOG_WINDOW_RESOURCE 130 - #if TARGET_API_MAC_CARBON #define HAVE_DIALOGS 1 #endif @@ -84,69 +55,6 @@ #undef HAVE_MULTILINGUAL_MENU /******************************************************************/ -/* Definitions copied from lwlib.h */ - -typedef void * XtPointer; - -enum button_type -{ - BUTTON_TYPE_NONE, - BUTTON_TYPE_TOGGLE, - BUTTON_TYPE_RADIO -}; - -/* This structure is based on the one in ../lwlib/lwlib.h, modified - for Mac OS. */ -typedef struct _widget_value -{ - /* name of widget */ - Lisp_Object lname; - char* name; - /* value (meaning depend on widget type) */ - char* value; - /* keyboard equivalent. no implications for XtTranslations */ - Lisp_Object lkey; - char* key; - /* Help string or nil if none. - GC finds this string through the frame's menu_bar_vector - or through menu_items. */ - Lisp_Object help; - /* true if enabled */ - Boolean enabled; - /* true if selected */ - Boolean selected; - /* The type of a button. */ - enum button_type button_type; - /* true if menu title */ - Boolean title; -#if 0 - /* true if was edited (maintained by get_value) */ - Boolean edited; - /* true if has changed (maintained by lw library) */ - change_type change; - /* true if this widget itself has changed, - but not counting the other widgets found in the `next' field. */ - change_type this_one_change; -#endif - /* Contents of the sub-widgets, also selected slot for checkbox */ - struct _widget_value* contents; - /* data passed to callback */ - XtPointer call_data; - /* next one in the list */ - struct _widget_value* next; -#if 0 - /* slot for the toolkit dependent part. Always initialize to NULL. */ - void* toolkit_data; - /* tell us if we should free the toolkit data slot when freeing the - widget_value itself. */ - Boolean free_toolkit_data; - - /* we resource the widget_value structures; this points to the next - one on the free list if this one has been deallocated. - */ - struct _widget_value *free_list; -#endif -} widget_value; /* Assumed by other routines to zero area returned. */ #define malloc_widget_value() (void *)memset (xmalloc (sizeof (widget_value)),\ @@ -198,12 +106,6 @@ static void list_of_panes P_ ((Lisp_Object)); static void list_of_items P_ ((Lisp_Object)); -static void find_and_call_menu_selection P_ ((FRAME_PTR, int, Lisp_Object, - void *)); -static int fill_menu P_ ((MenuRef, widget_value *, enum mac_menu_kind, int)); -static void fill_menubar P_ ((widget_value *, int)); -static void dispose_menus P_ ((enum mac_menu_kind, int)); - /* This holds a Lisp vector that holds the results of decoding the keymaps or alist-of-alists that specify a menu. @@ -260,7 +162,7 @@ static int menu_items_submenu_depth; /* Nonzero means a menu is currently active. */ -static int popup_activated_flag; +int popup_activated_flag; /* This is set nonzero after the user activates the menu bar, and set to zero again after the menu bars are redisplayed by prepare_menu_bar. @@ -880,32 +782,6 @@ #ifdef HAVE_MENUS -/* Regard ESC and C-g as Cancel even without the Cancel button. */ - -#if 0 /* defined (MAC_OSX) */ -static Boolean -mac_dialog_modal_filter (dialog, event, item_hit) - DialogRef dialog; - EventRecord *event; - DialogItemIndex *item_hit; -{ - Boolean result; - - result = StdFilterProc (dialog, event, item_hit); - if (result == false - && (event->what == keyDown || event->what == autoKey) - && ((event->message & charCodeMask) == kEscapeCharCode - || mac_quit_char_key_p (event->modifiers, - (event->message & keyCodeMask) >> 8))) - { - *item_hit = kStdCancelItemIndex; - return true; - } - - return result; -} -#endif - DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0, doc: /* Pop up a dialog box and return user's selection. POSITION specifies which frame to use. @@ -991,101 +867,6 @@ but I don't want to make one now. */ CHECK_WINDOW (window); -#if 0 /* defined (MAC_OSX) */ - /* Special treatment for Fmessage_box, Fyes_or_no_p, and Fy_or_n_p. */ - if (EQ (position, Qt) - && STRINGP (Fcar (contents)) - && ((!NILP (Fequal (XCDR (contents), - Fcons (Fcons (build_string ("OK"), Qt), Qnil))) - && EQ (header, Qt)) - || (!NILP (Fequal (XCDR (contents), - Fcons (Fcons (build_string ("Yes"), Qt), - Fcons (Fcons (build_string ("No"), Qnil), - Qnil)))) - && NILP (header)))) - { - OSStatus err = noErr; - AlertStdCFStringAlertParamRec param; - CFStringRef error_string, explanation_string; - DialogRef alert; - DialogItemIndex item_hit; - Lisp_Object tem; - - /* Force a redisplay before showing the dialog. If a frame is - created just before showing the dialog, its contents may not - have been fully drawn. */ - Fredisplay (Qt); - - tem = Fstring_match (concat3 (build_string ("\\("), - call0 (intern ("sentence-end")), - build_string ("\\)\n")), - XCAR (contents), Qnil); - BLOCK_INPUT; - if (NILP (tem)) - { - error_string = cfstring_create_with_string (XCAR (contents)); - if (error_string == NULL) - err = memFullErr; - explanation_string = NULL; - } - else - { - tem = Fmatch_end (make_number (1)); - error_string = - cfstring_create_with_string (Fsubstring (XCAR (contents), - make_number (0), tem)); - if (error_string == NULL) - err = memFullErr; - else - { - XSETINT (tem, XINT (tem) + 1); - explanation_string = - cfstring_create_with_string (Fsubstring (XCAR (contents), - tem, Qnil)); - if (explanation_string == NULL) - { - CFRelease (error_string); - err = memFullErr; - } - } - } - if (err == noErr) - err = GetStandardAlertDefaultParams (¶m, - kStdCFStringAlertVersionOne); - if (err == noErr) - { - param.movable = true; - param.position = kWindowAlertPositionParentWindow; - if (NILP (header)) - { - param.defaultText = CFSTR ("Yes"); - param.otherText = CFSTR ("No"); -#if 0 - param.cancelText = CFSTR ("Cancel"); - param.cancelButton = kAlertStdAlertCancelButton; -#endif - } - err = CreateStandardAlert (kAlertNoteAlert, error_string, - explanation_string, ¶m, &alert); - CFRelease (error_string); - if (explanation_string) - CFRelease (explanation_string); - } - if (err == noErr) - err = RunStandardAlert (alert, mac_dialog_modal_filter, &item_hit); - UNBLOCK_INPUT; - - if (err == noErr) - { - if (item_hit == kStdCancelItemIndex) - Fsignal (Qquit, Qnil); - else if (item_hit == kStdOkItemIndex) - return Qt; - else - return Qnil; - } - } -#endif #ifndef HAVE_DIALOGS /* Display a menu with these alternatives in the middle of frame F. */ @@ -1125,66 +906,12 @@ #endif /* HAVE_DIALOGS */ } -/* Activate the menu bar of frame F. - This is called from keyboard.c when it gets the - MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue. - - To activate the menu bar, we use the button-press event location - that was saved in saved_menu_event_location. - - But first we recompute the menu bar contents (the whole tree). - - The reason for saving the button event until here, instead of - passing it to the toolkit right away, is that we can safely - execute Lisp code. */ - -void -x_activate_menubar (f) - FRAME_PTR f; -{ - SInt32 menu_choice; - SInt16 menu_id, menu_item; - extern Point saved_menu_event_location; - - set_frame_menubar (f, 0, 1); - BLOCK_INPUT; - - popup_activated_flag = 1; - menu_choice = MenuSelect (saved_menu_event_location); - popup_activated_flag = 0; - menu_id = HiWord (menu_choice); - menu_item = LoWord (menu_choice); - -#if !TARGET_API_MAC_CARBON - if (menu_id == min_menu_id[MAC_MENU_M_APPLE]) - do_apple_menu (menu_item); - else -#endif - if (menu_id) - { - MenuRef menu = GetMenuRef (menu_id); - - if (menu) - { - UInt32 refcon; - - GetMenuItemRefCon (menu, menu_item, &refcon); - find_and_call_menu_selection (f, f->menu_bar_items_used, - f->menu_bar_vector, (void *) refcon); - } - } - - HiliteMenu (0); - - UNBLOCK_INPUT; -} - /* Find the menu selection and store it in the keyboard buffer. F is the frame the menu is on. MENU_BAR_ITEMS_USED is the length of VECTOR. VECTOR is an array of menu events for the whole menu. */ -static void +void find_and_call_menu_selection (f, menu_bar_items_used, vector, client_data) FRAME_PTR f; int menu_bar_items_used; @@ -1577,141 +1304,6 @@ } -#if TARGET_API_MAC_CARBON -extern Lisp_Object Vshow_help_function; - -static Lisp_Object -restore_show_help_function (old_show_help_function) - Lisp_Object old_show_help_function; -{ - Vshow_help_function = old_show_help_function; - - return Qnil; -} - -static pascal OSStatus -menu_target_item_handler (next_handler, event, data) - EventHandlerCallRef next_handler; - EventRef event; - void *data; -{ - OSStatus err; - MenuRef menu; - MenuItemIndex menu_item; - Lisp_Object help; - GrafPtr port; - int specpdl_count = SPECPDL_INDEX (); - - /* Don't be bothered with the overflowed toolbar items menu. */ - if (!popup_activated ()) - return eventNotHandledErr; - - err = GetEventParameter (event, kEventParamDirectObject, typeMenuRef, - NULL, sizeof (MenuRef), NULL, &menu); - if (err == noErr) - err = GetEventParameter (event, kEventParamMenuItemIndex, - typeMenuItemIndex, NULL, - sizeof (MenuItemIndex), NULL, &menu_item); - if (err == noErr) - err = GetMenuItemProperty (menu, menu_item, - MAC_EMACS_CREATOR_CODE, 'help', - sizeof (Lisp_Object), NULL, &help); - if (err != noErr) - help = Qnil; - - /* Temporarily bind Vshow_help_function to Qnil because we don't - want tooltips during menu tracking. */ - record_unwind_protect (restore_show_help_function, Vshow_help_function); - Vshow_help_function = Qnil; - GetPort (&port); - show_help_echo (help, Qnil, Qnil, Qnil, 1); - SetPort (port); - unbind_to (specpdl_count, Qnil); - - return err == noErr ? noErr : eventNotHandledErr; -} - -OSStatus -install_menu_target_item_handler () -{ - static const EventTypeSpec specs[] = - {{kEventClassMenu, kEventMenuTargetItem}}; - - return InstallApplicationEventHandler (NewEventHandlerUPP - (menu_target_item_handler), - GetEventTypeCount (specs), - specs, NULL, NULL); -} -#endif /* TARGET_API_MAC_CARBON */ - -/* Event handler function that pops down a menu on C-g. We can only pop - down menus if CancelMenuTracking is present (OSX 10.3 or later). */ - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 -static pascal OSStatus -menu_quit_handler (nextHandler, theEvent, userData) - EventHandlerCallRef nextHandler; - EventRef theEvent; - void* userData; -{ - OSStatus err; - UInt32 keyCode; - UInt32 keyModifiers; - - err = GetEventParameter (theEvent, kEventParamKeyCode, - typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode); - - if (err == noErr) - err = GetEventParameter (theEvent, kEventParamKeyModifiers, - typeUInt32, NULL, sizeof(UInt32), - NULL, &keyModifiers); - - if (err == noErr && mac_quit_char_key_p (keyModifiers, keyCode)) - { - MenuRef menu = userData != 0 - ? (MenuRef)userData : AcquireRootMenu (); - - CancelMenuTracking (menu, true, 0); - if (!userData) ReleaseMenu (menu); - return noErr; - } - - return CallNextEventHandler (nextHandler, theEvent); -} -#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */ - -/* Add event handler to all menus that belong to KIND so we can detect - C-g. ROOT_MENU is the root menu of the tracking session to dismiss - when C-g is detected. NULL means the menu bar. If - CancelMenuTracking isn't available, do nothing. */ - -static void -install_menu_quit_handler (kind, root_menu) - enum mac_menu_kind kind; - MenuRef root_menu; -{ -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 - static const EventTypeSpec typesList[] = - {{kEventClassKeyboard, kEventRawKeyDown}}; - int id; - -#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020 - if (CancelMenuTracking == NULL) - return; -#endif - for (id = min_menu_id[kind]; id < min_menu_id[kind + 1]; id++) - { - MenuRef menu = GetMenuRef (id); - - if (menu == NULL) - break; - InstallMenuEventHandler (menu, menu_quit_handler, - GetEventTypeCount (typesList), - typesList, root_menu, NULL); - } -#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */ -} - /* Set the contents of the menubar widgets of frame F. The argument FIRST_TIME is currently ignored; it is set the first time this is called, from initialize_frame_menubar. */ @@ -1947,11 +1539,8 @@ /* Non-null value to indicate menubar has already been "created". */ f->output_data.mac->menubar_widget = 1; - fill_menubar (first_wv->contents, deep_p); + mac_fill_menubar (first_wv->contents, deep_p); - /* Add event handler so we can detect C-g. */ - install_menu_quit_handler (MAC_MENU_MENU_BAR, NULL); - install_menu_quit_handler (MAC_MENU_MENU_BAR_SUB, NULL); free_menubar_widget_value_tree (first_wv); UNBLOCK_INPUT; @@ -1968,29 +1557,8 @@ } -static Lisp_Object -pop_down_menu (arg) - Lisp_Object arg; -{ - struct Lisp_Save_Value *p = XSAVE_VALUE (arg); - FRAME_PTR f = p->pointer; - MenuRef menu = GetMenuRef (min_menu_id[MAC_MENU_POPUP]); - - BLOCK_INPUT; - - /* Must reset this manually because the button release event is not - passed to Emacs event loop. */ - FRAME_MAC_DISPLAY_INFO (f)->grabbed = 0; - - /* delete all menus */ - dispose_menus (MAC_MENU_POPUP_SUB, 0); - DeleteMenu (min_menu_id[MAC_MENU_POPUP]); - DisposeMenu (menu); - - UNBLOCK_INPUT; - - return Qnil; -} +/* The item selected in the popup menu. */ +int menu_item_selection; /* Mac_menu_show actually displays a menu using the panes and items in menu_items and returns the value selected from it; we assume input @@ -2018,9 +1586,6 @@ char **error; { int i; - int menu_item_choice; - UInt32 menu_item_selection; - MenuRef menu; widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; widget_value **submenu_stack = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); @@ -2029,7 +1594,6 @@ int submenu_depth = 0; int first_pane; - int specpdl_count = SPECPDL_INDEX (); *error = NULL; @@ -2215,45 +1779,14 @@ first_wv->contents = wv_title; } - /* Actually create the menu. */ - menu = NewMenu (min_menu_id[MAC_MENU_POPUP], "\p"); - InsertMenu (menu, -1); - fill_menu (menu, first_wv->contents, MAC_MENU_POPUP_SUB, - min_menu_id[MAC_MENU_POPUP_SUB]); - - /* Free the widget_value objects we used to specify the - contents. */ - free_menubar_widget_value_tree (first_wv); - - /* Adjust coordinates to be root-window-relative. */ - x += f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f); - y += f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f); - /* No selection has been chosen yet. */ menu_item_selection = 0; - record_unwind_protect (pop_down_menu, make_save_value (f, 0)); - - /* Add event handler so we can detect C-g. */ - install_menu_quit_handler (MAC_MENU_POPUP, menu); - install_menu_quit_handler (MAC_MENU_POPUP_SUB, menu); - - /* Display the menu. */ - popup_activated_flag = 1; - menu_item_choice = PopUpMenuSelect (menu, y, x, 0); - popup_activated_flag = 0; + /* Actually create and show the menu until popped down. */ + create_and_show_popup_menu (f, first_wv, x, y, for_click); - /* Get the refcon to find the correct item */ - if (menu_item_choice) - { - MenuRef sel_menu = GetMenuRef (HiWord (menu_item_choice)); - - if (sel_menu) - GetMenuItemRefCon (sel_menu, LoWord (menu_item_choice), - &menu_item_selection); - } - - unbind_to (specpdl_count, Qnil); + /* Free the widget_value objects we used to specify the contents. */ + free_menubar_widget_value_tree (first_wv); /* Find the selected item, and its pane, to return the proper value. */ @@ -2320,582 +1853,6 @@ #ifdef HAVE_DIALOGS /* Construct native Mac OS dialog based on widget_value tree. */ -#if TARGET_API_MAC_CARBON - -#define DIALOG_BUTTON_COMMAND_ID_OFFSET 'Bt\0\0' -#define DIALOG_BUTTON_COMMAND_ID_P(id) \ - (((id) & ~0xffff) == DIALOG_BUTTON_COMMAND_ID_OFFSET) -#define DIALOG_BUTTON_COMMAND_ID_VALUE(id) \ - ((id) - DIALOG_BUTTON_COMMAND_ID_OFFSET) -#define DIALOG_BUTTON_MAKE_COMMAND_ID(value) \ - ((value) + DIALOG_BUTTON_COMMAND_ID_OFFSET) - -extern EMACS_TIME timer_check P_ ((int)); -static int quit_dialog_event_loop; - -static pascal OSStatus -mac_handle_dialog_event (next_handler, event, data) - EventHandlerCallRef next_handler; - EventRef event; - void *data; -{ - OSStatus err, result = eventNotHandledErr; - WindowRef window = (WindowRef) data; - - switch (GetEventClass (event)) - { - case kEventClassCommand: - { - HICommand command; - - err = GetEventParameter (event, kEventParamDirectObject, - typeHICommand, NULL, sizeof (HICommand), - NULL, &command); - if (err == noErr) - if (DIALOG_BUTTON_COMMAND_ID_P (command.commandID)) - { - SetWRefCon (window, command.commandID); - quit_dialog_event_loop = 1; - break; - } - - result = CallNextEventHandler (next_handler, event); - } - break; - - case kEventClassKeyboard: - { - OSStatus result; - char char_code; - - result = CallNextEventHandler (next_handler, event); - if (result != eventNotHandledErr) - break; - - err = GetEventParameter (event, kEventParamKeyMacCharCodes, - typeChar, NULL, sizeof (char), - NULL, &char_code); - if (err == noErr) - switch (char_code) - { - case kEscapeCharCode: - quit_dialog_event_loop = 1; - break; - - default: - { - UInt32 modifiers, key_code; - - err = GetEventParameter (event, kEventParamKeyModifiers, - typeUInt32, NULL, sizeof (UInt32), - NULL, &modifiers); - if (err == noErr) - err = GetEventParameter (event, kEventParamKeyCode, - typeUInt32, NULL, sizeof (UInt32), - NULL, &key_code); - if (err == noErr) - if (mac_quit_char_key_p (modifiers, key_code)) - quit_dialog_event_loop = 1; - } - break; - } - } - break; - - default: - abort (); - } - - if (quit_dialog_event_loop) - { - err = QuitEventLoop (GetCurrentEventLoop ()); - if (err == noErr) - result = noErr; - } - - return result; -} - -static OSStatus -install_dialog_event_handler (window) - WindowRef window; -{ - static const EventTypeSpec specs[] = - {{kEventClassCommand, kEventCommandProcess}, - {kEventClassKeyboard, kEventRawKeyDown}}; - static EventHandlerUPP handle_dialog_eventUPP = NULL; - - if (handle_dialog_eventUPP == NULL) - handle_dialog_eventUPP = NewEventHandlerUPP (mac_handle_dialog_event); - return InstallWindowEventHandler (window, handle_dialog_eventUPP, - GetEventTypeCount (specs), specs, - window, NULL); -} - -#define DIALOG_LEFT_MARGIN (112) -#define DIALOG_TOP_MARGIN (24) -#define DIALOG_RIGHT_MARGIN (24) -#define DIALOG_BOTTOM_MARGIN (20) -#define DIALOG_MIN_INNER_WIDTH (338) -#define DIALOG_MAX_INNER_WIDTH (564) -#define DIALOG_BUTTON_BUTTON_HORIZONTAL_SPACE (12) -#define DIALOG_BUTTON_BUTTON_VERTICAL_SPACE (12) -#define DIALOG_BUTTON_MIN_WIDTH (68) -#define DIALOG_TEXT_MIN_HEIGHT (50) -#define DIALOG_TEXT_BUTTONS_VERTICAL_SPACE (10) -#define DIALOG_ICON_WIDTH (64) -#define DIALOG_ICON_HEIGHT (64) -#define DIALOG_ICON_LEFT_MARGIN (24) -#define DIALOG_ICON_TOP_MARGIN (15) - -static Lisp_Object -pop_down_dialog (arg) - Lisp_Object arg; -{ - struct Lisp_Save_Value *p = XSAVE_VALUE (arg); - WindowRef window = p->pointer; - - BLOCK_INPUT; - - if (popup_activated_flag) - EndAppModalStateForWindow (window); - DisposeWindow (window); - popup_activated_flag = 0; - - UNBLOCK_INPUT; - - return Qnil; -} - -static int -create_and_show_dialog (f, first_wv) - FRAME_PTR f; - widget_value *first_wv; -{ - OSStatus err; - char *dialog_name, *message; - int nb_buttons, first_group_count, i, result = 0; - widget_value *wv; - short buttons_height, text_height, inner_width, inner_height; - Rect empty_rect, *rects; - WindowRef window = NULL; - ControlRef *buttons, default_button = NULL, text; - int specpdl_count = SPECPDL_INDEX (); - - dialog_name = first_wv->name; - nb_buttons = dialog_name[1] - '0'; - first_group_count = nb_buttons - (dialog_name[4] - '0'); - - wv = first_wv->contents; - message = wv->value; - - wv = wv->next; - SetRect (&empty_rect, 0, 0, 0, 0); - - /* Create dialog window. */ - err = CreateNewWindow (kMovableModalWindowClass, - kWindowStandardHandlerAttribute, - &empty_rect, &window); - if (err == noErr) - { - record_unwind_protect (pop_down_dialog, make_save_value (window, 0)); - err = SetThemeWindowBackground (window, kThemeBrushMovableModalBackground, - true); - } - if (err == noErr) - err = SetWindowTitleWithCFString (window, (dialog_name[0] == 'Q' - ? CFSTR ("Question") - : CFSTR ("Information"))); - - /* Create button controls and measure their optimal bounds. */ - if (err == noErr) - { - buttons = alloca (sizeof (ControlRef) * nb_buttons); - rects = alloca (sizeof (Rect) * nb_buttons); - for (i = 0; i < nb_buttons; i++) - { - CFStringRef label = cfstring_create_with_utf8_cstring (wv->value); - - if (label == NULL) - err = memFullErr; - else - { - err = CreatePushButtonControl (window, &empty_rect, - label, &buttons[i]); - CFRelease (label); - } - if (err == noErr) - { - if (!wv->enabled) - { -#ifdef MAC_OSX - err = DisableControl (buttons[i]); -#else - err = DeactivateControl (buttons[i]); -#endif - } - else if (default_button == NULL) - default_button = buttons[i]; - } - if (err == noErr) - { - SInt16 unused; - - rects[i] = empty_rect; - err = GetBestControlRect (buttons[i], &rects[i], &unused); - } - if (err == noErr) - { - UInt32 command_id; - - OffsetRect (&rects[i], -rects[i].left, -rects[i].top); - if (rects[i].right < DIALOG_BUTTON_MIN_WIDTH) - rects[i].right = DIALOG_BUTTON_MIN_WIDTH; - else if (rects[i].right > DIALOG_MAX_INNER_WIDTH) - rects[i].right = DIALOG_MAX_INNER_WIDTH; - - command_id = DIALOG_BUTTON_MAKE_COMMAND_ID ((int) wv->call_data); - err = SetControlCommandID (buttons[i], command_id); - } - if (err != noErr) - break; - wv = wv->next; - } - } - - /* Layout buttons. rects[i] is set relative to the bottom-right - corner of the inner box. */ - if (err == noErr) - { - short bottom, right, max_height, left_align_shift; - - inner_width = DIALOG_MIN_INNER_WIDTH; - bottom = right = max_height = 0; - for (i = 0; i < nb_buttons; i++) - { - if (right - rects[i].right < - inner_width) - { - if (i != first_group_count - && right - rects[i].right >= - DIALOG_MAX_INNER_WIDTH) - inner_width = - (right - rects[i].right); - else - { - bottom -= max_height + DIALOG_BUTTON_BUTTON_VERTICAL_SPACE; - right = max_height = 0; - } - } - if (max_height < rects[i].bottom) - max_height = rects[i].bottom; - OffsetRect (&rects[i], right - rects[i].right, - bottom - rects[i].bottom); - right = rects[i].left - DIALOG_BUTTON_BUTTON_HORIZONTAL_SPACE; - if (i == first_group_count - 1) - right -= DIALOG_BUTTON_BUTTON_HORIZONTAL_SPACE; - } - buttons_height = - (bottom - max_height); - - left_align_shift = - (inner_width + rects[nb_buttons - 1].left); - for (i = nb_buttons - 1; i >= first_group_count; i--) - { - if (bottom != rects[i].bottom) - { - left_align_shift = - (inner_width + rects[i].left); - bottom = rects[i].bottom; - } - OffsetRect (&rects[i], left_align_shift, 0); - } - } - - /* Create a static text control and measure its bounds. */ - if (err == noErr) - { - CFStringRef message_string; - Rect bounds; - - message_string = cfstring_create_with_utf8_cstring (message); - if (message_string == NULL) - err = memFullErr; - else - { - ControlFontStyleRec text_style; - - text_style.flags = 0; - SetRect (&bounds, 0, 0, inner_width, 0); - err = CreateStaticTextControl (window, &bounds, message_string, - &text_style, &text); - CFRelease (message_string); - } - if (err == noErr) - { - SInt16 unused; - - bounds = empty_rect; - err = GetBestControlRect (text, &bounds, &unused); - } - if (err == noErr) - { - text_height = bounds.bottom - bounds.top; - if (text_height < DIALOG_TEXT_MIN_HEIGHT) - text_height = DIALOG_TEXT_MIN_HEIGHT; - } - } - - /* Place buttons. */ - if (err == noErr) - { - inner_height = (text_height + DIALOG_TEXT_BUTTONS_VERTICAL_SPACE - + buttons_height); - - for (i = 0; i < nb_buttons; i++) - { - OffsetRect (&rects[i], DIALOG_LEFT_MARGIN + inner_width, - DIALOG_TOP_MARGIN + inner_height); - SetControlBounds (buttons[i], &rects[i]); - } - } - - /* Place text. */ - if (err == noErr) - { - Rect bounds; - - SetRect (&bounds, DIALOG_LEFT_MARGIN, DIALOG_TOP_MARGIN, - DIALOG_LEFT_MARGIN + inner_width, - DIALOG_TOP_MARGIN + text_height); - SetControlBounds (text, &bounds); - } - - /* Create the application icon at the upper-left corner. */ - if (err == noErr) - { - ControlButtonContentInfo content; - ControlRef icon; - static const ProcessSerialNumber psn = {0, kCurrentProcess}; -#ifdef MAC_OSX - FSRef app_location; -#else - ProcessInfoRec pinfo; - FSSpec app_spec; -#endif - SInt16 unused; - - content.contentType = kControlContentIconRef; -#ifdef MAC_OSX - err = GetProcessBundleLocation (&psn, &app_location); - if (err == noErr) - err = GetIconRefFromFileInfo (&app_location, 0, NULL, 0, NULL, - kIconServicesNormalUsageFlag, - &content.u.iconRef, &unused); -#else - bzero (&pinfo, sizeof (ProcessInfoRec)); - pinfo.processInfoLength = sizeof (ProcessInfoRec); - pinfo.processAppSpec = &app_spec; - err = GetProcessInformation (&psn, &pinfo); - if (err == noErr) - err = GetIconRefFromFile (&app_spec, &content.u.iconRef, &unused); -#endif - if (err == noErr) - { - Rect bounds; - - SetRect (&bounds, DIALOG_ICON_LEFT_MARGIN, DIALOG_ICON_TOP_MARGIN, - DIALOG_ICON_LEFT_MARGIN + DIALOG_ICON_WIDTH, - DIALOG_ICON_TOP_MARGIN + DIALOG_ICON_HEIGHT); - err = CreateIconControl (window, &bounds, &content, true, &icon); - ReleaseIconRef (content.u.iconRef); - } - } - - /* Show the dialog window and run event loop. */ - if (err == noErr) - if (default_button) - err = SetWindowDefaultButton (window, default_button); - if (err == noErr) - err = install_dialog_event_handler (window); - if (err == noErr) - { - SizeWindow (window, - DIALOG_LEFT_MARGIN + inner_width + DIALOG_RIGHT_MARGIN, - DIALOG_TOP_MARGIN + inner_height + DIALOG_BOTTOM_MARGIN, - true); - err = RepositionWindow (window, FRAME_MAC_WINDOW (f), - kWindowAlertPositionOnParentWindow); - } - if (err == noErr) - { - SetWRefCon (window, 0); - ShowWindow (window); - BringToFront (window); - popup_activated_flag = 1; - err = BeginAppModalStateForWindow (window); - } - if (err == noErr) - { - EventTargetRef toolbox_dispatcher = GetEventDispatcherTarget (); - - quit_dialog_event_loop = 0; - while (1) - { - EMACS_TIME next_time = timer_check (1); - long secs = EMACS_SECS (next_time); - long usecs = EMACS_USECS (next_time); - EventTimeout timeout; - EventRef event; - - if (secs < 0 || (secs == 0 && usecs == 0)) - { - /* Sometimes timer_check returns -1 (no timers) even if - there are timers. So do a timeout anyway. */ - secs = 1; - usecs = 0; - } - - timeout = (secs * kEventDurationSecond - + usecs * kEventDurationMicrosecond); - err = ReceiveNextEvent (0, NULL, timeout, kEventRemoveFromQueue, - &event); - if (err == noErr) - { - SendEventToEventTarget (event, toolbox_dispatcher); - ReleaseEvent (event); - } -#if 0 /* defined (MAC_OSX) */ - else if (err != eventLoopTimedOutErr) - { - if (err == eventLoopQuitErr) - err = noErr; - break; - } -#else - /* The return value of ReceiveNextEvent seems to be - unreliable. Use our own global variable instead. */ - if (quit_dialog_event_loop) - { - err = noErr; - break; - } -#endif - } - } - if (err == noErr) - { - UInt32 command_id = GetWRefCon (window); - - if (DIALOG_BUTTON_COMMAND_ID_P (command_id)) - result = DIALOG_BUTTON_COMMAND_ID_VALUE (command_id); - } - - unbind_to (specpdl_count, Qnil); - - return result; -} -#else /* not TARGET_API_MAC_CARBON */ -static int -mac_dialog (widget_value *wv) -{ - char *dialog_name; - char *prompt; - char **button_labels; - UInt32 *ref_cons; - int nb_buttons; - int left_count; - int i; - int dialog_width; - Rect rect; - WindowRef window_ptr; - ControlRef ch; - int left; - EventRecord event_record; - SInt16 part_code; - int control_part_code; - Point mouse; - - dialog_name = wv->name; - nb_buttons = dialog_name[1] - '0'; - left_count = nb_buttons - (dialog_name[4] - '0'); - button_labels = (char **) alloca (sizeof (char *) * nb_buttons); - ref_cons = (UInt32 *) alloca (sizeof (UInt32) * nb_buttons); - - wv = wv->contents; - prompt = (char *) alloca (strlen (wv->value) + 1); - strcpy (prompt, wv->value); - c2pstr (prompt); - - wv = wv->next; - for (i = 0; i < nb_buttons; i++) - { - button_labels[i] = wv->value; - button_labels[i] = (char *) alloca (strlen (wv->value) + 1); - strcpy (button_labels[i], wv->value); - c2pstr (button_labels[i]); - ref_cons[i] = (UInt32) wv->call_data; - wv = wv->next; - } - - window_ptr = GetNewCWindow (DIALOG_WINDOW_RESOURCE, NULL, (WindowRef) -1); - - SetPortWindowPort (window_ptr); - - TextFont (0); - /* Left and right margins in the dialog are 13 pixels each.*/ - dialog_width = 14; - /* Calculate width of dialog box: 8 pixels on each side of the text - label in each button, 12 pixels between buttons. */ - for (i = 0; i < nb_buttons; i++) - dialog_width += StringWidth (button_labels[i]) + 16 + 12; - - if (left_count != 0 && nb_buttons - left_count != 0) - dialog_width += 12; - - dialog_width = max (dialog_width, StringWidth (prompt) + 26); - - SizeWindow (window_ptr, dialog_width, 78, 0); - ShowWindow (window_ptr); - - SetPortWindowPort (window_ptr); - - TextFont (0); - - MoveTo (13, 29); - DrawString (prompt); - - left = 13; - for (i = 0; i < nb_buttons; i++) - { - int button_width = StringWidth (button_labels[i]) + 16; - SetRect (&rect, left, 45, left + button_width, 65); - ch = NewControl (window_ptr, &rect, button_labels[i], 1, 0, 0, 0, - kControlPushButtonProc, ref_cons[i]); - left += button_width + 12; - if (i == left_count - 1) - left += 12; - } - - i = 0; - while (!i) - { - if (WaitNextEvent (mDownMask, &event_record, 10, NULL)) - if (event_record.what == mouseDown) - { - part_code = FindWindow (event_record.where, &window_ptr); - if (part_code == inContent) - { - mouse = event_record.where; - GlobalToLocal (&mouse); - control_part_code = FindControl (mouse, window_ptr, &ch); - if (control_part_code == kControlButtonPart) - if (TrackControl (ch, mouse, NULL)) - i = GetControlReference (ch); - } - } - } - - DisposeWindow (window_ptr); - - return i; -} -#endif /* not TARGET_API_MAC_CARBON */ - static char * button_names [] = { "button1", "button2", "button3", "button4", "button5", "button6", "button7", "button8", "button9", "button10" }; @@ -2909,7 +1866,6 @@ { int i, nb_buttons=0; char dialog_name[6]; - int menu_item_selection; widget_value *wv, *first_wv = 0, *prev_wv = 0; @@ -3026,6 +1982,9 @@ first_wv = wv; } + /* No selection has been chosen yet. */ + menu_item_selection = 0; + /* Force a redisplay before showing the dialog. If a frame is created just before showing the dialog, its contents may not have been fully drawn. */ @@ -3033,7 +1992,7 @@ /* Actually create the dialog. */ #if TARGET_API_MAC_CARBON - menu_item_selection = create_and_show_dialog (f, first_wv); + create_and_show_dialog (f, first_wv); #else menu_item_selection = mac_dialog (first_wv); #endif @@ -3093,7 +2052,7 @@ /* Is this item a separator? */ -static int +int name_is_separator (name) const char *name; { @@ -3106,260 +2065,6 @@ them like normal separators. */ return (*name == '\0' || start + 2 == name); } - -static void -add_menu_item (menu, pos, wv) - MenuRef menu; - int pos; - widget_value *wv; -{ -#if TARGET_API_MAC_CARBON - CFStringRef item_name; -#else - Str255 item_name; -#endif - - if (name_is_separator (wv->name)) - AppendMenu (menu, "\p-"); - else - { - AppendMenu (menu, "\pX"); - -#if TARGET_API_MAC_CARBON - item_name = cfstring_create_with_utf8_cstring (wv->name); - - if (wv->key != NULL) - { - CFStringRef name, key; - - name = item_name; - key = cfstring_create_with_utf8_cstring (wv->key); - item_name = CFStringCreateWithFormat (NULL, NULL, CFSTR ("%@ %@"), - name, key); - CFRelease (name); - CFRelease (key); - } - - SetMenuItemTextWithCFString (menu, pos, item_name); - CFRelease (item_name); - - if (wv->enabled) - EnableMenuItem (menu, pos); - else - DisableMenuItem (menu, pos); - - if (STRINGP (wv->help)) - SetMenuItemProperty (menu, pos, MAC_EMACS_CREATOR_CODE, 'help', - sizeof (Lisp_Object), &wv->help); -#else /* ! TARGET_API_MAC_CARBON */ - item_name[sizeof (item_name) - 1] = '\0'; - strncpy (item_name, wv->name, sizeof (item_name) - 1); - if (wv->key != NULL) - { - int len = strlen (item_name); - - strncpy (item_name + len, " ", sizeof (item_name) - 1 - len); - len = strlen (item_name); - strncpy (item_name + len, wv->key, sizeof (item_name) - 1 - len); - } - c2pstr (item_name); - SetMenuItemText (menu, pos, item_name); - - if (wv->enabled) - EnableItem (menu, pos); - else - DisableItem (menu, pos); -#endif /* ! TARGET_API_MAC_CARBON */ - - /* Draw radio buttons and tickboxes. */ - if (wv->selected && (wv->button_type == BUTTON_TYPE_TOGGLE || - wv->button_type == BUTTON_TYPE_RADIO)) - SetItemMark (menu, pos, checkMark); - else - SetItemMark (menu, pos, noMark); - - SetMenuItemRefCon (menu, pos, (UInt32) wv->call_data); - } -} - -/* Construct native Mac OS menu based on widget_value tree. */ - -static int -fill_menu (menu, wv, kind, submenu_id) - MenuRef menu; - widget_value *wv; - enum mac_menu_kind kind; - int submenu_id; -{ - int pos; - - for (pos = 1; wv != NULL; wv = wv->next, pos++) - { - add_menu_item (menu, pos, wv); - if (wv->contents && submenu_id < min_menu_id[kind + 1]) - { - MenuRef submenu = NewMenu (submenu_id, "\pX"); - - InsertMenu (submenu, -1); -#if TARGET_API_MAC_CARBON - SetMenuItemHierarchicalMenu (menu, pos, submenu); -#else - SetMenuItemHierarchicalID (menu, pos, submenu_id); -#endif - submenu_id = fill_menu (submenu, wv->contents, kind, submenu_id + 1); - } - } - - return submenu_id; -} - -/* Construct native Mac OS menubar based on widget_value tree. */ - -static void -fill_menubar (wv, deep_p) - widget_value *wv; - int deep_p; -{ - int id, submenu_id; -#if !TARGET_API_MAC_CARBON - int title_changed_p = 0; -#endif - - /* Clean up the menu bar when filled by the entire menu trees. */ - if (deep_p) - { - dispose_menus (MAC_MENU_MENU_BAR, 0); - dispose_menus (MAC_MENU_MENU_BAR_SUB, 0); -#if !TARGET_API_MAC_CARBON - title_changed_p = 1; -#endif - } - - /* Fill menu bar titles and submenus. Reuse the existing menu bar - titles as much as possible to minimize redraw (if !deep_p). */ - submenu_id = min_menu_id[MAC_MENU_MENU_BAR_SUB]; - for (id = min_menu_id[MAC_MENU_MENU_BAR]; - wv != NULL && id < min_menu_id[MAC_MENU_MENU_BAR + 1]; - wv = wv->next, id++) - { - OSStatus err = noErr; - MenuRef menu; -#if TARGET_API_MAC_CARBON - CFStringRef title; - - title = CFStringCreateWithCString (NULL, wv->name, - kCFStringEncodingMacRoman); -#else - Str255 title; - - strncpy (title, wv->name, 255); - title[255] = '\0'; - c2pstr (title); -#endif - - menu = GetMenuRef (id); - if (menu) - { -#if TARGET_API_MAC_CARBON - CFStringRef old_title; - - err = CopyMenuTitleAsCFString (menu, &old_title); - if (err == noErr) - { - if (CFStringCompare (title, old_title, 0) != kCFCompareEqualTo) - { -#ifdef MAC_OSX - if (id + 1 == min_menu_id[MAC_MENU_MENU_BAR + 1] - || GetMenuRef (id + 1) == NULL) - { - /* This is a workaround for Mac OS X 10.5 where - just calling SetMenuTitleWithCFString fails - to change the title of the last (Help) menu - in the menu bar. */ - DeleteMenu (id); - DisposeMenu (menu); - menu = NULL; - } - else -#endif /* MAC_OSX */ - err = SetMenuTitleWithCFString (menu, title); - } - CFRelease (old_title); - } - else - err = SetMenuTitleWithCFString (menu, title); -#else /* !TARGET_API_MAC_CARBON */ - if (!EqualString (title, (*menu)->menuData, false, false)) - { - DeleteMenu (id); - DisposeMenu (menu); - menu = NewMenu (id, title); - InsertMenu (menu, GetMenuRef (id + 1) ? id + 1 : 0); - title_changed_p = 1; - } -#endif /* !TARGET_API_MAC_CARBON */ - } - - if (!menu) - { -#if TARGET_API_MAC_CARBON - err = CreateNewMenu (id, 0, &menu); - if (err == noErr) - err = SetMenuTitleWithCFString (menu, title); -#else - menu = NewMenu (id, title); -#endif - if (err == noErr) - { - InsertMenu (menu, 0); -#if !TARGET_API_MAC_CARBON - title_changed_p = 1; -#endif - } - } -#if TARGET_API_MAC_CARBON - CFRelease (title); -#endif - - if (err == noErr) - if (wv->contents) - submenu_id = fill_menu (menu, wv->contents, MAC_MENU_MENU_BAR_SUB, - submenu_id); - } - - if (id < min_menu_id[MAC_MENU_MENU_BAR + 1] && GetMenuRef (id)) - { - dispose_menus (MAC_MENU_MENU_BAR, id); -#if !TARGET_API_MAC_CARBON - title_changed_p = 1; -#endif - } - -#if !TARGET_API_MAC_CARBON - if (title_changed_p) - InvalMenuBar (); -#endif -} - -/* Dispose of menus that belong to KIND, and remove them from the menu - list. ID is the lower bound of menu IDs that will be processed. */ - -static void -dispose_menus (kind, id) - enum mac_menu_kind kind; - int id; -{ - for (id = max (id, min_menu_id[kind]); id < min_menu_id[kind + 1]; id++) - { - MenuRef menu = GetMenuRef (id); - - if (menu == NULL) - break; - DeleteMenu (id); - DisposeMenu (menu); - } -} - #endif /* HAVE_MENUS */ /* Detect if a menu is currently active. */