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