Annotation of GNUtools/emacs/src/xmenu.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.