|
|
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.