Add option to ask bzr itself for the emacs bzr revision
[bpt/emacs.git] / src / nsmenu.m
index 152127e..3057f4f 100644 (file)
@@ -24,7 +24,6 @@ Carbon version by Yamamoto Mitsuharu. */
 /* This should be the first include, as it may set up #defines affecting
    interpretation of even the system includes. */
 #include <config.h>
-#include <setjmp.h>
 
 #include "lisp.h"
 #include "window.h"
@@ -73,7 +72,6 @@ EmacsMenu *mainMenu, *svcsMenu, *dockMenu;
 
 /* Nonzero means a menu is currently active.  */
 static int popup_activated_flag;
-static NSModalSession popupSession;
 
 /* Nonzero means we are tracking and updating menus.  */
 static int trackingMenu;
@@ -193,7 +191,7 @@ ns_update_menubar (struct frame *f, int deep_p, EmacsMenu *submenu)
        = alloca (previous_menu_items_used * sizeof *previous_items);
 
       /* lisp preliminaries */
-      buffer = WGET (XWINDOW (FRAME_SELECTED_WINDOW (f)), buffer);
+      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
       specbind (Qinhibit_quit, Qt);
       specbind (Qdebug_on_next_call, Qnil);
       record_unwind_save_match_data ();
@@ -215,20 +213,20 @@ ns_update_menubar (struct frame *f, int deep_p, EmacsMenu *submenu)
       if (! NILP (Vlucid_menu_bar_dirty_flag))
        call0 (Qrecompute_lucid_menubar);
       safe_run_hooks (Qmenu_bar_update_hook);
-      FSET (f, menu_bar_items, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
+      fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
 
       /* Now ready to go */
       items = FRAME_MENU_BAR_ITEMS (f);
 
       /* Save the frame's previous menu bar contents data */
       if (previous_menu_items_used)
-       memcpy (previous_items, aref_addr (FGET (f, menu_bar_vector), 0),
+       memcpy (previous_items, aref_addr (f->menu_bar_vector, 0),
                previous_menu_items_used * sizeof (Lisp_Object));
 
       /* parse stage 1: extract from lisp */
       save_menu_items ();
 
-      menu_items = FGET (f, menu_bar_vector);
+      menu_items = f->menu_bar_vector;
       menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
       submenu_start = alloca (ASIZE (items) * sizeof *submenu_start);
       submenu_end = alloca (ASIZE (items) * sizeof *submenu_end);
@@ -341,7 +339,7 @@ ns_update_menubar (struct frame *f, int deep_p, EmacsMenu *submenu)
         }
       /* The menu items are different, so store them in the frame */
       /* FIXME: this is not correct for single-submenu case */
-      FSET (f, menu_bar_vector, menu_items);
+      fset_menu_bar_vector (f, menu_items);
       f->menu_bar_items_used = menu_items_used;
 
       /* Calls restore_menu_items, etc., as they were outside */
@@ -949,7 +947,7 @@ ns_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
          else if (EQ (type, QCradio))
            wv->button_type = BUTTON_TYPE_RADIO;
          else
-           abort ();
+           emacs_abort ();
 
          wv->selected = !NILP (selected);
 
@@ -1040,7 +1038,7 @@ update_frame_tool_bar (FRAME_PTR f)
   /* update EmacsToolbar as in GtkUtils, build items list */
   for (i = 0; i < f->n_tool_bar_items; ++i)
     {
-#define TOOLPROP(IDX) AREF (FGET (f, tool_bar_items), \
+#define TOOLPROP(IDX) AREF (f->tool_bar_items, \
                             i * TOOL_BAR_ITEM_NSLOTS + (IDX))
 
       BOOL enabled_p = !NILP (TOOLPROP (TOOL_BAR_ITEM_ENABLED_P));
@@ -1365,8 +1363,6 @@ pop_down_menu (Lisp_Object arg)
     {
       EmacsDialogPanel *panel = unwind_data->dialog;
       popup_activated_flag = 0;
-      [NSApp endModalSession: popupSession];
-
       [panel close];
       [unwind_data->pool release];
       [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
@@ -1500,6 +1496,8 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
   FlippedView *contentView;
   NSImage *img;
 
+  dialog_return   = Qundefined;
+  button_values   = NULL;
   area.origin.x   = 3*SPACER;
   area.origin.y   = 2*SPACER;
   area.size.width = ICONSIZE;
@@ -1581,44 +1579,65 @@ 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;
 }
 
 
 - (BOOL)windowShouldClose: (id)sender
 {
-  [NSApp stopModalWithCode: XHASH (Qnil)]; // FIXME: BIG UGLY HACK!!
+  window_closed = YES;
+  [NSApp stop:self];
   return NO;
 }
 
+- (void)dealloc
+{
+  xfree (button_values);
+  [super dealloc];
+}
 
-void process_dialog (id window, Lisp_Object list)
+- (void)process_dialog: (Lisp_Object) list
 {
-  Lisp_Object item;
+  Lisp_Object item, lst = list;
   int row = 0;
+  int buttons = 0, btnnr = 0;
+
+  for (; XTYPE (lst) == Lisp_Cons; lst = XCDR (lst))
+    {
+      item = XCAR (list);
+      if (XTYPE (item) == Lisp_Cons)
+        ++buttons;
+    }
+
+  if (buttons > 0)
+    button_values = (Lisp_Object *) xmalloc (buttons * sizeof (*button_values));
 
   for (; XTYPE (list) == Lisp_Cons; list = XCDR (list))
     {
       item = XCAR (list);
       if (XTYPE (item) == Lisp_String)
         {
-          [window addString: SSDATA (item) row: row++];
+          [self addString: SSDATA (item) row: row++];
         }
       else if (XTYPE (item) == Lisp_Cons)
         {
-          [window addButton: SSDATA (XCAR (item))
-                      value: XCDR (item) row: row++];
+          button_values[btnnr] = XCDR (item);
+          [self addButton: SSDATA (XCAR (item)) value: btnnr row: row++];
+          ++btnnr;
         }
       else if (NILP (item))
         {
-          [window addSplit];
+          [self addSplit];
           row = 0;
         }
     }
 }
 
 
-- addButton: (char *)str value: (Lisp_Object)val row: (int)row
+- (void)addButton: (char *)str value: (int)tag row: (int)row
 {
   id cell;
 
@@ -1631,15 +1650,13 @@ void process_dialog (id window, Lisp_Object list)
   [cell setTarget: self];
   [cell setAction: @selector (clicked: )];
   [cell setTitle: [NSString stringWithUTF8String: str]];
-  [cell setTag: XHASH (val)];  // FIXME: BIG UGLY HACK!!
+  [cell setTag: tag];
   [cell setBordered: YES];
   [cell setEnabled: YES];
-
-  return self;
 }
 
 
-- addString: (char *)str row: (int)row
+- (void)addString: (char *)str row: (int)row
 {
   id cell;
 
@@ -1652,32 +1669,28 @@ void process_dialog (id window, Lisp_Object list)
   [cell setTitle: [NSString stringWithUTF8String: str]];
   [cell setBordered: YES];
   [cell setEnabled: NO];
-
-  return self;
 }
 
 
-- addSplit
+- (void)addSplit
 {
   [matrix addColumn];
   cols++;
-  return self;
 }
 
 
-- clicked: sender
+- (void)clicked: sender
 {
   NSArray *sellist = nil;
   EMACS_INT seltag;
 
   sellist = [sender selectedCells];
-  if ([sellist count]<1)
-    return self;
+  if ([sellist count] < 1)
+    return;
 
   seltag = [[sellist objectAtIndex: 0] tag];
-  if (seltag != XHASH (Qundefined)) // FIXME: BIG UGLY HACK!!
-    [NSApp stopModalWithCode: seltag];
-  return self;
+  dialog_return = button_values[seltag];
+  [NSApp stop:self];
 }
 
 
@@ -1689,7 +1702,7 @@ void process_dialog (id window, Lisp_Object list)
   if (XTYPE (contents) == Lisp_Cons)
     {
       head = Fcar (contents);
-      process_dialog (self, Fcdr (contents));
+      [self process_dialog: Fcdr (contents)];
     }
   else
     head = contents;
@@ -1709,7 +1722,7 @@ void process_dialog (id window, Lisp_Object list)
     if (cols == 1 && rows > 1) /* Never told where to split */
       {
         [matrix addColumn];
-        for (i = 0; i<rows/2; i++)
+        for (i = 0; i < rows/2; i++)
           {
             [matrix putCell: [matrix cellAtRow: (rows+1)/2 column: 0]
                       atRow: i column: 1];
@@ -1756,27 +1769,63 @@ void process_dialog (id window, Lisp_Object list)
 }
 
 
+- (void)timeout_handler: (NSTimer *)timedEntry
+{
+  NSEvent *nxev = [NSEvent otherEventWithType: NSApplicationDefined
+                            location: NSMakePoint (0, 0)
+                       modifierFlags: 0
+                           timestamp: 0
+                        windowNumber: [[NSApp mainWindow] windowNumber]
+                             context: [NSApp context]
+                             subtype: 0
+                               data1: 0
+                               data2: 0];
+
+  timer_fired = YES;
+  /* We use sto because stopModal/abortModal out of the main loop does not
+     seem to work in 10.6.  But as we use stop we must send a real event so
+     the stop is seen and acted upon.  */
+  [NSApp stop:self];
+  [NSApp postEvent: nxev atStart: NO];
+}
+
 - (Lisp_Object)runDialogAt: (NSPoint)p
 {
-  NSInteger ret;
+  Lisp_Object ret = Qundefined;
 
-  /* initiate a session that will be ended by pop_down_menu */
-  popupSession = [NSApp beginModalSessionForWindow: self];
-  while (popup_activated_flag
-         && (ret = [NSApp runModalSession: popupSession])
-              == NSRunContinuesResponse)
+  while (popup_activated_flag)
     {
-      /* Run this for timers.el, indep of atimers; might not return.
-         TODO: use return value to avoid calling every iteration. */
-      timer_check ();
-      [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1]];
+      NSTimer *tmo = nil;
+      EMACS_TIME next_time = timer_check ();
+
+      if (EMACS_TIME_VALID_P (next_time))
+        {
+          double time = EMACS_TIME_TO_DOUBLE (next_time);
+          tmo = [NSTimer timerWithTimeInterval: time
+                                        target: self
+                                      selector: @selector (timeout_handler:)
+                                      userInfo: 0
+                                       repeats: NO];
+          [[NSRunLoop currentRunLoop] addTimer: tmo
+                                       forMode: NSModalPanelRunLoopMode];
+        }
+      timer_fired = NO;
+      dialog_return = Qundefined;
+      [NSApp runModalForWindow: self];
+      ret = dialog_return;
+      if (! timer_fired)
+        {
+          if (tmo != nil) [tmo invalidate]; /* Cancels timer */
+          break;
+        }
     }
 
-  {                            /* FIXME: BIG UGLY HACK!!! */
-      Lisp_Object tmp;
-      *(EMACS_INT*)(&tmp) = ret;
-      return tmp;
-  }
+  if (EQ (ret, Qundefined) && window_closed)
+    /* Make close button pressed equivalent to C-g.  */
+    Fsignal (Qquit, Qnil);
+
+  return ret;
 }
 
 @end