Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/util/xmenu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/xmenu.c')
-rw-r--r--src/util/xmenu.c998
1 files changed, 998 insertions, 0 deletions
diff --git a/src/util/xmenu.c b/src/util/xmenu.c
new file mode 100644
index 0000000..8a70b5d
--- /dev/null
+++ b/src/util/xmenu.c
@@ -0,0 +1,998 @@
+#ifdef _plan9_
+#include <u.h>
+#include <libc.h>
+#else
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#endif
+#include <config.h>
+#include <filter.h>
+#include <fractal.h>
+#include <ui_helper.h>
+#include <xerror.h>
+#include <xldio.h>
+#include <misc-f.h>
+#include "config.h"
+#include "xmenu.h"
+
+#define HASHBITS 8
+#define HASHSIZE (1<<HASHBITS)
+#define HASHMASK (HASHSIZE-1)
+#define HASH(c,len) (((len)*32+(c)[0]+(c)[(len)-1])&HASHMASK)
+
+static struct queuelist {
+ struct queuelist *next;
+ struct queuelist *previous;
+ CONST menuitem *item;
+ dialogparam *d;
+} *firstqueue = NULL, *lastqueue = NULL;
+static struct entry {
+ struct entry *next;
+ struct entry *previous;
+ struct entry *nextname;
+ CONST menuitem *item;
+} *firstitem = NULL, *lastitem = NULL;
+
+struct entry *namehash[HASHSIZE];
+
+static void
+x_menu_insert(CONST menuitem * item, struct entry *iitem, int n)
+{
+ int i;
+ int len;
+ int hashpos;
+ struct entry *list;
+ for (i = 0; i < n; i++) {
+ list = (struct entry *) calloc(1, sizeof(struct queuelist));
+ if (list == NULL) {
+ x_error("Warning:out of memory!");
+ return;
+ }
+ if (item->type != MENU_SEPARATOR) {
+ len = strlen(item->shortname);
+ hashpos = HASH(item->shortname, len);
+ list->nextname = namehash[hashpos];
+#ifdef DEBUG
+ {
+ struct entry *e = list->nextname;
+ while (e != NULL) {
+ if (e->item->type != MENU_SUBMENU
+ && e->item->type != MENU_SEPARATOR
+ && item->type != MENU_SEPARATOR);
+ if (!strcmp(e->item->shortname, item->shortname)
+ /*&& e->item->type != MENU_SUBMENU && item->type != MENU_SUBMENU */
+ ) {
+ x_error
+ ("Menu error:Name collision %s:'%s'(%s) and '%s'(%s)",
+ item->shortname, item->name, item->menuname,
+ e->item->name, e->item->menuname);
+ }
+ e = e->nextname;
+ }
+ }
+#endif
+ namehash[hashpos] = list;
+ }
+ list->item = item;
+ if (iitem == NULL) {
+ /*printf("ahoj\n"); */
+ list->previous = lastitem;
+ list->next = NULL;
+ if (lastitem != NULL)
+ lastitem->next = list;
+ else
+ firstitem = list;
+ lastitem = list;
+ } else {
+ list->next = iitem;
+ list->previous = iitem->previous;
+ if (iitem->previous)
+ iitem->previous->next = list;
+ else
+ firstitem = list;
+ iitem->previous = list;
+ }
+ item++;
+ }
+}
+
+void menu_add(CONST menuitem * item, int n)
+{
+ x_menu_insert(item, NULL, n);
+}
+
+void menu_insert(CONST menuitem * item, CONST char *before, int n)
+{
+ struct entry *e = firstitem;
+ while (e != NULL) {
+ if (!strcmp(e->item->shortname, before))
+ break;
+ e = e->next;
+ }
+ x_menu_insert(item, e, n);
+}
+
+void menu_delete(CONST menuitem * items, int n)
+{
+ int d = 0, i;
+ struct entry *item = firstitem;
+ struct entry *pe;
+ int hashpos;
+ for (i = 0; i < n; i++) {
+ if (items[i].type == MENU_SEPARATOR) {
+ struct entry *item = firstitem;
+ while (item && item->item != items + i)
+ item = item->next;
+ if (!item)
+ abort();
+ if (item->previous != NULL)
+ item->previous->next = item->next;
+ else
+ firstitem = item->next;
+ if (item->next != NULL)
+ item->next->previous = item->previous;
+ else
+ lastitem = item->previous;
+ free(item);
+ } else {
+ int len = strlen(items[i].shortname);
+ hashpos = HASH(items[i].shortname, len);
+ pe = NULL;
+ item = namehash[hashpos];
+ while (item != NULL) {
+ if (items + i == item->item) {
+ d++;
+ if (pe == NULL)
+ namehash[hashpos] = item->nextname;
+ else
+ pe->nextname = item->nextname;
+ if (item->previous != NULL)
+ item->previous->next = item->next;
+ else
+ firstitem = item->next;
+ if (item->next != NULL)
+ item->next->previous = item->previous;
+ else
+ lastitem = item->previous;
+ free(item);
+ break;
+ } /*if */
+ pe = item;
+ item = item->nextname;
+ } /*while */
+ }
+#ifdef DEBUG
+ if (item == NULL)
+ x_error("Item %s not found!", items[i].shortname);
+#endif
+ } /*for */
+}
+
+void menu_addqueue(CONST menuitem * item, dialogparam * d)
+{
+ struct queuelist *list;
+ list = (struct queuelist *) calloc(1, sizeof(struct queuelist));
+ if (list == NULL) {
+ x_error("Warning:out of memory!");
+ return;
+ }
+ list->previous = lastqueue;
+ list->next = NULL;
+ list->item = item;
+ list->d = d;
+ if (lastqueue != NULL)
+ lastqueue->next = list;
+ else
+ firstqueue = list;
+ lastqueue = list;
+}
+
+CONST menuitem *menu_delqueue(dialogparam ** d)
+{
+ CONST struct menuitem *item;
+ struct queuelist *list = firstqueue;
+ if (firstqueue == NULL)
+ return NULL;
+ item = firstqueue->item;
+ *d = firstqueue->d;
+ firstqueue = list->next;
+ if (list->next != NULL)
+ list->next->previous = NULL;
+ else
+ lastqueue = NULL;
+ free(list);
+ return (item);
+}
+
+CONST static void *menu_rfind(CONST void
+ *(*function) (struct entry * item),
+ CONST char *root)
+{
+ struct entry *item = firstitem;
+ CONST void *r;
+ while (item != NULL) {
+ if (!strcmp(root, item->item->menuname)) {
+ if ((r = function(item)) != NULL)
+ return r;
+ if (item->item->type == MENU_SUBMENU
+ && (r =
+ menu_rfind(function, item->item->shortname)) != NULL)
+ return r;
+ }
+ item = item->next;
+ }
+ return NULL;
+}
+
+CONST static char *findkey;
+CONST static void *cmpfunction(struct entry *item)
+{
+ if (item->item->key == NULL)
+ return NULL;
+ if (!strcmp(findkey, item->item->key))
+ return item->item;
+ return NULL;
+}
+
+CONST menuitem *menu_findkey(CONST char *key, CONST char *root)
+{
+ findkey = key;
+ return ((CONST menuitem *) menu_rfind(cmpfunction, root));
+}
+
+static CONST menuitem *finditem;
+CONST static void *cmpfunction2(struct entry *item)
+{
+ if (item->item == finditem)
+ return item;
+ return NULL;
+}
+
+int menu_available(CONST menuitem * item, CONST char *root)
+{
+ finditem = item;
+ return (menu_rfind(cmpfunction2, root) != NULL);
+}
+
+CONST char *menu_fullname(CONST char *menu)
+{
+ struct entry *item = firstitem;
+ while (item != NULL) {
+ if (item->item->type == MENU_SUBMENU
+ && !strcmp(menu, item->item->shortname)) {
+ return (item->item->name);
+ }
+ item = item->next;
+ }
+ return NULL;
+}
+
+CONST menuitem *menu_item(CONST char *menu, int n)
+{
+ struct entry *item = firstitem;
+ while (item != NULL) {
+ if (!strcmp(menu, item->item->menuname)) {
+ if (!(item->item->flags & MENUFLAG_NOMENU))
+ n--;
+ if (n < 0)
+ return (item->item);
+ }
+ item = item->next;
+ }
+ return NULL;
+}
+
+static CONST menuitem *menu_item2(CONST char *menu, int n)
+{
+ struct entry *item = firstitem;
+ while (item != NULL) {
+ if (!strcmp(menu, item->item->menuname)) {
+ n--;
+ if (n < 0)
+ return (item->item);
+ }
+ item = item->next;
+ }
+ return NULL;
+}
+
+int menu_havedialog(CONST menuitem * item, struct uih_context *c)
+{
+ if (item->type != MENU_DIALOG && item->type != MENU_CUSTOMDIALOG)
+ return 0;
+ if (!(item->type & MENUFLAG_RADIO) || c == NULL)
+ return 1;
+ if (item->flags & MENUFLAG_DIALOGATDISABLE)
+ return (menu_enabled(item, c));
+ return (!menu_enabled(item, c));
+}
+
+static void menu_freeparam(dialogparam * d, CONST struct dialog *di)
+{
+ switch (di->type) {
+ case DIALOG_STRING:
+ case DIALOG_KEYSTRING:
+ case DIALOG_IFILE:
+ case DIALOG_OFILE:
+ free(d->dstring);
+ }
+}
+
+void
+menu_destroydialog(CONST menuitem * item, dialogparam * d,
+ struct uih_context *uih)
+{
+ int i;
+ CONST struct dialog *di = menu_getdialog(uih, item);
+ for (i = 0; di[i].question; i++) {
+ menu_freeparam(d + i, di + i);
+ }
+ free(d);
+
+}
+
+void
+menu_activate(CONST menuitem * item, struct uih_context *c,
+ dialogparam * d)
+{
+ if (c == NULL
+ && (!(item->flags & MENUFLAG_ATSTARTUP) || firstqueue != NULL)) {
+ menu_addqueue(item, d);
+ return;
+ } else {
+ if (c != NULL && c->incalculation
+ && !(item->flags & MENUFLAG_INCALC)) {
+ if (c->flags & MENUFLAG_INTERRUPT)
+ c->interrupt = 1;
+ menu_addqueue(item, d);
+ return;
+ }
+ }
+ switch (item->type) {
+ case MENU_SEPARATOR:
+ x_error("separator activated!");
+ break;
+ case MENU_SUBMENU:
+ x_error("submenu activated!");
+ break;
+ case MENU_NOPARAM:
+ ((void (*)(struct uih_context *)) item->function) (c);
+ break;
+ case MENU_INT:
+ ((void (*)(struct uih_context *, int)) item->function) (c,
+ item->
+ iparam);
+ break;
+ case MENU_STRING:
+ ((void (*)(struct uih_context *, CONST char *)) item->function) (c,
+ (CONST
+ char
+ *)
+ item->pparam);
+ break;
+ case MENU_DIALOG:
+ case MENU_CUSTOMDIALOG:
+ if (!menu_havedialog(item, c)) {
+ ((void (*)(struct uih_context * c, dialogparam *)) item->
+ function)
+ (c, (dialogparam *) NULL);
+ } else {
+ CONST menudialog *di = menu_getdialog(c, item);
+ if (di[0].question == NULL) {
+ ((void (*)(struct uih_context * c, dialogparam *))
+ item->function) (c, (dialogparam *) NULL);
+ break;
+ } else if (di[1].question == NULL) {
+ /*call function with right
+ *parameter. This avoids need to write wrappers*/
+ switch (di[0].type) {
+ case DIALOG_INT:
+ case DIALOG_CHOICE:
+ case DIALOG_ONOFF:
+ ((void (*)(struct uih_context * c, int)) item->
+ function) (c, d[0].dint);
+ break;
+ case DIALOG_FLOAT:
+ ((void (*)(struct uih_context * c, number_t))
+ item->function) (c, d[0].number);
+ break;
+ case DIALOG_COORD:
+ ((void (*)(struct uih_context * c, number_t, number_t))
+ item->function) (c, d[0].dcoord[0], d[0].dcoord[1]);
+ break;
+ case DIALOG_STRING:
+ case DIALOG_KEYSTRING:
+ ((void (*)(struct uih_context * c, char *)) item->
+ function)
+ (c, d[0].dstring);
+ break;
+ case DIALOG_IFILE:
+ case DIALOG_OFILE:
+ ((void (*)(struct uih_context * c, xio_path))
+ item->function) (c, d[0].dpath);
+ break;
+ default:
+ x_error("dialog:unknown type!");
+ break;
+ }
+
+ } else
+ ((void (*)(struct uih_context * c, dialogparam *)) item->
+ function)
+ (c, d);
+ }
+ break;
+ default:
+ x_error("Menu_activate: unknown type %i!", item->type);
+ break;
+ }
+}
+
+int menu_enabled(CONST menuitem * item, struct uih_context *c)
+{
+ if (item->flags & (MENUFLAG_RADIO | MENUFLAG_CHECKBOX))
+ switch (item->type) {
+ case MENU_SEPARATOR:
+ return 0;
+ case MENU_SUBMENU:
+ case MENU_DIALOG:
+ case MENU_NOPARAM:
+ case MENU_CUSTOMDIALOG:
+ return (((int (*)(struct uih_context *)) item->control) (c));
+ case MENU_INT:
+ return (((int (*)(struct uih_context *, int)) item->
+ control) (c, item->iparam));
+ case MENU_STRING:
+ return (((int (*)(struct uih_context *, CONST char *)) item->
+ control)
+ (c, (CONST char *) item->pparam));
+ default:
+ x_error("Menu_enabled: unknown type!");
+ break;
+ }
+ return 0;
+}
+
+void menu_delnumbered(int n, CONST char *name)
+{
+ menuitem *items;
+ int i;
+ char s[256];
+ sprintf(s, "%s%i", name, 0);
+ items = (menuitem *) menu_findcommand(s);
+ menu_delete(items, n);
+ for (i = 0; i < n; i++) {
+ if (items[i].key)
+ free((char *) items[i].key);
+ free((char *) items[i].shortname);
+ }
+ free(items);
+}
+
+CONST menuitem *menu_genernumbered(int n, CONST char *menuname,
+ CONST char *CONST * CONST names,
+ CONST char *keys, int type, int flags,
+ void (*function) (struct uih_context *
+ context, int),
+ int (*control) (struct uih_context *
+ context, int),
+ CONST char *prefix)
+{
+ int l = keys != NULL ? (int) strlen(keys) : -1;
+ int i;
+ menuitem *item = (menuitem *) malloc(sizeof(menuitem) * n);
+ if (item == NULL)
+ return NULL;
+ for (i = 0; i < n; i++) {
+ item[i].menuname = menuname;
+ if (i < l) {
+ char *key = malloc(2);
+ item[i].key = key;
+ key[0] = keys[i];
+ key[1] = 0;
+ } else
+ item[i].key = 0;
+ item[i].type = type;
+ item[i].flags = flags;
+ item[i].iparam = i;
+ item[i].name = names[i];
+ item[i].shortname = names[i];
+ if (prefix != NULL) {
+ char *shortname = (char *) malloc(strlen(prefix) + 4);
+ item[i].shortname = shortname;
+ sprintf(shortname, "%s%i", prefix, i);
+ }
+ item[i].function = (void (*)(void)) function;
+ item[i].control = (int (*)(void)) control;
+ }
+ menu_add(item, n);
+ return (item);
+}
+
+number_t menu_getfloat(CONST char *s, CONST char **error)
+{
+#ifdef HAVE_LONG_DOUBLE
+ long double param = 0;
+#else
+ double param = 0;
+#endif
+#ifdef HAVE_LONG_DOUBLE
+#ifndef USE_ATOLD
+#ifdef USE_XLDIO
+ param = x_strtold(s, NULL);
+ if (0)
+#else
+ if (sscanf(s, "%LG", &param) == 0)
+#endif
+#else
+ param = _atold(s);
+ if (0)
+#endif
+ {
+#else
+ if (sscanf(s, "%lG", &param) == 0) {
+#endif
+ *error = "Floating point number expected";
+ return 0;
+ }
+ return (param);
+}
+
+int menuparse_scheme = 0;
+CONST char *menu_fillparam(struct uih_context *uih, tokenfunc f,
+ CONST menudialog * d, dialogparam * p)
+{
+ char *c = f(uih);
+ CONST char *error = NULL;
+ if (c == NULL)
+ return "Parameter expected";
+ switch (d->type) {
+ case DIALOG_INT:
+ if (sscanf(c, "%i", &p->dint) != 1) {
+ return "Integer parameter expected";
+ }
+ break;
+ case DIALOG_FLOAT:
+ p->number = menu_getfloat(c, &error);
+ if (error != NULL)
+ return (error);
+ break;
+ case DIALOG_COORD:
+ p->dcoord[0] = menu_getfloat(c, &error);
+ if (error != NULL)
+ return (error);
+ c = f(uih);
+ if (c == NULL)
+ return "Imaginary part expected";
+ p->dcoord[1] = menu_getfloat(c, &error);
+ if (error != NULL)
+ return (error);
+ break;
+ case DIALOG_KEYSTRING:
+ if (menuparse_scheme) {
+ if (c[0] != '\'')
+ return "Key string parameter expected";
+ p->dstring = mystrdup(c + 1);
+ } else
+ p->dstring = mystrdup(c);
+ break;
+ case DIALOG_STRING:
+ if (menuparse_scheme) {
+ int l = strlen(c);
+ if (l < 2 || c[0] != '"' || c[l - 1] != '"')
+ return "String parameter expected";
+ p->dstring = mystrdup(c + 1);
+ p->dstring[l - 2] = 0;
+ } else
+ p->dstring = mystrdup(c);
+ break;
+ case DIALOG_IFILE:
+ case DIALOG_OFILE:
+ if (menuparse_scheme) {
+ int l = strlen(c);
+ if (l < 2 || c[0] != '"' || c[l - 1] != '"')
+ return "String parameter expected";
+ p->dstring = mystrdup(c + 1);
+ p->dstring[l - 2] = 0;
+ } else
+ p->dstring = mystrdup(c);
+ break;
+ case DIALOG_CHOICE:
+ if (menuparse_scheme) {
+ if (c[0] != '\'')
+ return "Key string parameter expected";
+ c++;
+ }
+ {
+ int i;
+ CONST char **keys = (CONST char **) d->defstr;
+ for (i = 0;; i++) {
+ if (keys[i] == NULL)
+ return "Unknown parameter";
+ if (!strcmp(c, keys[i])) {
+ p->dint = i;
+ return NULL;
+ }
+ }
+ }
+ case DIALOG_ONOFF:
+ if (menuparse_scheme) {
+ if (!strcmp("#t", c)) {
+ p->dint = 1;
+ return NULL;
+ }
+ if (!strcmp("#f", c)) {
+ p->dint = 0;
+ return NULL;
+ }
+ } else {
+ if (!strcmp("on", c)) {
+ p->dint = 1;
+ return NULL;
+ }
+ if (!strcmp("off", c)) {
+ p->dint = 0;
+ return NULL;
+ }
+ }
+ default:
+ x_error("Unknown dialog parameter type!");
+ } /*switch */
+ return NULL;
+}
+
+static char errorstr[256];
+CONST menuitem *menu_findcommand(CONST char *name)
+{
+ struct entry *entry;
+ CONST menuitem *item;
+ int len;
+ len = strlen(name);
+ if (len > 100)
+ return NULL;
+ entry = namehash[HASH(name, len)];
+ while (entry != NULL) {
+ if (!strcmp(entry->item->shortname, name))
+ break;
+ entry = entry->nextname;
+ }
+ if (entry == NULL) {
+ return NULL;
+ }
+ item = entry->item;
+ return (item);
+}
+
+CONST char *menu_processcommand(struct uih_context *uih, tokenfunc f,
+ int scheme, int mask, CONST char *root)
+{
+ char *c = f(uih);
+ CONST menuitem *item;
+ menuparse_scheme = scheme;
+ if (c == NULL) {
+ if (!menuparse_scheme)
+ return "Command name expected";
+ return NULL;
+ }
+ item = menu_findcommand(c);
+ if (item == NULL) {
+ sprintf(errorstr, "%s:unknown function", c);
+ return errorstr;
+ }
+ if (item->flags & mask) {
+ sprintf(errorstr,
+ "function '%s' not available in this context (%i, %i)", c,
+ mask, item->flags);
+ return errorstr;
+ }
+ if ((item->flags & MENUFLAG_NOPLAY) && uih != NULL) {
+ if (root != NULL && !menu_available(item, root)) {
+ sprintf(errorstr, "function '%s' is disabled", c);
+ return errorstr;
+ }
+ }
+
+ if ((item->flags & MENUFLAG_CHECKBOX) && scheme) {
+ int w;
+ c = f(uih);
+ if (c == NULL) {
+ return ("Boolean parameter expected");
+ }
+
+ if (!strcmp("#t", c)) {
+ w = 1;
+ } else if (!strcmp("#f", c)) {
+ w = 0;
+ } else
+ return "Boolean parameter expected";
+ if (w == menu_enabled(item, uih)) {
+ if (((w != 0) ^ ((item->flags & MENUFLAG_DIALOGATDISABLE) !=
+ 0))
+ || (item->type != MENU_DIALOG
+ && item->type != MENU_CUSTOMDIALOG)) {
+ return NULL;
+ } else
+ menu_activate(item, uih, NULL); /*disable it... */
+ }
+ }
+ if (item->type != MENU_DIALOG && item->type != MENU_CUSTOMDIALOG) {
+ menu_activate(item, uih, NULL);
+ return NULL;
+ }
+ /*So we have some parameters */
+
+ {
+ dialogparam *param;
+ CONST menudialog *d = menu_getdialog(uih, item);
+ int i, n;
+ for (n = 0; d[n].question != NULL; n++);
+ param = (dialogparam *) malloc(n * sizeof(dialogparam));
+ for (i = 0; i < n; i++) {
+ CONST char *error;
+ error = menu_fillparam(uih, f, d + i, param + i);
+ if (error != NULL) {
+ sprintf(errorstr, "Function '%s' parameter %i:%s",
+ item->shortname, i, error);
+ for (n = 0; n < i; n++) {
+ menu_freeparam(param + i, d + i);
+ }
+ free(param);
+ return errorstr;
+ }
+ }
+ menu_activate(item, uih, param);
+ if (uih != NULL)
+ menu_destroydialog(item, param, uih);
+ }
+ return NULL;
+}
+
+static int argpos, margc;
+static char **margv;
+static int argposs;
+static char *gettoken(struct uih_context *c)
+{
+ if (argpos == margc)
+ return NULL;
+ if (argpos == argposs) {
+ if (!margv[argpos])
+ return NULL;
+ return (margv[argpos++] + 1);
+ } else
+ return (margv[argpos++]);
+}
+
+int menu_processargs(int n, int argc, char **argv)
+{
+ CONST char *error;
+ argpos = n;
+ argposs = n;
+ margc = argc;
+ margv = argv;
+ error =
+ menu_processcommand(NULL, gettoken, 0, MENUFLAG_NOOPTION, "root");
+ if (error) {
+ x_error("%s", error);
+ return -1;
+ }
+ return (argpos - 2);
+
+}
+
+void menu_printhelp(void)
+{
+ struct entry *e = firstitem;
+ while (e) {
+ if (e->item->type == MENU_SEPARATOR) {
+ e = e->next;
+ continue;
+ }
+ if (e->item->type == MENU_SUBMENU
+ && !(e->item->flags & MENUFLAG_NOOPTION)) {
+ struct entry *e1 = firstitem;
+ int n = 1;
+ while (e1) {
+ /*if (e->item->type == MENU_SEPARATOR) {printf ("\n"); e1=e1->next;continue;} */
+ if (e1->item->type != MENU_SUBMENU
+ && e1->item->type != MENU_SEPARATOR
+ && !(e1->item->flags & MENUFLAG_NOOPTION)
+ && !strcmp(e1->item->menuname, e->item->shortname)) {
+ if (n) {
+ printf("\n%s\n\n", e->item->name);
+ n = 0;
+ }
+ printf(" -%-15s", e1->item->shortname);
+ if (menu_havedialog(e1->item, NULL)) {
+ CONST menudialog *d =
+ menu_getdialog(NULL, e1->item);
+ while (d->question != NULL) {
+ switch (d->type) {
+ case DIALOG_INT:
+ printf("integer ");
+ break;
+ case DIALOG_FLOAT:
+ printf("real_number ");
+ break;
+ case DIALOG_COORD:
+ printf("real_number real_number ");
+ break;
+ case DIALOG_KEYSTRING:
+ case DIALOG_STRING:
+ printf("string ");
+ break;
+ case DIALOG_IFILE:
+ printf("input_file ");
+ break;
+ case DIALOG_OFILE:
+ printf("output_file ");
+ break;
+ case DIALOG_CHOICE:
+ {
+ int i;
+ CONST char **keys =
+ (CONST char **) d->defstr;
+ for (i = 0;; i++) {
+ if (keys[i] == NULL)
+ break;
+ if (i != 0)
+ putc('|', stdout);
+ printf("%s", keys[i]);
+ }
+ putc(' ', stdout);
+ }
+ break;
+ case DIALOG_ONOFF:
+ printf("on|off ");
+ }
+ d++;
+ }
+ printf("\n%14s ", "");
+ }
+ printf(" %s\n", e1->item->name);
+ }
+ e1 = e1->next;
+ }
+ }
+ e = e->next;
+ }
+}
+
+void uih_xshlprintmenu(struct uih_context *c, CONST char *name)
+{
+ int i = 0;
+ int nexti;
+ CONST menuitem *item, *nextitem, *lastitem;
+ int comma;
+ printf("%%%s\n\n", name);
+ printf("<menuhead><head>%s</head></menuhead>\n", menu_fullname(name));
+ printf("<menuitems><center>\n");
+ for (i = 0; (item = menu_item2(name, i)) != NULL; i++) {
+ if (item->type == MENU_SEPARATOR)
+ printf("<p>\n");
+ else if (item->type == MENU_SUBMENU)
+ printf("<p><submenu><a %s>%s</a>\n", item->shortname,
+ item->name);
+ else
+ printf("<p><a %s>%s</a>\n", item->shortname, item->name);
+ }
+ printf("</center></menuitems>\n");
+ lastitem = NULL;
+ for (i = 0; (item = menu_item2(name, i)) != NULL; i++) {
+ if (item->type == MENU_SEPARATOR)
+ continue;
+ if (item->type != MENU_SUBMENU) {
+ for (nexti = i + 1;
+ (nextitem = menu_item2(name, nexti)) != NULL
+ && nextitem->type == MENU_SUBMENU; nexti++);
+ printf("<node %s, %s, %s, %s>\n", item->shortname,
+ (lastitem != NULL ? lastitem->shortname : ""),
+ nextitem != NULL ? nextitem->shortname : "", name);
+ printf("%%%s\n", item->shortname);
+ printf("<head>%s</head>\n", item->name);
+ if (!(item->flags & MENUFLAG_NOPLAY)) {
+ printf("<p><emph>Syntax</emph>:(%s", item->shortname);
+ if (item->flags & MENUFLAG_CHECKBOX)
+ printf(" bool");
+ if (item->type == MENU_DIALOG
+ || item->type == MENU_CUSTOMDIALOG) {
+ int y;
+ CONST menudialog *di;
+ di = menu_getdialog(c, item);
+ if (item->flags & MENUFLAG_CHECKBOX)
+ printf(" [");
+ for (y = 0; di[y].question != NULL; y++) {
+ switch (di[y].type) {
+ case DIALOG_INT:
+ printf(" integer");
+ break;
+ case DIALOG_FLOAT:
+ printf(" float");
+ break;
+ case DIALOG_STRING:
+ printf(" string");
+ case DIALOG_KEYSTRING:
+ printf(" keyword");
+ break;
+ case DIALOG_IFILE:
+ printf(" file");
+ break;
+ case DIALOG_OFILE:
+ printf(" file");
+ break;
+ case DIALOG_ONOFF:
+ printf(" bool");
+ break;
+ case DIALOG_COORD:
+ printf(" complex");
+ break;
+ case DIALOG_CHOICE:
+ printf(" keyword");
+ break;
+ }
+ }
+ if (item->flags & MENUFLAG_CHECKBOX)
+ printf(" ]");
+ }
+ printf(")\n");
+ }
+ printf("<p>\n<emph>Available as</emph>: ");
+ comma = 0;
+ if (!(item->flags & MENUFLAG_NOMENU))
+ printf("menu item"), comma = 1;
+ if (!(item->flags & MENUFLAG_NOOPTION))
+ printf("%scommand line option", comma ? ", " : ""), comma =
+ 1;
+ if (!(item->flags & MENUFLAG_NOPLAY))
+ printf("%scommand", comma ? ", " : ""), comma = 1;
+ printf("\n");
+ printf("\n");
+ lastitem = item;
+ }
+ }
+}
+
+void uih_xshlprintmenus(struct uih_context *c)
+{
+ struct entry *e = firstitem;
+ struct entry *nexte;
+ struct entry *laste;
+ printf("%%menus\n");
+ printf("<main><head>Menus</head></main>\n");
+ printf("<menuitems><center>\n");
+ while (e != NULL) {
+ if (e->item->type == MENU_SUBMENU)
+ printf("<p><submenu><a %s>%s</a>\n", e->item->shortname,
+ e->item->name);
+ e = e->next;
+ }
+ printf("</center></menuitems>\n");
+ e = firstitem;
+ laste = NULL;
+ while (e != NULL) {
+ if (e->item->type == MENU_SUBMENU) {
+ nexte = e->next;
+ while (nexte != NULL && nexte->item->type != MENU_SUBMENU)
+ nexte = nexte->next;
+ printf("<node %s, %s, %s, %s>\n", e->item->shortname,
+ (laste != NULL ? laste->item->shortname : ""),
+ nexte != NULL ? nexte->item->shortname : "", "menus");
+ uih_xshlprintmenu(c, e->item->shortname);
+ laste = e;
+ }
+ e = e->next;
+ }
+ printf("%%endmenus");
+}
+
+void
+menu_forall(struct uih_context *c,
+ void (*callback) (struct uih_context * c,
+ CONST menuitem * item))
+{
+ struct entry *e = firstitem;
+ while (e != NULL) {
+ callback(c, e->item);
+ e = e->next;
+ }
+}