emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 5aef501d9c: Fix processing of dialog box items on NS


From: Po Lu
Subject: master 5aef501d9c: Fix processing of dialog box items on NS
Date: Sat, 14 May 2022 09:19:10 -0400 (EDT)

branch: master
commit 5aef501d9c3394599dd2e48ff7ba7bb5f13cd19a
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Fix processing of dialog box items on NS
    
    * src/nsmenu.m (pop_down_menu): Remove old hack and discard menu
    items.
    (ns_popup_dialog):
    ([EmacsDialogPanel initWithContentRect:styleMask:backing:defer:]):
    ([EmacsDialogPanel windowShouldClose:]):
    ([EmacsDialogPanel dealloc]):
    ([EmacsDialogPanel processdialog:]):
    ([EmacsDialogPanel addButton:value:row:]):
    ([EmacsDialogPanel addString:row:]):
    ([EmacsDialogPanel clicked:]):
    ([EmacsDialogPanel initFromContents:isQuestion:]):
    ([EmacsDialogPanel timeouthandler:]):
    ([EmacsDialogPanel runDialogAt:]): Use the regular menu item
    machinery to parse dialog items instead of the incorrect ad-hoc
    code used previously.
    
    * src/nsterm.h: Update prototypes.
---
 src/nsmenu.m | 271 ++++++++++++++++++++++++++++++++---------------------------
 src/nsterm.h |  42 +++++----
 2 files changed, 171 insertions(+), 142 deletions(-)

diff --git a/src/nsmenu.m b/src/nsmenu.m
index 531f0d3bb6..1ebaca4e87 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -1538,31 +1538,32 @@ pop_down_menu (void *arg)
 
   if (popup_activated_flag)
     {
-      block_input ();
       popup_activated_flag = 0;
       [panel close];
-      [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
-      unblock_input ();
+      discard_menu_items ();
     }
 }
 
-
 Lisp_Object
 ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
 {
-  id dialog;
+  EmacsDialogPanel *dialog;
   Lisp_Object tem, title;
   NSPoint p;
-  BOOL isQ;
+  BOOL is_question;
+  const char *error_name;
+  specpdl_ref specpdl_count;
 
   NSTRACE ("ns_popup_dialog");
+  specpdl_count = SPECPDL_INDEX ();
 
-  isQ = NILP (header);
-
+  is_question = NILP (header);
   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;
+  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);
 
   title = Fcar (contents);
   CHECK_STRING (title);
@@ -1572,21 +1573,30 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, 
Lisp_Object contents)
        the dialog.  */
     contents = list2 (title, Fcons (build_string ("Ok"), Qt));
 
-  block_input ();
-  dialog = [[EmacsDialogPanel alloc] initFromContents: contents
-                                           isQuestion: isQ];
-
-  {
-    specpdl_ref specpdl_count = SPECPDL_INDEX ();
+  record_unwind_protect_void (unuse_menu_items);
+  list_of_panes (list1 (contents));
 
-    record_unwind_protect_ptr (pop_down_menu, dialog);
-    popup_activated_flag = 1;
-    tem = [dialog runDialogAt: p];
-    unbind_to (specpdl_count, Qnil);  /* calls pop_down_menu */
-  }
+  block_input ();
+  dialog = [[EmacsDialogPanel alloc] initWithTitle: SSDATA (title)
+                                       isQuestion: is_question];
 
+  [dialog processMenuItems: menu_items
+                     used: menu_items_used
+          withErrorOutput: &error_name];
+  [dialog resizeBoundsPriorToDisplay];
   unblock_input ();
 
+  if (error_name)
+    {
+      discard_menu_items ();
+      [dialog close];
+      error ("%s", error_name);
+    }
+
+  record_unwind_protect_ptr (pop_down_menu, dialog);
+  popup_activated_flag = 1;
+  tem = [dialog runDialogAt: p];
+  unbind_to (specpdl_count, Qnil);
   return tem;
 }
 
@@ -1627,7 +1637,6 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, 
Lisp_Object contents)
   NSImage *img;
 
   dialog_return   = Qundefined;
-  button_values   = NULL;
   area.origin.x   = 3*SPACER;
   area.origin.y   = 2*SPACER;
   area.size.width = ICONSIZE;
@@ -1711,58 +1720,65 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, 
Lisp_Object contents)
 }
 
 
-- (BOOL)windowShouldClose: (id)sender
+- (BOOL)windowShouldClose: (id) sender
 {
   window_closed = YES;
-  [NSApp stop:self];
+  [NSApp stop: self];
   return NO;
 }
 
-- (void)dealloc
+- (void) dealloc
 {
-  xfree (button_values);
   [super dealloc];
 }
 
-- (void)process_dialog: (Lisp_Object) list
+- (void) processMenuItems: (Lisp_Object) menu_items
+                    used: (ptrdiff_t) menu_items_used
+         withErrorOutput: (const char **) error_name
 {
-  Lisp_Object item, lst = list;
-  int row = 0;
-  int buttons = 0, btnnr = 0;
+  int i, nb_buttons = 0, row = 0;
+  Lisp_Object item_name, enable;
 
-  for (; CONSP (lst); lst = XCDR (lst))
+  i = MENU_ITEMS_PANE_LENGTH;
+  *error_name = NULL;
+
+  /* Loop over all panes and items, filling in the tree.  */
+  while (i < menu_items_used)
     {
-      item = XCAR (list);
-      if (CONSP (item))
-        ++buttons;
-    }
+      item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
+      enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
 
-  if (buttons > 0)
-    button_values = xmalloc (buttons * sizeof *button_values);
+      if (NILP (item_name))
+       {
+         *error_name = "Submenu in dialog items";
+         return;
+       }
 
-  for (; CONSP (list); list = XCDR (list))
-    {
-      item = XCAR (list);
-      if (STRINGP (item))
-        {
-          [self addString: SSDATA (item) row: row++];
-        }
-      else if (CONSP (item))
-        {
-          button_values[btnnr] = XCDR (item);
-          [self addButton: SSDATA (XCAR (item)) value: btnnr row: row++];
-          ++btnnr;
-        }
-      else if (NILP (item))
-        {
-          [self addSplit];
-          row = 0;
-        }
+      if (EQ (item_name, Qquote))
+       /* This is the boundary between elements on the left and those
+          on the right, but that boundary is currently not handled on
+          NS.  */
+       continue;
+
+      if (nb_buttons > 9)
+       {
+         *error_name = "Too many dialog items";
+         return;
+       }
+
+      [self addButton: SSDATA (item_name)
+               value: (NSInteger) aref_addr (menu_items, i)
+                 row: row++
+              enable: !NILP (enable)];
+
+      i += MENU_ITEMS_ITEM_LENGTH;
+      nb_buttons++;
     }
 }
 
 
-- (void)addButton: (char *)str value: (int)tag row: (int)row
+- (void) addButton: (char *) str value: (NSInteger) tag
+              row: (int) row enable: (BOOL) enable
 {
   id cell;
 
@@ -1771,7 +1787,8 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, 
Lisp_Object contents)
       [matrix addRow];
       rows++;
     }
-  cell = [matrix cellAtRow: row column: cols-1];
+
+  cell = [matrix cellAtRow: row column: cols - 1];
   [cell setTarget: self];
   [cell setAction: @selector (clicked: )];
   [cell setTitle: [NSString stringWithUTF8String: str]];
@@ -1781,7 +1798,7 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, 
Lisp_Object contents)
 }
 
 
-- (void)addString: (char *)str row: (int)row
+- (void)addString: (char *) str row: (int) row
 {
   id cell;
 
@@ -1804,96 +1821,94 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, 
Lisp_Object contents)
 }
 
 
-- (void)clicked: sender
+- (void) clicked: sender
 {
   NSArray *sellist = nil;
-  EMACS_INT seltag;
+  NSUInteger seltag;
+  Lisp_Object *selarray;
 
   sellist = [sender selectedCells];
+
   if ([sellist count] < 1)
     return;
 
   seltag = [[sellist objectAtIndex: 0] tag];
-  dialog_return = button_values[seltag];
-  [NSApp stop:self];
+  selarray = (void *) seltag;
+  dialog_return = selarray[MENU_ITEMS_ITEM_VALUE];
+  [NSApp stop: self];
 }
 
 
-- (instancetype)initFromContents: (Lisp_Object)contents isQuestion: (BOOL)isQ
+- (instancetype) initWithTitle: (char *) title_string
+                   isQuestion: (BOOL) is_question
 {
-  Lisp_Object head;
   [super init];
 
-  if (CONSP (contents))
-    {
-      head = Fcar (contents);
-      [self process_dialog: Fcdr (contents)];
-    }
-  else
-    head = contents;
-
-  if (STRINGP (head))
-      [title setStringValue:
-                 [NSString stringWithUTF8String: SSDATA (head)]];
-  else if (isQ == YES)
-      [title setStringValue: @"Question"];
+  if (title_string)
+    [title setStringValue:
+            [NSString stringWithUTF8String: title_string]];
+  else if (is_question)
+    [title setStringValue: @"Question"];
   else
-      [title setStringValue: @"Information"];
+    [title setStringValue: @"Information"];
 
-  {
-    int i;
-    NSRect r, s, t;
+  return self;
+}
 
-    if (cols == 1 && rows > 1) /* Never told where to split.  */
-      {
-        [matrix addColumn];
-        for (i = 0; i < rows/2; i++)
-          {
-            [matrix putCell: [matrix cellAtRow: (rows+1)/2 column: 0]
-                      atRow: i column: 1];
-            [matrix removeRow: (rows+1)/2];
-          }
-      }
+- (void) resizeBoundsPriorToDisplay
+{
+  int i;
+  NSRect r, s, t;
+  NSSize csize;
 
-    [matrix sizeToFit];
+  if (cols == 1 && rows > 1)
     {
-      NSSize csize = [matrix cellSize];
-      if (csize.width < MINCELLWIDTH)
-        {
-          csize.width = MINCELLWIDTH;
-          [matrix setCellSize: csize];
-          [matrix sizeToCells];
-        }
+      [matrix addColumn];
+      for (i = 0; i < rows / 2; i++)
+       {
+         [matrix putCell: [matrix cellAtRow: (rows + 1) /2
+                                     column: 0]
+                   atRow: i column: 1];
+         [matrix removeRow: (rows + 1) / 2];
+       }
     }
 
-    [title sizeToFit];
-    [command sizeToFit];
+  [matrix sizeToFit];
 
-    t = [matrix frame];
-    r = [title frame];
-    if (r.size.width+r.origin.x > t.size.width+t.origin.x)
-      {
-        t.origin.x   = r.origin.x;
-        t.size.width = r.size.width;
-      }
-    r = [command frame];
-    if (r.size.width+r.origin.x > t.size.width+t.origin.x)
-      {
-        t.origin.x   = r.origin.x;
-        t.size.width = r.size.width;
-      }
+  csize = [matrix cellSize];
+  if (csize.width < MINCELLWIDTH)
+    {
+      csize.width = MINCELLWIDTH;
+      [matrix setCellSize: csize];
+      [matrix sizeToCells];
+    }
 
-    r = [self frame];
-    s = [(NSView *)[self contentView] frame];
-    r.size.width  += t.origin.x+t.size.width +2*SPACER-s.size.width;
-    r.size.height += t.origin.y+t.size.height+SPACER-s.size.height;
-    [self setFrame: r display: NO];
-  }
+  [title sizeToFit];
+  [command sizeToFit];
 
-  return self;
-}
+  t = [matrix frame];
+  r = [title frame];
+  if (r.size.width + r.origin.x > t.size.width + t.origin.x)
+    {
+      t.origin.x = r.origin.x;
+      t.size.width = r.size.width;
+    }
 
+  r = [command frame];
+  if (r.size.width + r.origin.x > t.size.width + t.origin.x)
+    {
+      t.origin.x = r.origin.x;
+      t.size.width = r.size.width;
+    }
 
+  r = [self frame];
+  s = [(NSView *) [self contentView] frame];
+  r.size.width += (t.origin.x + t.size.width
+                  + 2 * SPACER - s.size.width);
+  r.size.height += (t.origin.y + t.size.height
+                   + SPACER - s.size.height);
+  [self setFrame: r display: NO];
+}
 
 - (void)timeout_handler: (NSTimer *)timedEntry
 {
@@ -1911,11 +1926,11 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, 
Lisp_Object contents)
   /* We use stop 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 stop: self];
   [NSApp postEvent: nxev atStart: NO];
 }
 
-- (Lisp_Object)runDialogAt: (NSPoint)p
+- (Lisp_Object) runDialogAt: (NSPoint) p
 {
   Lisp_Object ret = Qundefined;
 
@@ -1935,13 +1950,17 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, 
Lisp_Object contents)
           [[NSRunLoop currentRunLoop] addTimer: tmo
                                        forMode: NSModalPanelRunLoopMode];
         }
+
       timer_fired = NO;
       dialog_return = Qundefined;
       [NSApp runModalForWindow: self];
       ret = dialog_return;
-      if (! timer_fired)
+
+      if (!timer_fired)
         {
-          if (tmo != nil) [tmo invalidate]; /* Cancels timer.  */
+          if (tmo != nil)
+           [tmo invalidate]; /* Cancels timer.  */
+
           break;
         }
     }
diff --git a/src/nsterm.h b/src/nsterm.h
index 1135225e7b..2c46298a93 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -574,22 +574,32 @@ typedef id instancetype;
    ========================================================================== 
*/
 
 @interface EmacsDialogPanel : NSPanel
-   {
-   NSTextField *command;
-   NSTextField *title;
-   NSMatrix *matrix;
-   int rows, cols;
-   BOOL timer_fired, window_closed;
-   Lisp_Object dialog_return;
-   Lisp_Object *button_values;
-   }
-- (instancetype)initFromContents: (Lisp_Object)menu isQuestion: (BOOL)isQ;
-- (void)process_dialog: (Lisp_Object)list;
-- (void)addButton: (char *)str value: (int)tag row: (int)row;
-- (void)addString: (char *)str row: (int)row;
-- (void)addSplit;
-- (Lisp_Object)runDialogAt: (NSPoint)p;
-- (void)timeout_handler: (NSTimer *)timedEntry;
+{
+  NSTextField *command;
+  NSTextField *title;
+  NSMatrix *matrix;
+  int rows, cols;
+  BOOL timer_fired, window_closed;
+  Lisp_Object dialog_return;
+}
+
+- (instancetype) initWithTitle: (char *) title_str
+                   isQuestion: (BOOL) is_question;
+- (void) processMenuItems: (Lisp_Object) menu_items
+                    used: (ptrdiff_t) menu_items_used
+         withErrorOutput: (const char **) error_name;
+
+- (void) addButton: (char *) str
+            value: (NSInteger) tag
+              row: (int) row
+           enable: (BOOL) enable;
+- (void) addString: (char *) str
+              row: (int) row;
+- (void) addSplit;
+- (void) resizeBoundsPriorToDisplay;
+
+- (Lisp_Object) runDialogAt: (NSPoint) p;
+- (void) timeout_handler: (NSTimer *) timedEntry;
 @end
 
 #ifdef NS_IMPL_COCOA



reply via email to

[Prev in Thread] Current Thread [Next in Thread]