1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1986, 1988, 1993 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
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 2, or (at your option)
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.
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. */
20 /* X pop-up deck-of-cards menu facility for gnuemacs.
22 * Written by Jon Arnold and Roman Budzianowski
23 * Mods and rewrite by Robert Krawitz
31 /* On 4.3 this loses if it comes after xterm.h. */
38 #include "blockinput.h"
40 /* This may include sys/types.h, and that somehow loses
41 if this is not done before the other system files. */
44 /* Load sys/types.h if not already loaded.
45 In some systems loading it twice is suicidal. */
47 #include <sys/types.h>
50 #include "dispextern.h"
53 #include "../oldXMenu/XMenu.h"
58 #define min(x,y) (((x) < (y)) ? (x) : (y))
59 #define max(x,y) (((x) > (y)) ? (x) : (y))
69 extern Display
*x_current_display
;
71 #define ButtonReleaseMask ButtonReleased
72 #endif /* not HAVE_X11 */
74 extern Lisp_Object Qmenu_enable
;
75 Lisp_Object
xmenu_show ();
76 extern int x_error_handler ();
78 /*************************************************************/
81 /* Ignoring the args is easiest. */
84 error ("Unknown XMenu error");
88 DEFUN ("x-popup-menu",Fx_popup_menu
, Sx_popup_menu
, 1, 2, 0,
89 "Pop up a deck-of-cards menu and return user's selection.\n\
90 POSITION is a position specification. This is either a mouse button event\n\
91 or a list ((XOFFSET YOFFSET) WINDOW)\n\
92 where XOFFSET and YOFFSET are positions in characters from the top left\n\
93 corner of WINDOW's frame. (WINDOW may be a frame object instead of a window.)\n\
94 This controls the position of the center of the first line\n\
95 in the first pane of the menu, not the top left of the menu as a whole.\n\
97 MENU is a specifier for a menu. For the simplest case, MENU is a keymap.\n\
98 The menu items come from key bindings that have a menu string as well as\n\
99 a definition; actually, the \"definition\" in such a key binding looks like\n\
100 \(STRING . REAL-DEFINITION). To give the menu a title, put a string into\n\
101 the keymap as a top-level element.\n\n\
102 You can also use a list of keymaps as MENU.\n\
103 Then each keymap makes a separate pane.\n\
104 When MENU is a keymap or a list of keymaps, the return value\n\
105 is a list of events.\n\n\
106 Alternatively, you can specify a menu of multiple panes\n\
107 with a list of the form (TITLE PANE1 PANE2...),\n\
108 where each pane is a list of form (TITLE ITEM1 ITEM2...).\n\
109 Each ITEM is normally a cons cell (STRING . VALUE);\n\
110 but a string can appear as an item--that makes a nonselectable line\n\
112 With this form of menu, the return value is VALUE from the chosen item.")
114 Lisp_Object position
, menu
;
117 Lisp_Object XMenu_return
, keymap
, tem
;
118 int XMenu_xpos
, XMenu_ypos
;
122 Lisp_Object
**obj_list
;
123 Lisp_Object
*prefixes
;
127 Lisp_Object ltitle
, selection
;
130 Lisp_Object x
, y
, window
;
132 /* Decode the first argument: find the window and the coordinates. */
133 tem
= Fcar (position
);
134 if (XTYPE (tem
) == Lisp_Cons
)
136 window
= Fcar (Fcdr (position
));
138 y
= Fcar (Fcdr (tem
));
142 tem
= Fcar (Fcdr (position
)); /* EVENT_START (position) */
143 window
= Fcar (tem
); /* POSN_WINDOW (tem) */
144 tem
= Fcar (Fcdr (Fcdr (tem
))); /* POSN_WINDOW_POSN (tem) */
151 if (XTYPE (window
) == Lisp_Frame
)
158 else if (XTYPE (window
) == Lisp_Window
)
160 CHECK_LIVE_WINDOW (window
, 0);
161 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
163 XMenu_xpos
= FONT_WIDTH (f
->display
.x
->font
) * XWINDOW (window
)->left
;
164 XMenu_ypos
= FONT_HEIGHT (f
->display
.x
->font
) * XWINDOW (window
)->top
;
167 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
168 but I don't want to make one now. */
169 CHECK_WINDOW (window
, 0);
174 int win_x
= 0, win_y
= 0;
176 /* Find the position of the outside upper-left corner of
177 the inner window, with respect to the outer window. */
178 if (f
->display
.x
->parent_desc
!= ROOT_WINDOW
)
181 XTranslateCoordinates (x_current_display
,
183 /* From-window, to-window. */
184 f
->display
.x
->window_desc
,
185 f
->display
.x
->parent_desc
,
187 /* From-position, to-position. */
188 0, 0, &win_x
, &win_y
,
190 /* Child of window. */
199 XMenu_xpos
+= FONT_WIDTH (f
->display
.x
->font
) * XINT (x
);
200 XMenu_ypos
+= FONT_HEIGHT (f
->display
.x
->font
) * XINT (y
);
202 XMenu_xpos
+= f
->display
.x
->left_pos
;
203 XMenu_ypos
+= f
->display
.x
->top_pos
;
205 keymap
= Fkeymapp (menu
);
207 if (XTYPE (menu
) == Lisp_Cons
)
208 tem
= Fkeymapp (Fcar (menu
));
211 /* We were given a keymap. Extract menu info from the keymap. */
213 keymap
= get_keymap (menu
);
215 /* Search for a string appearing directly as an element of the keymap.
216 That string is the title of the menu. */
217 prompt
= map_prompt (keymap
);
219 title
= (char *) XSTRING (prompt
)->data
;
221 /* Extract the detailed info to make one pane. */
222 number_of_panes
= keymap_panes (&obj_list
, &menus
, &names
, &enables
,
223 &items
, &prefixes
, &menu
, 1);
224 /* The menu title seems to be ignored,
225 so put it in the pane title. */
229 else if (!NILP (tem
))
231 /* We were given a list of keymaps. */
233 int nmaps
= XFASTINT (Flength (menu
));
235 = (Lisp_Object
*) alloca (nmaps
* sizeof (Lisp_Object
));
239 /* The first keymap that has a prompt string
240 supplies the menu title. */
241 for (tem
= menu
, i
= 0; XTYPE (tem
) == Lisp_Cons
; tem
= Fcdr (tem
))
243 maps
[i
++] = keymap
= get_keymap (Fcar (tem
));
245 prompt
= map_prompt (keymap
);
246 if (title
== 0 && !NILP (prompt
))
247 title
= (char *) XSTRING (prompt
)->data
;
250 /* Extract the detailed info to make one pane. */
251 number_of_panes
= keymap_panes (&obj_list
, &menus
, &names
, &enables
,
252 &items
, &prefixes
, maps
, nmaps
);
253 /* The menu title seems to be ignored,
254 so put it in the pane title. */
260 /* We were given an old-fashioned menu. */
261 ltitle
= Fcar (menu
);
262 CHECK_STRING (ltitle
, 1);
263 title
= (char *) XSTRING (ltitle
)->data
;
265 number_of_panes
= list_of_panes (&obj_list
, &menus
, &names
, &enables
,
266 &items
, Fcdr (menu
));
269 fprintf (stderr
, "Panes = %d\n", number_of_panes
);
270 for (i
= 0; i
< number_of_panes
; i
++)
272 fprintf (stderr
, "Pane %d has lines %d title %s\n",
273 i
, items
[i
], menus
[i
]);
274 for (j
= 0; j
< items
[i
]; j
++)
275 fprintf (stderr
, " Item %d %s\n", j
, names
[i
][j
]);
283 unsigned int dummy_uint
;
286 /* Figure out which root window F is on. */
287 XGetGeometry (x_current_display
, FRAME_X_WINDOW (f
), &root
,
288 &dummy_int
, &dummy_int
, &dummy_uint
, &dummy_uint
,
289 &dummy_uint
, &dummy_uint
);
291 /* Translate the menu co-ordinates within f to menu co-ordinates
292 on that root window. */
293 if (! XTranslateCoordinates (x_current_display
,
294 FRAME_X_WINDOW (f
), root
,
295 XMenu_xpos
, XMenu_ypos
, &root_x
, &root_y
,
297 /* But XGetGeometry said root was the root window of f's screen! */
300 selection
= xmenu_show (root
, XMenu_xpos
, XMenu_ypos
, names
, enables
,
301 menus
, prefixes
, items
, number_of_panes
, obj_list
,
305 /* fprintf (stderr, "selection = %x\n", selection); */
306 if (selection
!= NUL
)
307 { /* selected something */
308 XMenu_return
= selection
;
311 { /* nothing selected */
314 /* now free up the strings */
315 for (i
= 0; i
< number_of_panes
; i
++)
327 if (error_name
) error (error_name
);
337 xmenu_show (parent
, startx
, starty
, line_list
, enable_list
, pane_list
,
338 prefixes
, line_cnt
, pane_cnt
, item_list
, title
, error
)
340 int startx
, starty
; /* upper left corner position BROKEN */
341 char **line_list
[]; /* list of strings for items */
342 int *enable_list
[]; /* list of strings for items */
343 char *pane_list
[]; /* list of pane titles */
344 Lisp_Object
*prefixes
; /* Prefix key for each pane */
346 int pane_cnt
; /* total number of panes */
347 Lisp_Object
*item_list
[]; /* All items */
348 int line_cnt
[]; /* Lines in each pane */
349 char **error
; /* Error returned */
352 int last
, panes
, selidx
, lpane
, status
;
355 /* struct indices *datap, *datap_save; */
357 int ulx
, uly
, width
, height
;
358 int dispwidth
, dispheight
;
365 *error
= (char *) 0; /* Initialize error pointer to null */
366 GXMenu
= XMenuCreate (XDISPLAY parent
, "emacs");
369 *error
= "Can't create menu";
374 for (panes
= 0, lines
= 0; panes
< pane_cnt
;
375 lines
+= line_cnt
[panes
], panes
++)
377 /* datap = (struct indices *) xmalloc (lines * sizeof (struct indices)); */
378 /* datap = (char *) xmalloc (lines * sizeof (char));
379 datap_save = datap;*/
381 for (panes
= 0, sofar
= 0; panes
< pane_cnt
;
382 sofar
+= line_cnt
[panes
], panes
++)
384 /* create all the necessary panes */
385 lpane
= XMenuAddPane (XDISPLAY GXMenu
, pane_list
[panes
], TRUE
);
386 if (lpane
== XM_FAILURE
)
388 XMenuDestroy (XDISPLAY GXMenu
);
389 *error
= "Can't create pane";
393 for (selidx
= 0; selidx
< line_cnt
[panes
]; selidx
++)
395 /* add the selection stuff to the menus */
396 /* datap[selidx+sofar].pane = panes;
397 datap[selidx+sofar].line = selidx; */
398 if (XMenuAddSelection (XDISPLAY GXMenu
, lpane
, 0,
399 line_list
[panes
][selidx
],
400 enable_list
[panes
][selidx
])
403 XMenuDestroy (XDISPLAY GXMenu
);
405 *error
= "Can't add selection to menu";
406 /* error ("Can't add selection to menu"); */
412 /* all set and ready to fly */
413 XMenuRecompute (XDISPLAY GXMenu
);
414 dispwidth
= DisplayWidth (x_current_display
, XDefaultScreen (x_current_display
));
415 dispheight
= DisplayHeight (x_current_display
, XDefaultScreen (x_current_display
));
416 startx
= min (startx
, dispwidth
);
417 starty
= min (starty
, dispheight
);
418 startx
= max (startx
, 1);
419 starty
= max (starty
, 1);
420 XMenuLocate (XDISPLAY GXMenu
, 0, 0, startx
, starty
,
421 &ulx
, &uly
, &width
, &height
);
422 if (ulx
+width
> dispwidth
)
424 startx
-= (ulx
+ width
) - dispwidth
;
425 ulx
= dispwidth
- width
;
427 if (uly
+height
> dispheight
)
429 starty
-= (uly
+ height
) - dispheight
;
430 uly
= dispheight
- height
;
432 if (ulx
< 0) startx
-= ulx
;
433 if (uly
< 0) starty
-= uly
;
435 XMenuSetFreeze (GXMenu
, TRUE
);
438 status
= XMenuActivate (XDISPLAY GXMenu
, &panes
, &selidx
,
439 startx
, starty
, ButtonReleaseMask
, &datap
);
444 fprintf (stderr
, "pane= %d line = %d\n", panes
, selidx
);
446 entry
= item_list
[panes
][selidx
];
449 entry
= Fcons (entry
, Qnil
);
450 if (!NILP (prefixes
[panes
]))
451 entry
= Fcons (prefixes
[panes
], entry
);
455 /* free (datap_save); */
456 XMenuDestroy (XDISPLAY GXMenu
);
457 *error
= "Can't activate menu";
458 /* error ("Can't activate menu"); */
464 XMenuDestroy (XDISPLAY GXMenu
);
466 /* free (datap_save);*/
472 defsubr (&Sx_popup_menu
);
475 /* Construct the vectors that describe a menu
476 and store them in *VECTOR, *PANES, *NAMES, *ENABLES and *ITEMS.
477 Each of those four values is a vector indexed by pane number.
478 Return the number of panes.
480 KEYMAPS is a vector of keymaps. NMAPS gives the length of KEYMAPS. */
483 keymap_panes (vector
, panes
, names
, enables
, items
, prefixes
, keymaps
, nmaps
)
484 Lisp_Object
***vector
; /* RETURN all menu objects */
485 char ***panes
; /* RETURN pane names */
486 char ****names
; /* RETURN all line names */
487 int ***enables
; /* RETURN enable-flags of lines */
488 int **items
; /* RETURN number of items per pane */
489 Lisp_Object
**prefixes
; /* RETURN vector of prefix keys, per pane */
490 Lisp_Object
*keymaps
;
493 /* Number of panes we have made. */
495 /* Number of panes we have space for. */
496 int npanes_allocated
= nmaps
;
499 if (npanes_allocated
< 4)
500 npanes_allocated
= 4;
502 /* Make space for an estimated number of panes. */
503 *vector
= (Lisp_Object
**) xmalloc (npanes_allocated
* sizeof (Lisp_Object
*));
504 *panes
= (char **) xmalloc (npanes_allocated
* sizeof (char *));
505 *items
= (int *) xmalloc (npanes_allocated
* sizeof (int));
506 *names
= (char ***) xmalloc (npanes_allocated
* sizeof (char **));
507 *enables
= (int **) xmalloc (npanes_allocated
* sizeof (int *));
508 *prefixes
= (Lisp_Object
*) xmalloc (npanes_allocated
* sizeof (Lisp_Object
));
510 /* Loop over the given keymaps, making a pane for each map.
511 But don't make a pane that is empty--ignore that map instead.
512 P is the number of panes we have made so far. */
513 for (mapno
= 0; mapno
< nmaps
; mapno
++)
514 single_keymap_panes (keymaps
[mapno
], panes
, vector
, names
, enables
, items
,
515 prefixes
, &p
, &npanes_allocated
, "");
517 /* Return the number of panes. */
521 /* This is a recursive subroutine of the previous function.
522 It handles one keymap, KEYMAP.
523 The other arguments are passed along
524 or point to local variables of the previous function. */
526 single_keymap_panes (keymap
, panes
, vector
, names
, enables
, items
, prefixes
,
527 p_ptr
, npanes_allocated_ptr
, pane_name
)
529 Lisp_Object
***vector
; /* RETURN all menu objects */
530 char ***panes
; /* RETURN pane names */
531 char ****names
; /* RETURN all line names */
532 int ***enables
; /* RETURN enable flags of lines */
533 int **items
; /* RETURN number of items per pane */
534 Lisp_Object
**prefixes
; /* RETURN vector of prefix keys, per pane */
536 int *npanes_allocated_ptr
;
540 Lisp_Object pending_maps
;
541 Lisp_Object tail
, item
, item1
, item2
, table
;
545 /* Make sure we have room for another pane. */
546 if (*p_ptr
== *npanes_allocated_ptr
)
548 *npanes_allocated_ptr
*= 2;
551 = (Lisp_Object
**) xrealloc (*vector
,
552 *npanes_allocated_ptr
* sizeof (Lisp_Object
*));
554 = (char **) xrealloc (*panes
,
555 *npanes_allocated_ptr
* sizeof (char *));
557 = (int *) xrealloc (*items
,
558 *npanes_allocated_ptr
* sizeof (int));
560 = (Lisp_Object
*) xrealloc (*prefixes
,
561 (*npanes_allocated_ptr
562 * sizeof (Lisp_Object
)));
564 = (char ***) xrealloc (*names
,
565 *npanes_allocated_ptr
* sizeof (char **));
567 = (int **) xrealloc (*enables
,
568 *npanes_allocated_ptr
* sizeof (int *));
571 /* When a menu comes from keymaps, don't give names to the panes. */
572 (*panes
)[*p_ptr
] = pane_name
;
574 /* Normally put nil as pane's prefix key.
575 Caller will override this if appropriate. */
576 (*prefixes
)[*p_ptr
] = Qnil
;
578 /* Get the length of the list level of the keymap. */
579 i
= XFASTINT (Flength (keymap
));
581 /* Add in lengths of any arrays. */
582 for (tail
= keymap
; XTYPE (tail
) == Lisp_Cons
; tail
= XCONS (tail
)->cdr
)
583 if (XTYPE (XCONS (tail
)->car
) == Lisp_Vector
)
584 i
+= XVECTOR (XCONS (tail
)->car
)->size
;
586 /* Create vectors for the names and values of the items in the pane.
587 I is an upper bound for the number of items. */
588 (*vector
)[*p_ptr
] = (Lisp_Object
*) xmalloc (i
* sizeof (Lisp_Object
));
589 (*names
)[*p_ptr
] = (char **) xmalloc (i
* sizeof (char *));
590 (*enables
)[*p_ptr
] = (int *) xmalloc (i
* sizeof (int));
592 /* I is now the index of the next unused slots. */
594 for (tail
= keymap
; XTYPE (tail
) == Lisp_Cons
; tail
= XCONS (tail
)->cdr
)
596 /* Look at each key binding, and if it has a menu string,
597 make a menu item from it. */
598 item
= XCONS (tail
)->car
;
599 if (XTYPE (item
) == Lisp_Cons
)
601 item1
= XCONS (item
)->cdr
;
602 if (XTYPE (item1
) == Lisp_Cons
)
604 item2
= XCONS (item1
)->car
;
605 if (XTYPE (item2
) == Lisp_String
)
607 Lisp_Object def
, tem
;
612 if (XTYPE (def
) == Lisp_Symbol
)
614 /* No property, or nil, means enable.
615 Otherwise, enable if value is not nil. */
616 tem
= Fget (def
, Qmenu_enable
);
618 enabled
= Feval (tem
);
620 tem
= Fkeymapp (def
);
621 if (XSTRING (item2
)->data
[0] == '@' && !NILP (tem
))
622 pending_maps
= Fcons (Fcons (def
, Fcons (item2
, XCONS (item
)->car
)),
626 (*names
)[*p_ptr
][i
] = (char *) XSTRING (item2
)->data
;
627 /* The menu item "value" is the key bound here. */
628 (*vector
)[*p_ptr
][i
] = XCONS (item
)->car
;
629 (*enables
)[*p_ptr
][i
]
630 = (NILP (def
) ? -1 : !NILP (enabled
) ? 1 : 0);
636 else if (XTYPE (item
) == Lisp_Vector
)
638 /* Loop over the char values represented in the vector. */
639 int len
= XVECTOR (item
)->size
;
641 for (c
= 0; c
< len
; c
++)
643 Lisp_Object character
;
644 XFASTINT (character
) = c
;
645 item1
= XVECTOR (item
)->contents
[c
];
646 if (XTYPE (item1
) == Lisp_Cons
)
648 item2
= XCONS (item1
)->car
;
649 if (XTYPE (item2
) == Lisp_String
)
657 if (XTYPE (def
) == Lisp_Symbol
)
659 tem
= Fget (def
, Qmenu_enable
);
660 /* No property, or nil, means enable.
661 Otherwise, enable if value is not nil. */
663 enabled
= Feval (tem
);
666 tem
= Fkeymapp (def
);
667 if (XSTRING (item2
)->data
[0] == '@' && !NILP (tem
))
668 pending_maps
= Fcons (Fcons (def
, Fcons (item2
, character
)),
672 (*names
)[*p_ptr
][i
] = (char *) XSTRING (item2
)->data
;
673 /* The menu item "value" is the key bound here. */
674 (*vector
)[*p_ptr
][i
] = character
;
675 (*enables
)[*p_ptr
][i
]
676 = (NILP (def
) ? -1 : !NILP (enabled
) ? 1 : 0);
684 /* Record the number of items in the pane. */
685 (*items
)[*p_ptr
] = i
;
687 /* If we just made an empty pane, get rid of it. */
690 xfree ((*vector
)[*p_ptr
]);
691 xfree ((*names
)[*p_ptr
]);
692 xfree ((*enables
)[*p_ptr
]);
694 /* Otherwise, advance past it. */
698 /* Process now any submenus which want to be panes at this level. */
699 while (!NILP (pending_maps
))
701 Lisp_Object elt
, eltcdr
;
702 int panenum
= *p_ptr
;
703 elt
= Fcar (pending_maps
);
704 eltcdr
= XCONS (elt
)->cdr
;
705 single_keymap_panes (Fcar (elt
), panes
, vector
, names
, enables
, items
,
706 prefixes
, p_ptr
, npanes_allocated_ptr
,
707 /* Add 1 to discard the @. */
708 (char *) XSTRING (XCONS (eltcdr
)->car
)->data
+ 1);
709 (*prefixes
)[panenum
] = XCONS (eltcdr
)->cdr
;
710 pending_maps
= Fcdr (pending_maps
);
714 /* Construct the vectors that describe a menu
715 and store them in *VECTOR, *PANES, *NAMES, *ENABLES and *ITEMS.
716 Each of those four values is a vector indexed by pane number.
717 Return the number of panes.
719 MENU is the argument that was given to Fx_popup_menu. */
722 list_of_panes (vector
, panes
, names
, enables
, items
, menu
)
723 Lisp_Object
***vector
; /* RETURN all menu objects */
724 char ***panes
; /* RETURN pane names */
725 char ****names
; /* RETURN all line names */
726 int ***enables
; /* RETURN enable flags of lines */
727 int **items
; /* RETURN number of items per pane */
730 Lisp_Object tail
, item
, item1
;
733 if (XTYPE (menu
) != Lisp_Cons
) menu
= wrong_type_argument (Qlistp
, menu
);
735 i
= XFASTINT (Flength (menu
));
737 *vector
= (Lisp_Object
**) xmalloc (i
* sizeof (Lisp_Object
*));
738 *panes
= (char **) xmalloc (i
* sizeof (char *));
739 *items
= (int *) xmalloc (i
* sizeof (int));
740 *names
= (char ***) xmalloc (i
* sizeof (char **));
741 *enables
= (int **) xmalloc (i
* sizeof (int *));
743 for (i
= 0, tail
= menu
; !NILP (tail
); tail
= Fcdr (tail
), i
++)
745 item
= Fcdr (Fcar (tail
));
746 if (XTYPE (item
) != Lisp_Cons
) (void) wrong_type_argument (Qlistp
, item
);
748 fprintf (stderr
, "list_of_panes check tail, i=%d\n", i
);
750 item1
= Fcar (Fcar (tail
));
751 CHECK_STRING (item1
, 1);
753 fprintf (stderr
, "list_of_panes check pane, i=%d%s\n", i
,
754 XSTRING (item1
)->data
);
756 (*panes
)[i
] = (char *) XSTRING (item1
)->data
;
757 (*items
)[i
] = list_of_items ((*vector
)+i
, (*names
)+i
, (*enables
)+i
, item
);
758 /* (*panes)[i] = (char *) xmalloc ((XSTRING (item1)->size)+1);
759 bcopy (XSTRING (item1)->data, (*panes)[i], XSTRING (item1)->size + 1)
765 /* Construct the lists of values and names for a single pane, from the
766 alist PANE. Put them in *VECTOR and *NAMES. Put the enable flags
767 int *ENABLES. Return the number of items. */
770 list_of_items (vector
, names
, enables
, pane
)
771 Lisp_Object
**vector
; /* RETURN menu "objects" */
772 char ***names
; /* RETURN line names */
773 int **enables
; /* RETURN enable flags of lines */
776 Lisp_Object tail
, item
, item1
;
779 if (XTYPE (pane
) != Lisp_Cons
) pane
= wrong_type_argument (Qlistp
, pane
);
781 i
= XFASTINT (Flength (pane
));
783 *vector
= (Lisp_Object
*) xmalloc (i
* sizeof (Lisp_Object
));
784 *names
= (char **) xmalloc (i
* sizeof (char *));
785 *enables
= (int *) xmalloc (i
* sizeof (int));
787 for (i
= 0, tail
= pane
; !NILP (tail
); tail
= Fcdr (tail
), i
++)
793 (*names
)[i
] = (char *) XSTRING (item
)->data
;
798 CHECK_CONS (item
, 0);
799 (*vector
)[i
] = Fcdr (item
);
801 CHECK_STRING (item1
, 1);
802 (*names
)[i
] = (char *) XSTRING (item1
)->data
;