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