|
|
1.1 root 1: /* X Communication module for terminals which understand the X protocol.
2: Copyright (C) 1986 Free Software Foundation, Inc.
3:
4: This file is part of GNU Emacs.
5:
6: GNU Emacs is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU Emacs General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU Emacs, but only under the conditions described in the
15: GNU Emacs General Public License. A copy of this license is
16: supposed to have been given to you along with GNU Emacs so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies.
20:
21: * X pop-up deck-of-cards menu facility for gnuemacs.
22: *
23: * Written by Jon Arnold and Roman Budzianowski
24: * Mods and rewrite by Robert Krawitz
25: *
26: */
27:
28: /* $Source: /@/orpheus/u1/X11/clients/emacs/RCS/xmenu.c,v $
29: * $Author: newman $
30: * $Locker: $
31: * $Header: xmenu.c,v 1.1 87/09/12 16:33:40 newman Exp $
32: *
33: */
34:
35: #ifndef lint
36: static char *rcsid_GXMenu_c = "$Header: xmenu.c,v 1.1 87/09/12 16:33:40 newman Exp $";
37: #endif lint
38:
39: #ifdef HAVE_X_MENU
40:
41: #include "config.h"
42: #include <signal.h>
43: #include "xterm.h"
44:
45: /* Load sys/types.h if not already loaded.
46: In some systems loading it twice is suicidal. */
47: #ifndef makedev
48: #include <sys/types.h>
49: #endif
50:
51: #include <stdio.h>
52: #undef NULL
53: #include "dispextern.h"
54: #include <sys/time.h>
55: #include <fcntl.h>
56: #include "lisp.h"
57: #include "window.h"
58: #include <X11/XMenu.h>
59:
60: #define min(x,y) (((x) < (y)) ? (x) : (y))
61: #define max(x,y) (((x) > (y)) ? (x) : (y))
62:
63: #define NUL 0
64:
65: #ifndef TRUE
66: #define TRUE 1
67: #define FALSE 0
68: #endif TRUE
69: extern Display *XXdisplay;
70: extern int XXxoffset,XXyoffset;
71: extern int XXfontw,XXfonth;
72: extern int (*handler)();
73: extern int request_sigio(), unrequest_sigio();
74:
75: /*************************************************************/
76:
77: XMenuQuit ()
78: {
79: error("Unknown XMenu error");
80: }
81:
82: DEFUN ("x-popup-menu",Fx_popup_menu, Sx_popup_menu, 1, 2, 0,
83: "Interface to XMenu library; permits creation and use of\n\
84: deck-of-cards pop-up menus.\n\
85: \n\
86: ARG is a position specification; it is a list of (Xoffset, Yoffset)\n\
87: from the top-left corner of the editor window. Note that this offset\n\
88: is relative to the center of the first line in the first pane of the\n\
89: menu, not the top left of the menu as a whole.\n\
90: \n\
91: MENU is a specifier for a menu. It is a list of the form\n\
92: (title pane1 pane2...), and each pane is a list of form\n\
93: (title (line item)...). Each line should be a string, and item should\n\
94: be the return value for that line (i. e. if it is selected.")
95: (arg,menu)
96: Lisp_Object arg,menu;
97: {
98: int number_of_panes;
99: Lisp_Object XMenu_return;
100: int XMenu_xpos,XMenu_ypos;
101: char **menus;
102: char ***names;
103: Lisp_Object **obj_list;
104: int *items;
105: char *title;
106: char *error_name;
107: Lisp_Object ltitle, selection;
108: extern Lisp_Object Vx_mouse_abs_pos;
109: Lisp_Object XEmacsMenu();
110: int i;
111: int mask;
112:
113: check_xterm();
114: XMenu_xpos = XINT(Fcar(Vx_mouse_abs_pos));
115: XMenu_ypos = XINT(Fcar(Fcdr (Vx_mouse_abs_pos)));
116: ltitle = Fcar(menu);
117: CHECK_STRING(ltitle,1);
118: title = (char *) XSTRING(ltitle)->data;
119: /* title = (char *) xmalloc ((XSTRING(ltitle)->size + 1) * sizeof(char));
120: bcopy (XSTRING(ltitle)->data, title, XSTRING(ltitle)->size); */
121: number_of_panes=list_of_panes(&obj_list, &menus, &names, &items, Fcdr(menu));
122: #ifdef XDEBUG
123: fprintf(stderr,"Panes= %d\n", number_of_panes);
124: for(i=0; i < number_of_panes; i++)
125: {
126: fprintf (stderr,"Pane %d lines %d title %s\n", i, items[i], menus[i]);
127: for (j=0; j < items[i]; j++)
128: {
129: fprintf (stderr," Item %d %s\n", j, names[i][j]);
130: }
131: }
132: #endif
133: mask = sigblock (sigmask (SIGIO));
134: XSetErrorHandler(XMenuQuit);
135: selection = XEmacsMenu(RootWindow(XXdisplay,0), XMenu_xpos, XMenu_ypos, names, menus,
136: items, number_of_panes, obj_list ,title, &error_name);
137: XSetErrorHandler(handler);
138: sigsetmask (mask);
139: /** fprintf(stderr,"selection = %x\n",selection); **/
140: if (selection != NUL)
141: { /* selected something */
142: XMenu_return = selection;
143: }
144: else
145: { /* nothing selected */
146: XMenu_return = Qnil;
147: }
148: /* now free up the strings */
149: for (i=0; i < number_of_panes; i++)
150: {
151: free(names[i]);
152: free(obj_list[i]);
153: }
154: free(menus);
155: free(obj_list);
156: free(names);
157: free(items);
158: /* free(title); */
159: if (error_name) error(error_name);
160: return XMenu_return;
161: }
162:
163: struct indices {
164: int pane;
165: int line;
166: };
167:
168: Lisp_Object
169: XEmacsMenu(parent, startx, starty, line_list, pane_list, line_cnt,
170: pane_cnt, item_list, title, errorstr)
171: Window parent;
172: int startx, starty; /* upper left corner position BROKEN */
173: char **line_list[]; /* list of strings for items */
174: char *pane_list[]; /* list of pane titles */
175: char *title;
176: int pane_cnt; /* total number of panes */
177: Lisp_Object *item_list[]; /* All items */
178: int line_cnt[]; /* Lines in each pane */
179: char **errorstr; /* Error returned */
180: {
181: XMenu *GXMenu;
182: int panes, sel, lpane, status;
183: Lisp_Object entry;
184: /* struct indices *datap, *datap_save; */
185: char *datap;
186:
187: *errorstr = (char *) 0; /* Initialize errorstr pointer to null */
188: if ((GXMenu = XMenuCreate(XXdisplay, parent, "emacs" )) == NUL )
189: {
190: *errorstr = "Can't create menu";
191: /* error("Can't create menu"); */
192: return(0);
193: }
194:
195: for (panes=0; panes < pane_cnt; panes++ )
196: ;
197: /* datap = (struct indices *) xmalloc (lines * sizeof(struct indices)); */
198: /*datap = (char *) xmalloc(lines * sizeof(char));
199: datap_save = datap;*/
200:
201: for (panes = 0;panes < pane_cnt; panes++ )
202: {
203: /* create all the necessary panes */
204: if ((lpane= XMenuAddPane(XXdisplay, GXMenu, pane_list[panes] , TRUE ))
205: == XM_FAILURE)
206: {
207: XMenuDestroy(XXdisplay, GXMenu);
208: *errorstr = "Can't create pane";
209: /* error("Can't create pane"); */
210: /* free(datap); */
211: return(0);
212: }
213: for ( sel = 0; sel < line_cnt[panes] ; sel++ )
214: {
215: /* add the selection stuff to the menus */
216: /* datap[sel+sofar].pane = panes;
217: datap[sel+sofar].line = sel; */
218: if (XMenuAddSelection(XXdisplay, GXMenu, lpane, 0, line_list[panes][sel], TRUE)
219: == XM_FAILURE)
220: {
221: XMenuDestroy(XXdisplay, GXMenu);
222: /* free(datap); */
223: *errorstr = "Can't add selection to menu";
224: /* error ("Can't add selection to menu"); */
225: return(0);
226: }
227: }
228: }
229: /* all set and ready to fly */
230: XMenuSetFreeze(GXMenu, TRUE);
231: XMenuRecompute(XXdisplay,GXMenu);
232: panes = sel = 0;
233:
234: status = XMenuActivate(XXdisplay, GXMenu, &panes, &sel, startx, starty,
235: ButtonReleaseMask, &datap);
236: switch (status ) {
237: case XM_SUCCESS:
238: #ifdef XDEBUG
239: fprintf (stderr, "pane= %d line = %d\n", panes, sel);
240: #endif
241: entry = item_list[panes][sel];
242: break;
243: case XM_FAILURE:
244: /*free (datap_save); */
245: /*XMenuDestroy(XXdisplay, GXMenu);*/
246: *errorstr = "Can't activate menu";
247: /* error("Can't activate menu"); */
248: case XM_IA_SELECT:
249: case XM_NO_SELECT:
250: entry = Qnil;
251: break;
252: }
253: XMenuDestroy(XXdisplay, GXMenu);
254: XFlush(XXdisplay);
255: if (XPending(XXdisplay))
256: read_events_block();
257: /*free(datap_save);*/
258: return(entry);
259: }
260:
261: syms_of_xmenu ()
262: {
263: defsubr (&Sx_popup_menu);
264: }
265:
266: list_of_panes (vector, panes, names, items, menu)
267: Lisp_Object ***vector; /* RETURN all menu objects */
268: char ***panes; /* RETURN pane names */
269: char ****names; /* RETURN all line names */
270: int **items; /* RETURN number of items per pane */
271: Lisp_Object menu;
272: {
273: Lisp_Object tail, item, item1;
274: int i;
275:
276: if (XTYPE (menu) != Lisp_Cons) menu = wrong_type_argument(Qlistp, item);
277:
278: i= XFASTINT(Flength(menu,1));
279:
280: *vector = (Lisp_Object **) xmalloc(i * sizeof (Lisp_Object *));
281: *panes = (char **) xmalloc(i * sizeof (char *));
282: *items = (int *) xmalloc(i * sizeof (int));
283: *names = (char ***) xmalloc(i * sizeof (char **));
284:
285: for (i=0,tail = menu; !NULL (tail); tail = Fcdr (tail), i++)
286: {
287: item = Fcdr(Fcar(tail));
288: if (XTYPE (item) != Lisp_Cons) (void) wrong_type_argument(Qlistp, item);
289: #ifdef XDEBUG
290: fprintf (stderr, "list_of_panes check tail, i=%d\n", i);
291: #endif
292: item1 = Fcar(Fcar(tail));
293: CHECK_STRING (item1, 1);
294: #ifdef XDEBUG
295: fprintf (stderr, "list_of_panes check pane, i=%d%s\n", i,
296: XSTRING(item1)->data);
297: #endif
298: (*panes)[i] = (char *) XSTRING(item1)->data;
299: (*items)[i] = list_of_items ((*vector)+i, (*names)+i, item);
300: /* (*panes)[i] = (char *) xmalloc((XSTRING(item1)->size)+1);
301: bcopy (XSTRING (item1)->data, (*panes)[i], XSTRING(item1)->size + 1)
302: ; */
303: }
304: return i;
305: }
306:
307:
308: list_of_items (vector,names,pane) /* get list from emacs and put to vector */
309: Lisp_Object **vector; /* RETURN menu "objects" */
310: char ***names; /* RETURN line names */
311: Lisp_Object pane;
312: {
313: Lisp_Object tail, item, item1;
314: int i;
315:
316: if (XTYPE (pane) != Lisp_Cons) pane = wrong_type_argument(Qlistp, item);
317:
318: i= XFASTINT(Flength(pane,1));
319:
320: *vector = (Lisp_Object *) xmalloc(i * sizeof (Lisp_Object));
321: *names = (char **) xmalloc(i * sizeof (char *));
322:
323: for (i=0,tail = pane; !NULL (tail); tail = Fcdr (tail), i++)
324: {
325: item = Fcar(tail);
326: if (XTYPE (item) != Lisp_Cons) (void) wrong_type_argument(Qlistp, item);
327: #ifdef XDEBUG
328: fprintf (stderr, "list_of_items check tail, i=%d\n", i);
329: #endif
330: (*vector)[i] = Fcdr (item);
331: item1 = Fcar(item);
332: CHECK_STRING (item1, 1);
333: #ifdef XDEBUG
334: fprintf (stderr, "list_of_items check item, i=%d%s\n", i,
335: XSTRING(item1)->data);
336: #endif
337: (*names)[i] = (char *) XSTRING(item1)->data;
338: /* (*names)[i] = (char *) xmalloc((XSTRING(item1)->size)+1);
339: bcopy (XSTRING (item1)->data, (*names)[i], XSTRING(item1)->size + 1); */
340: }
341: return i;
342: }
343:
344: #endif HAVE_X_MENU
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.