void ui_menu_create(GtkWidget *w, GtkAccelGroup *accel, const char *menu_name, ui_menu_entry_t *list) { static int level = 0; unsigned int i, j; ui_menu_cb_obj *obj = NULL; level++; #ifdef DEBUG_MENUS printf("allocate new: %s\t(%p)\t%s\n", gtk_type_name(GTK_WIDGET_TYPE(w)), w, menu_name); #endif for (i = j = 0; list[i].string; i++) { GtkWidget *new_item = NULL; int do_right_justify = 0; char name[256]; sprintf(name, "MenuItem%d", j); /* ugly... */ switch (*list[i].string) { case '-': /* line */ new_item = gtk_menu_item_new(); break; case '*': /* toggle */ { /* Add this item to the list of calls to perform to update the menu status. */ char *label = make_menu_label(&list[i]); if (list[i].callback) { checkmark_t *cmt; new_item = gtk_check_menu_item_new_with_label(label + 1); cmt = (checkmark_t *)lib_malloc(sizeof(checkmark_t)); cmt->name = lib_stralloc(list[i].string+1); cmt->w = new_item; cmt->cb = list[i].callback; cmt->obj.value = (void*) list[i].callback_data; cmt->obj.status = CB_NORMAL; cmt->handlerid = g_signal_connect(G_OBJECT(new_item),"activate", G_CALLBACK(list[i].callback), (gpointer) &(cmt->obj)); g_signal_connect(G_OBJECT(new_item), "destroy", G_CALLBACK(delete_checkmark_cb), (gpointer) cmt); checkmark_list = g_list_prepend(checkmark_list, cmt); obj = &cmt->obj; } else new_item = gtk_menu_item_new_with_label(label + 1); j++; lib_free(label); break; } case 0: break; default: { char *item, *itemp; item = itemp = make_menu_label(&list[i]); if (strncmp(item, "RJ", 2) == 0) { do_right_justify = 1; item += 2; } new_item = gtk_menu_item_new_with_label(item); if (list[i].callback) { obj = (ui_menu_cb_obj*)lib_malloc(sizeof(ui_menu_cb_obj)); obj->value = (void*) list[i].callback_data; g_signal_connect(G_OBJECT(new_item),"activate", G_CALLBACK(list[i].callback), (gpointer) obj); } lib_free(itemp); j++; } } if (new_item) { gtk_menu_shell_append(GTK_MENU_SHELL(w), new_item); gtk_widget_show(new_item); if (do_right_justify) gtk_menu_item_set_right_justified(GTK_MENU_ITEM(new_item), TRUE); #ifdef DEBUG_MENUS printf("allocate new: %s\t(%p)\t%s\n", gtk_type_name(GTK_WIDGET_TYPE(new_item)), new_item, list[i].string); #endif } if (list[i].sub_menu) { GtkWidget *sub; if (new_item && *list[i].string != '-') { sub = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(new_item),sub); } else { sub = w; } ui_menu_create(sub, accel, list[i].string, list[i].sub_menu); } else { /* no submenu */ if (accel && list[i].hotkey_keysym != KEYSYM_NONE && list[i].callback != NULL && new_item != NULL) add_accelerator(new_item, accel, list[i].hotkey_keysym, list[i].hotkey_modifier); } } level--; }
static void ui_add_items_to_shell(Widget w, int menulevel, ui_menu_entry_t *list) { unsigned int i, j; for (i = j = 0; list[i].string; i++) { Widget new_item = NULL; char *name; name = lib_msprintf("MenuItem%d", j); switch (list[i].type) { case UI_MENU_TYPE_SEPARATOR: /* line */ new_item = XtVaCreateManagedWidget("separator", smeLineObjectClass, w, XtNsensitive, 0, NULL); break; case UI_MENU_TYPE_TICK: /* toggle */ case UI_MENU_TYPE_TICKDOTS: /* toggle */ { char *label = make_menu_label(&list[i]); new_item = XtVaCreateManagedWidget(name, smeBSBObjectClass, w, XtNrightMargin, 20, XtNleftMargin, 20, XtNlabel, label, NULL); /* Add this item to the list of calls to perform to update the menu status. */ if (list[i].callback) { if (num_checkmark_menu_items >= num_checkmark_menu_items_max) { num_checkmark_menu_items_max += 100; checkmark_menu_items = lib_realloc(checkmark_menu_items, num_checkmark_menu_items_max * sizeof(Widget)); } XtAddCallback(new_item, XtNdestroyCallback, tick_destroy, (XtPointer)num_checkmark_menu_items); checkmark_menu_items[num_checkmark_menu_items++] = new_item; } j++; lib_free(label); } break; case UI_MENU_TYPE_NONE: break; default: { char *label = make_menu_label(&list[i]); new_item = XtVaCreateManagedWidget(name, smeBSBObjectClass, w, XtNleftMargin, 20, XtNrightMargin, 20, XtNlabel, label, NULL); lib_free(label); j++; } } lib_free(name); if (list[i].callback) { XtAddCallback(new_item, XtNcallback, (XtCallbackProc)list[i].callback, list[i].callback_data); } if (list[i].sub_menu) { /* * Apparently, the submenu support of Xaw is not used * (it isn't documented in the specs document but exists since * patch "#2716 24 Apr 1999"; see its old-doc/ChangeLog; * see also the man page Xaw(3) which mentions it.) * If the "menuName" resource (XtNmenuName) of a SmeBSB (item) * contains a menu name, that is the submenu and it will * pop up automatically. */ if (num_submenus > MAX_SUBMENUS) { fprintf(stderr, "Maximum number of sub menus reached! Please fix the code.\n"); exit(-1); } if (new_item != NULL && (list[i].type != UI_MENU_TYPE_SEPARATOR)) { Widget subw; XtVaSetValues(new_item, XtNrightBitmap, right_arrow_bitmap, NULL); subw = ui_create_shell(_ui_top_level, "SUB", simpleMenuWidgetClass); XtAddCallback(subw, XtNpopupCallback, submenu_popup_callback, submenus + num_submenus); XtAddCallback(subw, XtNpopdownCallback, submenu_popdown_callback, (XtPointer)w); XtOverrideTranslations(subw, menu_translations); ui_add_items_to_shell(subw, menulevel + 1, list[i].sub_menu); submenus[num_submenus].widget = subw; submenus[num_submenus].parent = new_item; submenus[num_submenus].level = menulevel; num_submenus++; } else { ui_add_items_to_shell(w, menulevel, list[i].sub_menu); } } else { /* no submenu */ if (list[i].hotkey_keysym != (KeySym)0 && list[i].callback != NULL) { ui_hotkey_register(list[i].hotkey_modifier, (signed long)list[i].hotkey_keysym, (ui_callback_t)list[i].callback, (ui_callback_data_t)list[i].callback_data); } } } #ifdef UI_MENU_DEBUG fprintf(stderr, "num_checkmark_menu_items: %d\tnum_submenus = %d.\n", num_checkmark_menu_items, num_submenus); #endif }