home *** CD-ROM | disk | FTP | other *** search
- /* fontmenu.c - Create a menu structure from the fonts on Font$Path. The
- * returned structure is static; it is only recreated if Font$Path or
- * Font$Prefix changes
- */
-
- /*
- #define DEBUG
- */
-
- #include <stdlib.h>
- #include <string.h>
-
- #include "font.h"
- #include "menu.h"
- #include "wimpt.h"
- #include "werr.h"
- #include "visdelay.h"
- #include "os.h"
- #include "swis.h"
- #include "dbox.h"
- #include "msgs.h"
- #include "tracker.h"
-
- #include "fontmenu.h"
-
- typedef struct fontname
- { struct fontname *left, *right; /* Text follows in memory */
- int main, sub;
- } fontname;
-
- #define TB_LEN 128
-
- static menu fontmenu = NULL;
- static menu submenu;
- static menu *subs;
- static char lastroot[40], thisroot[40];
- static int item, sub;
- static fontname *fonttree;
- static int maintick, subtick;
- static BOOL hassysfont;
- static BOOL needs_submenu;
- static char tbuf[TB_LEN];
-
- #define VARLEN 512
- static char varvals[VARLEN];
- #define FONTVARS "<Font$Prefix> and <Font$Path>"
-
- #ifdef DEBUG
-
- static menu safe_menu_new(char *title, char *text)
- { menu m;
-
- werr(FALSE, "menu_new(\"%s\", \"%s\")", title, text);
- m = menu_new(title, text);
- werr(FALSE, "menu_new() returned %p", m);
- return m;
- }
-
- static void safe_menu_extend(menu m, char *text)
- { werr(FALSE, "menu_extend(%p, \"%s\")", m, text);
- menu_extend(m, text);
- werr(FALSE, "menu_extend() returned");
- }
-
- static void safe_menu_submenu(menu m, int i, menu s)
- { werr(FALSE, "menu_submenu(%p, %d, %p)", m, i, s);
- menu_submenu(m, i, s);
- werr(FALSE, "menu_submenu() returned");
- }
-
- #else
-
- #define safe_menu_new(title, text) menu_new(title, text)
- #define safe_menu_extend(m, text) menu_extend(m, text)
- #define safe_menu_submenu(m, i, s) menu_submenu(m, i, s)
-
- #endif
-
- static void getfontvars(char *buf, int len)
- { os_regset regs;
-
- regs.r[0] = (int) FONTVARS;
- regs.r[1] = (int) buf;
- regs.r[2] = len-1;
-
- os_swix(OS_GSTrans, ®s);
-
- buf[regs.r[2]] = '\0';
- }
-
- static void freenames(fontname *node)
- { if (node)
- { freenames(node->left);
- freenames(node->right);
- free(node);
- }
- }
-
- static fontname *putname(fontname *node, char *name)
- { if (!node)
- { if (node = malloc(sizeof(fontname) + strlen(name) + 1), !node)
- werr(TRUE,
- msgs_lookup("fontmenu3:Fatally out of store while reading font names"));
- node->left = node->right = NULL;
- strcpy((char *) (node + 1), name);
- return node;
- }
- else
- { int cmp = strcmp(name, (char *) (node + 1));
- if (cmp < 0)
- node->left = putname(node->left, name);
- else if (cmp > 0)
- node->right = putname(node->right, name);
- }
-
- return node;
- }
-
- static fontname *readnames(char *dbname)
- { char fname[41];
- int fnum;
- fontname *tree = NULL;
- dbox db;
- wimp_eventstr ev;
- BOOL open = FALSE;
-
- if (dbname && *dbname)
- { if (db = dbox_new(dbname), !db)
- werr(FALSE, msgs_lookup("fontmenu4:Can't find template %s"), dbname);
- }
- else
- db = NULL;
-
- for (fnum = 0; fnum >= 0; )
- { if (wimpt_complain(font_list(fname, &fnum)))
- { freenames(tree);
- return NULL;
- }
-
- if (fnum >= 0)
- { if (db)
- { if (!open)
- { dbox_showstatic(db);
- wimpt_poll(0, &ev);
- wimpt_fake_event(&ev);
- open = TRUE;
- }
- dbox_setfield(db, 1, fname);
- }
- tree = putname(tree, fname);
- }
- }
-
- if (db)
- dbox_dispose(&db);
-
- return tree;
- }
-
- static void copyroot(char *buf, char *name)
- { int c;
-
- for (c = 0; c < 39 && name[c] != '.' && name[c] != '\0'; c++)
- buf[c] = name[c];
- buf[c] = '\0';
- }
-
- static void extendmenu(menu *mp, char *name, char *with)
- { if (!*with) return;
-
- if (*mp)
- safe_menu_extend(*mp, with+1);
- else
- *mp = safe_menu_new(name, with+1);
-
- *with = '\0';
- }
-
- static void pass1(fontname *node)
- { if (node)
- { pass1(node->left);
- copyroot(thisroot, (char *) (node + 1));
- if (strcmp(lastroot, thisroot) != 0)
- { if (*lastroot) item++;
-
- if (strlen(tbuf) + strlen(thisroot) + 2 > TB_LEN)
- extendmenu(&fontmenu, msgs_lookup("fontmenu5:Font"), tbuf);
-
- strcat(tbuf, ",");
- strcat(tbuf, thisroot);
- strcpy(lastroot, thisroot);
- }
- pass1(node->right);
- }
- }
-
- static void pass2(fontname *node)
- { char *np;
-
- if (node)
- { pass2(node->left);
- copyroot(thisroot, (char *) (node + 1));
-
- if (strcmp(lastroot, thisroot) != 0)
- { if (*lastroot)
- { if (needs_submenu)
- { extendmenu(&submenu, lastroot, tbuf);
- subs[item++] = submenu;
- }
- else
- { if (submenu)
- menu_dispose(&submenu, FALSE);
- subs[item++] = NULL;
- }
-
- *tbuf = '\0';
- submenu = NULL;
- sub = 1;
- needs_submenu = FALSE;
- }
- strcpy(lastroot, thisroot);
- }
-
- for (np = (char *) (node + 1); *np && *np != '.'; np++)
- ;
-
- if (*np == '.')
- { ++np;
- needs_submenu = TRUE;
- }
- else
- np = msgs_lookup("fontmenu6:(Regular)");
-
- node->main = item;
- node->sub = sub++;
-
- if (strlen(tbuf) + strlen(np) + 2 > TB_LEN)
- extendmenu(&submenu, thisroot, tbuf);
-
- strcat(tbuf, ",");
- strcat(tbuf, np);
-
- pass2(node->right);
- }
- }
-
- void fontmenu_init(void)
- { *varvals = '\0';
- fontmenu = NULL;
- subs = NULL;
- fonttree = NULL;
- }
-
- BOOL fontmenu_pathchanged(void)
- { char vbuf[VARLEN];
-
- getfontvars(vbuf, VARLEN);
- return !!strcmp(vbuf, varvals);
- }
-
- /* Build a font menu, and store its address in 'fontmenu'. It is the callers
- * responsibility to have freed any previous font menu.
- */
-
- menu fontmenu_make(BOOL sysfont, char *dbname)
- { int i;
-
- visdelay_begin();
-
- if (fontmenu_pathchanged())
- { getfontvars(varvals, VARLEN);
- if (fonttree)
- { freenames(fonttree);
- fonttree = NULL;
- }
- }
-
- if (subs)
- free(subs);
-
- if (!fonttree)
- fonttree = readnames(dbname);
-
- if (sysfont)
- fontmenu = safe_menu_new(msgs_lookup("fontmenu5:Font"),
- msgs_lookup("fontmenu1:System font"));
- else
- fontmenu = NULL;
-
- *tbuf = '\0';
- item = sysfont ? 2 : 1;
- *lastroot = '\0';
- pass1(fonttree);
-
- /* Flush remaining main menu definition */
-
- extendmenu(&fontmenu, msgs_lookup("fontmenu5:Font"), tbuf);
-
- if (subs = malloc(sizeof(menu) * (item + 1)), !subs)
- werr(TRUE, msgs_lookup("fontmenu2:Fatal memory shortage while building font menu"));
-
- for (i = 0; i <= item; i++)
- subs[i] = NULL;
-
- submenu = NULL;
- *tbuf = '\0';
- item = sysfont ? 2 : 1;
- sub = 1;
- *lastroot = '\0';
- needs_submenu = FALSE;
- pass2(fonttree);
-
- /* Flush remaining submenu definition */
-
- if (needs_submenu)
- { extendmenu(&submenu, lastroot, tbuf);
- subs[item++] = submenu;
- }
- else
- { if (submenu)
- menu_dispose(&submenu, FALSE);
- subs[item++] = NULL;
- }
-
- /* Attach submenus to main menu */
-
- for (i = 1; i < item; i++)
- if (subs[i])
- safe_menu_submenu(fontmenu, i, subs[i]);
-
- maintick =
- subtick = -1;
-
- submenu = NULL;
- hassysfont = sysfont;
-
- visdelay_end();
-
- return fontmenu;
- }
-
- static void settick(int main, int sub, BOOL state)
- { if (main > 0)
- { menu_setflags(fontmenu, main, state, FALSE);
- if (sub > 0)
- menu_setflags(subs[main], sub, state, FALSE);
- }
- }
-
- static void findtick(char *name, fontname *node)
- { int cmp;
-
- if (node)
- { cmp = strcmp(name, (char *) (node + 1));
- if (cmp < 0)
- findtick(name, node->left);
- else if (cmp > 0)
- findtick(name, node->right);
- else
- { maintick = node->main;
- subtick = node->sub;
- }
- }
- }
-
- void fontmenu_tick(char *name)
- { settick(maintick, subtick, FALSE);
- if (hassysfont && strcmp(name, msgs_lookup("fontmenu1:System font")) == 0)
- { maintick = 1;
- subtick = 0;
- }
- else
- findtick(name, fonttree);
-
- settick(maintick, subtick, TRUE);
- }
-
- static char *scan(char *hit, fontname *node, char *ideal)
- { char *np;
-
- if (node)
- { if (hit[0] == node->main)
- { if (hit[1] == node->sub)
- return (char *) (node + 1);
-
- if (hit[1] == 0)
- { if (!ideal && node->sub == 1)
- return (char *) (node + 1);
-
- for (np = (char *) (node + 1); *np && *np != '.'; np++)
- ;
-
- if (*np == '.')
- ++np;
- else
- np = msgs_lookup("fontmenu6:(Regular)");
-
- if (strcmp(ideal, np) == 0)
- return (char *) (node + 1);
- }
- }
-
- if (np = scan(hit, node->left, ideal), np)
- return np;
- if (np = scan(hit, node->right, ideal), np)
- return np;
- }
-
- return NULL;
- }
-
- char *fontmenu_decode(char *hit)
- { char *ideals = msgs_lookup("fontmenu7:(Regular),Medium,Roman,Book");
- char *result;
- char ideal[32], *ip;
-
- if (hassysfont && hit[0] == 1)
- return msgs_lookup("fontmenu1:System font");
- else
- { for (ip = ideals; *ip; )
- { int c;
-
- for (c = 0; c < 31 && *ip && *ip != ','; c++, ip++)
- ideal[c] = *ip;
-
- if (*ip == ',')
- ip++;
-
- ideal[c] = '\0';
-
- result = scan(hit, fonttree, ideal);
-
- if (result)
- return result;
- }
-
- return scan(hit, fonttree, NULL);
- }
- }
-