/*
* Copyright (C) 1997 and 1998 WIDE Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* $Id: parse.c,v 1.102 2007/01/12 10:38:56 nishida Exp $
*/
#include "mgp.h"
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
static struct ctrl *parse_text __P((char *, u_int));
static void read_rc __P((FILE *, char *));
static void read_file __P((FILE *, char *, u_int *, u_int *, int));
static void secondpass __P((void));
static void thirdpass __P((void));
static void debug __P((void));
static int define_font __P((struct ctrl *));
static struct ctrl *find_font __P((char *));
static char* clear_esc __P((char*));
/*image*/
extern int findImage __P((char *, char *));
/* lex/yacc variables */
extern int n_errors;
extern struct ctrl *root;
extern char *yyfilename;
extern int yylineno;
/* Prevent warning if -Wall. */
#ifdef __GNUC__
extern void lex_init(u_char *);
extern int yyparse (void);
#endif
static int filterval = 0;
void
load_file(filename)
char *filename;
{
FILE *fp;
u_int page;
u_int line;
char rc[MAXPATHLEN];
char *dir;
page = 1;
line = 0;
dir = getenv("HOME");
if (dir) {
snprintf(rc, sizeof(rc), "%s/%s", dir, RCFILE);
fp = fopen(rc, "r");
if (fp) {
read_rc(fp, rc);
fclose(fp);
}
}
if ((fp = fopen(filename, "r")) == NULL) {
fprintf(stderr, "can't open %s\n", filename);
exit(-1);
}
read_file(fp, filename, &page, &line, 1);
fclose(fp);
secondpass();
thirdpass();
if (parse_debug)
debug();
}
void
cleanup_file()
{
u_int line;
u_int page;
for (line = 0; line < MAXLINE; line ++) {
if (default_control[line]) {
ctlfree(default_control[line]);
default_control[line] = NULL;
}
if (init_control[line]) {
ctlfree(init_control[line]);
init_control[line] = NULL;
}
}
for (page = 0; page < MAXPAGE; page ++) {
for (line = 0; line < MAXLINE; line ++) {
if (!page_control[page][line])
continue;
ctlfree(page_control[page][line]);
page_control[page][line] = NULL;
}
memset(&page_attribute[page], 0, sizeof(page_attribute[page]));
}
for (line = 0; line < MAXTAB + MAXSTYLE; line++) {
if (!tab_control[line])
continue;
ctlfree(tab_control[line]);
tab_control[line] = NULL;
}
for (line = 0; line < MAXFONTDEF; line++) {
if (!fontdef_control[line])
continue;
ctlfree(fontdef_control[line]);
fontdef_control[line] = NULL;
}
}
/*
* clear the given data from escape sequences, so identifying
* a character by its hexadecimal value is possible by using \xHH
*/
static char*
clear_esc(s)
char* s;
{
char* p;
int len;
int i;
int j;
int k;
int error = 0;
int unicode = 0;
int chars;
unsigned int code;
i = j = 0;
len = strlen(s);
p = (char*)malloc(len + 1);
while (i < len)
{
code = 0x0;
/*
* expecting either beginning of unicode or
* an ascii-character (may be an escape sequence)
*/
if (!unicode) {
/* beginning of unicode */
if (s[i] == 0x1b && s[i+1] == '$' &&
'@' <= s[i+2] && s[i+2] < 'C') {
unicode = 1;
for (chars = 0; chars < 3; chars++)
p[j++] = s[i++];
continue;
}
/* backslash */
if (s[i] == 0x5c) {
i++;
/* any escape sequence */
if (s[i] != 0x5c) {
/* hexadecimal token: \xHH */
if ((s[i] == 'x' || s[i] == 'X') && i+2 < len) {
i++;
if (isxdigit(s[i]) && isxdigit(s[i+1])) {
for (k = 2; k > 0; k--, i++) {
code <<= 4;
if (isdigit(s[i]))
code += s[i] - 48;
else
code += tolower(s[i]) - 87;
}
} else
error = 1;
} else
error = 1;
}
}
if (error)
return (char*) NULL;
if (code == 0x0)
p[j++] = s[i++];
else
p[j++] = code;
} else {
/*
* expecting either the end of unicode or
* a part of a unicode character
*/
/* end of unicode */
if (s[i] == 0x1b && s[i+1] == '(' &&
(s[i+2] == 'B' || s[i+2] == 'J')) {
unicode = 0;
for (chars = 0; chars < 3; chars++)
p[j++] = s[i++];
continue;
}
/* just take the unicode character */
p[j++] = s[i++];
}
}
p[j] = 0x0;
strcpy(s, p);
free(p);
return s;
}
static struct ctrl *
parse_text(p, page)
char *p;
u_int page;
{
struct ctrl sentinel;
struct ctrl *cp;
assert(p);
cp = &sentinel;
cp->ct_next = ctlalloc1(CTL_TEXT);
if (!cp->ct_next) {
ctlfree(cp);
return NULL;
}
cp = cp->ct_next;
cp->ct_page = page;
cp->ctc_value = strdup(p);
return sentinel.ct_next;
}
/*
* read ~/.mgprc: there's no percentage sign
*/
static void
read_rc(fp, filename)
FILE *fp;
char *filename;
{
char buf[BUFSIZ];
#if 0
struct ctrl *cp;
#endif
int lineno;
if (2 <= parse_debug)
fprintf(stderr, "read_rc(%s):\n", filename);
lineno = 0;
while (fgets(buf, sizeof(buf), fp) != NULL) {
lineno++;
if (buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = '\0';
if (buf[0] == '#' || !buf[0])
continue;
yyfilename = filename;
yylineno = lineno;
lex_init(buf);
if (yyparse() || n_errors) {
fprintf(stderr, "%s:%d: fatal syntax error detected\n",
filename, lineno);
exit(-1);
}
if (!root) {
fprintf(stderr, "%s:%d: something bad happened\n",
filename, lineno);
exit(-1);
}
if (2 <= parse_debug) {
fprintf(stderr, "%s:%d: %s\n", filename, lineno, buf);
debug1(root);
}
switch (root->ct_op) {
#if 0
case CTL_DEFFONT:
/* safety check */
for (cp = root; cp; cp = cp->ct_next) {
if (cp->ct_op == CTL_FONT) {
fprintf(stderr,
"%s:%d: %%font used in %%deffont, which is disallowed\n",
filename, lineno);
exit(-1);
}
}
if (define_font(root) < 0) {
fprintf(stderr, "%s:%d: could not define "
"font \"%s\"\n", filename, lineno,
root->ctc_value);
exit(-1);
}
break;
#endif
#ifdef VFLIB
case CTL_VFCAP:
vfcap_name = root->ctc_value;
break;
#endif
#ifdef FREETYPE
case CTL_TFDIR:
freetypefontdir = root->ctc_value;
break;
case CTL_TFONT0:
freetypefont0 = root->ctc_value;
break;
case CTL_TMFONT0:
freetypemfont0 = root->ctc_value;
break;
#endif
case CTL_NOOP:
/* done in grammar.y */
break;
default:
fprintf(stderr, "%s:%d: operator disallowed:\n\t",
filename, lineno);
debug0(root);
exit(-1);
}
}
}
static void
read_file(fp, filename, page, line, preamble)
FILE *fp;
char *filename;
u_int *page;
u_int *line;
int preamble;
{
char buf[BUFSIZ];
char buf2[BUFSIZ];
struct ctrl **ch;
struct ctrl *cp;
struct ctrl *p;
int line_cont;
char *infilename;
struct ctrl *filtermode;
int filterfd = -1;
char filtername[MAXPATHLEN];
pid_t filterpid = -1;
void (*filtersig)() = (void (*)())NULL;
int lineno;
static char *searchpath[] = {
"", /*mgp_fname*/
#ifdef MGPLIBDIR
MGPLIBDIR "/",
#endif
NULL,
};
if (2 <= parse_debug)
fprintf(stderr, "read_file(%s):\n", filename);
filtername[0] = '\0';
lineno = 0;
if (!preamble)
goto page;
/*
* default analysis in preamble
*/
while (fgets(buf, sizeof(buf), fp) != NULL) {
lineno++;
if (buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = '\0';
if (buf[0] == '#')
continue;
if (buf[0] != '%') {
fprintf(stderr, "%s:%d: no text allowed in preamble; "
"ignored\n", filename, lineno);
continue;
}
if (buf[1] == '%')
continue;
yyfilename = filename;
yylineno = lineno;
lex_init(buf + 1);
if (yyparse() || n_errors) {
fprintf(stderr, "%s:%d: fatal syntax error detected\n",
filename, lineno);
exit(-1);
}
if (!root) {
fprintf(stderr, "%s:%d: something bad happened\n",
filename, lineno);
exit(-1);
}
if (2 <= parse_debug)
debug1(root);
switch (root->ct_op) {
case CTL_PAGE:
goto page;
case CTL_INCLUDE:
{
FILE *infp;
infilename = root->ctc_value;
searchpath[0] = mgp_fname;
infp = fsearchopen(infilename, "r", searchpath);
if (infp == NULL) {
fprintf(stderr, "%s:%d: can't open "
"include file \"%s\"\n",
filename, lineno, infilename);
exit(-1);
}
read_file(infp, infilename, page, line, 1);
fclose(infp);
continue;
}
case CTL_DEFAULT:
ch = &default_control[root->cti_value - 1];
if (*ch)
ctlappend(*ch, root->ct_next);
else
*ch = root->ct_next;
break;
case CTL_TAB:
{
int i = root->cti_value;
if (i < 0) {
fprintf(stderr, "%s:%d: "
"invalid tab index %d\n",
filename, lineno, root->cti_value);
exit(-1);
}
if (i >= MAXTAB) { /*XXX*/
/* must be a string */
/* find a free entry */
for (i = MAXTAB ; i < MAXTAB + MAXSTYLE ; i++) {
if (!tab_control[i])
continue;
if (strcmp(tab_control[i]->ctc_value,
root->ctc_value) == 0) {
ctlfree(tab_control[i]);
tab_control[i] = NULL;
break;
}
}
for (i = MAXTAB ; i < MAXTAB + MAXSTYLE ; i++) {
if (!tab_control[i])
break;
}
if (i == MAXTAB + MAXSTYLE) {
fprintf(stderr, "%s:%d: "
"too many styles\n",
filename, lineno);
exit(-1);
}
}
ch = &tab_control[i];
if (*ch)
ctlappend(*ch, root->ct_next);
else if (i < MAXTAB)
*ch = root->ct_next;
else
*ch = root; /* keep name as well */
}
break;
case CTL_DEFFONT:
/* safety check */
for (cp = root; cp; cp = cp->ct_next) {
if (cp->ct_op == CTL_FONT) {
fprintf(stderr,
"%s:%d: %%font used in %%deffont, which is disallowed\n",
filename, lineno);
exit(-1);
}
}
if (define_font(root) < 0) {
fprintf(stderr, "%s:%d: could not define "
"font \"%s\"\n", filename, lineno,
root->ctc_value);
exit(-1);
}
break;
default:
fprintf(stderr, "%s:%d: invalid operator\n",
filename, lineno);
exit(-1);
}
}
/*
* page analysis
*/
page:
line_cont = 0;
filtermode = NULL;
command:
while (fgets(buf, sizeof(buf), fp) != NULL) {
lineno++;
if (filtermode && strncmp(buf, "%endfilter", 10) != 0) {
write(filterfd, buf, strlen(buf));
continue;
}
{
char *p, *q, *s;
int cnt; /* counter for backslashes at the end of a line */
p = buf + strlen(buf);
if (buf < p && p[-1] == '\n') {
p--;
*p = '\0';
}
while (buf < p && p - buf < sizeof(buf) && p[-1] == '\\') {
/*
* check for quoted backslashes at the end of a line:
* if it is so, then do NOT ignore the line break and
* continue as usual
*/
s = p;
cnt = 0;
while (buf < s && s[-1] == '\\') {
s--;
cnt++;
}
if (cnt % 2 == 0)
break;
p--;
if (fgets(buf2, sizeof(buf) - (p - buf), fp) == NULL)
break;
q = buf2;
/* ignore blanks */
while (*q && isspace(*q))
q++;
strncpy(p, q, sizeof(buf) - (p - buf));
p[sizeof(buf) - (p - buf) -1] = '\0';
p += strlen(p);
if (buf < p && p[-1] == '\n') {
p--;
*p = '\0';
}
}
}
if (buf[0] == '#')
continue;
if (buf[0] == '%') {
/* this is directive */
int pb;
int ct;
int prevfiltermode;
if (buf[1] == '%')
continue;
prevfiltermode = filtermode ? 1 : 0;
yyfilename = filename;
yylineno = lineno;
lex_init(buf + 1);
if (yyparse() || n_errors) {
fprintf(stderr,
"%s:%d: fatal syntax error detected !!!\n",
filename, lineno);
exit(-1);
}
if (!root) {
fprintf(stderr,
"%s:%d: something bad happened\n",
filename, lineno);
exit(-1);
}
if (2 <= parse_debug)
debug1(root);
cp = root;
pb = ct = 0;
for (p = cp; p; p = p->ct_next) {
switch (p->ct_op) {
case CTL_PAGE:
pb++;
break;
case CTL_NODEF:
page_attribute[*page].pg_flag
|= PGFLAG_NODEF;
break;
case CTL_CONT:
ct++;
break;
case CTL_FILTER:
filtermode = p;
break;
case CTL_ENDFILTER:
filtermode = NULL;
break;
case CTL_EMBED:
embed_file(fp, p, &lineno);
goto command;
}
}
/* filter */
if (!prevfiltermode && filtermode) {
int filtertmp;
int pipefd[2];
if (mgp_flag & FL_NOFORK) {
int i;
if (mgp_flag & FL_VERBOSE) {
fprintf(stderr, "%s:%d: %%filter ",
filename, lineno);
for (i = 0; i < cp->cta_argc; i++) {
fprintf(stderr, "%c%s",
(i == 0) ? '"' : ' ',
cp->cta_argv[i]);
}
fprintf(stderr, "\": "
"directive skipped\n");
}
filterfd = open("/dev/null", O_WRONLY);
strcpy(filtername, "/dev/null");
continue;
}
sprintf(filtername, "/tmp/%d.%ld.%d",
getpid(), (long)time(NULL),
filterval++);
filtertmp = open(filtername, O_CREAT|O_WRONLY,
0644);
if (filtertmp < 0) {
fprintf(stderr,
"%s:%d: cannot open file tmp file "
"for filter\n", filename, lineno);
exit(-1);
}
if (pipe(pipefd) < 0) {
fprintf(stderr,
"%s:%d: cannot open pipe for "
"filter\n", filename, lineno);
exit(-1);
}
filterpid = fork();
if (filterpid < 0) {
perror("fork");
exit(1);
} else if (filterpid == 0) {
close(pipefd[1]);
close(STDIN_FILENO);
dup2(pipefd[0], STDIN_FILENO);
close(pipefd[0]);
close(STDOUT_FILENO);
dup2(filtertmp, STDOUT_FILENO);
close(STDERR_FILENO);
dup2(filtertmp, STDERR_FILENO);
close(filtertmp);
execvp(filtermode->cta_argv[0],
(char **)filtermode->cta_argv);
} else {
close(filtertmp);
close(pipefd[0]);
filterfd = pipefd[1];
filtersig = signal(SIGCHLD, SIG_DFL);
}
continue;
} else if (prevfiltermode && !filtermode
&& filtername[0]) {
FILE *filterfp;
int estat;
if (mgp_flag & FL_NOFORK) {
close(filterfd);
filtername[0] = '\0';
continue;
}
close(filterfd);
waitpid(filterpid, &estat, 0);
signal(SIGCHLD, filtersig);
filterfp = fopen(filtername, "r");
if (filterfp == NULL) {
fprintf(stderr, "%s:%d: cant read "
"filter output\n",
filename, lineno);
exit(-1);
}
read_file(filterfp, filtername, page, line, 0);
fclose(filterfp);
unlink(filtername);
filtername[0] = '\0';
continue;
}
if (pb) {
/* Seen pagebreak. */
page_attribute[*page].pg_linenum = *line;
*page = *page + 1;
*line = 0;
continue;
}
if (ct)
line_cont = 1;
if (cp) {
/*
* append to the currently existing
* page struct.
*/
ch = &page_control[*page][*line];
#if 0
if (!line_cont &&
(/* cp->ct_op == CTL_IMAGE || */
cp->ct_op == CTL_BAR)) {
struct ctrl *cp1;
cp1 = ctlalloc1(CTL_LINESTART);
if (cp1) {
if (!*ch)
*ch = cp1;
else
ctlappend(*ch, cp1);
}
}
#endif
if (!*ch)
*ch = cp;
else
ctlappend(*ch, cp);
/*
* special case: %image and %bar has to be
* treated as independent item
*/
if (cp->ct_op == CTL_IMAGE
|| cp->ct_op == CTL_ANIM
|| cp->ct_op == CTL_BAR) {
line_cont = 0;
*line = *line + 1;
}
}
} else {
/* this is data */
/*
* escape # and % by backslash (at the beginning
* of a line)
*/
if (buf[0] == 0x5c && (buf[1] == 0x23 ||
buf[1] == 0x25))
memcpy(&buf[0], &buf[1], strlen(buf));
/*
* clear escape sequences
*/
#if 1
if (clear_esc(buf) == NULL) {
fprintf(stderr, "%s:%d: unknown escape"
" sequence\n",
filename, lineno);
exit(-1);
}
#endif
cp = parse_text(buf, *page);
if (cp) {
ch = &page_control[*page][*line];
if (!*ch)
*ch = cp;
else
ctlappend(*ch, cp);
}
line_cont = 0;
*line = *line + 1;
}
}
/* Treat as we've seen pagebreak. See the above comment for detail. */
page_attribute[*page].pg_linenum = *line;
#if 0
*page = *page + 1;
*line = 0;
#endif
maxpage = *page;
}
/*
* rather simple rewrites.
*/
static void
secondpass()
{
u_int page;
u_int l, text;
struct ctrl **ch;
struct ctrl *cp;
struct ctrl *cp1;
/*
* add CTL_PAUSE to the last line of a page.
* we don't add one at the last page, intentionally.
*/
for (page = 1; page < maxpage; page++) {
l = page_attribute[page].pg_linenum;
ch = &page_control[page][l + 1];
cp = ctlalloc1(CTL_PAUSE);
if (cp) {
cp->cti_value = 1; /* 1 indicates page end */
if (!*ch)
*ch = cp;
else
ctlappend(*ch, cp);
}
page_attribute[page].pg_linenum++;
}
/*
* split GAP into VGAP and HGAP.
*/
for (page = 1; page <= maxpage; page++) {
text = 1;
for (l = 0; l <= page_attribute[page].pg_linenum; l++) {
for (cp = page_control[page][l];
cp;
cp = cp->ct_next) {
if (cp->ct_op == CTL_GAP) {
cp->ct_op = CTL_VGAP;
cp1 = ctlalloc1(CTL_HGAP);
cp1->cti_value = cp->cti_value;
cp1->ct_next = cp->ct_next;
cp->ct_next = cp1->ct_next;
}
/*
* check if this page contains only texts
*/
if (cp->ct_op == CTL_BIMAGE || cp->ct_op == CTL_BGRAD ||
cp->ct_op == CTL_IMAGE ||
#ifdef MNG
cp->ct_op == CTL_ANIM ||
#endif /* MNG */
(cp->ct_op == CTL_PAUSE
&& l != page_attribute[page].pg_linenum)) {
text = 0;
}
}
}
page_attribute[page].pg_text = text;
}
/* CTL_PREFIX in tab_control should be CTL_TABPREFIX. */
for (l = 0; l < MAXTAB + MAXSTYLE; l++) {
for (cp = tab_control[l]; cp; cp = cp->ct_next) {
if (cp->ct_op == CTL_PREFIX)
cp->ct_op = CTL_TABPREFIX;
if (cp->ct_op == CTL_PREFIXN)
cp->ct_op = CTL_TABPREFIXN;
}
}
}
/*
* rather complex rewrites. ordering is VERY important.
*/
static void
thirdpass()
{
u_int page;
u_int line;
u_int l;
struct ctrl **ch;
struct ctrl *cp;
struct ctrl *cp1;
struct ctrl *cp2;
struct ctrl *cpt;
char *p;
struct ctrl *carryover[MAXPAGE];
{
/*
* there are several control items that are to be carried
* over to the next line. make them explicit so that there'll
* be no bogus control items to be used when we go back a page.
*/
struct ctrl *tmpstr[10];
struct ctrl *tmpint[10];
struct ctrl *tmplong[10];
struct ctrl *tmpvoid[10];
struct ctrl *tmparea[10];
struct ctrl sentinel;
int i;
memset(carryover, 0, sizeof(carryover));
memset(tmpstr, 0, sizeof(tmpstr));
memset(tmpint, 0, sizeof(tmpint));
memset(tmplong, 0, sizeof(tmplong));
memset(tmpvoid, 0, sizeof(tmpvoid));
memset(tmparea, 0, sizeof(tmparea));
/* default value for page 1 */
tmpstr[0] = ctlalloc1(CTL_PREFIX);
tmpstr[0]->ctc_value = strdup("");
#if defined(VFLIB) && defined(VFONT)
tmpstr[1] = ctlalloc1(CTL_VFONT);
tmpstr[1]->ctc_value = strdup(VFONT); /*XXX*/
#else
tmpstr[1] = ctlalloc1(CTL_NOOP);
tmpstr[1]->ctc_value = strdup("");
#endif
tmpstr[2] = ctlalloc1(CTL_XFONT2);
tmpstr[2]->ctc2_value1 = strdup(DEFAULT_X_FONT);
tmpstr[2]->ctc2_value2 = strdup("iso8859-1");
#ifdef FREETYPE
tmpstr[3] = ctlalloc1(CTL_TFONT);
tmpstr[3]->ctc2_value1 = strdup(freetypefont0 ? freetypefont0 :"arial.ttf");
tmpstr[3]->ctc2_value2 = strdup("iso8859-1");
#else
tmpstr[3] = ctlalloc1(CTL_NOOP); /* CTL_TFONT */
tmpstr[3]->ctc_value = strdup("");
#endif
#ifdef FREETYPE_CHARSET16
tmpstr[4] = ctlalloc1(CTL_TMFONT); /* CTL_TMFONT */
tmpstr[4]->ctc_value = strdup("wadalab-gothic.ttf");
#else
tmpstr[4] = ctlalloc1(CTL_NOOP); /* CTL_TMFONT */
tmpstr[4]->ctc_value = strdup("");
#endif
tmpstr[5] = ctlalloc1(CTL_XFONT2);
tmpstr[5]->ctc2_value1 = strdup("k14");
tmpstr[5]->ctc2_value2 = strdup("jisx0208.1983-*");
#ifdef USE_M17N
if (! (mgp_flag & FL_NOM17N)) {
tmpstr[6] = ctlalloc1(CTL_M17N);
tmpstr[6]->ctc2_value1 = strdup("fontset");
tmpstr[6]->ctc2_value2 = NULL;
tmpstr[7] = ctlalloc1(CTL_M17N);
tmpstr[7]->ctc2_value1 = strdup("family");
tmpstr[7]->ctc2_value2 = NULL;
tmpstr[8] = ctlalloc1(CTL_M17N);
tmpstr[8]->ctc2_value1 = strdup("language");
tmpstr[8]->ctc2_value2 = NULL;
} else
#endif
{
tmpstr[6] = ctlalloc1(CTL_NOOP);
tmpstr[6]->ctc_value = strdup("");
tmpstr[7] = ctlalloc1(CTL_NOOP);
tmpstr[7]->ctc_value = strdup("");
tmpstr[8] = ctlalloc1(CTL_NOOP);
tmpstr[8]->ctc_value = strdup("");
}
tmplong[0] = ctlalloc1(CTL_FORE);
get_color(DEFAULT_FORE, &tmplong[0]->ctl_value);
tmplong[1] = ctlalloc1(CTL_BACK);
get_color(DEFAULT_BACK, &tmplong[1]->ctl_value);
tmplong[2] = ctlalloc1(CTL_CCOLOR);
get_color(DEFAULT_FORE, &tmplong[2]->ctl_value);
tmpint[0] = ctlalloc1(CTL_SIZE);
tmpint[0]->ctf_value = DEFAULT_CHARSIZE;
tmpint[1] = ctlalloc1(CTL_HGAP);
tmpint[1]->cti_value = DEFAULT_HGAP;
tmpint[2] = ctlalloc1(CTL_VGAP);
tmpint[2]->cti_value = DEFAULT_VGAP;
tmpint[3] = ctlalloc1(CTL_QUALITY);
tmpint[3]->cti_value = DEFAULT_BQUALITY;
#ifdef USE_XFT2
tmpint[4] = ctlalloc1(CTL_OPAQUE);
tmpint[4]->cti_value = DEFAULT_OPAQUE;
#endif
tmpvoid[0] = ctlalloc1(CTL_LEFT);
tmparea[0] = ctlalloc1(CTL_AREA);
tmparea[0]->ctar_width = 100;
tmparea[0]->ctar_height = 100;
tmparea[0]->ctar_xoff = 0;
tmparea[0]->ctar_yoff = 0;
/* for page 1 */
cp = &sentinel;
for (i = 0; i < 10; i++) {
if (!tmpstr[i])
continue;
cp->ct_next = ctlalloc1(tmpstr[i]->ct_op);
if (ctl_words[tmpstr[i]->ct_op].ctl_vtype == T_STR2) {
if (tmpstr[i]->ctc2_value1) {
cp->ct_next->ctc2_value1 =
strdup(tmpstr[i]->ctc2_value1);
} else
cp->ct_next->ctc2_value1 = NULL;
if (tmpstr[i]->ctc2_value2) {
cp->ct_next->ctc2_value2 =
strdup(tmpstr[i]->ctc2_value2);
} else
cp->ct_next->ctc2_value2 = NULL;
} else {
if (tmpstr[i]->ctc_value) {
cp->ct_next->ctc_value =
strdup(tmpstr[i]->ctc_value);
} else
cp->ct_next->ctc_value = NULL;
}
cp = cp->ct_next;
}
for (i = 0; i < 10; i++) {
if (!tmplong[i])
continue;
cp->ct_next = ctlalloc1(tmplong[i]->ct_op);
cp->ct_next->ctl_value = tmplong[i]->ctl_value;
cp = cp->ct_next;
}
for (i = 0; i < 10; i++) {
if (!tmpint[i])
continue;
cp->ct_next = ctlalloc1(tmpint[i]->ct_op);
cp->ct_next->ct_val = tmpint[i]->ct_val;
cp = cp->ct_next;
}
for (i = 0; i < 10; i++) {
if (!tmpvoid[i])
continue;
cp->ct_next = ctlalloc1(tmpvoid[i]->ct_op);
cp = cp->ct_next;
}
for (i = 0; i < 10; i++) {
if (!tmparea[i])
continue;
cp->ct_next = ctlalloc1(tmparea[i]->ct_op);
cp->ct_next->ctar_width = tmparea[i]->ctar_width;
cp->ct_next->ctar_height = tmparea[i]->ctar_height;
cp->ct_next->ctar_xoff = tmparea[i]->ctar_xoff;
cp->ct_next->ctar_yoff = tmparea[i]->ctar_yoff;
cp = cp->ct_next;
}
carryover[0] = sentinel.ct_next;
/*
* parse through the pages, remember what kind of directives are there.
*/
for (page = 1; page <= maxpage; page++) {
for (l = 0; l <= page_attribute[page].pg_linenum; l++) {
for (cp = page_control[page][l];
cp;
cp = cp->ct_next) {
switch (cp->ct_op) {
case CTL_PREFIX: tmpstr[0] = cp; break;
case CTL_VFONT: tmpstr[1] = cp; break;
case CTL_TFONT: tmpstr[3] = cp; break;
#ifdef FREETYPE_CHARSET16
case CTL_TMFONT: tmpstr[4] = cp; break;
#endif
case CTL_XFONT2:
if (strcmp(cp->ctc2_value2,
"iso8859-1") == 0) {
tmpstr[2] = cp;
break;
}
{
struct ctrl **cpe; /*empty cp*/
cpe = (struct ctrl **)NULL;
for (i = 5; i < 10; i++) {
if (!tmpstr[i]) {
if (!cpe)
cpe = &tmpstr[i];
continue;
}
if (strcmp(cp->ctc2_value2,
tmpstr[i]->ctc2_value2) == 0) {
tmpstr[i] = cp;
goto xfont_ok;
}
}
if (cpe)
*cpe = cp;
xfont_ok:
break;
}
case CTL_FORE: tmplong[0] = cp; break;
case CTL_BACK: tmplong[1] = cp; break;
case CTL_CCOLOR: tmpint[2] = cp; break;
case CTL_SIZE: tmpint[0] = cp; break;
case CTL_HGAP: tmpint[1] = cp; break;
case CTL_VGAP: tmpint[2] = cp; break;
case CTL_QUALITY: tmpint[3] = cp; break;
case CTL_OPAQUE: tmpint[4] = cp; break;
case CTL_LEFT: tmpvoid[0] = cp; break;
case CTL_RIGHT: tmpvoid[0] = cp; break;
case CTL_CENTER: tmpvoid[0] = cp; break;
case CTL_LEFTFILL: tmpvoid[0] = cp; break;
case CTL_AREA: tmparea[0] = cp; break;
}
}
}
cp = &sentinel;
for (i = 0; i < 10; i++) {
if (!tmpstr[i])
continue;
cp->ct_next = ctlalloc1(tmpstr[i]->ct_op);
if (ctl_words[tmpstr[i]->ct_op].ctl_vtype == T_STR2) {
if (tmpstr[i]->ctc2_value1) {
cp->ct_next->ctc2_value1 =
strdup(tmpstr[i]->ctc2_value1);
} else
cp->ct_next->ctc2_value1 = NULL;
if (tmpstr[i]->ctc2_value2) {
cp->ct_next->ctc2_value2 =
strdup(tmpstr[i]->ctc2_value2);
} else
cp->ct_next->ctc2_value2 = NULL;
} else {
if (tmpstr[i]->ctc_value) {
cp->ct_next->ctc_value =
strdup(tmpstr[i]->ctc_value);
} else
cp->ct_next->ctc_value = NULL;
}
cp = cp->ct_next;
}
for (i = 0; i < 10; i++) {
if (!tmplong[i])
continue;
cp->ct_next = ctlalloc1(tmplong[i]->ct_op);
cp->ct_next->ctl_value = tmplong[i]->ctl_value;
cp = cp->ct_next;
}
for (i = 0; i < 10; i++) {
if (!tmpint[i])
continue;
cp->ct_next = ctlalloc1(tmpint[i]->ct_op);
cp->ct_next->ct_val = tmpint[i]->ct_val;
cp = cp->ct_next;
}
for (i = 0; i < 10; i++) {
if (!tmpvoid[i])
continue;
cp->ct_next = ctlalloc1(tmpvoid[i]->ct_op);
cp = cp->ct_next;
}
for (i = 0; i < 10; i++) {
if (!tmparea[i])
continue;
cp->ct_next = ctlalloc1(tmparea[i]->ct_op);
cp->ct_next->ctar_width = tmparea[i]->ctar_width;
cp->ct_next->ctar_height = tmparea[i]->ctar_height;
cp->ct_next->ctar_xoff = tmparea[i]->ctar_xoff;
cp->ct_next->ctar_yoff = tmparea[i]->ctar_yoff;
cp = cp->ct_next;
}
carryover[page] = sentinel.ct_next;
}
}
/* add default directives to each line */
for (page = 1; page <= maxpage; page++) {
if (page_attribute[page].pg_flag & PGFLAG_NODEF)
continue;
line = page_attribute[page].pg_linenum;
for (l = 0; l <= line; l++) {
int contseen;
contseen = 0;
ch = &page_control[page][l];
/*
* if this line contains CTL_CONT, we don't add
* default directive to this line
*/
for (cp = page_control[page][l]; cp; cp = cp->ct_next) {
if (cp->ct_op == CTL_CONT) {
contseen++;
break;
}
}
if (default_control[l] && !contseen) {
ctlinsert(ch, ctlcopy(default_control[l]));
}
}
}
/*
* add carryover directives to each page.
* default directive has priority over the carryover items,
* so carryover items should appear earlier than default directive.
*/
for (page = 1; page <= maxpage; page++) {
ch = &page_control[page][0];
if (carryover[page - 1])
ctlinsert(ch, carryover[page - 1]);
}
/*
* add CTL_LINEEND and CTL_LINESTART to each lines that contain
* CTL_TEXT/CTL_IMAGE/CTL_BAR/CTL_ICON.
* note that we must carefully handle CTL_CONT.
*/
{
int textseen;
int contseen;
for (page = 1; page <= maxpage; page++) {
line = page_attribute[page].pg_linenum;
for (l = 0; l <= line; l++) {
textseen = 0;
for (cp = page_control[page][l];
cp;
cp = cp->ct_next) {
if (cp->ct_op == CTL_TEXT
|| cp->ct_op == CTL_IMAGE
|| cp->ct_op == CTL_BAR
#ifdef MNG
|| cp->ct_op == CTL_ANIM
#endif /* MNG */
|| cp->ct_op == CTL_ICON) {
textseen++;
break;
}
}
if (!textseen)
continue;
/*
* check if the line #l includes CONT directive.
* if it has, don't add LINESTART to the line #l.
*/
contseen = 0;
for (cp = page_control[page][l];
cp;
cp = cp->ct_next) {
if (cp->ct_op == CTL_CONT) {
contseen++;
break;
}
}
if (!contseen) {
cp = ctlalloc1(CTL_LINESTART);
if (cp) {
for (ch = &page_control[page][l];
ch && *ch;
ch = &((*ch)->ct_next)) {
if ((*ch)->ct_op == CTL_TEXT
|| (*ch)->ct_op == CTL_IMAGE
|| (*ch)->ct_op == CTL_BAR
#ifdef MNG
|| (*ch)->ct_op == CTL_ANIM
#endif /* MNG */
|| (*ch)->ct_op == CTL_ICON) {
break;
}
}
ctlinsert(ch, cp);
}
}
/*
* check if the line #(l+1) includes CONT directive.
* if it has, don't add LINEEND to the line #l.
*/
contseen = 0;
if (l + 1 <= line) {
for (cp = page_control[page][l + 1];
cp;
cp = cp->ct_next) {
if (cp->ct_op == CTL_CONT) {
contseen++;
break;
}
}
}
if (!contseen) {
cp2 = NULL;
for (cp1 = page_control[page][l];
cp1;
cp1 = cp1->ct_next) {
if (cp1->ct_op == CTL_TEXT
|| cp1->ct_op == CTL_IMAGE
|| cp1->ct_op == CTL_BAR
#ifdef MNG
|| cp1->ct_op == CTL_ANIM
#endif /* MNG */
|| cp1->ct_op == CTL_ICON) {
cp2 = cp1;
}
}
/* cp2 has the last TEXT/IMAGE/whatever */
if (cp2) {
cp = ctlalloc1(CTL_LINEEND);
if (cp)
ctlinsert(&(cp2->ct_next), cp);
}
}
}
if (contseen){
/* we have extra cont in the last line */
for (cp2 = page_control[page][line-1];
cp2->ct_next; cp2 = cp2->ct_next);
cp = ctlalloc1(CTL_LINEEND);
if (cp) ctlinsert(&(cp2->ct_next), cp);
}
}
}
/* insert CTL_TAB */
for (page = 1; page <= maxpage; page++) {
line = page_attribute[page].pg_linenum;
for (l = 0; l <= line; l++) {
int tab_depth = 0;
/*
* if we don't have CTL_LINESTART, we don't add
* directives here.
*/
cp = page_control[page][l];
while (cp && cp->ct_op != CTL_LINESTART)
cp = cp->ct_next;
if (!cp)
continue;
/* cp2: CTL_LINESTART */
cp2 = cp1 = cp;
while (cp && cp->ct_op != CTL_TEXT) {
cp1 = cp;
cp = cp->ct_next;
}
if (!cp)
continue;
if (cp1->ct_next != cp)
continue;
p = cp->ctc_value;
if (p && *p == '\t') {
p++;
tab_depth++;
while (*p == '\t') {
tab_depth++;
p++;
}
if (p) {
char *tmp;
tmp = cp->ctc_value;
p = cp->ctc_value = strdup(p);
free(tmp);
}
}
#if 0
/* insert CTL_TAB items into CTL_LINESTART */
if (tab_control[tab_depth]) {
ctlinsert(&cp1->ct_next,
ctlcopy(tab_control[tab_depth]));
}
#else
if (tab_control[tab_depth]) {
ch = &page_control[page][l];
for (cpt = tab_control[tab_depth]; cpt; cpt = cpt->ct_next){
/* Thses ctrl items should be in CTL_LINESTART */
if (cpt->ct_op == CTL_IMAGE || cpt->ct_op == CTL_TABPREFIX ||
cpt->ct_op == CTL_ICON){
ctlinsert(&cp1->ct_next, ctlcopy1(cpt));
cp1 = cp1->ct_next;
} else
/* other ctrl items should be in the head of the ctrls */
ctlinsert(ch, ctlcopy1(cpt));
}
}
#endif
/* special: style escape */
if (p && *p == '&') {
char *p0;
char *tmp;
int i;
p0 = p;
while (*p && !isspace(*p))
p++;
tmp = cp->ctc_value;
if (!*p)
cp->ctc_value = strdup(p);
else {
*p++ = '\0';
while (*p && isspace(*p))
p++;
cp->ctc_value = strdup(p);
}
for (i = MAXTAB; i < MAXTAB + MAXSTYLE ; i++) {
if (tab_control[i]
&& strcmp(p0 + 1, tab_control[i]->ctc_value) == 0)
break;
}
if (i == MAXTAB + MAXSTYLE) {
fprintf(stderr, "style %s not found\n",
p0 + 1);
} else {
ctlinsert(&cp1->ct_next,
ctlcopy(tab_control[i]->ct_next));
}
free(tmp);
}
}
}
/* find where to put PREFIX. */
for (page = 1; page <= maxpage; page++) {
line = page_attribute[page].pg_linenum;
for (l = 0; l <= line; l++) {
for (cp = page_control[page][l]; cp; cp = cp->ct_next) {
if (cp->ct_op == CTL_LINESTART)
break;
}
if (!cp)
continue;
cp1 = cp; /* cp1: CTL_LINESTART */
for (cp = cp1; cp->ct_next; cp = cp->ct_next) {
if (cp->ct_next->ct_op == CTL_TEXT
|| cp->ct_next->ct_op == CTL_IMAGE
#ifdef MNG
|| cp->ct_next->ct_op == CTL_ANIM
#endif /* MNG */
|| cp->ct_next->ct_op == CTL_ICON) {
break;
}
}
if (!cp)
continue;
cp2 = ctlalloc1(CTL_PREFIXPOS);
if (!cp2)
continue;
cp2->ct_next = cp->ct_next;
cp->ct_next = cp2;
}
}
/*
* CTL_FONT must be replaced with appropriate font def defined by
* CTL_DEFFONT.
*/
for (page = 1; page <= maxpage; page++) {
for (l = 0; l <= page_attribute[page].pg_linenum; l++) {
for (cp = page_control[page][l];
cp;
cp = cp->ct_next) {
if (cp->ct_op == CTL_FONT) {
cp->ct_op = CTL_NOOP;
cp1 = find_font(cp->ctc_value);
if (!cp1) {
fprintf(stderr,
"page %d line %d: font def for \"%s\" not found: ignored\n",
page, l, cp->ctc_value);
continue;
}
ctlinsert(&cp->ct_next,
ctlcopy(cp1->ct_next));
}
}
}
}
/*
* CTL_XFONT is now obsolete, use CTL_XFONT2.
*/
for (page = 1; page <= maxpage; page++) {
for (l = 0; l <= page_attribute[page].pg_linenum; l++) {
for (cp = page_control[page][l];
cp;
cp = cp->ct_next) {
if (cp->ct_op == CTL_XFONT) {
p = cp->ctc_value;
cp->ct_op = CTL_XFONT2;
cp->ctc2_value1 = p;
cp->ctc2_value2 = strdup("iso8859-1");
}
}
}
}
}
void
debug0(p)
struct ctrl *p;
{
int i;
fprintf(stderr, "%p: ", p);
fprintf(stderr, " %s ", ctl_words[p->ct_op].ctl_string);
switch (ctl_words[p->ct_op].ctl_vtype) {
case T_STR:
fprintf(stderr, "\"%s\"", p->ctc_value);
break;
case T_STR2:
fprintf(stderr, "\"%s\" \"%s\"",
p->ctc2_value1, p->ctc2_value2);
break;
case T_INT:
fprintf(stderr, "%d", p->cti_value);
break;
case T_LONG:
fprintf(stderr, "#%lx", p->ctl_value);
break;
case T_DOUBLE:
fprintf(stderr, "#%g", p->ctf_value);
break;
case T_VOID:
break;
case T_SP:
break;
default:
fprintf(stderr, "(UNDEFINED TYPE)");
}
if (ctl_words[p->ct_op].ctl_vtype != T_SP)
goto done;
switch (p->ct_op) {
case CTL_PAUSE:
fprintf(stderr, "(%s)",
p->cti_value ? "page end" : "normal");
break;
case CTL_TAB:
if (p->cti_value > MAXTAB)
fprintf(stderr, "\"%s\"", p->ctc_value);
else
fprintf(stderr, "%d", p->cti_value);
break;
case CTL_SYSTEM:
case CTL_XSYSTEM:
case CTL_TSYSTEM:
case CTL_FILTER:
fprintf(stderr, "argc=%d term=%s flag=%d",
p->cta_argc,
p->cta_argv[p->cta_argc] ? "bad" : "good",
p->cta_flag);
for (i = 0; i < p->cta_argc; i++)
fprintf(stderr, "%s ", p->cta_argv[i]);
break;
case CTL_BAR:
fprintf(stderr, "color=#%lx width=%d start=%d length=%d",
p->ctb_color, p->ctb_width,
p->ctb_start, p->ctb_length);
break;
case CTL_BIMAGE:
case CTL_IMAGE:
fprintf(stderr, "file=%s colors=%d x=%d y=%d zoom=%d",
p->ctm_fname, p->ctm_numcolor,
p->ctm_ximagesize, p->ctm_yimagesize,
p->ctm_zoomflag);
break;
case CTL_BGRAD:
fprintf(stderr, "w=%d h=%d nc=%d dir=%d zoom=%d colors=%d",
p->ctd_width, p->ctd_height,
p->ctd_numcolor, p->ctd_dir,
p->ctd_zoomflag, p->ctd_g_colors);
break;
case CTL_ICON:
fprintf(stderr, "type=%s color=%x siz=%d",
p->ctic_value, (int)p->ctic_color, (int) p->ctic_size);
break;
case CTL_VALIGN:
fprintf(stderr, ((p->cti_value == VL_CENTER) ? "center"
: ((p->cti_value == VL_TOP) ? "top"
: ((p->cti_value == VL_BOTTOM) ? "bottom"
: "???"))));
break;
case CTL_AREA:
fprintf(stderr, "xoff=%d w=%d yoff=%d h=%d",
p->ctar_xoff, p->ctar_width,
p->ctar_yoff, p->ctar_height);
break;
default:
fprintf(stderr, "???");
}
done:
fprintf(stderr, "\n");
}
void
debug1(p)
struct ctrl *p;
{
while (p) {
fprintf(stderr, "\t");
debug0(p);
p = p->ct_next;
}
}
static void
debug()
{
int page, line;
for (line = 0; line < MAXLINE; line ++) {
if (!default_control[line])
continue;
fprintf(stderr, "def line %d:\n", line);
debug1(default_control[line]);
}
for (page = 0; page < MAXPAGE; page ++) {
for (line = 0; line < MAXLINE; line ++) {
if (!page_control[page][line])
continue;
fprintf(stderr, "page %d line %d:\n", page, line);
debug1(page_control[page][line]);
}
}
}
int
chkfile(p)
char *p;
{
char buf[BUFSIZ];
buf[0] = '\0';
if (findImage(p, buf) >= 0) {
if (parse_debug)
fprintf(stderr, "File %s found\n", p);
return 0;
}
fprintf(stderr, "File %s not found\n", p);
parse_error++;
return -1;
}
/*------------------------------------------------------------*/
struct ctrl *
ctllastitem(this)
struct ctrl *this;
{
struct ctrl *p;
assert(this);
p = this;
while (p && p->ct_next)
p = p->ct_next;
return p;
}
void
ctlappend(to, this)
struct ctrl *to;
struct ctrl *this;
{
struct ctrl *p;
assert(to);
assert(this);
p = ctllastitem(to);
p->ct_next = this;
}
void
ctlinsert(here, this)
struct ctrl **here;
struct ctrl *this;
{
struct ctrl *p;
struct ctrl *q;
assert(here); assert(this);
p = *here;
*here = this;
q = ctllastitem(this);
q->ct_next = p;
}
struct ctrl *
ctlalloc1(op)
u_int op;
{
struct ctrl *p;
p = (struct ctrl *)malloc(sizeof(struct ctrl));
if (!p) {
perror("malloc");
exit(-1);
}
memset(p, 0, sizeof(struct ctrl));
p->ct_op = op;
p->ct_next = NULL; /*just to make sure*/
return p;
}
void
ctlfree(this)
struct ctrl *this;
{
struct ctrl *p;
struct ctrl *q;
assert(this);
p = this;
do {
q = p->ct_next;
free(p);
p = q;
} while (p);
}
struct ctrl *
ctlcopy(this)
struct ctrl *this;
{
struct ctrl *dst0;
struct ctrl *dst;
struct ctrl *src;
src = this;
if (!src)
return NULL;
dst = dst0 = ctlalloc1(0);
memcpy(dst, src, sizeof(struct ctrl));
src = src->ct_next;
while (src) {
dst->ct_next = ctlalloc1(0);
dst = dst->ct_next;
memcpy(dst, src, sizeof(struct ctrl));
src = src->ct_next;
}
return dst0;
}
struct ctrl *
ctlcopy1(src)
struct ctrl *src;
{
struct ctrl *dst;
if (!src)
return NULL;
dst = ctlalloc1(0);
memcpy(dst, src, sizeof(struct ctrl));
dst->ct_next = NULL;
return dst;
}
int
ctlcmp(a, b)
struct ctrl *a;
struct ctrl *b;
{
int i;
assert(a);
assert(b);
if (a->ct_op != b->ct_op)
return 1;
if (a->ct_flag != b->ct_flag)
return 1;
switch (ctl_words[a->ct_op].ctl_vtype) {
case T_STR:
return strcmp(a->ctc_value, b->ctc_value);
case T_STR2:
if (strcmp(a->ctc2_value1, b->ctc2_value1) == 0
&& strcmp(a->ctc2_value2, b->ctc2_value2) == 0) {
return 0;
} else
return 1;
case T_INT:
return (a->cti_value == b->cti_value) ? 0 : 1;
case T_LONG:
return (a->ctl_value == b->ctl_value) ? 0 : 1;
case T_DOUBLE:
return (a->ctf_value == b->ctf_value) ? 0 : 1;
case T_VOID:
return 0;
case T_SP:
break;
default:
fprintf(stderr, "UNDEFINED TYPE in ctlcmp()\n");
return 1;
}
switch (a->ct_op) {
case CTL_TAB:
case CTL_PAUSE:
return (a->cti_value == b->cti_value) ? 0 : 1;
case CTL_SYSTEM:
case CTL_XSYSTEM:
case CTL_TSYSTEM:
case CTL_FILTER:
return 1;
case CTL_IMAGE:
case CTL_BIMAGE:
if (a->ctm_numcolor == b->ctm_numcolor
&& a->ctm_ximagesize == b->ctm_ximagesize
&& a->ctm_yimagesize == b->ctm_yimagesize
&& a->ctm_zoomflag == b->ctm_zoomflag)
return strcmp(a->ctm_fname, b->ctm_fname);
else
return 1;
case CTL_BGRAD:
if (a->ctd_g_colors == b->ctd_g_colors
&& a->ctd_numcolor == b->ctd_numcolor
&& a->ctd_dir == b->ctd_dir
&& a->ctd_width == b->ctd_width
&& a->ctd_height == b->ctd_height
&& a->ctd_zoomflag == b->ctd_zoomflag) {
for (i = 0; i < a->ctd_g_colors; i++) {
if (memcmp(a->ctd_colors[0], b->ctd_colors[0],
sizeof(struct g_color)) != 0)
return 1;
}
return 0;
} else
return 1;
case CTL_BAR:
if (a->ctb_color == b->ctb_color
&& a->ctb_width == b->ctb_width
&& a->ctb_start == b->ctb_start
&& a->ctb_length == b->ctb_length)
return 0;
else
return 1;
case CTL_ICON:
if (strcmp(a->ctic_value, b->ctic_value) == 0
&& a->ctic_color == b->ctic_color
&& a->ctic_size == b->ctic_size)
return 0;
else
return 1;
default:
assert(0);
}
}
FILE *
fsearchopen(fname, mode, path)
char *fname;
char *mode;
char **path;
{
FILE *fp;
char buf[MAXPATHLEN];
char *p;
int i;
i = -1;
fp = NULL;
while (1) {
p = (i == -1) ? "" : path[i];
if (!p)
break;
strcpy(buf, p);
if ((p = strrchr(buf, '/'))) {
p[1] = '\0';
}
strcat(buf, fname);
fp = fopen(buf, mode);
if (fp)
break;
i++;
}
return fp;
}
static int
define_font(cp)
struct ctrl *cp;
{
int i;
/* find duplicated def */
for (i = 0; i < MAXFONTDEF; i++) {
if (!fontdef_control[i])
continue;
if (strcmp(fontdef_control[i]->ctc_value,
cp->ctc_value) == 0) {
ctlfree(fontdef_control[i]);
fontdef_control[i] = NULL;
goto defineit;
}
}
/* find empty def */
for (i = 0; i < MAXFONTDEF; i++) {
if (!fontdef_control[i])
break;
}
if (i == MAXFONTDEF) {
return -1;
}
defineit:
/* define it */
fontdef_control[i] = cp;
return 0;
}
static struct ctrl *
find_font(font)
char *font;
{
int i;
/* find duplicated def */
for (i = 0; i < MAXFONTDEF; i++) {
if (!fontdef_control[i])
continue;
if (strcmp(fontdef_control[i]->ctc_value, font) == 0)
return fontdef_control[i];
}
return NULL;
}
syntax highlighted by Code2HTML, v. 0.9.1