home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ARM Club 3
/
TheARMClub_PDCD3.iso
/
hensa
/
programming
/
andylib_1
/
AndyLib
/
c
/
fontmenu
< prev
next >
Wrap
Text File
|
1995-03-06
|
10KB
|
440 lines
/* 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);
}
}