/* * This file is part of jcabc2ps, * Copyright (C) 1996,1997,1998 Michael Methfessel * See file jcabc2ps.c for details. */ #include #include #include #include "jcabc2ps.h" #include "style.h" #include "buffer.h" #include "util.h" #include "format.h" #include "pssubs.h" #include "parse.h" #include "subs.h" /* miscellaneous subroutines */ /* ----- write_help ----- */ void write_help () { fprintf(stderr,"jcabc2ps version %s compiled %s\n", version, __DATE__); fprintf(stderr,"Usage: jcabc2ps [files].. [-e nums-or-pats] [other flags] [outfile.ps]\n" " - show index of abc files or typeset tunes in Postscript.\n" "where: files input files in abc format\n" " nums tune xref numbers, i.e. 1 3 6-7,20-\n" " pats patterns for title search\n" "Tunes are selected if they match a number or a pattern.\n" "Flags: +o write output for selected tunes\n" " +a write audio file %s\n" " +E produce EPSF output, one tune per file\n" " +h show this command summary (on stderr)\n" " +i run in interactive mode\n" " +I write index to Ind.ps\n" " +o aa set outfile name to aaa\n" // " -q mn.. select audio quality for the voices\n" " -Q xx playback tempo, in beats per minute\n" " -v nn set verbosity level to nn\n" " Selection:\n" " -e following arguments are selectors\n" " -f following arguments are file names\n" " -T search Title field (default)\n" " -C search Composer field instead of title\n" " -R search Rhythm field instead of title\n" " -S search Source field instead of title\n" " -V str select voices, eg. -V 1,4-5\n" " Formatting:\n" " -1 write one tune per page\n" " -D bar look for format files in directory \"bar\"\n" " -d xx set staff separation (cm/in/pt)\n" " +F foo read format from \"foo.fmt\"\n" " -g xx set glue mode to shrink|space|stretch|fill\n" " +H show the format parameters\n" " -k nn number every nn bars; 0 for first in staff\n" " +l landscape mode\n" " -m xx set left margin (cm/in/pt)\n" " +n include notes and history in output\n" " +N write page numbers\n" " -p pretty output (looks better, needs more space)\n" " -P select second predefined pretty output style\n" " -s xx set scale factor for symbol size to xx\n" " -w xx set staff width (cm/in/pt)\n" " -X x set strictness for note spacing, 00) fprintf(stderr,"Default format directory %s\n", DEFAULT_FDIR); } /* ----- is_xrefstr: check if string ok for xref selection ---- */ int is_xrefstr (str) char str[]; { char *c; c=str; while (*c != '\0') { if ((!isdigit(*c)) && (*c!='-') && (*c!=',') && (*c!=' ')) return 0; c++; } return 1; } /* ----- make_arglist: splits one string into list or arguments ---- */ int make_arglist (str, av) char str[]; char *av[]; { char *q; int n; q=str; n=1; /* first real arg is 1, as in argv */ for (;;) { while (*q==' ') q++; if (*q=='\0') break; av[n]=q; n++; while ((*q!=' ') && (*q!='\0')) q++; if (*q=='\0') break; *q='\0'; q++; } return n; } char V_name[128]= {0}; // Verbosity name char V_file[128]= {0}; // Verbosity file /* ----- init_ops ----- */ void init_ops (job) int job; { char *F = "init_ops"; char *p; int i, f; V4 "%s: Called with job=%d myname=\"%s\".\n",F,job,myname V; sprintf(V_name,"V_%s\0",myname); if (p = getenv("V_jcabc2ps")) { if (sscanf(p,"%d",&db) < 1) // Original "debug" output flag db = DB_DF + 1; } elsif (p = getenv("D_jcabc2ps")) { if (sscanf(p,"%d",&db) < 1) // Original "debug" output flag db = DB_DF + 1; } if (p = getenv(V_name)) { V3 "%s: ENV(%s)=\"%s\"\n",F,V_name,p V; if ((i = sscanf(p,"%d%s",&vb,&V_file)) < 1) { // JC's "verbose" flag vb = VB_DF + 1; } elsif (i > 1 && *V_file) { // Did we get a file name? if (freopen(V_file,"w",stderr)) { // Make it our stderr file. V4 "%s: Reopened stderr as \"%s\"\n",F,V_file V; } else { V1 "%s: Can't open stderr to \"%s\"\n",F,V_file V; } } else { V3 "%s: Verbose level %d to stderr.\n",F,vb V; } } V3 "%s: db=%d vb=%d.\n",mypath,db,vb V; one_per_page = -1; landscape = -1; slurgraces = 0; scalefac = -1.0; lmargin = -1.0; swidth = -1.0; write_history = -1; staffsep = -1; dstaffsep = 0; break_continues = -1; continue_lines = -1; include_xrefs = -1; alfa_c = -1.0; strict1 = -1.0; strict2 = -1.0; barnums = -1; make_index = 0; make_audio = 0; playtempo = 0; select_all = 0; pagenumbers = 0; strcpy (styf, ""); strcpy (transpose, ""); strcpy (vcselstr, ""); strcpy (au_qstr, ""); if (job) { strcpy (styd, DEFAULT_FDIR); strcpy (outf, OUTPUTFILE); interactive = 0; pretty = 0; epsf = 0; choose_outname = 0; gmode = G_FILL; search_field0 = S_TITLE; } } /* ----- ops_into_fmt ----- */ void ops_into_fmt (fmt) struct FORMAT *fmt; { if (landscape >= 0) fmt->landscape=landscape; if (slurgraces >= 0) fmt->slurgraces=slurgraces; if (scalefac >= 0) fmt->scale=scalefac; if (lmargin >= 0) fmt->leftmargin=lmargin; if (swidth >= 0) fmt->staffwidth=swidth; if (continue_lines >= 0) fmt->continueall=continue_lines; if (break_continues >= 0) fmt->breakall=break_continues; if (write_history >= 0) fmt->writehistory=write_history; if (bars_per_line > 0) fmt->barsperstaff=bars_per_line; if (include_xrefs >= 0) fmt->withxrefs=include_xrefs; if (one_per_page >= 0) fmt->oneperpage=one_per_page; if (alfa_c >= 0) fmt->maxshrink=alfa_c; if (staffsep >= 0) fmt->staffsep=staffsep; if (strict1 >= 0) fmt->strict1=strict1; if (strict2 >= 0) fmt->strict2=strict2; if (barnums >= 0) fmt->barnums=barnums; if (playtempo > 0) fmt->playtempo=playtempo; if (strlen(au_qstr)>0) strcpy(fmt->auquality, au_qstr); fmt->staffsep = fmt->staffsep + dstaffsep; fmt->sysstaffsep = fmt->sysstaffsep + dstaffsep; } char aaa[201]; char ext[41]; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Process the +/-o command line option. The possibilities are: * -o means no PS output. * +o means PS output to stdout. * +o means PS output to * +o means PS output to * In the last case, the next arg will be treated as a file name if it doesn't * start with '+' or '-'. * * The return value is either ac or ac+1, depending on whether we use the next * arg as the file name. */ int Opt_o(a,ac,av) int a; int ac; char**av; { char *F="Opt_o"; int c0 = av[a][0]; int c1 = av[a][1]; int c; V6 "%s: Opt '%c%c' \"%s\"\n",F,c0,c1,av[a] V; if (c0 == '+') { V6 "%s: Enable PS output.\n",F V; do_mode = DO_OUTPUT; make_ps = 1; use_stdout = 0; // Not writing to stdout if (av[a][2]) { V6 "%s +o with file name \"%s\"\n",F,&av[a][2] V; strcpy (aaa, &av[a][2]); strcpy(outf, aaa); strext(outf, aaa, "ps", 1); } elsif (a+1 < ac && (c = av[a+1][0]) && c != '-' && c != '+') { ++a; strcpy (aaa, &av[a][0]); V6 "%s +o plus file arg \"%s\"\n",F,aaa V; if (!strcmp(aaa,"=")) { choose_outname=1; V6 "%s: Automatic choice of output name.\n",F V; } else { V6 "%s: Output file \"%s\"\n",F,aaa V; getext (aaa,ext); if (strcmp(ext,"ps") && strcmp(ext,"eps") && strcmp(ext,"")) { fprintf(stderr,"Wrong extension for output file: %s\n", aaa); return 1; } strcpy(outf, aaa); if (epsf || strcmp(ext,"eps") == 0) { strext(outf, aaa, "eps", 1); epsf = 1; // Note the request for EPS } else { strext(outf, aaa, "ps", 1); } V2 "%s: outf=\"%s\"\n",F,outf V; choose_outname=0; } } else { V6 "%s +o with no arg.\n",F V; } V5 "%s: Output PS file \"%s\"\n",F,outf V; } elsif (c0 == '-') { V6 "%s: Disable PS output.\n",F V; do_mode = 0; make_ps = 0; } else { } return a; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * parse_args: parse list of arguments, interpret flags. * The return value is an error code; if nonzero, we will exit. */ int parse_args(ac, av) int ac; char *av[]; { char *F = "parse_args"; int a,i,l,m,k,nsel,sel_arg,j,ok,f_pos,got_value; int c0, c1, c2; char c; V6 "%s: Called with %d args.\n",F,ac V; help_me = 0; ninf = 0; nsel = 0; sel_arg = 0; f_pos = -1; strcpy(sel_str[0], ""); s_field[0] = search_field0; for (a=1; a 3) && !strcmp(av[a]+l-4,".fmt")) { V3 "Arg \"%s\" is format file.\n",av[a] V; strcpy(styf, av[a]); } else { V3 "Arg \"%s\" is input file.\n",av[a] V; use_stdin = 0; // Not reading stdin if (sel_arg && !strcmp(av[a]+l-4,".abc")) { /* Input file if .abc */ V4 "Arg \"%s\" is .abc file.\n",av[a] V; nsel++; strcpy(sel_str[nsel], ""); s_field[nsel] = S_TITLE; V4 "s_field[%d]=%d=S_TITLE\n",nsel,s_field[nsel] V; if (ninf == 0) { V4 "Selector before first file.\n" V; strcpy(sel_str[nsel],sel_str[nsel-1]); V3 "sel_str[%d]=\"%s\"\n",nsel,sel_str[nsel] V; s_field[nsel]=s_field[nsel-1]; V4 "s_field[%d]=%d\n",nsel,s_field[nsel] V; } sel_arg=0; } if (is_xrefstr(av[a]) && (!sel_arg)) { /* sel if xref numbers */ V4 "Arg \"%s\" is xref number.\n",av[a] V; if (a-1 != f_pos) sel_arg=1; } if (!sel_arg) { /* this arg is a file name */ V4 "Arg \"%s\" is file name.\n",av[a] V; use_stdin = 0; // Not reading stdin if (ninf >= MAXINF) { V1 "%s: Too many input files, max is %d\n",myname,MAXINF V; return 1; } strcpy(in_file[ninf], av[a]); psel[ninf] = nsel; V3 "Input file %d is \"%s\"\n",ninf,in_file[ninf] V; ninf++; } else { /* this arg is a selector */ V3 "Arg \"%s\" is selector %d.\n",av[a],nsel V; strcat(sel_str[nsel], av[a]); strcat(sel_str[nsel], " "); } } V5 "sel_arg=%d.\n",sel_arg V; continue; case '-': // Option strings case '+': c1 = av[a][1]; V3 "Opt \"%s\" c0='%c' c1='%c'\n",av[a],c0,c1 V; switch(c1) { // New, revised options case '1': one_per_page = (c0 == '+') ? 1 : 0; continue; case 'B': // Bars per line if (c0 == '+') { if ((c2 = av[a][2]) && isdigit(c2)) { sscanf(av[a]+2,"%d",&bars_per_line); } elsif (av[a+1] && (c2 = av[a+1][0]) && isdigit(c2)) { sscanf(av[++a],"%d",&bars_per_line); } else { V2 "%s: \"%s\" needs a numeric value.\n",mypath,av[a] V; } continue_lines = 0; } else { bars_per_line = 0; } continue; case 'E': // EPS output; file name should follow epsf = (c0 == '+') ? 1 : 0; a = Opt_o(a,ac,av); continue; case 'e': sel_arg = (c0 == '+') ? 1 : 0; V5 "sel_arg=%d.\n",sel_arg V; continue; case 'F': // Format file V6 "%s: Format option.\n",F V; if (c0 == '+') { if (av[a][2]) { // +F strcpy(styf, av[a]+2); V3 "Use format file -F\"%s\"\n",styf V; continue; } else { // Try next arg if (a+1 < ac) { // +F strcpy(styf, av[++a]); V3 "Use format file av[%d]=\"%s\"\n",a,styf V; continue; } else { V1 "+F option has no file name.\n" V; continue; } } } else { V3 "Don't read format file.\n" V; strcpy(styf, ""); continue; } continue; case 'f': nsel++; strcpy (sel_str[nsel], ""); if (ninf==0) { /* selector before first file */ strcpy(sel_str[nsel],sel_str[nsel-1]); s_field[nsel]=s_field[nsel-1]; } s_field[nsel]=search_field0; sel_arg=0; V5 "sel_arg=%d f_pos=%d.\n",sel_arg,f_pos V; f_pos=a; continue; case 'H': help_me = (c0 == '+') ? 2 : 0; continue; case 'h': write_help(); continue; case 'N': pagenumbers = (c0 == '+') ? 1 : 0; continue; case 'P': pretty = (c0 == '+') ? 2 : 0; continue; case 'p': pretty = (c0 == '+') ? 1 : 0; continue; case 'a': if (c0 == '+') { do_mode = DO_OUTPUT; make_audio = 1; } else { make_audio = 0; } V3 "%srite audio; do_mode=%d.\n",(make_audio?"W":"Don't w"),do_mode V; continue; case 'b': // Break lines if (c0 == '+') { // Ignore line breaks break_continues= 1; // Ignore continues (/) continue_lines = 0; // All EOLs are staff break } else { // Respect line breaks break_continues= 0; // Honor continues } V3 "%s line breaks.\n",(continue_lines?"Ignore":"Honor") V; V3 "%s continues.\n",(break_continues?"Ignore":"Honor") V; continue; case 'c': // Continue lines if (c0 == '+') { // Ignore line breaks continue_lines = 1; // Treat all lines as continued break_continues= 0; // Honor existing continues } else { // Respect line breaks continue_lines = 0; // Honor line/staff breaks } V3 "%s line breaks.\n",(continue_lines?"Ignore":"Honor") V; V3 "%s continues.\n",(break_continues?"Ignore":"Honor") V; continue; case 'I': make_index = (c0 == '+') ? 1 : 0; continue; case 'i': // Interactive interactive = (c0 == '+') ? 1 : 0; V3 "%snteractive.\n",(interactive?"I":"Not i") V; continue; case 'l': landscape = (c0 == '+') ? 1 : 0; continue; case 'n': // Print notes write_history = (c0 == '+') ? 1 : 0; V3 "%s notes.\n",(write_history?"Show":"Ignore") V; continue; case 'o': // Output V6 "%s: Output option.\n",F V; a = Opt_o(a,ac,av); continue; case 'x': // Print index numbers include_xrefs = (c0 == '+') ? 1 : 0; V3 "%s X index numbers.\n",(include_xrefs?"Show":"Ignore") V; continue; case 'T': s_field[nsel]=S_TITLE; sel_arg=1; V5 "sel_arg=%d s_field[%d]=%d=S_TITLE.\n",sel_arg,nsel,s_field[nsel] V; continue; case 'C': s_field[nsel]=S_COMPOSER; sel_arg=1; V5 "sel_arg=%d s_field[%d]=%d=S_COMPOSER.\n",sel_arg,nsel,s_field[nsel] V; continue; case 'R': s_field[nsel]=S_RHYTHM; sel_arg=1; V5 "sel_arg=%d s_field[%d]=%d=S_RHYTHM.\n",sel_arg,nsel,s_field[nsel] V; continue; case 'S': s_field[nsel]=S_SOURCE; sel_arg=1; V5 "sel_arg=%d s_field[%d]=%d=S_SOURCE.\n",sel_arg,nsel,s_field[nsel] V; continue; case 'm': if (!strcmp(av[a]+1,"maxv")) { if ((a==ac-1)||(av[a+1][0]=='-')) { rx("missing parameter for ",av[a]); } sscanf(av[++a],"%d",&maxVc); V2 "maxVc=%d.\n",maxVc V; if (maxVc > MAXV) { maxVc = MAXV; V2 "maxVc=%d [MAXV limit].\n",maxVc,MAXV V; } } elsif (!strcmp(av[a]+1,"maxs")) { if ((a==ac-1)||(av[a+1][0]=='-')) { rx("missing parameter for ",av[a]); } sscanf(av[++a],"%d",&maxSyms); V2 "maxSyms=%d.\n",maxSyms V; } continue; default: V3 "Opt \"%s\" ...\n",av[a] V; m = 1; // Char position within option string k = strlen(av[a]); // Length of option string while (m < k) { // Run down option string c = av[a][m]; // Treat each char as option V3 "Opt \"%s\" char %d='%c'...\n",av[a]+m,m,c V; if (strchr("vsdwmgtkqQDFYBVXO",c)) { /* flags with parameter.. */ V3 "Opt '%c' needs parameter.\n",c V; strcpy (aaa, &av[a][m+1]); if ((strlen(aaa)>0) && strchr("glO",c)) { /* no sticky arg */ fprintf(stderr,"+++ Incorrect usage of flag -%c\n", c); return 1; } got_value=1; /* check for value */ if (strlen(aaa)==0) { got_value=0; a++; if ((a>=ac) || (av[a][0]=='-')) a--; else { strcpy (aaa,av[a]); got_value=1; } } if (got_value && strchr("vskYB",c)) { /* check num args */ ok=1; for (j=0;j for flag -%c\n",aaa,c V; return 1; } } /* --- next ops require a value --- */ if (!got_value) { /* check value was given */ fprintf(stderr,"+++ Missing parameter after flag -%c\n", c); return 1; } if (c=='k') { sscanf(aaa,"%d",&barnums); break; } if (c=='Q') { sscanf(aaa,"%f",&playtempo); if (playtempo < 6) playtempo=6; break; } if (c=='q') { strcpy (au_qstr, aaa); break; } if (c=='V') { /* -V flag */ ok=1; strcpy (vcselstr, aaa); } if (c=='X') { /* -X flag */ ok=1; if (aaa[0]==',') { sscanf(aaa,",%f",&strict2); if (strict2<-0.001 || strict2>1.001) ok=0; } elsif (strchr(aaa,',')) { sscanf (aaa,"%f,%f",&strict1,&strict2); if (strict1<-0.001 || strict1>1.001) ok=0; if (strict2<-0.001 || strict2>1.001) ok=0; } else { sscanf(aaa,"%f",&strict1); if (strict1<-0.001 || strict1>1.001) ok=0; strict2=strict1; } if (!ok) { fprintf(stderr,"+++ Invalid parameter <%s> for flag -%c\n",aaa,c); return 1; } } if (c=='o') { /* -O flag */ if (!strcmp(aaa,"=")) { choose_outname=1; } else { getext (aaa,ext); if (strcmp(ext,"ps") && strcmp(ext,"eps") && strcmp(ext,"")) { fprintf(stderr,"Wrong extension for output file: %s\n", aaa); return 1; } strext (outf, aaa, "ps", 1); choose_outname=0; } } if (c=='B') { sscanf(aaa,"%d",&bars_per_line); continue_lines=0; } if (c=='t') strcpy(transpose,aaa); if (c=='v') sscanf(aaa,"%d",&vb); if (c=='s') sscanf(aaa,"%f",&scalefac); if (c=='d') { if (aaa[0]=='+' || aaa[0]=='-') dstaffsep = scan_u(aaa); else staffsep = scan_u(aaa); } if (c=='w') swidth = scan_u(aaa); if (c=='m') lmargin = scan_u(aaa); if (c=='D') strcpy (styd,aaa); if (c=='g') { if (abbrev(aaa,"shrink", 2)) gmode=G_SHRINK; elsif (abbrev(aaa,"stretch",2)) gmode=G_STRETCH; elsif (abbrev(aaa,"space", 2)) gmode=G_SPACE; elsif (abbrev(aaa,"fill", 2)) gmode=G_FILL; else { fprintf(stderr,"+++ Bad parameter for flag -g: %s\n",aaa); return 1; } } break; } else { V1 "Unknown flag: %c%c\n",c0,c V; return 1; } m++; } continue; } } } return 0; } /* ----- alloc_structs ----- */ /* Thanks to Henrik Norbeck for this */ void alloc_structs () { int j; sym = (Sym *)calloc(maxSyms, sizeof(Sym)); if (sym==NULL) rx("Out of memory",""); symv = (Sym **)calloc(maxVc, sizeof(Sym *)); if (symv==NULL) rx("Out of memory",""); for (j=0;j0) { strext(styf,styf,"fmt",1); j=read_fmt_file (styf, styd, &cfmt); if (j==0) { fprintf(stderr,"\n+++ Cannot open file: %s\n", styf); return 0; } strcpy(cfmt.name, styf); } if (verbose > 1) if (i || j) fprintf(stderr,"\n"); ops_into_fmt (&cfmt); make_font_list (&cfmt); sfmt=cfmt; dfmt=cfmt; V5 "%s: Done.\n",F V; return 1; } /* ----- tex_str: change string to take care of some tex-style codes --- */ /* Puts \ in front of ( and ) in case brackets are not balanced, interprets some TeX-type strings using ISOLatin1 encodings. Returns the length of the string as finally given out on paper. Also returns an estimate of the string width... */ int tex_str (str,s,wid) char *str; char s[]; float *wid; { char *F="tex_str"; char *cp, c; int base,add,m,n; char t[21]; float w; cp=str; strcpy(s,""); n=0; w=0; while (*cp != '\0') { if ((*cp=='(') || (*cp==')')) /* ( ) becomes \( \) */ {sprintf(t, "\\%c", *cp); strcat(s,t); w+=cwid('('); n++; } elsif (*cp=='\\') { // backslash sequences */ if ((m = *++cp) == '\0') break; add=0; // accented vowels */ if (*cp=='`') add=1; if (*cp=='\'') add=2; if (*cp=='^') add=3; if (*cp=='"') add=4; if (add) { if ((c = *++cp) == '\0') break; base=0; switch (*cp) { case 'a': base=340; if (add==4) add=5; break; case 'e': base=350; break; case 'i': base=354; break; case 'o': base=362; if (add==4) add=5; break; case 'u': base=371; break; case 'y': if (m == '\'') {base=374;} break; case 'A': base=300; if (add==4) add=5; break; case 'E': base=310; break; case 'I': base=314; break; case 'O': base=322; if (add==4) add=5; break; case 'U': base=331; break; case 'Y': if (m == '\'') {base=332;} break; } V5 "%s: Mark m=%02d='%c' c=%02d='%c' base=%d add=%d\n",F,m,m,c,c,base,add V; w+=cwid(*cp); if (base) {sprintf(t,"\\%d",base+add-1); strcat(s,t); n+=1; } else { switch (add) { case 1: sprintf(t,"\\221%c",*cp); strcat(s,t); n+=1; break; case 2: sprintf(t,"\\222%c",*cp); strcat(s,t); n+=1; break; case 3: sprintf(t,"\\223%c",*cp); strcat(s,t); n+=1; break; case 4: sprintf(t,"\\230%c",*cp); strcat(s,t); n+=1; break; } } } elsif (*cp==' ') /* \-space */ { strcat(s," "); w+=cwid(' '); n++; } elsif (*cp=='-') /* macron */ { strcat(s,"\\225"); } elsif (*cp=='=') /* macron */ { strcat(s,"\\225"); } elsif (*cp=='.') /* dot-accent */ { strcat(s,"\\227"); } elsif (*cp=='u') /* breve */ { strcat(s,"\\226"); } elsif (*cp=='v') /* hacek/caron */ { strcat(s,"\\237"); } elsif (*cp=='k') /* ogonek */ { strcat(s,"\\236"); } // elsif (*cp=='?') /* ring above */ // { strcat(s,"\\232"); }*/ // elsif (*cp=='?') /* double acute */ // { strcat(s,"\\235"); }*/ elsif (*cp=='d') /* croatian d */ { strcat(s,"\\001d"); n++; } elsif (*cp=='D') /* croatian D */ { strcat(s,"\\002D"); n++; } // elsif (*cp=='L') /* L-slash */ // { strcat(s,"\\326"); w+=cwid('L'); n++; } // elsif (*cp=='l') /* l-slash */ // { strcat(s,"\\367"); w+=cwid('t'); n++; } elsif (*cp=='O') /* O-slash */ { strcat(s,"\\330"); w+=cwid('O'); n++; } elsif (*cp=='o') /* o-slash */ { strcat(s,"\\370"); w+=cwid('o'); n++; } elsif((*cp=='s')&&(*(cp+1)=='s')) /* sz */ { cp++; strcat(s,"\\337"); w+=cwid('s'); n++; } elsif((*cp=='a')&&(*(cp+1)=='a')) /* a-ring */ { cp++; strcat(s,"\\345"); w+=cwid('a'); n++; } elsif((*cp=='A')&&(*(cp+1)=='A')) /* A-ring */ { cp++; strcat(s,"\\305"); w+=cwid('A'); n++; } elsif((*cp=='a')&&(*(cp+1)=='e')) /* ae */ { cp++; strcat(s,"\\346"); w+=1.5*cwid('a'); n++; } elsif((*cp=='A')&&(*(cp+1)=='E')) /* AE */ { cp++; strcat(s,"\\306"); w+=1.5*cwid('A'); n++; } elsif (*cp==',') { /* c-cedilla */ cp++; w+=cwid(*cp); if (*cp=='C') {strcat(s,"\\307"); n++;} elsif (*cp=='c') {strcat(s,"\\347"); n++;} else {sprintf(t,"\\233%c",*cp); strcat(s,t); n++;} } elsif (*cp=='c') { /* c-cedilla */ cp++; w+=cwid(*cp); if (*cp=='C') {strcat(s,"\\307"); n++;} elsif (*cp=='c') {strcat(s,"\\347"); n++;} else {sprintf(t,"%c",*cp); strcat(s,t); n++;} } elsif (*cp=='~') { /* n-twiddle */ cp++; w+=cwid(*cp); if (*cp=='N') { strcat(s,"\\321"); n++; } elsif (*cp=='n') { strcat(s,"\\361"); n++; } /* * cd: changed default behaviour in order to enable escaping of '~' * else { sprintf(t,"%c",*cp); strcat(s,t); n++; } */ /* mr: I don't see why escaping of ~ would be necessary, trying it as an accent else { sprintf(t,"~%c",*cp); strcat(s,t); n++; } */ else { sprintf(t,"\224%c",*cp); strcat(s,t); n++; } } else { // \-something-else; pass through sprintf(t,"\\%c",*cp); strcat(s,t); w += cwid('A'); n++; } } elsif (*cp=='{') // It looks like braces are stripped out ; elsif (*cp=='}') ; else { /* other characters: pass though */ sprintf(t,"%c",*cp); strcat(s,t); n++; w+=cwid(*cp); } cp++; } *wid = w; return n; } /* ----- put_str: output a string in postscript ----- */ void put_str(str) char *str; { char *F="put_str"; char s[801]; float w; tex_str(str,s,&w); PUT1("%s", s); } /* ----- set_font ----- */ void set_font (fp,font,add_bracket) FILE *fp; struct FONTSPEC font; int add_bracket; { int i,fnum; fnum=-1; for (i=0;i= 1) { if (outfnam && *outfnam) { m = get_file_size (outfnam); if (vb > 1 || pagenum > 1) fprintf(stderr,"Output written to %s (%d page%s, %d title%s)\n", outfnam, pagenum, (pagenum==1 ? "" : "s"), tunenum, (tunenum==1 ? "" : "s")); // m, (m==1 ? "" : "s")); } else { if (vb > 1 || pagenum > 1) fprintf(stderr,"Output written to stdout (%d page%s, %d title%s)\n", pagenum, (pagenum==1 ? "" : "s"), tunenum, (tunenum==1 ? "" : "s")); // m, (m==1 ? "" : "s")); } } file_open=0; file_initialized=0; } /* ----- open_output_file ------ */ void open_output_file (fnam,tstr) char fnam[],tstr[]; { char*F="open_output_file"; V6 "%s: Called with fnam=\"%s\" tstr=\"%s\"\n",F,fnam,tstr V; if (*fnam && !strcmp(fnam,outfnam)) { V6 "%s: Continue with same output file \"%s\".\n",F,outfnam V; return; } if (file_open) { V2 "%s: close_output_file()\n",F V; close_output_file(); } if (interactive) fprintf(stderr,"(open \"%s\")\n", fnam); if (use_stdout) { fout = stdout; V2 "%s: Output file is now stdout.\n",F V; } else { strcpy(outfnam, fnam); V6 "%s: Output file is now \"%s\"\n",F,outfnam V; if (outfnam[0]) { V6 "%s: Open output file \"%s\"\n",F,outfnam V; if ((fout = fopen (outfnam,"w")) == NULL) { rx("Cannot open output file ", outf); } } else { V1 "%s: No output file name.\n",F V; } } pagenum=0; tunenum=tnum1=tnum2=0; file_open=1; file_initialized=0; } /* ----- open_index_file ------- */ void open_index_file (fnam) char fnam[]; { char *F = "open_index_file"; V5 "%s: Open index file \"%s\"\n",F,fnam V; if ((findex = fopen (fnam,"w")) == NULL) rx ("Cannot open index file: ", fnam); index_initialized=0; } /* ----- close_index_file ------- */ void close_index_file () { if (vb>=8) fprintf(stderr,"Close index file\n"); close_index_page (findex); fclose (findex); } /* ----- add_to_text_block ----- */ void add_to_text_block (ln,add_final_nl) char ln[]; int add_final_nl; { char *c,*a; char word[81]; int nt,nl; nt=ntxt; c=ln; for (;;) { while (*c==' ') c++; if (*c=='\0') break; a=word; while ((*c!=' ')&&(*c!='\0')&&(*c!='\n')) { nl=0; if ((*c=='\\')&&(*(c+1)=='\\')) { nl=1; c+=2; break; } *a=*c; c++; a++; } *a='\0'; if (strlen(word)>MAXWLEN) { word[MAXWLEN-1]='\0'; fprintf(stderr,"+++ Insanely long word truncated to %d chars: %s\n", MAXWLEN-1,word); } if (nt>=MAXNTEXT) { fprintf(stderr,"\n+++ Line %d: %s\n", linenum,ln); rx("Text overflow; increase MAXNTEXT and recompile.",""); } if (strlen(word)>0) { strcpy(txt[nt],word); nt++; } if (nl) { strcpy(txt[nt],"$$NL$$"); nt++; } } if (add_final_nl) { strcpy(txt[nt],"$$NL$$"); nt++; } ntxt=nt; } /* ----- write_text_block ----- */ void write_text_block (fp,job) FILE *fp; int job; { char *F = "write_text_block"; int i,i1,i2,ntline,nc,mc,nbreak; float textwidth,ftline,ftline0,swfac,baseskip,parskip; float wwidth,wtot,spw; char str[81]; if (ntxt<=0) return; baseskip = cfmt.textfont.size * cfmt.lineskipfac; parskip = cfmt.textfont.size * cfmt.parskipfac; set_font_str (page_init,cfmt.textfont); /* estimate text widths.. ok for T-R, wild guess for other fonts */ swfac=1.0; if (strstr(cfmt.textfont.name,"Times-Roman")) swfac=1.00; if (strstr(cfmt.textfont.name,"Times-Courier")) swfac=1.05; if (strstr(cfmt.textfont.name,"Helvetica")) swfac=1.10; if (strstr(cfmt.textfont.name,"Helvetica-Bold")) swfac=1.15; if (strstr(cfmt.textfont.name,"Palatino")) swfac=1.10; swfac=1.0; spw=cwid(' '); PUT1("/LF {0 %.1f rmoveto} bind def\n",-baseskip) /* output by pieces, separate at newline token */ i1=0; while (i1=i1;i--) { mc+=tex_str(txt[i],str,&wwidth)+1; wtot+=wwidth+spw; nc+=strlen(str)+2; if (nc>=72) {nc=0; PUT0("\n") } PUT1 ("(%s)",str); } if (job==RAGGED) { PUT1(" %.1f P1\n",cfmt.staffwidth) } else { PUT1(" %.1f P2\n",cfmt.staffwidth) /* first estimate: (total textwidth)/(available width) */ textwidth=wtot*swfac*cfmt.textfont.size; } if (strstr(cfmt.textfont.name,"Courier")) { textwidth=0.60*mc*cfmt.textfont.size; } ftline0=textwidth/cfmt.staffwidth; /* revised estimate: assume some chars lost at each line end */ nbreak=ftline0; textwidth=textwidth+5*nbreak*cwid('a')*swfac*cfmt.textfont.size; ftline=textwidth/cfmt.staffwidth; ntline=ftline+1.0; if (vb>=10) fprintf(stderr,"first estimate %.2f, revised %.2f\n", ftline0,ftline); if (vb >= 10) { fprintf(stderr,"Output %d word%s, about %.2f lines (fac %.2f)\n", i2-i1, i2-i1==1?"":"s", ftline,swfac); } Bskip((ntline-1)*baseskip); } buffer_eob (fp); /* next line to allow pagebreak after each text "line" */ /* if (!epsf && !within_tune) write_buffer(fp); */ i1=i2+1; } Bskip(parskip); buffer_eob (fp); /* next line to allow pagebreak after each paragraph */ if (!epsf && !within_tune) write_buffer(fp); strcpy (page_init,""); return; } /* ----- put_words ------- */ void put_words (fp) FILE *fp; { char *F = "put_words"; int i,nw,n; char str[81]; char *p,*q; set_font (fp,cfmt.wordsfont, 0); set_font_str (page_init,cfmt.wordsfont); n=0; for (i=0;i0)) buffer_eob(fp); if (nw>0) { if (strlen(str)>0) { PUT0("45 0 M (") put_str (str); PUT0(") lshow\n") } if (strlen(p)>0) { PUT0("50 0 M (") put_str (p); PUT0(") rshow\n") } } } } buffer_eob (fp); strcpy (page_init,""); } /* ----- put_text ------- */ void put_text (fp, type, str) FILE *fp; int type; char str[]; { int i,n; float baseskip,parskip; n=0; for (i=0;i0) { Bskip(baseskip); PUT0("0 0 M (Rhythm: ") put_str (info.rhyth); PUT0(") show\n") Bskip(parskip); } bookskip = 0.5; for (i=0; i0) { Bskip(bookskip*CM); bookskip = 0.3; PUT0("0 0 M (Book: ") put_str(info.book[i]); PUT0(") show\n") } Bskip(parskip); } if (strlen(info.src)>0) { Bskip(0.5*CM); PUT0("0 0 M (Source: ") put_str (info.src); PUT0(") show\n") Bskip(parskip); } put_text (fp, TEXT_D, "Discography: "); // put_text (fp, TEXT_N, "Notes: "); put_text (fp, TEXT_N, ""); put_text (fp, TEXT_Z, "Transcription: "); ok=0; for (i=0;i15) fprintf(stderr,"write inside title <%s>\n", t); if (strlen(t)==0) return; Bskip(cfmt.subtitlefont.size+0.2*CM); set_font (fp, cfmt.subtitlefont, 0); if (cfmt.titlecaps) cap_str(t); PUT0(" (") put_str (t); if (cfmt.titleleft) { PUT0(") 0 0 M rshow\n") } else { PUT1(") %.1f 0 M cshow\n", cfmt.staffwidth/2) } Bskip(cfmt.musicspace+0.2*CM); } /* ----- write_tunetop ----- */ void write_tunetop(fp) FILE *fp; { PUT2("\n\n%% --- tune %d %s\n", tunenum+1, info.title) if (!epsf) Bskip(cfmt.topspace); } /* ----- write_tempo ----- */ void write_tempo(fp,tempo,meter) FILE *fp; char tempo[]; Msig meter; { char *F = "write_tempo"; char *r, *q; char text[STRL]; int top,bot,value,len,i,err,fac,dig,div; Sym s; float stem,dotx,doty,sc,dx; if (vb>15) fprintf(stderr,"write tempo <%s>\n", info.tempo); r=tempo; set_font (fp,cfmt.tempofont,0); PUT0(" 18 0 M\n") for (;;) { V6 "%s: r=\"%s\"\n",F,r V; while (*r==' ') r++; /* skip blanks */ if (*r=='\0') break; Q = r; // Make sure this is defined, for syntax() calls if (*r=='"') { /* write string */ V6 "%s: r=\"%s\" (text)\n",F,r V; r++; q=text; while (*r!='"' && *r!='\0') { *q=*r; r++; q++; } if (*r=='"') r++; *q='\0'; if (strlen(text)>0) { PUT0("6 0 rmoveto (") put_str (text); PUT0(") rshow 12 0 \n") } } else { /* write tempo denotation */ V6 "%s: r=\"%s\"\n",F,r V; q=text; while (*r!=' ' && *r!='\0') { *q=*r; r++; q++; } *q='\0'; q=text; len=QUARTER; value=0; err=0; if (strchr(q,'=')) { if (*q=='C' || *q=='c') { V6 "%s: Found '%c' (C)\n",F,*q V; q++; len = meter.dlen; V6 "%s: len=%d.\n",F,len V; div = 0; if (*q=='/') { div=1; q++; } V6 "%s: len=%d div=%d.\n",F,len,div V; fac=0; while (isdigit(*q)) { dig = *q - '0'; fac = 10 * fac + dig; q++; } V6 "%s: len=%d div=%d fac=%d.\n",F,len,div,fac V; if (div) { if (fac==0) fac=2; if (len%fac) fprintf(stderr,"Bad length divisor in tempo: %s", text); len=len/fac; V6 "%s: len/fac len=%d div=%d fac=%d.\n",F,len,div,fac V; } elsif (fac>0) { len=len*fac; V6 "%s: len*fac len=%d div=%d fac=%d.\n",F,len,div,fac V; } if (*q!='=') err=1; q++; if (!isdigit(*q)) err=1; sscanf(q,"%d", &value); } elsif (isdigit(*q)) { V4 "%s: Digit \"%s\"\n",F,q V; if (sscanf(q,"%d/%d=%d", &top,&bot,&value) == 3) { V4 "%s: 3-term tempo top=%d bot=%d value=%d.\n",F,top,bot,value V; len = (BASE * top) / bot; } elsif (i = sscanf(q,"%d/%d",&top,&bot)) { value = 0; V4 "%s: 2-term tempo top=%d bot=%d value=%d.\n",F,top,bot,value V; len = (BASE * top) / bot; } else { err=1; } } else { err=1; } } else { if (sscanf(q,"%d/%d", &top,&bot) == 2) { value = 0; V4 "%s: 2-term tempo top=%d bot=%d value=%d.\n",F,top,bot,value V; len=(BASE*top)/bot; } elsif (isdigit(*q)) { sscanf(q,"%d", &value); top = bot = 0; V4 "%s: 1-term tempo top=%d bot=%d value=%d.\n",F,top,bot,value V; } else { err=1; } } V4 "%s: top=%d bot=%d value=%d.\n",F,top,bot,value V; if (err) { fprintf(stderr,"\n+++ invalid tempo specifier: %s\n", text); } else { /* draw note=value */ s.len=len; identify_note(&s,r); sc=0.55*cfmt.tempofont.size/10.0; PUT2("gsave %.2f %.2f scale 15 3 rmoveto currentpoint\n", sc,sc) if (s.head==H_OVAL) PUT0("HD") if (s.head==H_EMPTY) PUT0("Hd") if (s.head==H_FULL) PUT0("hd") dx=4.0; if (s.dots) { dotx=8; doty=0; if (s.flags>0) dotx=dotx+4; if (s.head==H_EMPTY) dotx=dotx+1; if (s.head==H_OVAL) dotx=dotx+2; for (i=0;i 1) stem += 3.0 * (s.flags - 1); V1 "%s: WHOLE=%d s.flags=%d stem=%.1f s.len=%d\n",F,WHOLE,s.flags,stem,s.len V; if (s.len < WHOLE) PUT1(" %.1f su",stem) if (s.flags > 0) PUT2(" %.1f f%du",stem,s.flags) if ((s.flags>0) && (dx<6.0)) dx=6.0; if (value > 0) { dx = (dx + 18) * sc; V4 "%s: PUT value=%d at dx=%.1f\n",F,value,dx V; PUT2(" grestore %.2f 0 rmoveto (=%d) rshow\n", dx,value) } else { dx = (dx + 10) * sc; PUT1(" grestore %.2f 0 rmoveto () rshow\n", dx) } } } } } /* ----- write_inside_tempo ----- */ void write_inside_tempo (fp) FILE *fp; { Bskip(cfmt.partsfont.size); write_tempo(fp,info.tempo,voice[ivc].meter); Bskip(0.1*CM); } /* ----- write_heading ----- */ void write_heading (fp) FILE *fp; { char *F = "write_heading"; float lwidth,down1,down2; int i,ncl; char t[201]; lwidth=cfmt.staffwidth; /* write the main title */ Bskip(cfmt.titlefont.size+cfmt.titlespace); set_font (fp,cfmt.titlefont,1); if (cfmt.withxrefs) PUT1("%d. ", xrefnum) strcpy (t,info.title); if (cfmt.titlecaps) cap_str(t); put_str (t); if (cfmt.titleleft) PUT0(") 0 0 M rshow\n") else PUT1(") %.1f 0 M cshow\n", lwidth/2) /* write second title */ if (numtitle>=2) { Bskip(cfmt.subtitlespace+cfmt.subtitlefont.size); set_font (fp,cfmt.subtitlefont,1); strcpy (t,info.title2); if (cfmt.titlecaps) cap_str(t); put_str (t); if (cfmt.titleleft) PUT0(") 0 0 M rshow\n") else PUT1(") %.1f 0 M cshow\n", lwidth/2) } /* write third title */ if (numtitle>=3) { Bskip(cfmt.subtitlespace+cfmt.subtitlefont.size); set_font (fp,cfmt.subtitlefont,1); strcpy (t,info.title3); if (cfmt.titlecaps) cap_str(t); put_str (t); if (cfmt.titleleft) PUT0(") 0 0 M rshow\n") else PUT1(") %.1f 0 M cshow\n", lwidth/2) } /* write fourth title */ if (numtitle>=4) { Bskip(cfmt.subtitlespace+cfmt.subtitlefont.size); set_font (fp,cfmt.subtitlefont,1); strcpy (t,info.title4); if (cfmt.titlecaps) cap_str(t); put_str (t); if (cfmt.titleleft) PUT0(") 0 0 M rshow\n") else PUT1(") %.1f 0 M cshow\n", lwidth/2) } /* write fifth title */ if (numtitle>=5) { Bskip(cfmt.subtitlespace+cfmt.subtitlefont.size); set_font (fp,cfmt.subtitlefont,1); strcpy (t,info.title5); if (cfmt.titlecaps) cap_str(t); put_str (t); if (cfmt.titleleft) PUT0(") 0 0 M rshow\n") else PUT1(") %.1f 0 M cshow\n", lwidth/2) } /* write sixth title */ if (numtitle>=6) { Bskip(cfmt.subtitlespace+cfmt.subtitlefont.size); set_font (fp,cfmt.subtitlefont,1); strcpy (t,info.title6); if (cfmt.titlecaps) cap_str(t); put_str (t); if (cfmt.titleleft) PUT0(") 0 0 M rshow\n") else PUT1(") %.1f 0 M cshow\n", lwidth/2) } /* write composer, origin */ if ((info.ncomp>0) || (strlen(info.orig)>0)) { set_font (fp,cfmt.composerfont,0); Bskip(cfmt.composerspace); ncl=info.ncomp; if ((strlen(info.orig)>0) && (ncl<1)) ncl=1; for (i=0;i0)) { put_str (" ("); put_str (info.orig); put_str (")"); } PUT0 (") lshow\n"); } down1=cfmt.composerspace+cfmt.musicspace+ncl*cfmt.composerfont.size; } else { Bskip(cfmt.composerfont.size+cfmt.composerspace); down1=cfmt.composerspace+cfmt.musicspace+cfmt.composerfont.size; } Bskip(cfmt.musicspace); /* decide whether we need extra shift for parts and tempo */ down2=cfmt.composerspace+cfmt.musicspace; if (strlen(info.parts)>0) down2=down2+cfmt.partsspace+cfmt.partsfont.size; if (strlen(info.tempo)>0) down2=down2+cfmt.partsspace+cfmt.partsfont.size; if (down2>down1) Bskip(down2-down1); /* write tempo and parts */ if (strlen(info.parts)>0 || strlen(info.tempo)>0) { if (strlen(info.tempo)>0) { Bskip(-0.2*CM); PUT1 (" %.2f 0 T ", cfmt.indent*cfmt.scale) write_tempo(fp, info.tempo, default_meter); PUT1 (" %.2f 0 T ", -cfmt.indent*cfmt.scale) Bskip(-cfmt.tempofont.size); } if (strlen(info.parts)>0) { Bskip(-cfmt.partsspace); set_font (fp,cfmt.partsfont,0); PUT0("0 0 M (") put_str (info.parts); PUT0(") rshow\n") Bskip(cfmt.partsspace); } if (strlen(info.tempo)>0) Bskip(cfmt.tempofont.size+0.3*CM); } } /* ----- write_parts ----- */ void write_parts (fp) FILE *fp; { char *F = "write_parts"; if (strlen(info.parts)>0) { Bskip(cfmt.partsfont.size); set_font (fp, cfmt.partsfont,0); PUT0("0 0 M (") put_str (info.parts); PUT0(") rshow\n") Bskip(cfmt.partsspace); } }