diff options
| author | Richard M. Stallman | 1992-09-05 00:08:07 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1992-09-05 00:08:07 +0000 |
| commit | 088831f649662badc2c1aaac2b195339e5376be9 (patch) | |
| tree | 1250533220fa9906db8738cfd4f6f0830985c7ee /src | |
| parent | c9c56492177bd74caf7fe63690aa2422cbbd70f8 (diff) | |
| download | emacs-088831f649662badc2c1aaac2b195339e5376be9.tar.gz emacs-088831f649662badc2c1aaac2b195339e5376be9.zip | |
(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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xmenu.c | 377 |
1 files changed, 319 insertions, 58 deletions
diff --git a/src/xmenu.c b/src/xmenu.c index 9c3375cb1cb..1e6dd98624f 100644 --- a/src/xmenu.c +++ b/src/xmenu.c | |||
| @@ -84,21 +84,30 @@ xmenu_quit () | |||
| 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; |
| @@ -111,39 +120,113 @@ be the return value for that line (i.e. if it is selected.") | |||
| 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)); |
| 131 | #ifdef XDEBUG | 156 | if (!NILP (keymap)) |
| 132 | fprintf (stderr, "Panes= %d\n", number_of_panes); | 157 | { |
| 133 | for (i=0; i < number_of_panes; i++) | 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)) | ||
| 134 | { | 177 | { |
| 135 | fprintf (stderr, "Pane %d lines %d title %s\n", i, items[i], menus[i]); | 178 | /* We were given a list of keymaps. */ |
| 136 | for (j=0; j < items[i]; j++) | 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)) | ||
| 137 | { | 189 | { |
| 138 | fprintf (stderr, " Item %d %s\n", j, names[i][j]); | 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; | ||
| 139 | } | 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 | } | ||
| 214 | #ifdef XDEBUG | ||
| 215 | fprintf (stderr, "Panes = %d\n", number_of_panes); | ||
| 216 | for (i = 0; i < number_of_panes; i++) | ||
| 217 | { | ||
| 218 | fprintf (stderr, "Pane %d has lines %d title %s\n", | ||
| 219 | i, items[i], menus[i]); | ||
| 220 | for (j = 0; j < items[i]; j++) | ||
| 221 | fprintf (stderr, " Item %d %s\n", j, names[i][j]); | ||
| 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; |
| @@ -153,7 +236,7 @@ be the return value for that line (i.e. if it is 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]); |
| @@ -162,7 +245,7 @@ be the return value for that line (i.e. if it is selected.") | |||
| 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 | } |
| @@ -193,7 +276,10 @@ xmenu_show (parent, startx, starty, line_list, pane_list, line_cnt, | |||
| 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) |
| @@ -202,13 +288,15 @@ xmenu_show (parent, startx, starty, line_list, pane_list, line_cnt, | |||
| 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); |
| @@ -218,7 +306,7 @@ xmenu_show (parent, startx, starty, line_list, pane_list, line_cnt, | |||
| 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; |
| @@ -272,7 +360,7 @@ xmenu_show (parent, startx, starty, line_list, pane_list, line_cnt, | |||
| 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"); */ |
| @@ -282,7 +370,7 @@ xmenu_show (parent, startx, starty, line_list, pane_list, line_cnt, | |||
| 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 | ||
| @@ -290,7 +378,176 @@ syms_of_xmenu () | |||
| 290 | { | 378 | { |
| 291 | defsubr (&Sx_popup_menu); | 379 | defsubr (&Sx_popup_menu); |
| 292 | } | 380 | } |
| 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. */ | ||
| 293 | 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 */ |
| @@ -303,36 +560,40 @@ list_of_panes (vector, panes, names, items, menu) | |||
| 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 | ||
| 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. */ | ||
| 335 | 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 */ |
| @@ -343,26 +604,26 @@ list_of_items (vector, names, pane) /* get list from emacs and put to vector */ | |||
| 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 | } |