|
|
1.1 root 1: /* X Communication module for terminals which understand the X protocol.
2: Copyright (C) 1986, 1988 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: /u2/third_party/gnuemacs.chow/src/RCS/xmenu.c,v $
29: * $Author: rlk $
30: * $Locker: $
31: * $Header: xmenu.c,v 1.6 86/08/26 17:23:26 rlk Exp $
32: *
33: */
34:
35: #ifndef lint
36: static char *rcsid_GXMenu_c = "$Header: xmenu.c,v 1.6 86/08/26 17:23:26 rlk Exp $";
37: #endif lint
38:
39: /* On 4.3 this loses if it comes after xterm.h. */
40: #include <signal.h>
41: #include "config.h"
42: #include "lisp.h"
43: #include "window.h"
44:
45: /* This may include sys/types.h, and that somehow loses
46: if this is not done before the other system files. */
47: #ifdef X11
48: #include "x11term.h"
49: #else
50: #include "xterm.h"
51: #endif
52:
53: /* Load sys/types.h if not already loaded.
54: In some systems loading it twice is suicidal. */
55: #ifndef makedev
56: #include <sys/types.h>
57: #endif
58:
59: #include "dispextern.h"
60:
61: #ifdef X11
62: #include "../oldXMenu/XMenu.h"
63: #define X11ONLY(arg) arg,
64: #else
65: #include <X/XMenu.h>
66: #define X11ONLY(arg)
67: #endif
68:
69: #include "termopts.h"
70:
71: #define min(x,y) (((x) < (y)) ? (x) : (y))
72: #define max(x,y) (((x) > (y)) ? (x) : (y))
73:
74: #define NUL 0
75:
76: #ifndef TRUE
77: #define TRUE 1
78: #define FALSE 0
79: #endif TRUE
80:
81: #ifdef X11
82: extern XFontStruct *fontinfo;
83: extern Display *XXdisplay;
84: extern Window XXwindow;
85: extern int XXfontw;
86: extern int XXfonth;
87: int XXscreen;
88: #else
89: extern int XXxoffset,XXyoffset;
90: extern FontInfo *fontinfo;
91: #define ButtonRelease ButtonReleased
92: #endif /* not X11 */
93:
94: extern int (*handler)();
95:
96: /*************************************************************/
97:
98: /* Ignoring the args is easiest. */
99: XMenuQuit ()
100: {
101: error("Unknown XMenu error");
102: }
103:
104: DEFUN ("x-popup-menu",Fx_popup_menu, Sx_popup_menu, 1, 2, 0,
105: "Interface to XMenu library; permits creation and use of\n\
106: deck-of-cards pop-up menus.\n\
107: \n\
108: ARG is a position specification; it is a list of (Xoffset, Yoffset)\n\
109: from the top-left corner of the editor window. Note that this offset\n\
110: is relative to the center of the first line in the first pane of the\n\
111: menu, not the top left of the menu as a whole.\n\
112: \n\
113: MENU is a specifier for a menu. It is a list of the form\n\
114: (title pane1 pane2...), and each pane is a list of form\n\
115: (title (line item)...). Each line should be a string, and item should\n\
116: be the return value for that line (i. e. if it is selected.")
117: (arg,menu)
118: Lisp_Object arg,menu;
119: {
120: int number_of_panes;
121: Lisp_Object XMenu_return;
122: int XMenu_xpos,XMenu_ypos;
123: char **menus;
124: char ***names;
125: Lisp_Object **obj_list;
126: int *items;
127: char *title;
128: char *error_name;
129: Lisp_Object ltitle, selection;
130: Lisp_Object XEmacsMenu();
131: int i, j;
132: #ifdef X11
133: Window root_window, wjunk;
134: int ijunk;
135: extern Lisp_Object Vx_mouse_abs_pos;
136: #endif
137: BLOCK_INPUT_DECLARE ();
138:
139: check_xterm();
140: #ifdef X11
141: #if 0
142: if (interrupt_input)
143: unrequest_sigio ();
144: #endif
145: BLOCK_INPUT ();
146: root_window = RootWindow (XXdisplay, DefaultScreen(XXdisplay));
147: UNBLOCK_INPUT ();
148: XMenu_xpos = Fcar (Vx_mouse_abs_pos);
149: XMenu_ypos = Fcar (Fcdr (Vx_mouse_abs_pos));
150: #if 0
151: if (interrupt_input)
152: request_sigio ();
153: #endif
154: #else
155: XMenu_xpos = fontinfo->width * XINT(Fcar(arg));
156: XMenu_ypos = fontinfo->height * XINT(Fcar(Fcdr (arg)));
157: XMenu_xpos += XXxoffset;
158: XMenu_ypos += XXyoffset;
159: #endif
160: ltitle = Fcar(menu);
161: CHECK_STRING(ltitle,1);
162: title = (char *) XSTRING(ltitle)->data;
163: number_of_panes=list_of_panes(&obj_list, &menus, &names, &items, Fcdr(menu));
164: #ifdef XDEBUG
165: fprintf(stderr,"Panes= %d\n", number_of_panes);
166: for(i=0; i < number_of_panes; i++)
167: {
168: fprintf (stderr,"Pane %d lines %d title %s\n", i, items[i], menus[i]);
169: for (j=0; j < items[i]; j++)
170: {
171: fprintf (stderr," Item %d %s\n", j, names[i][j]);
172: }
173: }
174: #endif
175: BLOCK_INPUT ();
176: #ifdef X11
177: XSetErrorHandler(XMenuQuit);
178: selection = XEmacsMenu(root_window, XMenu_xpos, XMenu_ypos, names, menus,
179: items, number_of_panes, obj_list ,title, &error_name);
180: XSetErrorHandler(handler);
181: #else
182: XErrorHandler(XMenuQuit);
183: selection = XEmacsMenu(RootWindow, XMenu_xpos, XMenu_ypos, names, menus,
184: items, number_of_panes, obj_list ,title, &error_name);
185: XErrorHandler(handler);
186: #endif
187: UNBLOCK_INPUT ();
188: force_input_read ();
189: /** fprintf(stderr,"selection = %x\n",selection); **/
190: if (selection != NUL)
191: { /* selected something */
192: XMenu_return = selection;
193: }
194: else
195: { /* nothing selected */
196: XMenu_return = Qnil;
197: }
198: /* now free up the strings */
199: for (i=0; i < number_of_panes; i++)
200: {
201: free(names[i]);
202: free(obj_list[i]);
203: }
204: free(menus);
205: free(obj_list);
206: free(names);
207: free(items);
208: /* free(title); */
209: if (error_name) error(error_name);
210: return XMenu_return;
211: }
212:
213: struct indices {
214: int pane;
215: int line;
216: };
217:
218: Lisp_Object
219: XEmacsMenu(parent, startx, starty, line_list, pane_list, line_cnt,
220: pane_cnt, item_list, title, error)
221: Window parent;
222: int startx, starty; /* upper left corner position BROKEN */
223: char **line_list[]; /* list of strings for items */
224: char *pane_list[]; /* list of pane titles */
225: char *title;
226: int pane_cnt; /* total number of panes */
227: Lisp_Object *item_list[]; /* All items */
228: int line_cnt[]; /* Lines in each pane */
229: char **error; /* Error returned */
230: {
231: XMenu *GXMenu;
232: int last, panes, selidx, lpane, status;
233: int lines, sofar;
234: Lisp_Object entry;
235: /* struct indices *datap, *datap_save; */
236: char *datap;
237: int ulx = 0, uly = 0, width, height;
238: int dispwidth, dispheight;
239:
240: *error = (char *) 0; /* Initialize error pointer to null */
241: if ((GXMenu = XMenuCreate( X11ONLY (XXdisplay) parent, "emacs" )) == NUL )
242: {
243: *error = "Can't create menu";
244: /* error("Can't create menu"); */
245: return(0);
246: }
247:
248: for (panes=0, lines=0; panes < pane_cnt; lines += line_cnt[panes], panes++ )
249: ;
250: /* datap = (struct indices *) xmalloc (lines * sizeof(struct indices)); */
251: /*datap = (char *) xmalloc(lines * sizeof(char));
252: datap_save = datap;*/
253:
254: for (panes = 0, sofar=0;panes < pane_cnt;sofar +=line_cnt[panes], panes++ )
255: {
256: /* create all the necessary panes */
257: if ((lpane= XMenuAddPane( X11ONLY (XXdisplay) GXMenu, pane_list[panes] , TRUE ))
258: == XM_FAILURE)
259: {
260: XMenuDestroy(X11ONLY (XXdisplay) GXMenu);
261: *error = "Can't create pane";
262: /* error("Can't create pane"); */
263: /* free(datap); */
264: return(0);
265: }
266: for ( selidx = 0; selidx < line_cnt[panes] ; selidx++ )
267: {
268: /* add the selection stuff to the menus */
269: /* datap[selidx+sofar].pane = panes;
270: datap[selidx+sofar].line = selidx; */
271: if (XMenuAddSelection(X11ONLY (XXdisplay) GXMenu, lpane, 0, line_list[panes][selidx], TRUE)
272: == XM_FAILURE)
273: {
274: XMenuDestroy(X11ONLY (XXdisplay) GXMenu);
275: /* free(datap); */
276: *error = "Can't add selection to menu";
277: /* error ("Can't add selection to menu"); */
278: return(0);
279: }
280: }
281: }
282: /* all set and ready to fly */
283: XMenuRecompute(X11ONLY (XXdisplay) GXMenu);
284: #ifdef X11
285: XXscreen = DefaultScreen(XXdisplay);
286: dispwidth = DisplayWidth(XXdisplay, XXscreen);
287: dispheight = DisplayHeight(XXdisplay, XXscreen);
288: #else
289: dispwidth = DisplayWidth();
290: dispheight = DisplayHeight();
291: #endif
292: startx = min(startx, dispwidth);
293: starty = min(starty, dispheight);
294: startx = max(startx, 1);
295: starty = max(starty, 1);
296: XMenuLocate(X11ONLY (XXdisplay) GXMenu, 0, 0, startx, starty, &ulx, &uly, &width, &height);
297: if (ulx+width > dispwidth)
298: {
299: startx -= (ulx + width) - dispwidth;
300: ulx = dispwidth - width;
301: }
302: if (uly+height > dispheight)
303: {
304: starty -= (uly + height) - dispheight;
305: uly = dispheight - height;
306: }
307: if (ulx < 0) startx -= ulx;
308: if (uly < 0) starty -= uly;
309:
310: XMenuSetFreeze(GXMenu, TRUE);
311: panes = selidx = 0;
312:
313: status = XMenuActivate(X11ONLY (XXdisplay) GXMenu, &panes, &selidx,
314: startx, starty, ButtonRelease, &datap);
315: switch (status ) {
316: case XM_SUCCESS:
317: #ifdef XDEBUG
318: fprintf (stderr, "pane= %d line = %d\n", panes, selidx);
319: #endif
320: entry = item_list[panes][selidx];
321: break;
322: case XM_FAILURE:
323: /*free (datap_save); */
324: XMenuDestroy(X11ONLY (XXdisplay) GXMenu);
325: *error = "Can't activate menu";
326: /* error("Can't activate menu"); */
327: case XM_IA_SELECT:
328: case XM_NO_SELECT:
329: entry = Qnil;
330: break;
331: }
332: XMenuDestroy(X11ONLY (XXdisplay) GXMenu);
333: /*free(datap_save);*/
334: return(entry);
335: }
336:
337: syms_of_xmenu ()
338: {
339: defsubr (&Sx_popup_menu);
340: }
341:
342: list_of_panes (vector, panes, names, items, menu)
343: Lisp_Object ***vector; /* RETURN all menu objects */
344: char ***panes; /* RETURN pane names */
345: char ****names; /* RETURN all line names */
346: int **items; /* RETURN number of items per pane */
347: Lisp_Object menu;
348: {
349: Lisp_Object tail, item, item1;
350: int i;
351:
352: if (XTYPE (menu) != Lisp_Cons) menu = wrong_type_argument(Qlistp, item);
353:
354: i= XFASTINT(Flength(menu,1));
355:
356: *vector = (Lisp_Object **) xmalloc(i * sizeof (Lisp_Object *));
357: *panes = (char **) xmalloc(i * sizeof (char *));
358: *items = (int *) xmalloc(i * sizeof (int));
359: *names = (char ***) xmalloc(i * sizeof (char **));
360:
361: for (i=0,tail = menu; !NULL (tail); tail = Fcdr (tail), i++)
362: {
363: item = Fcdr(Fcar(tail));
364: if (XTYPE (item) != Lisp_Cons) (void) wrong_type_argument(Qlistp, item);
365: #ifdef XDEBUG
366: fprintf (stderr, "list_of_panes check tail, i=%d\n", i);
367: #endif
368: item1 = Fcar(Fcar(tail));
369: CHECK_STRING (item1, 1);
370: #ifdef XDEBUG
371: fprintf (stderr, "list_of_panes check pane, i=%d%s\n", i,
372: XSTRING(item1)->data);
373: #endif
374: (*panes)[i] = (char *) XSTRING(item1)->data;
375: (*items)[i] = list_of_items ((*vector)+i, (*names)+i, item);
376: /* (*panes)[i] = (char *) xmalloc((XSTRING(item1)->size)+1);
377: bcopy (XSTRING (item1)->data, (*panes)[i], XSTRING(item1)->size + 1)
378: ; */
379: }
380: return i;
381: }
382:
383:
384: list_of_items (vector,names,pane) /* get list from emacs and put to vector */
385: Lisp_Object **vector; /* RETURN menu "objects" */
386: char ***names; /* RETURN line names */
387: Lisp_Object pane;
388: {
389: Lisp_Object tail, item, item1;
390: int i;
391:
392: if (XTYPE (pane) != Lisp_Cons) pane = wrong_type_argument(Qlistp, item);
393:
394: i= XFASTINT(Flength(pane,1));
395:
396: *vector = (Lisp_Object *) xmalloc(i * sizeof (Lisp_Object));
397: *names = (char **) xmalloc(i * sizeof (char *));
398:
399: for (i=0,tail = pane; !NULL (tail); tail = Fcdr (tail), i++)
400: {
401: item = Fcar(tail);
402: if (XTYPE (item) != Lisp_Cons) (void) wrong_type_argument(Qlistp, item);
403: #ifdef XDEBUG
404: fprintf (stderr, "list_of_items check tail, i=%d\n", i);
405: #endif
406: (*vector)[i] = Fcdr (item);
407: item1 = Fcar(item);
408: CHECK_STRING (item1, 1);
409: #ifdef XDEBUG
410: fprintf (stderr, "list_of_items check item, i=%d%s\n", i,
411: XSTRING(item1)->data);
412: #endif
413: (*names)[i] = (char *) XSTRING(item1)->data;
414: /* (*names)[i] = (char *) xmalloc((XSTRING(item1)->size)+1);
415: bcopy (XSTRING (item1)->data, (*names)[i], XSTRING(item1)->size + 1); */
416: }
417: return i;
418: }
419:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.