aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFred Pierresteguy1994-03-11 18:01:00 +0000
committerFred Pierresteguy1994-03-11 18:01:00 +0000
commit165e1749b20e7caf149c725db3737a275c3d3170 (patch)
tree429132b965c00217df074176a4b5aefe3860ee69 /src
parentce5a08a1b46e9d059ed7271f9cdbeaf337b30ff9 (diff)
downloademacs-165e1749b20e7caf149c725db3737a275c3d3170.tar.gz
emacs-165e1749b20e7caf149c725db3737a275c3d3170.zip
(xdialog_show): New function to handle the display of dialog boxes.
(Fx_popup_dialog): New function. (dialog_selection_callback): New function. (xmenu_show) [USE_X_TOOLKIT]: Don't call lw_destroy_all_widgets at the end. Do the work of construct_mouse_click in the ButtonRelease case.
Diffstat (limited to 'src')
-rw-r--r--src/xmenu.c337
1 files changed, 337 insertions, 0 deletions
diff --git a/src/xmenu.c b/src/xmenu.c
index eb9122b2d06..43811e751b7 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -94,6 +94,7 @@ extern void process_expose_from_menu ();
94extern XtAppContext Xt_app_con; 94extern XtAppContext Xt_app_con;
95 95
96static int string_width (); 96static int string_width ();
97static Lisp_Object xdialog_show ();
97#endif 98#endif
98 99
99static Lisp_Object xmenu_show (); 100static Lisp_Object xmenu_show ();
@@ -826,6 +827,133 @@ cached information about equivalent key sequences.")
826 if (error_name) error (error_name); 827 if (error_name) error (error_name);
827 return selection; 828 return selection;
828} 829}
830
831DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 1, 2, 0,
832 "Pop up a dialog box and return user's selection.\n\
833POSITION is a position specification. This is either a mouse button event\n\
834or a list ((XOFFSET YOFFSET) WINDOW)\n\
835where XOFFSET and YOFFSET are positions in characters from the top left\n\
836corner of WINDOW's frame. (WINDOW may be a frame object instead of a window.)\n\
837This controls the position of the center of the first line\n\
838in the first pane of the menu, not the top left of the menu as a whole.\n\
839If POSITION is t, it means to use the current mouse position.\n\
840\n\
841MENU is a specifier for a menu. For the simplest case, MENU is a keymap.\n\
842The menu items come from key bindings that have a menu string as well as\n\
843a definition; actually, the \"definition\" in such a key binding looks like\n\
844\(STRING . REAL-DEFINITION). To give the menu a title, put a string into\n\
845the keymap as a top-level element.\n\n\
846You can also use a list of keymaps as MENU.\n\
847 Then each keymap makes a separate pane.\n\
848When MENU is a keymap or a list of keymaps, the return value\n\
849is a list of events.\n\n\
850Alternatively, you can specify a menu of multiple panes\n\
851 with a list of the form (TITLE PANE1 PANE2...),\n\
852where each pane is a list of form (TITLE ITEM1 ITEM2...).\n\
853Each ITEM is normally a cons cell (STRING . VALUE);\n\
854but a string can appear as an item--that makes a nonselectable line\n\
855in the menu.\n\
856With this form of menu, the return value is VALUE from the chosen item.\n\
857\n\
858If POSITION is nil, don't display the menu at all, just precalculate the\n\
859cached information about equivalent key sequences.")
860 (position, menu)
861 Lisp_Object position, menu;
862{
863 int number_of_panes, panes;
864 Lisp_Object keymap, tem;
865 int xpos, ypos;
866 Lisp_Object title;
867 char *error_name;
868 Lisp_Object selection;
869 int i, j;
870 FRAME_PTR f;
871 Lisp_Object x, y, window;
872 int keymaps = 0;
873 int menubarp = 0;
874 struct gcpro gcpro1;
875
876 check_x ();
877
878 if (! NILP (position))
879 {
880 /* Decode the first argument: find the window and the coordinates. */
881 if (EQ (position, Qt))
882 {
883 /* Use the mouse's current position. */
884 FRAME_PTR new_f;
885 Lisp_Object bar_window;
886 int part;
887 unsigned long time;
888
889 (*mouse_position_hook) (&new_f, &bar_window, &part, &x, &y, &time);
890 XSET (window, Lisp_Frame, new_f);
891 }
892
893 CHECK_NUMBER (x, 0);
894 CHECK_NUMBER (y, 0);
895
896 /* Decode where to put the menu. */
897
898 if (XTYPE (window) == Lisp_Frame)
899 {
900 f = XFRAME (window);
901
902 xpos = 0;
903 ypos = 0;
904 }
905 else if (XTYPE (window) == Lisp_Window)
906 {
907 CHECK_LIVE_WINDOW (window, 0);
908 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
909
910 xpos = (FONT_WIDTH (f->display.x->font) * XWINDOW (window)->left);
911 ypos = (FONT_HEIGHT (f->display.x->font) * XWINDOW (window)->top);
912 }
913 else
914 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
915 but I don't want to make one now. */
916 CHECK_WINDOW (window, 0);
917
918 xpos += XINT (x);
919 ypos += XINT (y);
920 }
921
922 title = Qnil;
923 GCPRO1 (title);
924
925 /* Decode the dialog items from what was specified. */
926 {
927 /* We were given an old-fashioned menu. */
928 title = Fcar (menu);
929 CHECK_STRING (title, 1);
930
931 list_of_panes (Fcdr (menu));
932
933 keymaps = 0;
934 }
935
936 if (NILP (position))
937 {
938 discard_menu_items ();
939 UNGCPRO;
940 return Qnil;
941 }
942
943 /* Display them in a dialog box. */
944 BLOCK_INPUT;
945
946 selection = xdialog_show (f, xpos, ypos, menubarp,
947 keymaps, title, &error_name);
948 UNBLOCK_INPUT;
949
950 discard_menu_items ();
951
952 UNGCPRO;
953
954 if (error_name) error (error_name);
955 return selection;
956}
829 957
830#ifdef USE_X_TOOLKIT 958#ifdef USE_X_TOOLKIT
831 959
@@ -939,6 +1067,19 @@ popup_down_callback (widget, id, client_data)
939 UNBLOCK_INPUT; 1067 UNBLOCK_INPUT;
940} 1068}
941 1069
1070static void
1071dialog_selection_callback (widget, id, client_data)
1072 Widget widget;
1073 LWLIB_ID id;
1074 XtPointer client_data;
1075{
1076 if ((int)client_data != -1)
1077 menu_item_selection = (Lisp_Object *) client_data;
1078 BLOCK_INPUT;
1079 lw_destroy_all_widgets (id);
1080 UNBLOCK_INPUT;
1081}
1082
942/* This recursively calls free_widget_value() on the tree of widgets. 1083/* This recursively calls free_widget_value() on the tree of widgets.
943 It must free all data that was malloc'ed for these widget_values. 1084 It must free all data that was malloc'ed for these widget_values.
944 In Emacs, many slots are pointers into the data of Lisp_Strings, and 1085 In Emacs, many slots are pointers into the data of Lisp_Strings, and
@@ -1186,6 +1327,9 @@ check_mouse_other_menu_bar (f)
1186 1327
1187#ifdef USE_X_TOOLKIT 1328#ifdef USE_X_TOOLKIT
1188 1329
1330extern unsigned int x_mouse_grabbed;
1331extern Lisp_Object Vmouse_depressed;
1332
1189static Lisp_Object 1333static Lisp_Object
1190xmenu_show (f, x, y, menubarp, keymaps, title, error) 1334xmenu_show (f, x, y, menubarp, keymaps, title, error)
1191 FRAME_PTR f; 1335 FRAME_PTR f;
@@ -1426,6 +1570,16 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error)
1426 if (event.type == ButtonRelease) 1570 if (event.type == ButtonRelease)
1427 { 1571 {
1428 XtDispatchEvent (&event); 1572 XtDispatchEvent (&event);
1573 if (! menubarp)
1574 {
1575 /* Do the work of construct_mouse_click since it can't
1576 be called. Initially, the popup menu has been called
1577 from a ButtonPress in the edit_widget. Then the mouse
1578 has been set to grabbed. Reset it now. */
1579 x_mouse_grabbed &= ~(1 << event.xbutton.button);
1580 if (!x_mouse_grabbed)
1581 Vmouse_depressed = Qnil;
1582 }
1429 break; 1583 break;
1430 } 1584 }
1431 else if (event.type == Expose) 1585 else if (event.type == Expose)
@@ -1481,8 +1635,10 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error)
1481 dispatch_dummy_expose (f->display.x->menubar_widget, x, y); 1635 dispatch_dummy_expose (f->display.x->menubar_widget, x, y);
1482 } 1636 }
1483 1637
1638#if 0 /* No need to do that. The menu has disappeared. */
1484 /* Make sure the menu disappears. */ 1639 /* Make sure the menu disappears. */
1485 lw_destroy_all_widgets (menu_id); 1640 lw_destroy_all_widgets (menu_id);
1641#endif
1486 1642
1487 /* Unread any events that we got but did not handle. */ 1643 /* Unread any events that we got but did not handle. */
1488 while (queue != NULL) 1644 while (queue != NULL)
@@ -1548,6 +1704,186 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error)
1548 return Qnil; 1704 return Qnil;
1549} 1705}
1550 1706
1707static char * button_names [] = {
1708 "button1", "button2", "button3", "button4", "button5",
1709 "button6", "button7", "button8", "button9", "button10" };
1710
1711static Lisp_Object
1712xdialog_show (f, x, y, menubarp, keymaps, title, error)
1713 FRAME_PTR f;
1714 int x;
1715 int y;
1716 int menubarp;
1717 int keymaps;
1718 Lisp_Object title;
1719 char **error;
1720{
1721 int i, nb_buttons=0;
1722 int dialog_id;
1723 Widget menu;
1724 XlwMenuWidget menubar = (XlwMenuWidget) f->display.x->menubar_widget;
1725
1726 /* This is the menu bar item (if any) that led to this menu. */
1727 widget_value *menubar_item = 0;
1728
1729 widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
1730
1731 /* Define a queue to save up for later unreading
1732 all X events that don't pertain to the menu. */
1733 struct event_queue
1734 {
1735 XEvent event;
1736 struct event_queue *next;
1737 };
1738
1739 struct event_queue *queue = NULL;
1740 struct event_queue *queue_tmp;
1741
1742 *error = NULL;
1743
1744 /* Create a tree of widget_value objects
1745 representing the text label and buttons. */
1746 {
1747 Lisp_Object pane_name, prefix;
1748 char *pane_string;
1749 pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME];
1750 prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX];
1751 pane_string = (NILP (pane_name)
1752 ? "" : (char *) XSTRING (pane_name)->data);
1753 prev_wv = malloc_widget_value ();
1754 prev_wv->value = pane_string;
1755 if (keymaps && !NILP (prefix))
1756 prev_wv->name++;
1757 prev_wv->enabled = 1;
1758 prev_wv->name = "message";
1759 first_wv = prev_wv;
1760
1761 /* Loop over all panes and items, filling in the tree. */
1762 i = MENU_ITEMS_PANE_LENGTH;
1763 while (i < menu_items_used)
1764 {
1765
1766 /* Create a new item within current pane. */
1767 Lisp_Object item_name, enable, descrip;
1768 item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
1769 enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
1770 descrip
1771 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
1772
1773 wv = malloc_widget_value ();
1774 prev_wv->next = wv;
1775 wv->name = (char *) button_names [nb_buttons];
1776 if (!NILP (descrip))
1777 wv->key = XSTRING (descrip)->data;
1778 wv->value = XSTRING (item_name)->data;
1779 wv->call_data = (void *) &XVECTOR (menu_items)->contents[i];
1780 wv->enabled = !NILP (enable);
1781 prev_wv = wv;
1782
1783 nb_buttons++;
1784 i += MENU_ITEMS_ITEM_LENGTH;
1785 }
1786
1787 wv = malloc_widget_value ();
1788 wv->name = "Q2BR1";
1789 wv->contents = first_wv;
1790 first_wv = wv;
1791
1792 }
1793
1794 /* Actually create the dialog. */
1795 dialog_id = ++popup_id_tick;
1796 menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
1797 f->display.x->widget, 1, 0,
1798 dialog_selection_callback, 0);
1799 lw_modify_all_widgets (dialog_id, first_wv, True);
1800 lw_modify_all_widgets (dialog_id, first_wv->contents, True);
1801 /* Free the widget_value objects we used to specify the contents. */
1802 free_menubar_widget_value_tree (first_wv);
1803
1804 /* No selection has been chosen yet. */
1805 menu_item_selection = 0;
1806
1807
1808 /* Display the menu. */
1809 lw_pop_up_all_widgets (dialog_id);
1810
1811 /* Process events that apply to the menu. */
1812 while (1)
1813 {
1814 XEvent event;
1815
1816 XtAppNextEvent (Xt_app_con, &event);
1817 if (event.type == ButtonRelease)
1818 {
1819 XtDispatchEvent (&event);
1820 break;
1821 }
1822 else if (event.type == Expose)
1823 process_expose_from_menu (event);
1824 XtDispatchEvent (&event);
1825 if (XtWindowToWidget(XDISPLAY event.xany.window) != menu)
1826 {
1827 queue_tmp = (struct event_queue *) malloc (sizeof (struct event_queue));
1828
1829 if (queue_tmp != NULL)
1830 {
1831 queue_tmp->event = event;
1832 queue_tmp->next = queue;
1833 queue = queue_tmp;
1834 }
1835 }
1836 }
1837 pop_down:
1838
1839 /* Unread any events that we got but did not handle. */
1840 while (queue != NULL)
1841 {
1842 queue_tmp = queue;
1843 XPutBackEvent (XDISPLAY &queue_tmp->event);
1844 queue = queue_tmp->next;
1845 free ((char *)queue_tmp);
1846 }
1847
1848 /* Find the selected item, and its pane, to return
1849 the proper value. */
1850 if (menu_item_selection != 0)
1851 {
1852 Lisp_Object prefix;
1853
1854 prefix = Qnil;
1855 i = 0;
1856 while (i < menu_items_used)
1857 {
1858 Lisp_Object entry;
1859
1860 if (EQ (XVECTOR (menu_items)->contents[i], Qt))
1861 {
1862 prefix
1863 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
1864 i += MENU_ITEMS_PANE_LENGTH;
1865 }
1866 else
1867 {
1868 entry
1869 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
1870 if (menu_item_selection == &XVECTOR (menu_items)->contents[i])
1871 {
1872 if (keymaps != 0)
1873 {
1874 entry = Fcons (entry, Qnil);
1875 if (!NILP (prefix))
1876 entry = Fcons (prefix, entry);
1877 }
1878 return entry;
1879 }
1880 i += MENU_ITEMS_ITEM_LENGTH;
1881 }
1882 }
1883 }
1884
1885 return Qnil;
1886}
1551#else /* not USE_X_TOOLKIT */ 1887#else /* not USE_X_TOOLKIT */
1552 1888
1553static Lisp_Object 1889static Lisp_Object
@@ -1761,4 +2097,5 @@ syms_of_xmenu ()
1761 2097
1762 popup_id_tick = (1<<16); 2098 popup_id_tick = (1<<16);
1763 defsubr (&Sx_popup_menu); 2099 defsubr (&Sx_popup_menu);
2100 defsubr (&Sx_popup_dialog);
1764} 2101}