home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / emacs / src / xmenu.c < prev    next >
C/C++ Source or Header  |  1991-10-24  |  12KB  |  427 lines

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