Mercurial > emacs
comparison src/xmenu.c @ 1082:d24afc1bef38
(xmenu_show): If no panes, just return.
(Fx_popup_menu): Treat coords relative to spec'd window.
(single_keymap_panes): New function; contains guts of keymap_panes.
If a command binding for submenu has a prompt string starting with @,
make a separate pane for it at this level.
(keymap_panes): New function.
(Fx_popup_menu): Accept keymap or list of keymaps as MENU argument.
Accept mouse button event as POSITION argument.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Sat, 05 Sep 1992 00:08:07 +0000 |
parents | 3493118bc79f |
children | 3640e799d5fc |
comparison
equal
deleted
inserted
replaced
1081:4e7d09b779eb | 1082:d24afc1bef38 |
---|---|
82 } | 82 } |
83 #endif | 83 #endif |
84 | 84 |
85 DEFUN ("x-popup-menu",Fx_popup_menu, Sx_popup_menu, 1, 2, 0, | 85 DEFUN ("x-popup-menu",Fx_popup_menu, Sx_popup_menu, 1, 2, 0, |
86 "Pop up a deck-of-cards menu and return user's selection.\n\ | 86 "Pop up a deck-of-cards menu and return user's selection.\n\ |
87 ARG is a position specification: a list ((XOFFSET YOFFSET) WINDOW)\n\ | 87 POSITION is a position specification. This is either a mouse button event\n\ |
88 or a list ((XOFFSET YOFFSET) WINDOW)\n\ | |
88 where XOFFSET and YOFFSET are positions in characters from the top left\n\ | 89 where XOFFSET and YOFFSET are positions in characters from the top left\n\ |
89 corner of WINDOW's frame. A mouse-event list will serve for this.\n\ | 90 corner of WINDOW's frame. A mouse-event list will serve for this.\n\ |
90 This controls the position of the center of the first line\n\ | 91 This controls the position of the center of the first line\n\ |
91 in the first pane of the menu, not the top left of the menu as a whole.\n\ | 92 in the first pane of the menu, not the top left of the menu as a whole.\n\ |
92 \n\ | 93 \n\ |
93 MENU is a specifier for a menu. It is a list of the form\n\ | 94 MENU is a specifier for a menu. For the simplest case, MENU is a keymap.\n\ |
94 \(TITLE PANE1 PANE2...), and each pane is a list of form\n\ | 95 The menu items come from key bindings that have a menu string as well as\n\ |
96 a definition; actually, the \"definition\" in such a key binding looks like\n\ | |
97 \(STRING . REAL-DEFINITION). To give the menu a title, put a string into\n\ | |
98 the keymap as a top-level element.\n\n\ | |
99 You can also use a list of keymaps as MENU.\n\ | |
100 Then each keymap makes a separate pane.\n\n\ | |
101 Alternatively, you can specify a menu of multiple panes\n\ | |
102 with a list of the form\n\ | |
103 \(TITLE PANE1 PANE2...), where each pane is a list of form\n\ | |
95 \(TITLE (LINE ITEM)...). Each line should be a string, and item should\n\ | 104 \(TITLE (LINE ITEM)...). Each line should be a string, and item should\n\ |
96 be the return value for that line (i.e. if it is selected.") | 105 be the return value for that line (i.e. if it is selected.") |
97 (arg, menu) | 106 (position, menu) |
98 Lisp_Object arg, menu; | 107 Lisp_Object position, menu; |
99 { | 108 { |
100 int number_of_panes; | 109 int number_of_panes; |
101 Lisp_Object XMenu_return; | 110 Lisp_Object XMenu_return, keymap, tem; |
102 int XMenu_xpos, XMenu_ypos; | 111 int XMenu_xpos, XMenu_ypos; |
103 char **menus; | 112 char **menus; |
104 char ***names; | 113 char ***names; |
105 Lisp_Object **obj_list; | 114 Lisp_Object **obj_list; |
106 int *items; | 115 int *items; |
109 Lisp_Object ltitle, selection; | 118 Lisp_Object ltitle, selection; |
110 int i, j; | 119 int i, j; |
111 FRAME_PTR f; | 120 FRAME_PTR f; |
112 Lisp_Object x, y, window; | 121 Lisp_Object x, y, window; |
113 | 122 |
114 window = Fcar (Fcdr (arg)); | 123 /* Decode the first argument: find the window and the coordinates. */ |
115 x = Fcar (Fcar (arg)); | 124 tem = Fcar (position); |
116 y = Fcar (Fcdr (Fcar (arg))); | 125 if (XTYPE (tem) == Lisp_Cons) |
126 { | |
127 window = Fcar (Fcdr (position)); | |
128 x = Fcar (tem); | |
129 y = Fcar (Fcdr (tem)); | |
130 } | |
131 else | |
132 { | |
133 tem = Fcdr (position); | |
134 window = Fcar (tem); | |
135 tem = Fcar (Fcdr (Fcdr (tem))); | |
136 x = Fcar (tem); | |
137 y = Fcdr (tem); | |
138 } | |
117 CHECK_WINDOW (window, 0); | 139 CHECK_WINDOW (window, 0); |
118 CHECK_NUMBER (x, 0); | 140 CHECK_NUMBER (x, 0); |
119 CHECK_NUMBER (y, 0); | 141 CHECK_NUMBER (y, 0); |
142 | |
120 f = XFRAME (WINDOW_FRAME (XWINDOW (window))); | 143 f = XFRAME (WINDOW_FRAME (XWINDOW (window))); |
121 | 144 |
122 XMenu_xpos = FONT_WIDTH (f->display.x->font) * XINT (x); | 145 XMenu_xpos |
123 XMenu_ypos = FONT_HEIGHT (f->display.x->font) * XINT (y); | 146 = FONT_WIDTH (f->display.x->font) * (XINT (x) + XWINDOW (window)->left); |
147 XMenu_ypos | |
148 = FONT_HEIGHT (f->display.x->font) * (XINT (y) + XWINDOW (window)->top); | |
124 XMenu_xpos += f->display.x->left_pos; | 149 XMenu_xpos += f->display.x->left_pos; |
125 XMenu_ypos += f->display.x->top_pos; | 150 XMenu_ypos += f->display.x->top_pos; |
126 | 151 |
127 ltitle = Fcar (menu); | 152 keymap = Fkeymapp (menu); |
128 CHECK_STRING (ltitle, 1); | 153 tem = Qnil; |
129 title = (char *) XSTRING (ltitle)->data; | 154 if (XTYPE (menu) == Lisp_Cons) |
130 number_of_panes=list_of_panes (&obj_list, &menus, &names, &items, Fcdr (menu)); | 155 tem = Fkeymapp (Fcar (menu)); |
156 if (!NILP (keymap)) | |
157 { | |
158 /* We were given a keymap. Extract menu info from the keymap. */ | |
159 Lisp_Object prompt; | |
160 keymap = get_keymap (menu); | |
161 | |
162 /* Search for a string appearing directly as an element of the keymap. | |
163 That string is the title of the menu. */ | |
164 prompt = map_prompt (keymap); | |
165 if (!NILP (prompt)) | |
166 title = (char *) XSTRING (prompt)->data; | |
167 | |
168 /* Extract the detailed info to make one pane. */ | |
169 number_of_panes = keymap_panes (&obj_list, &menus, &names, &items, | |
170 &menu, 1); | |
171 /* The menu title seems to be ignored, | |
172 so put it in the pane title. */ | |
173 if (menus[0] == 0) | |
174 menus[0] = title; | |
175 } | |
176 else if (!NILP (tem)) | |
177 { | |
178 /* We were given a list of keymaps. */ | |
179 Lisp_Object prompt; | |
180 int nmaps = XFASTINT (Flength (menu)); | |
181 Lisp_Object *maps | |
182 = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object)); | |
183 int i; | |
184 title = 0; | |
185 | |
186 /* The first keymap that has a prompt string | |
187 supplies the menu title. */ | |
188 for (tem = menu, i = 0; XTYPE (tem) == Lisp_Cons; tem = Fcdr (tem)) | |
189 { | |
190 maps[i++] = keymap = get_keymap (Fcar (tem)); | |
191 | |
192 prompt = map_prompt (keymap); | |
193 if (title == 0 && !NILP (prompt)) | |
194 title = (char *) XSTRING (prompt)->data; | |
195 } | |
196 | |
197 /* Extract the detailed info to make one pane. */ | |
198 number_of_panes = keymap_panes (&obj_list, &menus, &names, &items, | |
199 maps, nmaps); | |
200 /* The menu title seems to be ignored, | |
201 so put it in the pane title. */ | |
202 if (menus[0] == 0) | |
203 menus[0] = title; | |
204 } | |
205 else | |
206 { | |
207 /* We were given an old-fashioned menu. */ | |
208 ltitle = Fcar (menu); | |
209 CHECK_STRING (ltitle, 1); | |
210 title = (char *) XSTRING (ltitle)->data; | |
211 number_of_panes = list_of_panes (&obj_list, &menus, &names, &items, | |
212 Fcdr (menu)); | |
213 } | |
131 #ifdef XDEBUG | 214 #ifdef XDEBUG |
132 fprintf (stderr, "Panes= %d\n", number_of_panes); | 215 fprintf (stderr, "Panes = %d\n", number_of_panes); |
133 for (i=0; i < number_of_panes; i++) | 216 for (i = 0; i < number_of_panes; i++) |
134 { | 217 { |
135 fprintf (stderr, "Pane %d lines %d title %s\n", i, items[i], menus[i]); | 218 fprintf (stderr, "Pane %d has lines %d title %s\n", |
136 for (j=0; j < items[i]; j++) | 219 i, items[i], menus[i]); |
137 { | 220 for (j = 0; j < items[i]; j++) |
138 fprintf (stderr, " Item %d %s\n", j, names[i][j]); | 221 fprintf (stderr, " Item %d %s\n", j, names[i][j]); |
139 } | |
140 } | 222 } |
141 #endif | 223 #endif |
142 BLOCK_INPUT; | 224 BLOCK_INPUT; |
143 selection = xmenu_show (ROOT_WINDOW, XMenu_xpos, XMenu_ypos, names, menus, | 225 selection = xmenu_show (ROOT_WINDOW, XMenu_xpos, XMenu_ypos, names, menus, |
144 items, number_of_panes, obj_list, title, &error_name); | 226 items, number_of_panes, obj_list, title, |
227 &error_name); | |
145 UNBLOCK_INPUT; | 228 UNBLOCK_INPUT; |
146 /** fprintf (stderr, "selection = %x\n", selection); **/ | 229 /* fprintf (stderr, "selection = %x\n", selection); */ |
147 if (selection != NUL) | 230 if (selection != NUL) |
148 { /* selected something */ | 231 { /* selected something */ |
149 XMenu_return = selection; | 232 XMenu_return = selection; |
150 } | 233 } |
151 else | 234 else |
152 { /* nothing selected */ | 235 { /* nothing selected */ |
153 XMenu_return = Qnil; | 236 XMenu_return = Qnil; |
154 } | 237 } |
155 /* now free up the strings */ | 238 /* now free up the strings */ |
156 for (i=0; i < number_of_panes; i++) | 239 for (i = 0; i < number_of_panes; i++) |
157 { | 240 { |
158 free (names[i]); | 241 free (names[i]); |
159 free (obj_list[i]); | 242 free (obj_list[i]); |
160 } | 243 } |
161 free (menus); | 244 free (menus); |
162 free (obj_list); | 245 free (obj_list); |
163 free (names); | 246 free (names); |
164 free (items); | 247 free (items); |
165 /* free (title); */ | 248 /* free (title); */ |
166 if (error_name) error (error_name); | 249 if (error_name) error (error_name); |
167 return XMenu_return; | 250 return XMenu_return; |
168 } | 251 } |
169 | 252 |
170 struct indices { | 253 struct indices { |
191 Lisp_Object entry; | 274 Lisp_Object entry; |
192 /* struct indices *datap, *datap_save; */ | 275 /* struct indices *datap, *datap_save; */ |
193 char *datap; | 276 char *datap; |
194 int ulx, uly, width, height; | 277 int ulx, uly, width, height; |
195 int dispwidth, dispheight; | 278 int dispwidth, dispheight; |
196 | 279 |
280 if (pane_cnt == 0) | |
281 return 0; | |
282 | |
197 *error = (char *) 0; /* Initialize error pointer to null */ | 283 *error = (char *) 0; /* Initialize error pointer to null */ |
198 GXMenu = XMenuCreate (XDISPLAY parent, "emacs"); | 284 GXMenu = XMenuCreate (XDISPLAY parent, "emacs"); |
199 if (GXMenu == NUL) | 285 if (GXMenu == NUL) |
200 { | 286 { |
201 *error = "Can't create menu"; | 287 *error = "Can't create menu"; |
202 return (0); | 288 return (0); |
203 } | 289 } |
204 | 290 |
205 for (panes=0, lines=0; panes < pane_cnt; lines += line_cnt[panes], panes++) | 291 for (panes = 0, lines = 0; panes < pane_cnt; |
292 lines += line_cnt[panes], panes++) | |
206 ; | 293 ; |
207 /* datap = (struct indices *) xmalloc (lines * sizeof (struct indices)); */ | 294 /* datap = (struct indices *) xmalloc (lines * sizeof (struct indices)); */ |
208 /*datap = (char *) xmalloc (lines * sizeof (char)); | 295 /* datap = (char *) xmalloc (lines * sizeof (char)); |
209 datap_save = datap;*/ | 296 datap_save = datap;*/ |
210 | 297 |
211 for (panes = 0, sofar=0;panes < pane_cnt;sofar +=line_cnt[panes], panes++) | 298 for (panes = 0, sofar = 0; panes < pane_cnt; |
299 sofar += line_cnt[panes], panes++) | |
212 { | 300 { |
213 /* create all the necessary panes */ | 301 /* create all the necessary panes */ |
214 lpane = XMenuAddPane (XDISPLAY GXMenu, pane_list[panes], TRUE); | 302 lpane = XMenuAddPane (XDISPLAY GXMenu, pane_list[panes], TRUE); |
215 if (lpane == XM_FAILURE) | 303 if (lpane == XM_FAILURE) |
216 { | 304 { |
217 XMenuDestroy (XDISPLAY GXMenu); | 305 XMenuDestroy (XDISPLAY GXMenu); |
218 *error = "Can't create pane"; | 306 *error = "Can't create pane"; |
219 return (0); | 307 return (0); |
220 } | 308 } |
221 for (selidx = 0; selidx < line_cnt[panes] ; selidx++) | 309 for (selidx = 0; selidx < line_cnt[panes]; selidx++) |
222 { | 310 { |
223 /* add the selection stuff to the menus */ | 311 /* add the selection stuff to the menus */ |
224 /* datap[selidx+sofar].pane = panes; | 312 /* datap[selidx+sofar].pane = panes; |
225 datap[selidx+sofar].line = selidx; */ | 313 datap[selidx+sofar].line = selidx; */ |
226 if (XMenuAddSelection (XDISPLAY GXMenu, lpane, 0, | 314 if (XMenuAddSelection (XDISPLAY GXMenu, lpane, 0, |
270 fprintf (stderr, "pane= %d line = %d\n", panes, selidx); | 358 fprintf (stderr, "pane= %d line = %d\n", panes, selidx); |
271 #endif | 359 #endif |
272 entry = item_list[panes][selidx]; | 360 entry = item_list[panes][selidx]; |
273 break; | 361 break; |
274 case XM_FAILURE: | 362 case XM_FAILURE: |
275 /*free (datap_save); */ | 363 /* free (datap_save); */ |
276 XMenuDestroy (XDISPLAY GXMenu); | 364 XMenuDestroy (XDISPLAY GXMenu); |
277 *error = "Can't activate menu"; | 365 *error = "Can't activate menu"; |
278 /* error ("Can't activate menu"); */ | 366 /* error ("Can't activate menu"); */ |
279 case XM_IA_SELECT: | 367 case XM_IA_SELECT: |
280 case XM_NO_SELECT: | 368 case XM_NO_SELECT: |
281 entry = Qnil; | 369 entry = Qnil; |
282 break; | 370 break; |
283 } | 371 } |
284 XMenuDestroy (XDISPLAY GXMenu); | 372 XMenuDestroy (XDISPLAY GXMenu); |
285 /*free (datap_save);*/ | 373 /* free (datap_save);*/ |
286 return (entry); | 374 return (entry); |
287 } | 375 } |
288 | 376 |
289 syms_of_xmenu () | 377 syms_of_xmenu () |
290 { | 378 { |
291 defsubr (&Sx_popup_menu); | 379 defsubr (&Sx_popup_menu); |
292 } | 380 } |
293 | 381 |
382 /* Construct the vectors that describe a menu | |
383 and store them in *VECTOR, *PANES, *NAMES and *ITEMS. | |
384 Each of those four values is a vector indexed by pane number. | |
385 Return the number of panes. | |
386 | |
387 KEYMAPS is a vector of keymaps. NMAPS gives the length of KEYMAPS. */ | |
388 | |
389 int | |
390 keymap_panes (vector, panes, names, items, keymaps, nmaps) | |
391 Lisp_Object ***vector; /* RETURN all menu objects */ | |
392 char ***panes; /* RETURN pane names */ | |
393 char ****names; /* RETURN all line names */ | |
394 int **items; /* RETURN number of items per pane */ | |
395 Lisp_Object *keymaps; | |
396 int nmaps; | |
397 { | |
398 /* Number of panes we have made. */ | |
399 int p = 0; | |
400 /* Number of panes we have space for. */ | |
401 int npanes_allocated = nmaps; | |
402 int mapno; | |
403 | |
404 if (npanes_allocated < 4) | |
405 npanes_allocated = 4; | |
406 | |
407 /* Make space for an estimated number of panes. */ | |
408 *vector = (Lisp_Object **) xmalloc (npanes_allocated * sizeof (Lisp_Object *)); | |
409 *panes = (char **) xmalloc (npanes_allocated * sizeof (char *)); | |
410 *items = (int *) xmalloc (npanes_allocated * sizeof (int)); | |
411 *names = (char ***) xmalloc (npanes_allocated * sizeof (char **)); | |
412 | |
413 /* Loop over the given keymaps, making a pane for each map. | |
414 But don't make a pane that is empty--ignore that map instead. | |
415 P is the number of panes we have made so far. */ | |
416 for (mapno = 0; mapno < nmaps; mapno++) | |
417 single_keymap_panes (keymaps[mapno], panes, vector, names, items, | |
418 &p, &npanes_allocated, ""); | |
419 | |
420 /* Return the number of panes. */ | |
421 return p; | |
422 } | |
423 | |
424 /* This is a recursive subroutine of the previous function. | |
425 It handles one keymap, KEYMAP. | |
426 The other arguments are passed along | |
427 or point to local variables of the previous function. */ | |
428 | |
429 single_keymap_panes (keymap, panes, vector, names, items, | |
430 p_ptr, npanes_allocated_ptr, pane_name) | |
431 Lisp_Object keymap; | |
432 Lisp_Object ***vector; /* RETURN all menu objects */ | |
433 char ***panes; /* RETURN pane names */ | |
434 char ****names; /* RETURN all line names */ | |
435 int **items; /* RETURN number of items per pane */ | |
436 int *p_ptr; | |
437 int *npanes_allocated_ptr; | |
438 char *pane_name; | |
439 { | |
440 int i; | |
441 Lisp_Object pending_maps; | |
442 Lisp_Object tail, item, item1, item2, table; | |
443 | |
444 pending_maps = Qnil; | |
445 | |
446 /* Make sure we have room for another pane. */ | |
447 if (*p_ptr == *npanes_allocated_ptr) | |
448 { | |
449 *npanes_allocated_ptr *= 2; | |
450 | |
451 *vector | |
452 = (Lisp_Object **) xrealloc (*vector, | |
453 *npanes_allocated_ptr * sizeof (Lisp_Object *)); | |
454 *panes | |
455 = (char **) xrealloc (*panes, | |
456 *npanes_allocated_ptr * sizeof (char *)); | |
457 *items | |
458 = (int *) xrealloc (*items, | |
459 *npanes_allocated_ptr * sizeof (int)); | |
460 *names | |
461 = (char ***) xrealloc (*names, | |
462 *npanes_allocated_ptr * sizeof (char **)); | |
463 } | |
464 | |
465 /* When a menu comes from keymaps, don't give names to the panes. */ | |
466 (*panes)[*p_ptr] = pane_name; | |
467 | |
468 /* Get the length of the list level of the keymap. */ | |
469 i = XFASTINT (Flength (keymap)); | |
470 | |
471 /* If the keymap has a dense table, put it in TABLE, | |
472 and leave only the list level in KEYMAP. | |
473 Include the length of the dense table in I. */ | |
474 table = keymap_table (keymap); | |
475 if (!NILP (table)) | |
476 { | |
477 i += XFASTINT (Flength (table)); | |
478 keymap = XCONS (XCONS (keymap)->cdr)->cdr; | |
479 } | |
480 | |
481 /* Create vectors for the names and values of the items in the pane. | |
482 I is an upper bound for the number of items. */ | |
483 (*vector)[*p_ptr] = (Lisp_Object *) xmalloc (i * sizeof (Lisp_Object)); | |
484 (*names)[*p_ptr] = (char **) xmalloc (i * sizeof (char *)); | |
485 | |
486 /* I is now the index of the next unused slots. */ | |
487 i = 0; | |
488 for (tail = keymap; XTYPE (tail) == Lisp_Cons; tail = XCONS (tail)->cdr) | |
489 { | |
490 /* Look at each key binding, and if it has a menu string, | |
491 make a menu item from it. */ | |
492 item = XCONS (tail)->car; | |
493 if (XTYPE (item) == Lisp_Cons) | |
494 { | |
495 item1 = XCONS (item)->cdr; | |
496 if (XTYPE (item1) == Lisp_Cons) | |
497 { | |
498 item2 = XCONS (item1)->car; | |
499 if (XTYPE (item2) == Lisp_String) | |
500 { | |
501 Lisp_Object tem; | |
502 tem = Fkeymapp (Fcdr (item1)); | |
503 if (XSTRING (item2)->data[0] == '@' && !NILP (tem)) | |
504 pending_maps = Fcons (Fcons (Fcdr (item1), item2), | |
505 pending_maps); | |
506 else | |
507 { | |
508 (*names)[*p_ptr][i] = (char *) XSTRING (item2)->data; | |
509 /* The menu item "value" is the key bound here. */ | |
510 (*vector)[*p_ptr][i] = XCONS (item)->car; | |
511 i++; | |
512 } | |
513 } | |
514 } | |
515 } | |
516 } | |
517 /* Record the number of items in the pane. */ | |
518 (*items)[*p_ptr] = i; | |
519 | |
520 /* If we just made an empty pane, get rid of it. */ | |
521 if (i == 0) | |
522 { | |
523 free ((*vector)[*p_ptr]); | |
524 free ((*names)[*p_ptr]); | |
525 } | |
526 /* Otherwise, advance past it. */ | |
527 else | |
528 (*p_ptr)++; | |
529 | |
530 /* Process now any submenus which want to be panes at this level. */ | |
531 while (!NILP (pending_maps)) | |
532 { | |
533 Lisp_Object elt; | |
534 elt = Fcar (pending_maps); | |
535 single_keymap_panes (Fcar (elt), panes, vector, names, items, | |
536 p_ptr, npanes_allocated_ptr, | |
537 /* Add 1 to discard the @. */ | |
538 (char *) XSTRING (XCONS (elt)->cdr)->data + 1); | |
539 pending_maps = Fcdr (pending_maps); | |
540 } | |
541 } | |
542 | |
543 /* Construct the vectors that describe a menu | |
544 and store them in *VECTOR, *PANES, *NAMES and *ITEMS. | |
545 Each of those four values is a vector indexed by pane number. | |
546 Return the number of panes. | |
547 | |
548 MENU is the argument that was given to Fx_popup_menu. */ | |
549 | |
550 int | |
294 list_of_panes (vector, panes, names, items, menu) | 551 list_of_panes (vector, panes, names, items, menu) |
295 Lisp_Object ***vector; /* RETURN all menu objects */ | 552 Lisp_Object ***vector; /* RETURN all menu objects */ |
296 char ***panes; /* RETURN pane names */ | 553 char ***panes; /* RETURN pane names */ |
297 char ****names; /* RETURN all line names */ | 554 char ****names; /* RETURN all line names */ |
298 int **items; /* RETURN number of items per pane */ | 555 int **items; /* RETURN number of items per pane */ |
301 Lisp_Object tail, item, item1; | 558 Lisp_Object tail, item, item1; |
302 int i; | 559 int i; |
303 | 560 |
304 if (XTYPE (menu) != Lisp_Cons) menu = wrong_type_argument (Qlistp, menu); | 561 if (XTYPE (menu) != Lisp_Cons) menu = wrong_type_argument (Qlistp, menu); |
305 | 562 |
306 i= XFASTINT (Flength (menu, 1)); | 563 i = XFASTINT (Flength (menu)); |
307 | 564 |
308 *vector = (Lisp_Object **) xmalloc (i * sizeof (Lisp_Object *)); | 565 *vector = (Lisp_Object **) xmalloc (i * sizeof (Lisp_Object *)); |
309 *panes = (char **) xmalloc (i * sizeof (char *)); | 566 *panes = (char **) xmalloc (i * sizeof (char *)); |
310 *items = (int *) xmalloc (i * sizeof (int)); | 567 *items = (int *) xmalloc (i * sizeof (int)); |
311 *names = (char ***) xmalloc (i * sizeof (char **)); | 568 *names = (char ***) xmalloc (i * sizeof (char **)); |
312 | 569 |
313 for (i=0, tail = menu; !NILP (tail); tail = Fcdr (tail), i++) | 570 for (i = 0, tail = menu; !NILP (tail); tail = Fcdr (tail), i++) |
314 { | 571 { |
315 item = Fcdr (Fcar (tail)); | 572 item = Fcdr (Fcar (tail)); |
316 if (XTYPE (item) != Lisp_Cons) (void) wrong_type_argument (Qlistp, item); | 573 if (XTYPE (item) != Lisp_Cons) (void) wrong_type_argument (Qlistp, item); |
317 #ifdef XDEBUG | 574 #ifdef XDEBUG |
318 fprintf (stderr, "list_of_panes check tail, i=%d\n", i); | 575 fprintf (stderr, "list_of_panes check tail, i=%d\n", i); |
319 #endif | 576 #endif |
320 item1 = Fcar (Fcar (tail)); | 577 item1 = Fcar (Fcar (tail)); |
321 CHECK_STRING (item1, 1); | 578 CHECK_STRING (item1, 1); |
322 #ifdef XDEBUG | 579 #ifdef XDEBUG |
323 fprintf (stderr, "list_of_panes check pane, i=%d%s\n", i, | 580 fprintf (stderr, "list_of_panes check pane, i=%d%s\n", i, |
324 XSTRING (item1)->data); | 581 XSTRING (item1)->data); |
325 #endif | 582 #endif |
326 (*panes)[i] = (char *) XSTRING (item1)->data; | 583 (*panes)[i] = (char *) XSTRING (item1)->data; |
327 (*items)[i] = list_of_items ((*vector)+i, (*names)+i, item); | 584 (*items)[i] = list_of_items ((*vector)+i, (*names)+i, item); |
328 /* (*panes)[i] = (char *) xmalloc ((XSTRING (item1)->size)+1); | 585 /* (*panes)[i] = (char *) xmalloc ((XSTRING (item1)->size)+1); |
329 bcopy (XSTRING (item1)->data, (*panes)[i], XSTRING (item1)->size + 1) | 586 bcopy (XSTRING (item1)->data, (*panes)[i], XSTRING (item1)->size + 1) |
330 ; */ | 587 ; */ |
331 } | 588 } |
332 return i; | 589 return i; |
333 } | 590 } |
334 | 591 |
335 | 592 /* Construct the lists of values and names for a single pane, from the |
593 alist PANE. Put them in *VECTOR and *NAMES. | |
594 Return the number of items. */ | |
595 | |
596 int | |
336 list_of_items (vector, names, pane) /* get list from emacs and put to vector */ | 597 list_of_items (vector, names, pane) /* get list from emacs and put to vector */ |
337 Lisp_Object **vector; /* RETURN menu "objects" */ | 598 Lisp_Object **vector; /* RETURN menu "objects" */ |
338 char ***names; /* RETURN line names */ | 599 char ***names; /* RETURN line names */ |
339 Lisp_Object pane; | 600 Lisp_Object pane; |
340 { | 601 { |
341 Lisp_Object tail, item, item1; | 602 Lisp_Object tail, item, item1; |
342 int i; | 603 int i; |
343 | 604 |
344 if (XTYPE (pane) != Lisp_Cons) pane = wrong_type_argument (Qlistp, pane); | 605 if (XTYPE (pane) != Lisp_Cons) pane = wrong_type_argument (Qlistp, pane); |
345 | 606 |
346 i= XFASTINT (Flength (pane, 1)); | 607 i = XFASTINT (Flength (pane, 1)); |
347 | 608 |
348 *vector = (Lisp_Object *) xmalloc (i * sizeof (Lisp_Object)); | 609 *vector = (Lisp_Object *) xmalloc (i * sizeof (Lisp_Object)); |
349 *names = (char **) xmalloc (i * sizeof (char *)); | 610 *names = (char **) xmalloc (i * sizeof (char *)); |
350 | 611 |
351 for (i=0, tail = pane; !NILP (tail); tail = Fcdr (tail), i++) | 612 for (i = 0, tail = pane; !NILP (tail); tail = Fcdr (tail), i++) |
352 { | 613 { |
353 item = Fcar (tail); | 614 item = Fcar (tail); |
354 if (XTYPE (item) != Lisp_Cons) (void) wrong_type_argument (Qlistp, item); | 615 if (XTYPE (item) != Lisp_Cons) (void) wrong_type_argument (Qlistp, item); |
355 #ifdef XDEBUG | 616 #ifdef XDEBUG |
356 fprintf (stderr, "list_of_items check tail, i=%d\n", i); | 617 fprintf (stderr, "list_of_items check tail, i=%d\n", i); |
357 #endif | 618 #endif |
358 (*vector)[i] = Fcdr (item); | 619 (*vector)[i] = Fcdr (item); |
359 item1 = Fcar (item); | 620 item1 = Fcar (item); |
360 CHECK_STRING (item1, 1); | 621 CHECK_STRING (item1, 1); |
361 #ifdef XDEBUG | 622 #ifdef XDEBUG |
362 fprintf (stderr, "list_of_items check item, i=%d%s\n", i, | 623 fprintf (stderr, "list_of_items check item, i=%d%s\n", i, |
363 XSTRING (item1)->data); | 624 XSTRING (item1)->data); |
364 #endif | 625 #endif |
365 (*names)[i] = (char *) XSTRING (item1)->data; | 626 (*names)[i] = (char *) XSTRING (item1)->data; |
366 } | 627 } |
367 return i; | 628 return i; |
368 } | 629 } |