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