X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/d76bf86f438d4f5f9fe493ab76f02ffc78f3ae2e..9f62b5dd0e873f6048630e1e59a371112bdcf720:/src/nsmenu.m diff --git a/src/nsmenu.m b/src/nsmenu.m index b764d3f595..7600b607f0 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -1,5 +1,5 @@ /* NeXT/Open/GNUstep and MacOSX Cocoa menu and toolbar module. - Copyright (C) 2007-2013 Free Software Foundation, Inc. + Copyright (C) 2007-2014 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -45,8 +45,6 @@ Carbon version by Yamamoto Mitsuharu. */ #include #endif -#define MenuStagger 10.0 - #if 0 int menu_trace_num = 0; #define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \ @@ -88,14 +86,6 @@ static int trackingMenu; ========================================================================== */ -/* FIXME: not currently used, but should normalize with other terms. */ -void -x_activate_menubar (struct frame *f) -{ - fprintf (stderr, "XXX: Received x_activate_menubar event.\n"); -} - - /* Supposed to discard menubar and free storage. Since we share the menubar among frames and update its context for the focused window, there is nothing to do here. */ @@ -120,14 +110,13 @@ popup_activated (void) 2) deep_p, submenu = nil: Recompute all submenus. 3) deep_p, submenu = non-nil: Update contents of a single submenu. -------------------------------------------------------------------------- */ -void +static void ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) { NSAutoreleasePool *pool; id menu = [NSApp mainMenu]; static EmacsMenu *last_submenu = nil; BOOL needsSet = NO; - const char *submenuTitle = [[submenu title] UTF8String]; bool owfi; Lisp_Object items; widget_value *wv, *first_wv, *prev_wv = 0; @@ -138,7 +127,7 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) long t; #endif - NSTRACE (set_frame_menubar); + NSTRACE (ns_update_menubar); if (f != SELECTED_FRAME ()) return; @@ -185,11 +174,12 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) int *submenu_n_panes; struct buffer *prev = current_buffer; Lisp_Object buffer; - ptrdiff_t specpdl_count = SPECPDL_INDEX (); int previous_menu_items_used = f->menu_bar_items_used; Lisp_Object *previous_items = alloca (previous_menu_items_used * sizeof *previous_items); + dynwind_begin (); + /* lisp preliminaries */ buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contents; specbind (Qinhibit_quit, Qt); @@ -247,7 +237,7 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) /* FIXME: we'd like to only parse the needed submenu, but this was causing crashes in the _common parsing code.. need to make sure proper initialization done.. */ -/* if (submenu && strcmp (submenuTitle, SSDATA (string))) +/* if (submenu && strcmp ([[submenu title] UTF8String], SSDATA (string))) continue; */ submenu_start[i] = menu_items_used; @@ -267,9 +257,9 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) { /* should have found a menu for this one but didn't */ fprintf (stderr, "ERROR: did not find lisp menu for submenu '%s'.\n", - submenuTitle); + [[submenu title] UTF8String]); discard_menu_items (); - unbind_to (specpdl_count, Qnil); + dynwind_end (); [pool release]; unblock_input (); return; @@ -277,12 +267,8 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) /* parse stage 2: insert into lucid 'widget_value' structures [comments in other terms say not to evaluate lisp code here] */ - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; for (i = 0; i < 4*n; i += 4) @@ -331,7 +317,7 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) free_menubar_widget_value_tree (first_wv); discard_menu_items (); - unbind_to (specpdl_count, Qnil); + dynwind_end (); [pool release]; unblock_input (); return; @@ -343,7 +329,7 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) f->menu_bar_items_used = menu_items_used; /* Calls restore_menu_items, etc., as they were outside */ - unbind_to (specpdl_count, Qnil); + dynwind_end (); /* Parse stage 2a: now GC cannot happen during the lifetime of the widget_value, so it's safe to store data from a Lisp_String */ @@ -354,8 +340,6 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) string = AREF (items, i + 1); if (NILP (string)) break; -/* if (submenu && strcmp (submenuTitle, SSDATA (string))) - continue; */ wv->name = SSDATA (string); update_submenu_strings (wv->contents); @@ -366,6 +350,7 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) create a new menu for each sub and fill it. */ if (submenu) { + const char *submenuTitle = [[submenu title] UTF8String]; for (wv = first_wv->contents; wv; wv = wv->next) { if (!strcmp (submenuTitle, wv->name)) @@ -378,7 +363,7 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) } else { - [menu fillWithWidgetValue: first_wv->contents]; + [menu fillWithWidgetValue: first_wv->contents frame: f]; } } @@ -390,12 +375,8 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) int n; Lisp_Object string; - wv = xmalloc_widget_value (); - wv->name = "menubar"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; /* Make widget-value tree w/ just the top level menu bar strings */ @@ -451,12 +432,8 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu) memcpy (previous_strings[i/4], SDATA (string), min (10, SBYTES (string) + 1)); - wv = xmalloc_widget_value (); - wv->name = SSDATA (string); - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value (SSDATA (string), NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; wv->call_data = (void *) (intptr_t) (-1); #ifdef NS_IMPL_COCOA @@ -512,6 +489,19 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) ns_update_menubar (f, deep_p, nil); } +void +x_activate_menubar (struct frame *f) +{ +#ifdef NS_IMPL_COCOA +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + ns_update_menubar (f, true, nil); + ns_check_pending_open_menu (); +#endif +#endif +} + + + /* ========================================================================== @@ -528,6 +518,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) /* override designated initializer */ - initWithTitle: (NSString *)title { + frame = 0; if ((self = [super initWithTitle: title])) [self setAutoenablesItems: NO]; return self; @@ -563,9 +554,36 @@ extern NSString *NSMenuDidBeginTrackingNotification; /* Update menu in menuNeedsUpdate only while tracking menus. */ trackingMenu = ([notification name] == NSMenuDidBeginTrackingNotification ? 1 : 0); +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + if (! trackingMenu) ns_check_menu_open (nil); +#endif } + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +- (void)menuWillOpen:(NSMenu *)menu +{ + ++trackingMenu; + +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 + // On 10.6 we get repeated calls, only the one for NSSystemDefined is "real". + if ([[NSApp currentEvent] type] != NSSystemDefined) return; #endif + /* When dragging from one menu to another, we get willOpen followed by didClose, + i.e. trackingMenu == 3 in willOpen and then 2 after didClose. + We have updated all menus, so avoid doing it when trackingMenu == 3. */ + if (trackingMenu == 2) + ns_check_menu_open (menu); +} + +- (void)menuDidClose:(NSMenu *)menu +{ + --trackingMenu; +} +#endif /* OSX >= 10.5 */ + +#endif /* NS_IMPL_COCOA */ + /* delegate method called when a submenu is being opened: run a 'deep' call to set_frame_menubar */ - (void)menuNeedsUpdate: (NSMenu *)menu @@ -591,7 +609,12 @@ extern NSString *NSMenuDidBeginTrackingNotification; if (trackingMenu == 0) return; /*fprintf (stderr, "Updating menu '%s'\n", [[self title] UTF8String]); NSLog (@"%@\n", event); */ - ns_update_menubar (frame, 1, self); +#if (! defined (NS_IMPL_COCOA) \ + || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5) + /* Don't know how to do this for anything other than OSX >= 10.5 + This is wrong, as it might run Lisp code in the event loop. */ + ns_update_menubar (frame, true, self); +#endif } @@ -695,6 +718,11 @@ extern NSString *NSMenuDidBeginTrackingNotification; - (void)fillWithWidgetValue: (void *)wvptr +{ + [self fillWithWidgetValue: wvptr frame: (struct frame *)nil]; +} + +- (void)fillWithWidgetValue: (void *)wvptr frame: (struct frame *)f { widget_value *wv = (widget_value *)wvptr; @@ -709,12 +737,17 @@ extern NSString *NSMenuDidBeginTrackingNotification; if (wv->contents) { - EmacsMenu *submenu = [[EmacsMenu alloc] initWithTitle: [item title]]; + EmacsMenu *submenu; + + if (f) + submenu = [[EmacsMenu alloc] initWithTitle: [item title] frame:f]; + else + submenu = [[EmacsMenu alloc] initWithTitle: [item title]]; [self setSubmenu: submenu forItem: item]; [submenu fillWithWidgetValue: wv->contents]; [submenu release]; - [item setAction: nil]; + [item setAction: (SEL)nil]; } } @@ -731,7 +764,7 @@ extern NSString *NSMenuDidBeginTrackingNotification; { NSString *titleStr = [NSString stringWithUTF8String: title]; NSMenuItem *item = [self addItemWithTitle: titleStr - action: nil /*@selector (menuDown:) */ + action: (SEL)nil /*@selector (menuDown:) */ keyEquivalent: @""]; EmacsMenu *submenu = [[EmacsMenu alloc] initWithTitle: titleStr frame: f]; [self setSubmenu: submenu forItem: item]; @@ -780,24 +813,24 @@ extern NSString *NSMenuDidBeginTrackingNotification; ========================================================================== */ Lisp_Object -ns_menu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps, +ns_menu_show (struct frame *f, int x, int y, int menuflags, Lisp_Object title, const char **error) { EmacsMenu *pmenu; NSPoint p; Lisp_Object tem; - ptrdiff_t specpdl_count = SPECPDL_INDEX (); widget_value *wv, *first_wv = 0; + bool keymaps = (menuflags & MENU_KEYMAPS); + + block_input (); + + dynwind_begin (); p.x = x; p.y = y; /* now parse stage 2 as in ns_update_menubar */ - wv = xmalloc_widget_value (); - wv->name = "contextmenu"; - wv->value = 0; - wv->enabled = 1; + wv = make_widget_value ("contextmenu", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; first_wv = wv; #if 0 @@ -868,18 +901,14 @@ ns_menu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps, with its items as a submenu beneath it. */ if (!keymaps && strcmp (pane_string, "")) { - wv = xmalloc_widget_value (); + wv = make_widget_value (pane_string, NULL, true, Qnil); if (save_wv) save_wv->next = wv; else first_wv->contents = wv; - wv->name = pane_string; if (keymaps && !NILP (prefix)) wv->name++; - wv->value = 0; - wv->enabled = 1; wv->button_type = BUTTON_TYPE_NONE; - wv->help = Qnil; save_wv = wv; prev_wv = 0; } @@ -917,20 +946,18 @@ ns_menu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps, } #endif /* not HAVE_MULTILINGUAL_MENU */ - wv = xmalloc_widget_value (); + wv = make_widget_value (SSDATA (item_name), NULL, !NILP (enable), + STRINGP (help) ? help : Qnil); if (prev_wv) prev_wv->next = wv; else save_wv->contents = wv; - wv->name = SSDATA (item_name); if (!NILP (descrip)) wv->key = SSDATA (descrip); - wv->value = 0; /* If this item has a null value, make the call_data null so that it won't display a box when the mouse is on it. */ wv->call_data = !NILP (def) ? aref_addr (menu_items, i) : 0; - wv->enabled = !NILP (enable); if (NILP (type)) wv->button_type = BUTTON_TYPE_NONE; @@ -943,11 +970,6 @@ ns_menu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps, wv->selected = !NILP (selected); - if (! STRINGP (help)) - help = Qnil; - - wv->help = help; - prev_wv = wv; i += MENU_ITEMS_ITEM_LENGTH; @@ -958,24 +980,19 @@ ns_menu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps, if (!NILP (title)) { - widget_value *wv_title = xmalloc_widget_value (); - widget_value *wv_sep = xmalloc_widget_value (); + widget_value *wv_title; + widget_value *wv_sep = make_widget_value ("--", NULL, false, Qnil); /* Maybe replace this separator with a bitmap or owner-draw item so that it looks better. Having two separators looks odd. */ - wv_sep->name = "--"; wv_sep->next = first_wv->contents; - wv_sep->help = Qnil; #ifndef HAVE_MULTILINGUAL_MENU if (STRING_MULTIBYTE (title)) title = ENCODE_MENU_STRING (title); #endif - - wv_title->name = SSDATA (title); - wv_title->enabled = NO; + wv_title = make_widget_value (SSDATA (title), NULL, false, Qnil); wv_title->button_type = BUTTON_TYPE_NONE; - wv_title->help = Qnil; wv_title->next = wv_sep; first_wv->contents = wv_title; } @@ -984,13 +1001,14 @@ ns_menu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps, [NSString stringWithUTF8String: SSDATA (title)]]; [pmenu fillWithWidgetValue: first_wv->contents]; free_menubar_widget_value_tree (first_wv); - unbind_to (specpdl_count, Qnil); + dynwind_end (); popup_activated_flag = 1; tem = [pmenu runMenuAt: p forFrame: f keymaps: keymaps]; popup_activated_flag = 0; [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow]; + unblock_input (); return tem; } @@ -1002,30 +1020,38 @@ ns_menu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps, ========================================================================== */ void -free_frame_tool_bar (FRAME_PTR f) +free_frame_tool_bar (struct frame *f) /* -------------------------------------------------------------------------- Under NS we just hide the toolbar until it might be needed again. -------------------------------------------------------------------------- */ { + EmacsView *view = FRAME_NS_VIEW (f); block_input (); - [[FRAME_NS_VIEW (f) toolbar] setVisible: NO]; + view->wait_for_tool_bar = NO; + [[view toolbar] setVisible: NO]; FRAME_TOOLBAR_HEIGHT (f) = 0; unblock_input (); } void -update_frame_tool_bar (FRAME_PTR f) +update_frame_tool_bar (struct frame *f) /* -------------------------------------------------------------------------- Update toolbar contents -------------------------------------------------------------------------- */ { - int i; + int i, k = 0; EmacsView *view = FRAME_NS_VIEW (f); NSWindow *window = [view window]; EmacsToolbar *toolbar = [view toolbar]; + if (view == nil || toolbar == nil) return; block_input (); + +#ifdef NS_IMPL_COCOA [toolbar clearActive]; +#else + [toolbar clearAll]; +#endif /* update EmacsToolbar as in GtkUtils, build items list */ for (i = 0; i < f->n_tool_bar_items; ++i) @@ -1041,6 +1067,15 @@ update_frame_tool_bar (FRAME_PTR f) Lisp_Object helpObj; const char *helpText; + /* Check if this is a separator. */ + if (EQ (TOOLPROP (TOOL_BAR_ITEM_TYPE), Qt)) + { + /* Skip separators. Newer OSX don't show them, and on GNUstep they + are wide as a button, thus overflowing the toolbar most of + the time. */ + continue; + } + /* If image is a vector, choose the image according to the button state. */ image = TOOLPROP (TOOL_BAR_ITEM_IMAGES); @@ -1077,7 +1112,10 @@ update_frame_tool_bar (FRAME_PTR f) continue; } - [toolbar addDisplayItemWithImage: img->pixmap idx: i helpText: helpText + [toolbar addDisplayItemWithImage: img->pixmap + idx: k++ + tag: i + helpText: helpText enabled: enabled_p]; #undef TOOLPROP } @@ -1085,6 +1123,7 @@ update_frame_tool_bar (FRAME_PTR f) if (![toolbar isVisible]) [toolbar setVisible: YES]; +#ifdef NS_IMPL_COCOA if ([toolbar changed]) { /* inform app that toolbar has changed */ @@ -1106,13 +1145,18 @@ update_frame_tool_bar (FRAME_PTR f) [toolbar setConfigurationFromDictionary: newDict]; [newDict release]; } +#endif FRAME_TOOLBAR_HEIGHT (f) = NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)]) - FRAME_NS_TITLEBAR_HEIGHT (f); - if (FRAME_TOOLBAR_HEIGHT (f) < 0) // happens if frame is fullscreen. - FRAME_TOOLBAR_HEIGHT (f) = 0; - unblock_input (); + if (FRAME_TOOLBAR_HEIGHT (f) < 0) // happens if frame is fullscreen. + FRAME_TOOLBAR_HEIGHT (f) = 0; + + if (view->wait_for_tool_bar && FRAME_TOOLBAR_HEIGHT (f) > 0) + [view setNeedsDisplay: YES]; + + unblock_input (); } @@ -1133,6 +1177,7 @@ update_frame_tool_bar (FRAME_PTR f) [self setDelegate: self]; identifierToItem = [[NSMutableDictionary alloc] initWithCapacity: 10]; activeIdentifiers = [[NSMutableArray alloc] initWithCapacity: 8]; + prevIdentifiers = nil; prevEnablement = enablement = 0L; return self; } @@ -1154,18 +1199,29 @@ update_frame_tool_bar (FRAME_PTR f) enablement = 0L; } +- (void) clearAll +{ + [self clearActive]; + while ([[self items] count] > 0) + [self removeItemAtIndex: 0]; +} + - (BOOL) changed { return [activeIdentifiers isEqualToArray: prevIdentifiers] && enablement == prevEnablement ? NO : YES; } -- (void) addDisplayItemWithImage: (EmacsImage *)img idx: (int)idx - helpText: (const char *)help enabled: (BOOL)enabled +- (void) addDisplayItemWithImage: (EmacsImage *)img + idx: (int)idx + tag: (int)tag + helpText: (const char *)help + enabled: (BOOL)enabled { /* 1) come up w/identifier */ NSString *identifier - = [NSString stringWithFormat: @"%u", [img hash]]; + = [NSString stringWithFormat: @"%lu", (unsigned long)[img hash]]; + [activeIdentifiers addObject: identifier]; /* 2) create / reuse item */ NSToolbarItem *item = [identifierToItem objectForKey: identifier]; @@ -1177,20 +1233,25 @@ update_frame_tool_bar (FRAME_PTR f) [item setToolTip: [NSString stringWithUTF8String: help]]; [item setTarget: emacsView]; [item setAction: @selector (toolbarClicked:)]; + [identifierToItem setObject: item forKey: identifier]; } - [item setTag: idx]; +#ifdef NS_IMPL_GNUSTEP + [self insertItemWithItemIdentifier: identifier atIndex: idx]; +#endif + + [item setTag: tag]; [item setEnabled: enabled]; /* 3) update state */ - [identifierToItem setObject: item forKey: identifier]; - [activeIdentifiers addObject: identifier]; enablement = (enablement << 1) | (enabled == YES); } /* This overrides super's implementation, which automatically sets all items to enabled state (for some reason). */ -- (void)validateVisibleItems { } +- (void)validateVisibleItems +{ +} /* delegate methods */ @@ -1213,7 +1274,8 @@ update_frame_tool_bar (FRAME_PTR f) - (NSArray *)toolbarAllowedItemIdentifiers: (NSToolbar *)toolbar { /* return entire set... */ - return [identifierToItem allKeys]; + return activeIdentifiers; + //return [identifierToItem allKeys]; } /* optional and unneeded */ @@ -1300,6 +1362,7 @@ update_frame_tool_bar (FRAME_PTR f) wr.size = [textField frame].size; [win setFrame: wr display: YES]; + [win setLevel: NSPopUpMenuWindowLevel]; [win orderFront: self]; [win display]; timer = [NSTimer scheduledTimerWithTimeInterval: (float)seconds target: self @@ -1346,10 +1409,10 @@ struct Popdown_data EmacsDialogPanel *dialog; }; -static Lisp_Object -pop_down_menu (Lisp_Object arg) +static void +pop_down_menu (void *arg) { - struct Popdown_data *unwind_data = XSAVE_POINTER (arg, 0); + struct Popdown_data *unwind_data = arg; block_input (); if (popup_activated_flag) @@ -1363,61 +1426,23 @@ pop_down_menu (Lisp_Object arg) xfree (unwind_data); unblock_input (); - - return Qnil; } Lisp_Object -ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header) +ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) { id dialog; Lisp_Object window, tem, title; - struct frame *f; NSPoint p; BOOL isQ; NSAutoreleasePool *pool; NSTRACE (x-popup-dialog); - check_ns (); - isQ = NILP (header); - if (EQ (position, Qt) - || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar) - || EQ (XCAR (position), Qtool_bar)))) - { - window = selected_window; - } - else if (CONSP (position)) - { - Lisp_Object tem; - tem = Fcar (position); - if (XTYPE (tem) == Lisp_Cons) - window = Fcar (Fcdr (position)); - else - { - tem = Fcar (Fcdr (position)); /* EVENT_START (position) */ - window = Fcar (tem); /* POSN_WINDOW (tem) */ - } - } - else if (WINDOWP (position) || FRAMEP (position)) - { - window = position; - } - else - window = Qnil; - - if (FRAMEP (window)) - f = XFRAME (window); - else if (WINDOWP (window)) - { - CHECK_LIVE_WINDOW (window); - f = XFRAME (WINDOW_FRAME (XWINDOW (window))); - } - else - CHECK_WINDOW (window); + check_window_system (f); p.x = (int)f->left_pos + ((int)FRAME_COLUMN_WIDTH (f) * f->text_cols)/2; p.y = (int)f->top_pos + (FRAME_LINE_HEIGHT (f) * f->text_lines)/2; @@ -1428,7 +1453,7 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header) if (NILP (Fcar (Fcdr (contents)))) /* No buttons specified, add an "Ok" button so users can pop down the dialog. */ - contents = Fcons (title, Fcons (Fcons (build_string ("Ok"), Qt), Qnil)); + contents = list2 (title, Fcons (build_string ("Ok"), Qt)); block_input (); pool = [[NSAutoreleasePool alloc] init]; @@ -1436,16 +1461,16 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header) isQuestion: isQ]; { - ptrdiff_t specpdl_count = SPECPDL_INDEX (); struct Popdown_data *unwind_data = xmalloc (sizeof (*unwind_data)); unwind_data->pool = pool; unwind_data->dialog = dialog; - record_unwind_protect (pop_down_menu, make_save_pointer (unwind_data)); + dynwind_begin (); + record_unwind_protect_ptr (pop_down_menu, unwind_data); popup_activated_flag = 1; tem = [dialog runDialogAt: p]; - unbind_to (specpdl_count, Qnil); /* calls pop_down_menu */ + dynwind_end (); } unblock_input (); @@ -1504,7 +1529,7 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header) [img autorelease]; [imgView autorelease]; - aStyle = NSTitledWindowMask; + aStyle = NSTitledWindowMask|NSClosableWindowMask|NSUtilityWindowMask; flag = YES; rows = 0; cols = 1; @@ -1572,9 +1597,6 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header) [self setOneShot: YES]; [self setReleasedWhenClosed: YES]; [self setHidesOnDeactivate: YES]; - [self setStyleMask: - NSTitledWindowMask|NSClosableWindowMask|NSUtilityWindowMask]; - return self; } @@ -1598,24 +1620,24 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header) int row = 0; int buttons = 0, btnnr = 0; - for (; XTYPE (lst) == Lisp_Cons; lst = XCDR (lst)) + for (; CONSP (lst); lst = XCDR (lst)) { item = XCAR (list); - if (XTYPE (item) == Lisp_Cons) + if (CONSP (item)) ++buttons; } if (buttons > 0) - button_values = (Lisp_Object *) xmalloc (buttons * sizeof (*button_values)); + button_values = xmalloc (buttons * sizeof *button_values); - for (; XTYPE (list) == Lisp_Cons; list = XCDR (list)) + for (; CONSP (list); list = XCDR (list)) { item = XCAR (list); - if (XTYPE (item) == Lisp_String) + if (STRINGP (item)) { [self addString: SSDATA (item) row: row++]; } - else if (XTYPE (item) == Lisp_Cons) + else if (CONSP (item)) { button_values[btnnr] = XCDR (item); [self addButton: SSDATA (XCAR (item)) value: btnnr row: row++]; @@ -1692,7 +1714,7 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header) Lisp_Object head; [super init]; - if (XTYPE (contents) == Lisp_Cons) + if (CONSP (contents)) { head = Fcar (contents); [self process_dialog: Fcdr (contents)]; @@ -1700,7 +1722,7 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header) else head = contents; - if (XTYPE (head) == Lisp_String) + if (STRINGP (head)) [title setStringValue: [NSString stringWithUTF8String: SSDATA (head)]]; else if (isQ == YES) @@ -1790,11 +1812,11 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header) while (popup_activated_flag) { NSTimer *tmo = nil; - EMACS_TIME next_time = timer_check (); + struct timespec next_time = timer_check (); - if (EMACS_TIME_VALID_P (next_time)) + if (timespec_valid_p (next_time)) { - double time = EMACS_TIME_TO_DOUBLE (next_time); + double time = timespectod (next_time); tmo = [NSTimer timerWithTimeInterval: time target: self selector: @selector (timeout_handler:) @@ -1839,34 +1861,6 @@ DEFUN ("ns-reset-menu", Fns_reset_menu, Sns_reset_menu, 0, 0, 0, } -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. -This is normally a mouse button event or a window or frame. -If POSITION is t, it means to use the frame the mouse is on. -The dialog box appears in the middle of the specified frame. - -CONTENTS specifies the alternatives to display in the dialog box. -It is a list of the form (DIALOG ITEM1 ITEM2...). -Each ITEM is a cons cell (STRING . VALUE). -The return value is VALUE from the chosen item. - -An ITEM may also be just a string--that makes a nonselectable item. -An ITEM may also be nil--that means to put all preceding items -on the left of the dialog box and all following items on the right. -\(By default, approximately half appear on each side.) - -If HEADER is non-nil, the frame title for the box is "Information", -otherwise it is "Question". - -If the user gets rid of the dialog box without making a valid choice, -for instance using the window manager, then this produces a quit and -`x-popup-dialog' does not return. */) - (Lisp_Object position, Lisp_Object contents, Lisp_Object header) -{ - return ns_popup_dialog (position, contents, header); -} - 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. */) (void) @@ -1883,14 +1877,13 @@ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_ void syms_of_nsmenu (void) { +#include "nsmenu.x" + #ifndef NS_IMPL_COCOA - /* Don't know how to keep track of this in Next/Open/Gnustep. Always + /* Don't know how to keep track of this in Next/Open/GNUstep. Always update menus there. */ trackingMenu = 1; #endif - defsubr (&Sx_popup_dialog); - defsubr (&Sns_reset_menu); - defsubr (&Smenu_or_popup_active_p); Qdebug_on_next_call = intern_c_string ("debug-on-next-call"); staticpro (&Qdebug_on_next_call);