1 /* SCCS Id: @(#)gnmenu.c 3.4 2000/07/16 */
2 /* Copyright (C) 1998 by Erik Andersen <andersee@debian.org> */
3 /* NetHack may be freely redistributed. See license for details. */
21 gchar accelerator[BUFSZ];
33 static GdkColor color_blue = { 0, 0, 0, 0xffff };
37 ghack_menu_window_key(GtkWidget *menuWin, GdkEventKey *event, gpointer data)
43 isMenu = (MenuWinType) GPOINTER_TO_INT
44 (gtk_object_get_data (GTK_OBJECT (menuWin), "isMenu"));
46 if (isMenu == MenuMenu) {
50 clist = GTK_WIDGET(gtk_object_get_data (GTK_OBJECT (menuWin), "clist"));
51 g_assert (clist != NULL);
52 numRows = GPOINTER_TO_INT
53 (gtk_object_get_data(GTK_OBJECT(clist), "numRows"));
54 selection_mode = GPOINTER_TO_INT
55 (gtk_object_get_data (GTK_OBJECT(clist), "selection_mode"));
56 for (i = 0; i <= numRows; ++i) {
57 item = (menuItem*) gtk_clist_get_row_data(GTK_CLIST(clist), i);
58 if (item == NULL) continue;
59 if (!strcmp(item->accelerator, "")) continue;
61 if ((!strcmp(item->accelerator, event->string)) ||
62 ((selection_mode == GTK_SELECTION_MULTIPLE) &&
63 (event->keyval == ','))) {
65 gtk_clist_unselect_row( GTK_CLIST (clist),
67 item->selected = FALSE;
69 gtk_clist_select_row(GTK_CLIST (clist),
71 if (gtk_clist_row_is_visible(GTK_CLIST(clist),
72 item->itemNumber) != GTK_VISIBILITY_FULL)
73 gtk_clist_moveto(GTK_CLIST(clist),
74 item->itemNumber, 0, 0.5, 0);
75 item->selected = TRUE;
84 ghack_menu_row_selected (GtkCList *clist, int row, int col, GdkEvent *event)
86 /* FIXME: Do something */
91 ghack_menu_window_clear(GtkWidget *menuWin, gpointer data)
97 isMenu = (MenuWinType) GPOINTER_TO_INT
98 (gtk_object_get_data (GTK_OBJECT (menuWin), "isMenu"));
100 if (isMenu == MenuMenu) {
103 clist = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (menuWin), "clist"));
104 g_assert (clist != NULL);
106 /* destroy existing menu data, if any */
108 /* destroy all the row_data we stored in the clist */
109 numRows = GPOINTER_TO_INT( gtk_object_get_data(
110 GTK_OBJECT(clist), "numRows") );
111 for( i=0; i<numRows; i++) {
112 item = (menuItem*) gtk_clist_get_row_data(
113 GTK_CLIST (clist), i);
116 gtk_clist_set_row_data (GTK_CLIST (clist), i,
120 gtk_object_set_data (GTK_OBJECT (clist), "numItems",
121 GINT_TO_POINTER (-1));
122 gtk_clist_clear (GTK_CLIST (clist));
126 else if (isMenu == MenuText) {
129 gless = GNOME_LESS (gtk_object_get_data (GTK_OBJECT (menuWin), "gless"));
130 g_assert (gless != NULL);
132 gtk_editable_delete_text (GTK_EDITABLE (gless->text), 0, 0);
138 ghack_menu_window_display(GtkWidget *menuWin, gboolean blocking,
142 gnome_dialog_close_hides (GNOME_DIALOG (menuWin), TRUE);
143 gnome_dialog_set_close (GNOME_DIALOG (menuWin), TRUE);
144 gnome_dialog_run_and_close(GNOME_DIALOG (menuWin));
147 //gtk_widget_show(menuWin);
152 ghack_menu_hide( GtkWidget *menuWin, GdkEvent *event, gpointer data )
154 gtk_widget_hide (menuWin);
155 return FALSE; /* FIXME: what is correct result here? */
160 ghack_menu_window_start_menu (GtkWidget *menuWin, gpointer data)
162 GtkWidget *frame1, *swin, *clist;
165 g_assert (menuWin != NULL);
166 g_assert (data == NULL);
168 /* destroy existing menu data, if any */
169 frame1 = gtk_object_get_data (GTK_OBJECT (menuWin), "frame1");
171 gtk_widget_destroy (frame1);
174 gtk_object_set_data (GTK_OBJECT (menuWin), "isMenu",
175 GINT_TO_POINTER (isMenu));
177 gtk_widget_set_usize (GTK_WIDGET (menuWin), 500, 400);
178 gtk_window_set_policy (GTK_WINDOW (menuWin), TRUE, TRUE, FALSE);
180 frame1 = gtk_frame_new ("Make your selection");
181 g_assert (frame1 != NULL);
182 gtk_object_set_data (GTK_OBJECT(menuWin), "frame1", frame1);
183 gtk_widget_show (GTK_WIDGET (frame1));
184 gtk_container_set_border_width (GTK_CONTAINER (frame1), 5);
185 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG(menuWin)->vbox), frame1,
188 swin = gtk_scrolled_window_new (NULL, NULL);
189 g_assert (swin != NULL);
190 gtk_object_set_data (GTK_OBJECT(menuWin), "swin", swin);
191 gtk_widget_show (GTK_WIDGET (swin));
192 gtk_container_add (GTK_CONTAINER (frame1), swin);
194 clist = gtk_clist_new (4);
195 g_assert (clist != NULL);
196 gtk_object_set_data (GTK_OBJECT(menuWin), "clist", clist);
197 gtk_widget_show (GTK_WIDGET (clist));
198 gtk_container_add (GTK_CONTAINER (swin), clist);
200 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
201 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
203 gtk_signal_connect (GTK_OBJECT (clist), "select_row",
204 GTK_SIGNAL_FUNC (ghack_menu_row_selected), NULL);
205 gtk_object_set_data (GTK_OBJECT (clist), "numItems",
206 GINT_TO_POINTER (-1));
211 ghack_menu_window_select_menu (GtkWidget *menuWin,
212 MENU_ITEM_P **_selected, gint how)
215 guint num_sel, i, idx;
218 MENU_ITEM_P *selected = NULL;
221 g_assert (_selected != NULL);
225 if (how == PICK_NONE) {
226 gnome_dialog_close_hides (GNOME_DIALOG (menuWin), TRUE);
227 rc = gnome_dialog_run_and_close (GNOME_DIALOG (menuWin));
228 return( rc == 1 ? -1 : 0);
231 clist = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (menuWin), "clist"));
232 g_assert (clist != NULL);
234 gtk_object_set_data (GTK_OBJECT (clist), "selection_mode",
235 GINT_TO_POINTER ((how == PICK_ANY)?
236 GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE));
237 gtk_clist_set_selection_mode (GTK_CLIST (clist),
238 (how == PICK_ANY)? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE);
239 gnome_dialog_close_hides (GNOME_DIALOG (menuWin), TRUE);
240 rc = gnome_dialog_run_and_close (GNOME_DIALOG (menuWin));
241 if ((rc == 1) || (GTK_CLIST (clist)->selection == NULL)) {
245 num_sel = g_list_length (GTK_CLIST (clist)->selection);
250 /* fill in array with selections from clist */
251 selected = g_new0( MENU_ITEM_P, num_sel);
252 g_assert (selected != NULL);
253 cur = GTK_CLIST (clist)->selection;
256 g_assert (i < num_sel);
258 /* grab row number from clist selection list */
259 idx = GPOINTER_TO_INT (cur->data);
261 item = (menuItem*) gtk_clist_get_row_data( GTK_CLIST (clist), idx);
262 selected[i].item = item->identifier;
263 selected[i].count = -1;
264 cur = g_list_next(cur);
268 *_selected = selected;
270 return( (int) num_sel);
274 ghack_menu_window_add_menu( GtkWidget *menuWin, gpointer menu_item,
279 gchar buf[BUFSZ]="", accelBuf[BUFSZ]="";
281 char *text[4] = { buf, NULL, NULL, NULL };
282 gint nCurrentRow = -1, numItems = -1;
284 GtkStyle *bigStyle = NULL;
285 gboolean item_selectable;
286 GdkImlibImage* image;
287 static gboolean special;
289 g_assert (menu_item != NULL);
290 item = (GHackMenuItem*) menu_item;
291 item_selectable = ( item->identifier->a_int == 0)? FALSE : TRUE;
292 isMenu = (MenuWinType) GPOINTER_TO_INT
293 (gtk_object_get_data (GTK_OBJECT (menuWin), "isMenu"));
295 clist = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (menuWin), "clist"));
296 g_assert (clist != NULL);
297 /* This is a special kludge to make the special hidden help menu item work as designed */
298 if ( special==TRUE ) {
300 item_selectable=TRUE;
302 if ( ! strcmp( item->str, "The NetHack license.")) {
308 /* First, make a new blank entry in the clist */
309 nCurrentRow = gtk_clist_append (GTK_CLIST (clist), text);
311 if (item->glyph != NO_GLYPH) {
312 image = ghack_image_from_glyph( item->glyph, FALSE);
313 if (image==NULL || image->pixmap==NULL) {
314 g_warning("Bummer -- having to force rendering for glyph %d!", item->glyph);
315 /* wierd -- pixmap is NULL so retry rendering it */
316 image = ghack_image_from_glyph( item->glyph, TRUE);
318 if (image==NULL || image->pixmap==NULL) {
319 g_error("Aiiee! glyph is still NULL for item\n\"%s\"",
323 gtk_clist_set_pixmap (GTK_CLIST (clist),
325 gdk_imlib_move_image( image),
326 gdk_imlib_move_mask( image));
328 if (item->accelerator) {
329 /* FIXME: handle accelerator, */
330 g_snprintf(accelBuf, sizeof(accelBuf), "%c ", item->accelerator);
331 gtk_clist_set_text (GTK_CLIST (clist), nCurrentRow, 0, accelBuf);
332 g_snprintf(buf, sizeof(buf), "%s", item->str);
333 gtk_clist_set_text (GTK_CLIST (clist), nCurrentRow, 2, buf);
335 if (item->group_accel) {
336 /* FIXME: maybe some day I should try to handle
337 * group accelerators... */
339 if (( (item->attr == 0) && (item->identifier->a_int != 0)) || (special ==TRUE) ) {
340 numItems = GPOINTER_TO_INT( gtk_object_get_data(
341 GTK_OBJECT(clist), "numItems") )+1;
343 /* Ok, now invent a unique accelerator */
344 if ( ('a'+numItems) <= 'z' ) {
345 g_snprintf(accelBuf, sizeof(accelBuf), "%c ", 'a'+numItems);
346 gtk_clist_set_text(GTK_CLIST(clist), nCurrentRow, 0, accelBuf);
348 else if ( ('A'+numItems-26)<='Z') {
349 g_snprintf(accelBuf, sizeof(accelBuf), "%c ", 'A'+numItems-26);
350 gtk_clist_set_text(GTK_CLIST(clist), nCurrentRow, 0, accelBuf);
352 accelBuf[0] = buf[0] = 0;
354 g_snprintf(buf, sizeof(buf), "%s", item->str);
355 gtk_clist_set_text (GTK_CLIST (clist), nCurrentRow, 2, buf);
356 gtk_object_set_data (GTK_OBJECT (clist), "numItems",
357 GINT_TO_POINTER (numItems));
359 /* This junk is to specially handle the options menu */
360 pbuf = strstr( buf, " [");
362 pbuf = strstr( buf, "\t[");
367 gtk_clist_set_text (GTK_CLIST (clist), nCurrentRow, 3, pbuf);
370 /* FIXME: handle more than 26*2 accelerators (but how?
371 * since I only have so many keys to work with???)
378 g_snprintf(buf, sizeof(buf), "%s", item->str);
379 pbuf = strstr( buf, " [");
381 pbuf = strstr( buf, "\t[");
386 gtk_clist_set_text (GTK_CLIST (clist), nCurrentRow, 3, pbuf);
388 gtk_clist_set_text (GTK_CLIST (clist), nCurrentRow, 2, buf);
399 bigStyle = gtk_style_copy (GTK_WIDGET (clist)->style);
400 g_assert (bigStyle != NULL);
401 gdk_font_unref (bigStyle->font);
402 bigStyle->font = gdk_font_load (
403 "-misc-fixed-*-*-*-*-20-*-*-*-*-*-*-*");
404 bigStyle->fg[GTK_STATE_NORMAL] = color_blue;
405 gtk_clist_set_cell_style (GTK_CLIST (clist),
406 nCurrentRow, 2, bigStyle);
407 item_selectable = FALSE;
412 g_assert (nCurrentRow >= 0);
413 gtk_clist_set_selectable (GTK_CLIST (clist), nCurrentRow,
416 if ( item_selectable==TRUE && item->presel== TRUE) {
417 /* pre-select this item */
418 gtk_clist_select_row( GTK_CLIST (clist), nCurrentRow, 0);
421 gtk_object_set_data (GTK_OBJECT (clist), "numRows",
422 GINT_TO_POINTER (nCurrentRow));
424 /* We have to allocate memory here, since the menu_item currently
425 * lives on the stack, and will otherwise go to the great bit bucket
426 * in the sky as soon as this function exits, which would leave a
427 * pointer to crap in the row_data. Use g_memdup to make a private,
428 * persistant copy of the item identifier.
430 * We need to arrange to blow away this memory somewhere (like
431 * ghack_menu_destroy and ghack_menu_window_clear for example).
439 newItem.identifier = *item->identifier;
440 newItem.itemNumber=nCurrentRow;
441 newItem.selected=FALSE;
442 newItem.accelerator[0]=0;
443 /* only copy 1 char, since accel keys are by definition 1 char */
445 strncpy(newItem.accelerator, accelBuf, 1);
447 newItem.accelerator[1]=0;
449 pNewItem = g_memdup(&newItem, sizeof( menuItem));
450 gtk_clist_set_row_data (GTK_CLIST (clist), nCurrentRow,
451 (gpointer) pNewItem);
454 /* Now adjust the column widths to match the contents */
455 gtk_clist_columns_autosize (GTK_CLIST (clist));
459 ghack_menu_window_end_menu (GtkWidget *menuWin, gpointer data)
461 const char* p = (const char*) data;
464 GtkWidget *frame1 = gtk_object_get_data (GTK_OBJECT (menuWin), "frame1");
465 g_assert (frame1 != NULL);
467 gtk_frame_set_label (GTK_FRAME(frame1), p);
473 void ghack_menu_window_put_string(GtkWidget *menuWin, int attr,
474 const char* text, gpointer data)
482 isMenu = (MenuWinType) GPOINTER_TO_INT
483 (gtk_object_get_data (GTK_OBJECT (menuWin), "isMenu"));
485 if (isMenu == MenuText) {
486 gless = GNOME_LESS (gtk_object_get_data (GTK_OBJECT (menuWin), "gless"));
487 g_assert (gless != NULL);
488 g_assert (gless->text != NULL);
489 g_assert (GTK_IS_TEXT (gless->text));
491 /* Don't bother with attributes yet */
492 gtk_text_insert (GTK_TEXT (gless->text), NULL, NULL, NULL, text, -1);
493 gtk_text_insert (GTK_TEXT (gless->text), NULL, NULL, NULL, "\n", -1);
497 else if (isMenu == MenuUnknown) {
499 gtk_object_set_data (GTK_OBJECT (menuWin), "isMenu",
500 GINT_TO_POINTER (isMenu));
502 gtk_widget_set_usize (GTK_WIDGET (menuWin), 500, 400);
503 gtk_window_set_policy (GTK_WINDOW (menuWin), TRUE, TRUE, FALSE);
505 gless = GNOME_LESS (gnome_less_new ());
506 g_assert (gless != NULL);
507 gtk_object_set_data (GTK_OBJECT (menuWin), "gless", gless);
508 gtk_widget_show (GTK_WIDGET (gless));
510 gnome_less_show_string (gless, text);
511 gtk_text_insert (GTK_TEXT (gless->text), NULL, NULL, NULL, "\n", -1);
513 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (menuWin)->vbox),
514 GTK_WIDGET (gless), TRUE, TRUE, 0);
520 ghack_menu_destroy (GtkWidget *menuWin, gpointer data)
524 isMenu = (MenuWinType) GPOINTER_TO_INT
525 (gtk_object_get_data (GTK_OBJECT (menuWin), "isMenu"));
527 if (isMenu == MenuText) {
530 gless = GNOME_LESS (gtk_object_get_data (GTK_OBJECT (menuWin), "gless"));
531 g_assert (gless != NULL);
532 g_assert (gless->text != NULL);
533 g_assert (GTK_IS_TEXT (gless->text));
534 gtk_widget_destroy(GTK_WIDGET(gless));
537 else if (isMenu == MenuMenu) {
538 GtkWidget *frame1, *swin, *clist;
540 /* destroy existing menu data, if any */
541 clist = gtk_object_get_data (GTK_OBJECT (menuWin), "clist");
543 /* destroy all the row_data we stored in the clist */
546 numRows = GPOINTER_TO_INT( gtk_object_get_data(
547 GTK_OBJECT(clist), "numRows") );
548 for( i=0; i<numRows; i++) {
549 item = (menuItem*) gtk_clist_get_row_data(
550 GTK_CLIST (clist), i);
553 gtk_clist_set_row_data (GTK_CLIST (clist), i,
558 gtk_object_set_data (GTK_OBJECT (clist), "numItems",
559 GINT_TO_POINTER (-1));
560 gtk_widget_destroy (clist);
562 swin = gtk_object_get_data (GTK_OBJECT (menuWin), "swin");
564 gtk_widget_destroy (swin);
566 frame1 = gtk_object_get_data (GTK_OBJECT (menuWin), "frame1");
568 gtk_widget_destroy (frame1);
571 gnome_delete_nhwindow_by_reference (menuWin);
576 ghack_init_menu_window (void)
578 GtkWidget *menuWin = NULL;
579 GtkWidget *parent = ghack_get_main_window ();
581 menuWin = gnome_dialog_new("GnomeHack", GNOME_STOCK_BUTTON_OK,
582 GNOME_STOCK_BUTTON_CANCEL, NULL);
584 gnome_dialog_set_default( GNOME_DIALOG(menuWin), 0);
585 gtk_signal_connect(GTK_OBJECT(menuWin), "destroy",
586 GTK_SIGNAL_FUNC(ghack_menu_destroy),
589 gtk_signal_connect (GTK_OBJECT (menuWin), "delete_event",
590 GTK_SIGNAL_FUNC (ghack_menu_hide),
593 gtk_signal_connect(GTK_OBJECT(menuWin), "ghack_clear",
594 GTK_SIGNAL_FUNC(ghack_menu_window_clear),
597 gtk_signal_connect(GTK_OBJECT(menuWin), "ghack_display",
598 GTK_SIGNAL_FUNC(ghack_menu_window_display),
601 gtk_signal_connect(GTK_OBJECT(menuWin), "ghack_start_menu",
602 GTK_SIGNAL_FUNC(ghack_menu_window_start_menu),
605 gtk_signal_connect(GTK_OBJECT(menuWin), "ghack_add_menu",
606 GTK_SIGNAL_FUNC(ghack_menu_window_add_menu),
609 gtk_signal_connect(GTK_OBJECT(menuWin), "ghack_end_menu",
610 GTK_SIGNAL_FUNC(ghack_menu_window_end_menu),
613 gtk_signal_connect(GTK_OBJECT(menuWin), "ghack_select_menu",
614 GTK_SIGNAL_FUNC(ghack_menu_window_select_menu),
617 gtk_signal_connect(GTK_OBJECT(menuWin), "ghack_putstr",
618 GTK_SIGNAL_FUNC(ghack_menu_window_put_string),
621 gtk_signal_connect(GTK_OBJECT(menuWin), "key_press_event",
622 GTK_SIGNAL_FUNC(ghack_menu_window_key),
625 /* Center the dialog over parent */
626 g_assert (parent != NULL);
627 g_assert (menuWin != NULL);
628 g_assert (GTK_IS_WINDOW (parent));
629 g_assert (GNOME_IS_DIALOG (menuWin));
630 gnome_dialog_set_parent (GNOME_DIALOG (menuWin), GTK_WINDOW (parent));
636 ghack_ext_key_hit(GtkWidget *menuWin, GdkEventKey *event, gpointer data)
639 extMenu* info = (extMenu*) data;
641 char c = event->string[0];
643 clist = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(menuWin), "clist"));
644 g_assert(clist != NULL);
646 /* if too long between keystrokes, reset to initial state */
647 if (event->time - info->lastTime > 500) goto init_state;
649 /* see if current item continue to match */
650 if (info->charIdx > 0) {
651 if (extcmdlist[info->curItem].ef_txt[info->charIdx] == c) {
657 /* see if the prefix matches a later command in the list */
658 if (info->curItem >= 0) {
659 for (i = info->curItem + 1; i < info->numRows; ++i) {
660 if (!strncmp(extcmdlist[info->curItem].ef_txt,
661 extcmdlist[i].ef_txt, info->charIdx)) {
662 if (extcmdlist[i].ef_txt[info->charIdx] == c) {
672 /* reset to initial state, look for matching 1st character */
673 for (i = 0; i < info->numRows; ++i) {
674 if (extcmdlist[i].ef_txt[0] == c) {
681 /* no match: leave prior, if any selection in place */
685 info->lastTime = event->time;
686 gtk_clist_select_row(GTK_CLIST(clist), info->curItem, 0);
687 if (gtk_clist_row_is_visible(GTK_CLIST(clist),
688 info->curItem) != GTK_VISIBILITY_FULL)
689 gtk_clist_moveto(GTK_CLIST(clist), info->curItem, 0, 0.5, 0);
693 ghack_menu_ext_cmd(void)
702 dialog = gnome_dialog_new("Extended Commands",
703 GNOME_STOCK_BUTTON_OK,
704 GNOME_STOCK_BUTTON_CANCEL,
706 gnome_dialog_close_hides(GNOME_DIALOG(dialog), FALSE);
707 gtk_signal_connect(GTK_OBJECT(dialog), "key_press_event",
708 GTK_SIGNAL_FUNC(ghack_ext_key_hit), &info);
710 frame1 = gtk_frame_new("Make your selection");
711 gtk_object_set_data(GTK_OBJECT(dialog), "frame1", frame1);
712 gtk_widget_show(frame1);
713 gtk_container_border_width(GTK_CONTAINER(frame1), 3);
715 swin = gtk_scrolled_window_new(NULL, NULL);
716 clist = gtk_clist_new(2);
717 gtk_object_set_data(GTK_OBJECT(dialog), "clist", clist);
718 gtk_widget_set_usize(clist, 500, 400);
719 gtk_container_add(GTK_CONTAINER(swin), clist);
720 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin),
721 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
723 gtk_signal_connect(GTK_OBJECT(clist), "select_row",
724 GTK_SIGNAL_FUNC(ghack_menu_row_selected), NULL);
726 gtk_container_add(GTK_CONTAINER(frame1), swin);
727 gtk_box_pack_start_defaults(GTK_BOX(GNOME_DIALOG(dialog)->vbox), frame1);
729 /* Add the extended commands into the list here... */
730 for (n = 0; extcmdlist[n].ef_txt; ++n) {
731 const char *text[3]={extcmdlist[n].ef_txt,extcmdlist[n].ef_desc,NULL};
732 gtk_clist_insert(GTK_CLIST(clist), n, (char**) text);
735 /* fill in starting info fields */
741 gtk_clist_columns_autosize(GTK_CLIST(clist));
742 gtk_widget_show_all(swin);
744 /* Center the dialog over over parent */
745 gnome_dialog_set_default(GNOME_DIALOG(dialog), 0);
746 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
747 gnome_dialog_set_parent(GNOME_DIALOG(dialog),
748 GTK_WINDOW(ghack_get_main_window()));
750 /* Run the dialog -- returning whichever button was pressed */
751 n = gnome_dialog_run_and_close(GNOME_DIALOG(dialog));
753 /* Quit on button 2 or error */
754 return (n != 0) ? -1 : info.curItem;