/* Menu support for GNU Emacs on Mac OS.
Copyright (C) 2000, 2001, 2002, 2003, 2004,
- 2005, 2006 Free Software Foundation, Inc.
+ 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
#define DIALOG_WINDOW_RESOURCE 130
+#if TARGET_API_MAC_CARBON
#define HAVE_DIALOGS 1
+#endif
#undef HAVE_MULTILINGUAL_MENU
-#undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
/******************************************************************/
/* Definitions copied from lwlib.h */
/* Current depth within submenus. */
static int menu_items_submenu_depth;
+/* Nonzero means a menu is currently active. */
+static 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.
While it is nonzero, all calls to set_frame_menubar go deep.
menu_items_used = XINT (XCAR (saved));
saved = XCDR (saved);
menu_items_n_panes = XINT (XCAR (saved));
- saved = XCDR (saved);
+ saved = XCDR (saved);
menu_items_submenu_depth = XINT (XCAR (saved));
return Qnil;
}
#ifdef HAVE_MENUS
+/* Regard ESC and C-g as Cancel even without the Cancel button. */
+
+#ifdef 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.
but I don't want to make one now. */
CHECK_WINDOW (window);
+#ifdef 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. */
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);
}
\f
+#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, result;
+ MenuRef menu;
+ MenuItemIndex menu_item;
+ Lisp_Object help;
+ GrafPtr port;
+ int specpdl_count = SPECPDL_INDEX ();
+
+ result = CallNextEventHandler (next_handler, event);
+
+ 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 : result;
+}
+#endif
+
+OSStatus
+install_menu_target_item_handler (window)
+ WindowPtr window;
+{
+ OSStatus err = noErr;
+#if TARGET_API_MAC_CARBON
+ static const EventTypeSpec specs[] =
+ {{kEventClassMenu, kEventMenuTargetItem}};
+ static EventHandlerUPP menu_target_item_handlerUPP = NULL;
+
+ if (menu_target_item_handlerUPP == NULL)
+ menu_target_item_handlerUPP =
+ NewEventHandlerUPP (menu_target_item_handler);
+
+ err = InstallWindowEventHandler (window, menu_target_item_handlerUPP,
+ GetEventTypeCount (specs), specs,
+ NULL, NULL);
+#endif
+ return err;
+}
+
/* 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). */
-#ifdef HAVE_CANCELMENUTRACKING
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
static pascal OSStatus
menu_quit_handler (nextHandler, theEvent, userData)
EventHandlerCallRef nextHandler;
OSStatus err;
UInt32 keyCode;
UInt32 keyModifiers;
- extern int mac_quit_char_modifiers;
- extern int mac_quit_char_keycode;
err = GetEventParameter (theEvent, kEventParamKeyCode,
typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
typeUInt32, NULL, sizeof(UInt32),
NULL, &keyModifiers);
- if (err == noErr && keyCode == mac_quit_char_keycode
- && keyModifiers == mac_quit_char_modifiers)
+ if (err == noErr && mac_quit_char_key_p (keyModifiers, keyCode))
{
MenuRef menu = userData != 0
? (MenuRef)userData : AcquireRootMenu ();
return CallNextEventHandler (nextHandler, theEvent);
}
-#endif /* HAVE_CANCELMENUTRACKING */
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
/* Add event handler to all menus that belong to KIND so we can detect C-g.
MENU_HANDLE is the root menu of the tracking session to dismiss
enum mac_menu_kind kind;
MenuHandle menu_handle;
{
-#ifdef HAVE_CANCELMENUTRACKING
+#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++)
{
MenuHandle menu = GetMenuHandle (id);
break;
InstallMenuEventHandler (menu, menu_quit_handler,
GetEventTypeCount (typesList),
- typesList, menu_handle, NULL);
+ typesList, menu_handle, NULL);
}
-#endif /* HAVE_CANCELMENUTRACKING */
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
}
/* Set the contents of the menubar widgets of frame F.
char **error;
{
int i;
- UInt32 refcon;
int menu_item_choice;
- int menu_item_selection;
+ UInt32 menu_item_selection;
MenuHandle menu;
Point pos;
widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
LocalToGlobal (&pos);
/* No selection has been chosen yet. */
- menu_item_choice = 0;
menu_item_selection = 0;
record_unwind_protect (pop_down_menu, make_save_value (f, 0));
install_menu_quit_handler (MAC_MENU_POPUP_SUB, menu);
/* Display the menu. */
+ popup_activated_flag = 1;
menu_item_choice = PopUpMenuSelect (menu, pos.v, pos.h, 0);
- menu_item_selection = LoWord (menu_item_choice);
+ popup_activated_flag = 0;
/* Get the refcon to find the correct item */
- if (menu_item_selection)
+ if (menu_item_choice)
{
MenuHandle sel_menu = GetMenuHandle (HiWord (menu_item_choice));
- if (sel_menu) {
- GetMenuItemRefCon (sel_menu, menu_item_selection, &refcon);
- }
+
+ if (sel_menu)
+ GetMenuItemRefCon (sel_menu, LoWord (menu_item_choice),
+ &menu_item_selection);
}
- else if (! for_click)
- /* Make "Cancel" equivalent to C-g unless this menu was popped up by
- a mouse press. */
- Fsignal (Qquit, Qnil);
+
+ unbind_to (specpdl_count, Qnil);
/* Find the selected item, and its pane, to return
the proper value. */
{
entry
= XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
- if ((int) (EMACS_INT) refcon == i)
+ if (menu_item_selection == i)
{
if (keymaps != 0)
{
/* Make "Cancel" equivalent to C-g. */
Fsignal (Qquit, Qnil);
- unbind_to (specpdl_count, Qnil);
-
return Qnil;
}
\f
#ifdef HAVE_DIALOGS
-/* Construct native Mac OS menubar based on widget_value tree. */
+/* Construct native Mac OS dialog based on widget_value tree. */
+
+#if TARGET_API_MAC_CARBON
+
+static pascal OSStatus
+mac_handle_dialog_event (next_handler, event, data)
+ EventHandlerCallRef next_handler;
+ EventRef event;
+ void *data;
+{
+ OSStatus err;
+ 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 ((command.commandID & ~0xffff) == 'Bt\0\0')
+ {
+ SetWRefCon (window, command.commandID);
+ err = QuitAppModalLoopForWindow (window);
+
+ return err == noErr ? noErr : eventNotHandledErr;
+ }
+
+ return CallNextEventHandler (next_handler, event);
+ }
+ break;
+
+ case kEventClassKeyboard:
+ {
+ OSStatus result;
+ char char_code;
+
+ result = CallNextEventHandler (next_handler, event);
+ if (result == noErr)
+ return noErr;
+
+ err = GetEventParameter (event, kEventParamKeyMacCharCodes,
+ typeChar, NULL, sizeof (char),
+ NULL, &char_code);
+ if (err == noErr)
+ switch (char_code)
+ {
+ case kEscapeCharCode:
+ err = QuitAppModalLoopForWindow (window);
+ 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))
+ err = QuitAppModalLoopForWindow (window);
+ else
+ err = eventNotHandledErr;
+ }
+ }
+ break;
+ }
+
+ return err == noErr ? noErr : result;
+ }
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+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 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;
+
+ 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)
+ 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)
+ {
+ 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;
+
+ err = SetControlCommandID (buttons[i],
+ 'Bt\0\0' + (int) wv->call_data);
+ }
+ 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);
+ err = RunAppModalLoopForWindow (window);
+ }
+ if (err == noErr)
+ {
+ UInt32 command_id = GetWRefCon (window);
+
+ if ((command_id & ~0xffff) == 'Bt\0\0')
+ result = command_id - 'Bt\0\0';
+ }
+
+ if (window)
+ DisposeWindow (window);
+
+ return result;
+}
+#else /* not TARGET_API_MAC_CARBON */
static int
mac_dialog (widget_value *wv)
{
return i;
}
+#endif /* not TARGET_API_MAC_CARBON */
static char * button_names [] = {
"button1", "button2", "button3", "button4", "button5",
first_wv = wv;
}
+ /* 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);
+
/* Actually create the dialog. */
-#ifdef HAVE_DIALOGS
- menu_item_selection = mac_dialog (first_wv);
+#if TARGET_API_MAC_CARBON
+ menu_item_selection = create_and_show_dialog (f, first_wv);
#else
- menu_item_selection = 0;
+ menu_item_selection = mac_dialog (first_wv);
#endif
/* Free the widget_value objects we used to specify the contents. */
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);
GetMenuTitle (menu, old_title);
if (!EqualString (title, old_title, false, false))
- SetMenuTitle (menu, title);
+ {
+#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 SetMenuTitle fails to change the title of
+ the last (Help) menu in the menu bar. */
+ DeleteMenu (id);
+ DisposeMenu (menu);
+ menu = NULL;
+ }
+ else
+#endif /* MAC_OSX */
+ SetMenuTitle (menu, title);
+ }
#else /* !TARGET_API_MAC_CARBON */
if (!EqualString (title, (*menu)->menuData, false, false))
{
}
#endif /* !TARGET_API_MAC_CARBON */
}
- else
+
+ if (!menu)
{
menu = NewMenu (id, title);
InsertMenu (menu, 0);
}
#endif /* HAVE_MENUS */
+
+/* Detect if a menu is currently active. */
+
+int
+popup_activated ()
+{
+ return popup_activated_flag;
+}
+
+/* The following is used by delayed window autoselection. */
+
+DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
+ doc: /* Return t if a menu or popup dialog is active. */)
+ ()
+{
+ /* Always return Qnil since menu selection functions do not return
+ until a selection has been made or cancelled. */
+ return Qnil;
+}
\f
void
syms_of_macmenu ()
staticpro (&Qdebug_on_next_call);
defsubr (&Sx_popup_menu);
+ defsubr (&Smenu_or_popup_active_p);
#ifdef HAVE_MENUS
defsubr (&Sx_popup_dialog);
#endif