summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Rumney <jasonr@gnu.org>2008-04-10 15:20:07 +0000
committerJason Rumney <jasonr@gnu.org>2008-04-10 15:20:07 +0000
commit31403b2446c0f130398c64bdfd3a0b81cc87baac (patch)
tree1b4534a04bd1c1da4a42fda014d4bbff85d0fc45 /src
parenta45868562f9b4719c61512cd646db476ca4a0dad (diff)
downloademacs-31403b2446c0f130398c64bdfd3a0b81cc87baac.tar.gz
(is_simple_dialog, simple_dialog_show): New functions.
(Fx_popup_dialog): Handle simple yes/no questions as dialogs.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog3
-rw-r--r--src/w32menu.c181
2 files changed, 163 insertions, 21 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index f36731450d4..34edb2370b3 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,8 @@
2008-04-10 Jason Rumney <jasonr@gnu.org>
+ * w32menu.c (is_simple_dialog, simple_dialog_show): New functions.
+ (Fx_popup_dialog): Handle simple yes/no questions as dialogs.
+
* w32.c (logon_network_drive): Also logon to remote drives that
are mapped to drive letters.
diff --git a/src/w32menu.c b/src/w32menu.c
index f4857eb9d10..1f8561210c1 100644
--- a/src/w32menu.c
+++ b/src/w32menu.c
@@ -168,22 +168,28 @@ extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
extern Lisp_Object Qmenu_bar_update_hook;
-void set_frame_menubar ();
+void set_frame_menubar P_ ((FRAME_PTR, int, int));
static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object));
#ifdef HAVE_DIALOGS
-static Lisp_Object w32_dialog_show ();
+static Lisp_Object w32_dialog_show P_ ((FRAME_PTR, int, Lisp_Object, char**));
+#else
+static int is_simple_dialog P_ ((Lisp_Object));
+static Lisp_Object simple_dialog_show P_ ((FRAME_PTR, Lisp_Object, Lisp_Object));
#endif
-static Lisp_Object w32_menu_show ();
-
-static void keymap_panes ();
-static void single_keymap_panes ();
-static void single_menu_item ();
-static void list_of_panes ();
-static void list_of_items ();
-void w32_free_menu_strings (HWND);
+static Lisp_Object w32_menu_show P_ ((FRAME_PTR, int, int, int, int,
+ Lisp_Object, char **));
+
+static void keymap_panes P_ ((Lisp_Object *, int, int));
+static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
+ int, int));
+static void single_menu_item P_ ((Lisp_Object, Lisp_Object,
+ Lisp_Object *, int, int));
+static void list_of_panes P_ ((Lisp_Object));
+static void list_of_items P_ ((Lisp_Object));
+void w32_free_menu_strings P_((HWND));
/* This holds a Lisp vector that holds the results of decoding
the keymaps or alist-of-alists that specify a menu.
@@ -928,17 +934,23 @@ otherwise it is "Question". */)
CHECK_WINDOW (window);
#ifndef HAVE_DIALOGS
- /* Display a menu with these alternatives
- in the middle of frame F. */
+
{
- Lisp_Object x, y, frame, newpos;
- XSETFRAME (frame, f);
- XSETINT (x, x_pixel_width (f) / 2);
- XSETINT (y, x_pixel_height (f) / 2);
- newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil));
-
- return Fx_popup_menu (newpos,
- Fcons (Fcar (contents), Fcons (contents, Qnil)));
+ /* Handle simple Yes/No choices as MessageBox popups. */
+ if (is_simple_dialog (contents))
+ return simple_dialog_show (f, contents, header);
+ else
+ {
+ /* Display a menu with these alternatives
+ in the middle of frame F. */
+ Lisp_Object x, y, frame, newpos;
+ XSETFRAME (frame, f);
+ XSETINT (x, x_pixel_width (f) / 2);
+ XSETINT (y, x_pixel_height (f) / 2);
+ newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil));
+ return Fx_popup_menu (newpos,
+ Fcons (Fcar (contents), Fcons (contents, Qnil)));
+ }
}
#else /* HAVE_DIALOGS */
{
@@ -2001,6 +2013,29 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
#ifdef HAVE_DIALOGS
+/* TODO: On Windows, there are two ways of defining a dialog.
+
+ 1. Create a predefined dialog resource and include it in nt/emacs.rc.
+ Using this method, we could then set the titles and make unneeded
+ buttons invisible before displaying the dialog. Everything would
+ be a fixed size though, so there is a risk that text does not
+ fit on a button.
+ 2. Create the dialog template in memory on the fly. This allows us
+ to size the dialog and buttons dynamically, probably giving more
+ natural looking results for dialogs with few buttons, and eliminating
+ the problem of text overflowing the buttons. But the API for this is
+ quite complex - structures have to be allocated in particular ways,
+ text content is tacked onto the end of structures in variable length
+ arrays with further structures tacked on after these, there are
+ certain alignment requirements for all this, and we have to
+ measure all the text and convert to "dialog coordinates" to figure
+ out how big to make everything.
+
+ For now, we'll just stick with menus for dialogs that are more
+ complicated than simple yes/no type questions for which we can use
+ the MessageBox function.
+*/
+
static char * button_names [] = {
"button1", "button2", "button3", "button4", "button5",
"button6", "button7", "button8", "button9", "button10" };
@@ -2192,7 +2227,111 @@ w32_dialog_show (f, keymaps, title, header, error)
return Qnil;
}
-#endif /* HAVE_DIALOGS */
+#else /* !HAVE_DIALOGS */
+
+/* Currently we only handle Yes No dialogs (y-or-n-p and yes-or-no-p) as
+ simple dialogs. We could handle a few more, but I'm not aware of
+ anywhere in Emacs that uses the other specific dialog choices that
+ MessageBox provides. */
+
+static int is_simple_dialog (contents)
+ Lisp_Object contents;
+{
+ Lisp_Object options = XCDR (contents);
+ Lisp_Object name, yes, no, other;
+
+ yes = build_string ("Yes");
+ no = build_string ("No");
+
+ if (!CONSP (options))
+ return 0;
+
+ name = XCAR (XCAR (options));
+ if (!CONSP (options))
+ return 0;
+
+ if (!NILP (Fstring_equal (name, yes)))
+ other = no;
+ else if (!NILP (Fstring_equal (name, no)))
+ other = yes;
+ else
+ return 0;
+
+ options = XCDR (options);
+ if (!CONSP (options))
+ return 0;
+
+ name = XCAR (XCAR (options));
+ if (NILP (Fstring_equal (name, other)))
+ return 0;
+
+ /* Check there are no more options. */
+ options = XCDR (options);
+ return !(CONSP (options));
+}
+
+static Lisp_Object simple_dialog_show (f, contents, header)
+ FRAME_PTR f;
+ Lisp_Object contents, header;
+{
+ int answer;
+ UINT type;
+ char *text, *title;
+ Lisp_Object lispy_answer = Qnil, temp = XCAR (contents);
+
+ if (STRINGP (temp))
+ text = SDATA (temp);
+ else
+ text = "";
+
+ if (NILP (header))
+ {
+ title = "Question";
+ type = MB_ICONQUESTION;
+ }
+ else
+ {
+ title = "Information";
+ type = MB_ICONINFORMATION;
+ }
+ type |= MB_YESNO;
+
+ /* Since we only handle Yes/No dialogs, and we already checked
+ is_simple_dialog, we don't need to worry about checking contents
+ to see what type of dialog to use. */
+ answer = MessageBox (FRAME_W32_WINDOW (f), text, title, type);
+
+ if (answer == IDYES)
+ lispy_answer = build_string ("Yes");
+ else if (answer == IDNO)
+ lispy_answer = build_string ("No");
+ else
+ Fsignal (Qquit, Qnil);
+
+ for (temp = XCDR (contents); CONSP (temp); temp = XCDR (temp))
+ {
+ Lisp_Object item, name, value;
+ item = XCAR (temp);
+ if (CONSP (item))
+ {
+ name = XCAR (item);
+ value = XCDR (item);
+ }
+ else
+ {
+ name = item;
+ value = Qnil;
+ }
+
+ if (!NILP (Fstring_equal (name, lispy_answer)))
+ {
+ return value;
+ }
+ }
+ Fsignal (Qquit, Qnil);
+ return Qnil;
+}
+#endif /* !HAVE_DIALOGS */
/* Is this item a separator? */