/*
 *  This file is part of jcabc2ps,
 *  Copyright (C) 1996,1997,1998  Michael Methfessel
 *  See file jcabc2ps.c for details.
 */

#include <string.h>

#include "jcabc2ps.h"
#include "misc.h"
#include "util.h"

#include "format.h"

/*  subroutines connected with page layout  */


/* ----- fontspec ----- */
void fontspec (struct FONTSPEC *f, char name[], float size, int box)
{
	strcpy (f->name, name);
	f->size = size;
	f->box  = box;
}

/* ----- add_font ----- */
/* checks font list, adds font if new */
int add_font (f)
struct FONTSPEC *f;
{	char *F = "add_font";
	int i,i0,fnum;

	i0=-1;
	for (i=0;i<nfontnames;i++) {
		if (streq(f->name,fontnames[i])) i0=i;
	}

	if (i0>=0) {
		fnum=i0;
		V6 "%s: Already at %d: font %s\n",F,fnum,f->name V;
	}
	else {
		fnum=nfontnames;
		strcpy(fontnames[fnum],f->name);
		V6 "%s: Add new at %d: font %s\n",F,fnum,f->name V;
		nfontnames++;
	}
	return fnum;
}


/* ----- make_font_list ----- */
void make_font_list (f)
struct FORMAT *f;
{	char *F = "make_font_list";
	V6 "%s: Adding fonts from format..\n",F V;
	add_font (&f->achordfont);
	add_font (&f->annotfont);
	add_font (&f->barlabelfont);
	add_font (&f->barnumfont);
	add_font (&f->composerfont);
	add_font (&f->partsfont);
	add_font (&f->subtitlefont);
	add_font (&f->textfont);
	add_font (&f->titlefont);
	add_font (&f->vocalfont);
	add_font (&f->voicefont);
	add_font (&f->wordsfont);
}

/* ----- set_standard_format ----- */
void set_standard_format (f)
struct FORMAT *f;
{	char *F = "set_standard_format";
	strcpy (f->name,          "standard");
	strcpy (f->auquality,     "1");
	f->playtempo              =   PLAY_TEMPO;
	f->pageheight             =   PAGEHEIGHT * CM;
	f->staffwidth             =   STAFFWIDTH * CM;
	f->leftmargin             =   LEFTMARGIN * CM;
	f->topmargin              =   1.0  * CM;
	f->botmargin              =   1.0  * CM;
	f->topspace               =   0.8  * CM;
	f->titlespace             =   0.2  * CM;
	f->subtitlespace          =   0.1  * CM;
	f->composerspace          =   0.1  * CM;	// was 0.2 [jc]
	f->musicspace             =   0.1  * CM;	// was 0.2 [jc]
	f->partsspace             =   0.1  * CM;	// was 0.3 [jc]
	f->staffsep               =  25.0  * PT;	// was 46.0 [jc]
	f->sysstaffsep            =  25.0  * PT;	// was 30.0 [jc]
	f->systemsep              =  40.0  * PT;
	f->vocalspace             =  20.0  * PT;
	f->textspace              =   0.5  * CM;
	f->wordsspace             =   0.0  * CM;
	f->scale                  =   0.70;
	f->maxshrink              =   0.60;
	f->landscape              =   0;
	f->slurgraces             =   0;
	f->titleleft              =   0;
	f->stretchstaff           =   1;
	f->stretchlast            =   0;
	f->continueall            =   0;
	f->breakall               =   0;
	f->writehistory           =   0;
	f->withxrefs              =   0;
	f->oneperpage             =   0;
	f->titlecaps              =   0;
	f->barsperstaff           =   0;
	f->barnums                =   -1;
	f->lineskipfac            =   1.1;
	f->parskipfac             =   0.4;
	f->strict1                =   0.3;	/* Was 0.5 [jc] */
	f->strict2                =   0.5;	/* Was 0.8 [jc] */
	f->indent                 =   0.0;
	fontspec (&f->achordfont,    "Helvetica",      12.0, 0);
	fontspec (&f->annotfont,     "Times-Roman",    12.0, 0);
	fontspec (&f->barlabelfont,  "Times-Courier",  14.0, 1);	// was 18.0 [jc]
	fontspec (&f->barnumfont,    "Times-Italic",   12.0, 0);
	fontspec (&f->composerfont,  "Times-Italic",   11.0, 0);
	fontspec (&f->indexfont,     "Times-Roman",    11.0, 0);
	fontspec (&f->partsfont,     "Times-Roman",    11.0, 0);
	fontspec (&f->subtitlefont,  "Times-Roman",    12.0, 0);
	fontspec (&f->tempofont,     "Times-Courier",  10.0, 0);
	fontspec (&f->textfont,      "Times-Roman",    12.0, 0);
	fontspec (&f->titlefont,     "Times-Roman",    15.0, 0);
	fontspec (&f->vocalfont,     "Times-Courier",  13.0, 0);
	fontspec (&f->voicefont,     "Times-Roman",    12.0, 0);
	fontspec (&f->wordsfont,     "Times-Roman",    12.0, 0);
	V6 "%s: Loading format \"%s\"\n",F,f->name V;
}

/* ----- set_pretty_format ----- */
void set_pretty_format (f)
struct FORMAT *f;
{
	set_standard_format (f);
	strcpy (f->name,    "pretty");
	f->titlespace             =   0.4  * CM;
	f->composerspace          =   0.25 * CM;
	f->musicspace             =   0.25 * CM;
	f->partsspace             =   0.3  * CM;
	f->staffsep               =  50.0  * PT;
	f->sysstaffsep            =  45.0  * PT;
	f->systemsep              =  55.0  * PT;
	f->scale                  =   0.75;
	f->maxshrink              =   0.55;
	f->parskipfac             =   0.1;
	fontspec (&f->achordfont,    "Helvetica",      12.0, 0);
	fontspec (&f->annotfont,     "Times-Roman",    12.0, 0);
	fontspec (&f->composerfont,  "Times-Italic",   12.0, 0);
	fontspec (&f->partsfont,     "Times-Roman",    12.0, 0);
	fontspec (&f->subtitlefont,  "Times-Roman",    15.0, 0);
	fontspec (&f->tempofont,     "Times-Courier",  10.0, 0);
	fontspec (&f->textfont,      "Times-Roman",    10.0, 0);
	fontspec (&f->titlefont,     "Times-Roman",    18.0, 0);
	fontspec (&f->vocalfont,     "Times-Courier",  14.0, 0);
	fontspec (&f->voicefont,     "Times-Roman",    12.0, 0);
	fontspec (&f->wordsfont,     "Times-Roman",    10.0, 0);
}

/* ----- set_pretty2_format ----- */
void set_pretty2_format (f)
struct FORMAT *f;
{
	set_standard_format (f);
	strcpy (f->name,    "pretty2");
	f->titlespace             =   0.4  * CM;
	f->composerspace          =   0.3  * CM;
	f->musicspace             =   0.25 * CM;
	f->partsspace             =   0.2  * CM;
	f->staffsep               =  55.0  * PT;
	f->sysstaffsep            =  45.0  * PT;
	f->systemsep              =  55.0  * PT;
	f->textspace              =   0.2  * CM;
	f->scale                  =   0.70;
	f->maxshrink              =   0.55;
	f->titleleft              =   1;
	f->parskipfac             =   0.1;
	fontspec (&f->achordfont,    "Helvetica",      12.0, 0);
	fontspec (&f->annotfont,     "Times-Roman",    12.0, 0);
	fontspec (&f->barlabelfont,  "Times-Courier",  14.0, 1);	// was 18.0 [jc]
	fontspec (&f->barnumfont,    "Times-Roman",    11.0, 1);
	fontspec (&f->composerfont,  "Helvetica",      10.0, 0);
	fontspec (&f->partsfont,     "Times-Roman",    12.0, 0);
	fontspec (&f->subtitlefont,  "Helvetica-Bold", 13.0, 0);
	fontspec (&f->tempofont,     "Times-Courier",  10.0, 0);
	fontspec (&f->textfont,      "Times-Roman",    10.0, 0);
	fontspec (&f->titlefont,     "Helvetica-Bold", 16.0, 0);
	fontspec (&f->vocalfont,     "Times-Courier",  13.0, 0);
	fontspec (&f->voicefont,     "Times-Roman",    12.0, 0);
	fontspec (&f->wordsfont,     "Times-Roman",    10.0, 0);
}


/* ----- print_font ----- */
void print_font (str,fs)
char *str;
struct FONTSPEC fs;
{
	fprintf(stderr,"  %-14s %s %.1f", str, fs.name, fs.size);
	if (fs.box) fprintf(stderr," box");
	fprintf(stderr,"\n");
}


/* ----- print_format ----- */
void print_format (f)
struct FORMAT f;
{
	char yn[2][5]={"no","yes"};

	fprintf(stderr,"\nFormat \"%s\":\n", f.name);
	fprintf(stderr,"  pageheight     %.2fcm\n",    f.pageheight/CM);
	fprintf(stderr,"  staffwidth     %.2fcm\n",    f.staffwidth/CM);
	fprintf(stderr,"  topmargin      %.2fcm\n",    f.topmargin/CM);
	fprintf(stderr,"  botmargin      %.2fcm\n",    f.botmargin/CM);
	fprintf(stderr,"  leftmargin     %.2fcm\n",    f.leftmargin/CM);
	fprintf(stderr,"  topspace       %.2fcm\n",    f.topspace/CM);
	fprintf(stderr,"  titlespace     %.2fcm\n",    f.titlespace/CM);
	fprintf(stderr,"  subtitlespace  %.2fcm\n",    f.subtitlespace/CM);
	fprintf(stderr,"  composerspace  %.2fcm\n",    f.composerspace/CM);
	fprintf(stderr,"  musicspace     %.2fcm\n",    f.musicspace/CM);
	fprintf(stderr,"  partsspace     %.2fcm\n",    f.partsspace/CM);
	fprintf(stderr,"  wordsspace     %.2fcm\n",    f.wordsspace/CM);
	fprintf(stderr,"  textspace      %.2fcm\n",    f.textspace/CM);
	fprintf(stderr,"  vocalspace     %.1fpt\n",    f.vocalspace);
	fprintf(stderr,"  staffsep       %.1fpt\n",    f.staffsep);
	fprintf(stderr,"  sysstaffsep    %.1fpt\n",    f.sysstaffsep);
	fprintf(stderr,"  systemsep      %.1fpt\n",    f.systemsep);
	fprintf(stderr,"  scale          %.2f\n",      f.scale);
	fprintf(stderr,"  maxshrink      %.2f\n",      f.maxshrink);
	fprintf(stderr,"  strictness1    %.2f\n",      f.strict1);
	fprintf(stderr,"  strictness2    %.2f\n",      f.strict2);
	fprintf(stderr,"  indent         %.1fpt\n",    f.indent);
	print_font("achordfont",   f.achordfont);
	print_font("annotfont",    f.annotfont);
	print_font("barlabelfont", f.barlabelfont);
	print_font("barnumberfont",f.barnumfont);
	print_font("composerfont", f.composerfont);
	print_font("indexfont",    f.indexfont);
	print_font("partsfont",    f.partsfont);
	print_font("subtitlefont", f.subtitlefont);
	print_font("tempofont",    f.tempofont);
	print_font("textfont",     f.textfont);
	print_font("titlefont",    f.titlefont);
	print_font("vocalfont",    f.vocalfont);
	print_font("voicefont",    f.voicefont);
	print_font("wordsfont",    f.wordsfont);
	fprintf(stderr,"  lineskipfac    %.1f\n",    f.lineskipfac);
	fprintf(stderr,"  parskipfac     %.1f\n",    f.parskipfac);
	fprintf(stderr,"  barsperstaff   %d\n",      f.barsperstaff);
	fprintf(stderr,"  barnumbers     %d\n",      f.barnums);
	fprintf(stderr,"  landscape      %s\n", yn[f.landscape]);
	fprintf(stderr,"  slurgraces     %s\n", yn[f.slurgraces]);
	fprintf(stderr,"  titleleft      %s\n", yn[f.titleleft]);
	fprintf(stderr,"  titlecaps      %s\n", yn[f.titlecaps]);
	fprintf(stderr,"  stretchstaff   %s\n", yn[f.stretchstaff]);
	fprintf(stderr,"  stretchlast    %s\n", yn[f.stretchlast]);
	fprintf(stderr,"  writehistory   %s\n", yn[f.writehistory]);
	fprintf(stderr,"  continueall    %s\n", yn[f.continueall]);
	fprintf(stderr,"  breakall       %s\n", yn[f.breakall]);
	fprintf(stderr,"  oneperpage     %s\n", yn[f.oneperpage]);
	fprintf(stderr,"  withxrefs      %s\n", yn[f.withxrefs]);
	fprintf(stderr,"  playtempo      %.0f\n", f.playtempo);
	fprintf(stderr,"  auquality      %s\n",   f.auquality);

}


/* ----- g_unum: read a number with a unit ----- */
void g_unum (l,s,num)
	char *l,*s;
	float *num;
{	char *F = "g_unum";
	float a,b;
	char unit[81];

	strcpy(unit,"pt");
	sscanf(s,"%f%s", &a, unit);
	V7 "%s: l=\"%s\" s=\"%s\" a=%6.3f unit=\"%s\"\n",F,l,s,a,unit V;

	if      (streq(unit,"cm")) b=a*CM;
	elsif (streq(unit,"mm")) b=a*CM*0.1;
	elsif (streq(unit,"in")) b=a*IN;
	elsif (streq(unit,"pt")) b=a*PT;
	else {
		fprintf(stderr,"+++ Unknown unit \"%s\" in line: %s\n",unit,l);
		exit (3);
	}
	V6 "%s: l=\"%s\" s=\"%s\" a=%6.3f unit=\"%s\" b=%6.3f\n",F,l,s,a,unit,b V;
	*num = b;
}

/* ----- g_logv: read a logical variable ----- */
void g_logv (l,s,v)
char *l,*s;
int  *v;
{
	int k;
	char t[31];

	strcpy(t,"1");
	sscanf (s,"%s", t);
	if    (streq(t,"1") || streq(t,"on") || streq(t,"yes") || streq(t,"true"))
		k=1;
	elsif (streq(t,"0") || streq(t,"off") || streq(t,"no") || streq(t,"false"))
		k=0;
	else {
		fprintf(stderr,"\n+++ Unknown logical value \"%s\" near \"%s\"\n",t,l);
		exit (3);
	}
	*v = k;
}


/* ----- g_fltv: read a float variable, no units ----- */
void g_fltv (l,nch,v)
char   *l;
int    nch;
float  *v;
{
	float k;

	sscanf (l+nch,"%f", &k);
	*v = k;
}

/* ----- g_intv: read an int variable, no units ----- */
void g_intv (l,nch,v)
char   *l;
int    nch;
int    *v;
{
	int k;

	sscanf (l+nch,"%d", &k);
	*v = k;
}



/* ----- g_fspc: read a font specifier ----- */
void g_fspc (l,nch,fn)
char *l;
int  nch;
struct FONTSPEC *fn;
{
	char  fname[101],ssiz[101],sbox[101];
	float fsize;

	fsize=fn->size;
	strcpy(sbox,"SnOt");
	strcpy(ssiz,"SnOt");

	sscanf (l+nch,"%s %s %s", fname, ssiz, sbox);
	if (strcmp(fname,"*")) strcpy (fn->name, fname);

	if (strcmp(ssiz,"*")) sscanf(ssiz,"%f",&fsize);
	fn->size = fsize;

	if (streq(sbox,"box"))       fn->box=1;
	elsif (streq(sbox,"SnOt")) ;
	else wng ("incorrect font spec: ", l+nch);

	if (!file_initialized) add_font (fn);
}


/* ----- interpret_format_line ----- */
/* read a line with a format directive, set in format struct f */
int interpret_format_line (l,f)
	char l[];
	struct FORMAT *f;
{	char *F = "interpret_format_line";
	char w[81],fnm[81];
	int nch,i,fnum;
	char *s;
	struct FONTSPEC tempfont;

	strcpy(w,"");
	sscanf(l,"%s%n", w, &nch);
	if (streq(w,"")) return 0;
	if (w[0]=='%') return 0;
	V4 "%s: Interpret format line: %s\n",F,l V;
	if (streq(w,"end")) return 1;
	s=l+nch;

	if    (streq(w,"pageheight"))    g_unum(l,s,&f->pageheight);
	elsif (streq(w,"staffwidth"))    g_unum(l,s,&f->staffwidth);
	elsif (streq(w,"topmargin"))     g_unum(l,s,&f->topmargin);
	elsif (streq(w,"botmargin"))     g_unum(l,s,&f->botmargin);
	elsif (streq(w,"leftmargin"))    g_unum(l,s,&f->leftmargin);
	elsif (streq(w,"topspace"))      g_unum(l,s,&f->topspace);
	elsif (streq(w,"wordsspace"))    g_unum(l,s,&f->wordsspace);
	elsif (streq(w,"titlespace"))    g_unum(l,s,&f->titlespace);
	elsif (streq(w,"subtitlespace")) g_unum(l,s,&f->subtitlespace);
	elsif (streq(w,"composerspace")) g_unum(l,s,&f->composerspace);
	elsif (streq(w,"musicspace"))    g_unum(l,s,&f->musicspace);
	elsif (streq(w,"partsspace"))    g_unum(l,s,&f->partsspace);
	elsif (streq(w,"staffsep"))      g_unum(l,s,&f->staffsep);
	elsif (streq(w,"sysstaffsep"))   g_unum(l,s,&f->sysstaffsep);
	elsif (streq(w,"systemsep"))     g_unum(l,s,&f->systemsep);
	elsif (streq(w,"vocalspace"))    g_unum(l,s,&f->vocalspace);
	elsif (streq(w,"textspace"))     g_unum(l,s,&f->textspace);

	elsif (streq(w,"scale"))         g_fltv(l,nch,&f->scale);
	elsif (streq(w,"maxshrink"))     g_fltv(l,nch,&f->maxshrink);
	elsif (streq(w,"lineskipfac"))   g_fltv(l,nch,&f->lineskipfac);
	elsif (streq(w,"parskipfac"))    g_fltv(l,nch,&f->parskipfac);
	elsif (streq(w,"barsperstaff"))  g_intv(l,nch,&f->barsperstaff);
	elsif (streq(w,"barnumbers"))    g_intv(l,nch,&f->barnums);
	elsif (streq(w,"strictness1"))   g_fltv(l,nch,&f->strict1);
	elsif (streq(w,"strictness2"))   g_fltv(l,nch,&f->strict2);
	elsif (streq(w,"strictness")) {
		g_fltv(l,nch,&f->strict1); f->strict2=f->strict1; }
	elsif (streq(w,"indent"))        g_unum(l,s,&f->indent);

	elsif (streq(w,"titleleft"))     g_logv(l,s,&f->titleleft);
	elsif (streq(w,"titlecaps"))     g_logv(l,s,&f->titlecaps);
	elsif (streq(w,"landscape"))     g_logv(l,s,&f->landscape);
	elsif (streq(w,"slurgraces"))    g_logv(l,s,&f->slurgraces);
	elsif (streq(w,"graceslurs"))    g_logv(l,s,&f->slurgraces);
	elsif (streq(w,"stretchstaff"))  g_logv(l,s,&f->stretchstaff);
	elsif (streq(w,"stretchlast"))   g_logv(l,s,&f->stretchlast);
	elsif (streq(w,"continueall"))   g_logv(l,s,&f->continueall);
	elsif (streq(w,"breakall"))      g_logv(l,s,&f->breakall);
	elsif (streq(w,"writehistory"))  g_logv(l,s,&f->writehistory);
	elsif (streq(w,"withxrefs") )    g_logv(l,s,&f->withxrefs);
	elsif (streq(w,"oneperpage") )   g_logv(l,s,&f->oneperpage);

	elsif (streq(w,"achordfont"))    g_fspc(l,nch,&f->achordfont);
	elsif (streq(w,"gchordfont"))    g_fspc(l,nch,&f->achordfont);
	elsif (streq(w,"annotfont"))     g_fspc(l,nch,&f->annotfont);
	elsif (streq(w,"barlabelfont"))  g_fspc(l,nch,&f->barlabelfont);
	elsif (streq(w,"barnumberfont")) g_fspc(l,nch,&f->barnumfont);
	elsif (streq(w,"composerfont"))  g_fspc(l,nch,&f->composerfont);
	elsif (streq(w,"indexfont"))     g_fspc(l,nch,&f->indexfont);
	elsif (streq(w,"partsfont"))     g_fspc(l,nch,&f->partsfont);
	elsif (streq(w,"subtitlefont"))  g_fspc(l,nch,&f->subtitlefont);
	elsif (streq(w,"tempofont"))     g_fspc(l,nch,&f->tempofont);
	elsif (streq(w,"textfont"))      g_fspc(l,nch,&f->textfont);
	elsif (streq(w,"titlefont"))     g_fspc(l,nch,&f->titlefont);
	elsif (streq(w,"vocalfont"))     g_fspc(l,nch,&f->vocalfont);
	elsif (streq(w,"voicefont"))     g_fspc(l,nch,&f->voicefont);
	elsif (streq(w,"wordsfont"))     g_fspc(l,nch,&f->wordsfont);

	elsif (streq(w,"playtempo"))     g_fltv(l,nch,&f->playtempo);
	elsif (streq(w,"auquality"))     sscanf (l+nch,"%s", &f->auquality[0]);

	elsif (streq(w,"font")) {
		sscanf(l,"%*s %s", fnm);
		fnum=-1;
		for (i=0;i<nfontnames;i++) {
			if (streq(fnm,fontnames[i])) fnum=i;
		}
		if (fnum<0) {
			if (file_initialized) {
				fprintf(stderr,"+++ Cannot predefine when output file open: %s\n", l);
				exit (3);
			}
			tempfont.size=12.0;
			g_fspc(l,nch,&tempfont);
		}
	} else {
		V4 "%s: Ignore format line: %s\n",F, l V;
		return 2;
	}
	slurgraces = f->slurgraces;		// Global flag [jc]
	return 0;
}

/* ----- read_fmt_file ----- */
int read_fmt_file (filename,dirname,f)
	char filename [],dirname[];
	struct FORMAT *f;
{	char *F = "read_fmt_file";
	FILE *fp;
	char line[BSIZE],fname[201];
	int i,end, lines=0;

	strcpy(fname,filename);
	if ((fp = fopen (fname,"r")) == NULL) {
		if (strlen(dirname)==0) {
			return 0;
		} else {
			strcpy(fname,dirname);
			strcat(fname,"/");
			strcat(fname,filename);
			if ((fp = fopen (fname,"r")) == NULL) return 0;
		}
	}
	V3 "%s: Reading format file %s:\n",F,fname V;
	strcpy (line, "");
	getaline(line, BSIZE, fp);
	for (i=0;i<200;i++) {
		end = interpret_format_line (line,f);
		++lines;
		if (end==1) return lines;
		strcpy (line, "");
		if (feof(fp)) return lines;
		if (!getaline(line, BSIZE, fp)) return lines ;
	}
	fclose (fp);
	return lines;
}

