2 * Formatting functions.
4 * This file is part of abcm2ps.
6 * Copyright (C) 1998-2008 Jean-François Moine
7 * Adapted from abc2ps, Copyright (C) 1996,1997 Michael Methfessel
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 struct FORMAT cfmt
; /* current format for output */
35 char font_enc
[MAXFONTS
]; /* font encoding */
36 static char def_font_enc
[MAXFONTS
]; /* default font encoding */
37 static char *fontnames
[MAXFONTS
]; /* list of font names */
38 static char used_font
[MAXFONTS
]; /* used fonts */
39 static int nfontnames
;
40 static float staffwidth
;
43 static struct format
{
47 #define FORMAT_I 0 /* int */
48 #define FORMAT_R 1 /* float */
49 #define FORMAT_F 2 /* font spec */
50 #define FORMAT_U 3 /* float with unit */
51 #define FORMAT_B 4 /* boolean */
52 #define FORMAT_S 5 /* string */
53 char subtype
; /* special cases - see code */
56 {"abc2pscompat", &cfmt
.abc2pscompat
, FORMAT_B
, 0},
57 {"alignbars", &cfmt
.alignbars
, FORMAT_I
, 0},
58 {"aligncomposer", &cfmt
.aligncomposer
, FORMAT_I
, 0},
59 {"autoclef", &cfmt
.autoclef
, FORMAT_B
, 0},
60 {"annotationfont", &cfmt
.font_tb
[ANNOTATIONFONT
], FORMAT_F
, 0},
61 {"barsperstaff", &cfmt
.barsperstaff
, FORMAT_I
, 0},
62 {"botmargin", &cfmt
.botmargin
, FORMAT_U
, 0},
63 {"breakoneoln", &cfmt
.breakoneoln
, FORMAT_B
, 0},
64 {"bstemdown", &cfmt
.bstemdown
, FORMAT_B
, 0},
65 {"combinevoices", &cfmt
.combinevoices
, FORMAT_B
, 0},
66 {"comball", &cfmt
.comball
, FORMAT_B
, 0},
67 {"composerfont", &cfmt
.font_tb
[COMPOSERFONT
], FORMAT_F
, 0},
68 {"composerspace", &cfmt
.composerspace
, FORMAT_U
, 0},
69 {"contbarnb", &cfmt
.contbarnb
, FORMAT_B
, 0},
70 {"continueall", &cfmt
.continueall
, FORMAT_B
, 0},
71 {"dateformat", &cfmt
.dateformat
, FORMAT_S
, 0},
72 {"dynalign", &cfmt
.dynalign
, FORMAT_B
, 0},
73 {"encoding", &cfmt
.encoding
, FORMAT_I
, 1},
74 {"exprabove", &cfmt
.exprabove
, FORMAT_B
, 0},
75 {"exprbelow", &cfmt
.exprbelow
, FORMAT_B
, 0},
76 {"footer", &cfmt
.footer
, FORMAT_S
, 0},
77 {"footerfont", &cfmt
.font_tb
[FOOTERFONT
], FORMAT_F
, 0},
78 {"freegchord", &cfmt
.freegchord
, FORMAT_B
, 0},
79 {"flatbeams", &cfmt
.flatbeams
, FORMAT_B
, 0},
80 {"gchordbox", &cfmt
.gchordbox
, FORMAT_B
, 0},
81 {"gchordfont", &cfmt
.font_tb
[GCHORDFONT
], FORMAT_F
, 3},
82 {"graceslurs", &cfmt
.graceslurs
, FORMAT_B
, 0},
83 {"gracespace", &cfmt
.gracespace
, FORMAT_I
, 5},
84 {"header", &cfmt
.header
, FORMAT_S
, 0},
85 {"headerfont", &cfmt
.font_tb
[HEADERFONT
], FORMAT_F
, 0},
86 {"historyfont", &cfmt
.font_tb
[HISTORYFONT
], FORMAT_F
, 0},
87 {"hyphencont", &cfmt
.hyphencont
, FORMAT_B
, 0},
88 {"indent", &cfmt
.indent
, FORMAT_U
, 0},
89 {"infofont", &cfmt
.font_tb
[INFOFONT
], FORMAT_F
, 0},
90 {"infoline", &cfmt
.infoline
, FORMAT_B
, 0},
91 {"infospace", &cfmt
.infospace
, FORMAT_U
, 0},
92 {"landscape", &cfmt
.landscape
, FORMAT_B
, 0},
93 {"leftmargin", &cfmt
.leftmargin
, FORMAT_U
, 0},
94 {"lineskipfac", &cfmt
.lineskipfac
, FORMAT_R
, 0},
95 {"maxshrink", &cfmt
.maxshrink
, FORMAT_R
, 0},
96 {"maxstaffsep", &cfmt
.maxstaffsep
, FORMAT_U
, 0},
97 {"maxsysstaffsep", &cfmt
.maxsysstaffsep
, FORMAT_U
, 0},
98 {"measurebox", &cfmt
.measurebox
, FORMAT_B
, 0},
99 {"measurefirst", &cfmt
.measurefirst
, FORMAT_I
, 2},
100 {"measurefont", &cfmt
.font_tb
[MEASUREFONT
], FORMAT_F
, 2},
101 {"measurenb", &cfmt
.measurenb
, FORMAT_I
, 0},
102 {"musiconly", &cfmt
.musiconly
, FORMAT_B
, 0},
103 {"musicspace", &cfmt
.musicspace
, FORMAT_U
, 0},
104 {"notespacingfactor", &cfmt
.notespacingfactor
, FORMAT_R
, 1},
105 {"oneperpage", &cfmt
.oneperpage
, FORMAT_B
, 0},
106 {"pageheight", &cfmt
.pageheight
, FORMAT_U
, 0},
107 {"pagewidth", &cfmt
.pagewidth
, FORMAT_U
, 0},
108 {"parskipfac", &cfmt
.parskipfac
, FORMAT_R
, 0},
109 {"partsbox", &cfmt
.partsbox
, FORMAT_B
, 0},
110 {"partsfont", &cfmt
.font_tb
[PARTSFONT
], FORMAT_F
, 1},
111 {"partsspace", &cfmt
.partsspace
, FORMAT_U
, 0},
112 {"printparts", &cfmt
.printparts
, FORMAT_B
, 0},
113 {"printtempo", &cfmt
.printtempo
, FORMAT_B
, 0},
114 {"repeatfont", &cfmt
.font_tb
[REPEATFONT
], FORMAT_F
, 0},
115 {"rightmargin", &cfmt
.rightmargin
, FORMAT_U
, 0},
116 {"scale", &cfmt
.scale
, FORMAT_R
, 0},
117 {"setdefl", &cfmt
.setdefl
, FORMAT_B
, 0},
118 {"setfont-1", &cfmt
.font_tb
[1], FORMAT_F
, 0},
119 {"setfont-2", &cfmt
.font_tb
[2], FORMAT_F
, 0},
120 {"setfont-3", &cfmt
.font_tb
[3], FORMAT_F
, 0},
121 {"setfont-4", &cfmt
.font_tb
[4], FORMAT_F
, 0},
123 # error Bad number of user fonts
125 {"shifthnote", &cfmt
.shiftunisson
, FORMAT_B
, 0}, /*to remove*/
126 {"shiftunisson", &cfmt
.shiftunisson
, FORMAT_B
, 0},
127 {"slurheight", &cfmt
.slurheight
, FORMAT_R
, 0},
128 {"splittune", &cfmt
.splittune
, FORMAT_B
, 0},
129 {"squarebreve", &cfmt
.squarebreve
, FORMAT_B
, 0},
130 {"staffnonote", &cfmt
.staffnonote
, FORMAT_B
, 0},
131 {"staffsep", &cfmt
.staffsep
, FORMAT_U
, 0},
132 {"staffwidth", &staffwidth
, FORMAT_U
, 1},
133 {"stemheight", &cfmt
.stemheight
, FORMAT_R
, 0},
134 {"straightflags", &cfmt
.straightflags
, FORMAT_B
, 0},
135 {"stretchlast", &cfmt
.stretchlast
, FORMAT_B
, 0},
136 {"stretchstaff", &cfmt
.stretchstaff
, FORMAT_B
, 0},
137 {"subtitlefont", &cfmt
.font_tb
[SUBTITLEFONT
], FORMAT_F
, 0},
138 {"subtitlespace", &cfmt
.subtitlespace
, FORMAT_U
, 0},
139 {"sysstaffsep", &cfmt
.sysstaffsep
, FORMAT_U
, 0},
140 {"tempofont", &cfmt
.font_tb
[TEMPOFONT
], FORMAT_F
, 0},
141 {"textfont", &cfmt
.font_tb
[TEXTFONT
], FORMAT_F
, 0},
142 {"textoption", &cfmt
.textoption
, FORMAT_I
, 4},
143 {"textspace", &cfmt
.textspace
, FORMAT_U
, 0},
144 {"titlecaps", &cfmt
.titlecaps
, FORMAT_B
, 0},
145 {"titlefont", &cfmt
.font_tb
[TITLEFONT
], FORMAT_F
, 0},
146 {"titleformat", &cfmt
.titleformat
, FORMAT_S
, 0},
147 {"titleleft", &cfmt
.titleleft
, FORMAT_B
, 0},
148 {"titlespace", &cfmt
.titlespace
, FORMAT_U
, 0},
149 {"titletrim", &cfmt
.titletrim
, FORMAT_B
, 0},
150 {"timewarn", &cfmt
.timewarn
, FORMAT_B
, 0},
151 {"topmargin", &cfmt
.topmargin
, FORMAT_U
, 0},
152 {"topspace", &cfmt
.topspace
, FORMAT_U
, 0},
153 {"tuplets", &cfmt
.tuplets
, FORMAT_I
, 3},
154 {"vocalabove", &cfmt
.vocalabove
, FORMAT_B
, 0},
155 {"vocalfont", &cfmt
.font_tb
[VOCALFONT
], FORMAT_F
, 0},
156 {"vocalspace", &cfmt
.vocalspace
, FORMAT_U
, 0},
157 {"voicefont", &cfmt
.font_tb
[VOICEFONT
], FORMAT_F
, 0},
158 {"withxrefs", &cfmt
.withxrefs
, FORMAT_B
, 0},
159 {"wordsfont", &cfmt
.font_tb
[WORDSFONT
], FORMAT_F
, 0},
160 {"wordsspace", &cfmt
.wordsspace
, FORMAT_U
, 0},
161 {"writehistory", &cfmt
.writehistory
, FORMAT_B
, 0},
162 {0, 0, 0, 0} /* end of table */
165 static char *enc_name
[20] = {
167 "iso-8859-1", /* 1 */
168 "iso-8859-2", /* 2 */
169 "iso-8859-3", /* 3 */
170 "iso-8859-4", /* 4 */
171 "iso-8859-9", /* 5 (Latin5) */
172 "iso-8859-10", /* 6 (Latin6) */
173 "native", /* 7 = ENC_NATIVE */
179 /* -- search a font and add it if not yet defined -- */
180 static int get_font(char *fname
, int encoding
)
184 /* get or set the default encoding */
185 for (fnum
= nfontnames
; --fnum
>= 0; )
186 if (strcmp(fname
, fontnames
[fnum
]) == 0) {
188 encoding
= def_font_enc
[fnum
];
189 if (encoding
== font_enc
[fnum
])
190 return fnum
; /* font found */
192 for ( ; --fnum
>= 0; )
193 if (strcmp(fname
, fontnames
[fnum
]) == 0
194 && encoding
== font_enc
[fnum
])
198 if (nfontnames
>= MAXFONTS
) {
199 error(1, 0, "Too many fonts");
202 if (file_initialized
)
204 "Cannot have a new font when the output file is opened");
206 fontnames
[fnum
] = strdup(fname
);
208 encoding
= cfmt
.encoding
;
209 font_enc
[fnum
] = encoding
;
213 /* -- set a dynamic font -- */
214 static int dfont_set(struct FONTSPEC
*f
)
218 for (i
= FONT_DYN
; i
< cfmt
.ndfont
; i
++) {
219 if (cfmt
.font_tb
[i
].fnum
== f
->fnum
220 && cfmt
.font_tb
[i
].size
== f
->size
)
223 if (i
>= FONT_MAX
- 1) {
224 error(1, 0, "Too many dynamic fonts");
227 memcpy(&cfmt
.font_tb
[i
], f
, sizeof cfmt
.font_tb
[0]);
232 /* -- define a font -- */
233 static void fontspec(struct FONTSPEC
*f
,
239 f
->fnum
= get_font(name
, encoding
);
240 else name
= fontnames
[f
->fnum
];
243 if (strncmp(name
, "Times", 5) == 0) {
244 if (strcmp(name
, "Times-Bold") == 0)
246 } else if (strcmp(name
, "Helvetica-Bold") == 0)
248 else if (strncmp(name
, "Helvetica", 9) == 0
249 || strncmp(name
, "Palatino", 8) == 0)
251 else if (strncmp(name
, "Courier", 7) == 0)
253 else f
->swfac
*= 1.2; /* unknown font */
254 if (f
== &cfmt
.font_tb
[GCHORDFONT
])
255 cfmt
.gcf
= dfont_set(f
);
256 else if (f
== &cfmt
.font_tb
[ANNOTATIONFONT
])
257 cfmt
.anf
= dfont_set(f
);
258 else if (f
== &cfmt
.font_tb
[VOCALFONT
])
259 cfmt
.vof
= dfont_set(f
);
262 /* -- output the encodings -- */
263 void define_encodings(void)
268 for (i
= 0; i
< nfontnames
; i
++) {
270 enc
|= 1 << font_enc
[i
];
276 define_encoding(i
, enc_name
[i
]);
281 /* -- output the font definitions with their encodings -- */
282 void define_fonts(void)
286 for (i
= 0; i
< nfontnames
; i
++) {
288 define_font(fontnames
[i
], i
, font_enc
[i
]);
292 /* -- mark the used fonts -- */
293 void make_font_list(void)
298 used_font
[f
->font_tb
[ANNOTATIONFONT
].fnum
] = 1;
299 used_font
[f
->font_tb
[COMPOSERFONT
].fnum
] = 1;
300 used_font
[f
->font_tb
[FOOTERFONT
].fnum
] = 1;
301 used_font
[f
->font_tb
[GCHORDFONT
].fnum
] = 1;
302 used_font
[f
->font_tb
[HEADERFONT
].fnum
] = 1;
303 used_font
[f
->font_tb
[HISTORYFONT
].fnum
] = 1;
304 used_font
[f
->font_tb
[INFOFONT
].fnum
] = 1;
305 used_font
[f
->font_tb
[MEASUREFONT
].fnum
] = 1;
306 used_font
[f
->font_tb
[PARTSFONT
].fnum
] = 1;
307 used_font
[f
->font_tb
[REPEATFONT
].fnum
] = 1;
308 used_font
[f
->font_tb
[SUBTITLEFONT
].fnum
] = 1;
309 used_font
[f
->font_tb
[TEMPOFONT
].fnum
] = 1;
310 used_font
[f
->font_tb
[TEXTFONT
].fnum
] = 1;
311 used_font
[f
->font_tb
[TITLEFONT
].fnum
] = 1;
312 used_font
[f
->font_tb
[VOCALFONT
].fnum
] = 1;
313 used_font
[f
->font_tb
[VOICEFONT
].fnum
] = 1;
314 used_font
[f
->font_tb
[WORDSFONT
].fnum
] = 1;
317 /* -- set the name of an information header type -- */
319 * <letter> [ <possibly quoted string> ]
320 * this information is kept in the 'I' information */
321 static void set_infoname(char *p
)
323 struct SYMBOL
*s
, *prev
;
331 if (s
->as
.text
[0] == *p
)
336 if (p
[1] == '\0') { /* if delete */
338 if ((prev
->next
= s
->next
) != 0)
339 prev
->next
->prev
= prev
;
343 old_lvl
= lvlarena(0);
345 s
= (struct SYMBOL
*) getarena(sizeof *s
);
346 memset(s
, 0, sizeof *s
);
354 s
->as
.text
= (char *) getarena(strlen(p
) + 1);
355 strcpy(s
->as
.text
, p
);
359 /* -- set the default format -- */
360 void set_format(void)
365 memset(f
, 0, sizeof *f
);
366 f
->pageheight
= PAGEHEIGHT
;
367 f
->pagewidth
= PAGEWIDTH
;
368 f
->leftmargin
= MARGIN
;
369 f
->rightmargin
= MARGIN
;
370 f
->topmargin
= 1.0 CM
;
371 f
->botmargin
= 1.0 CM
;
372 f
->topspace
= 0.8 CM
;
373 f
->titlespace
= 0.2 CM
;
374 f
->subtitlespace
= 0.1 CM
;
375 f
->composerspace
= 0.2 CM
;
376 f
->musicspace
= 0.2 CM
;
377 f
->partsspace
= 0.3 CM
;
378 f
->staffsep
= 46.0 PT
;
379 f
->sysstaffsep
= 34.0 PT
;
380 f
->maxstaffsep
= 2000.0 PT
;
381 f
->maxsysstaffsep
= 2000.0 PT
;
382 f
->vocalspace
= 23.0 PT
;
383 f
->textspace
= 0.5 CM
;
389 f
->lineskipfac
= 1.1;
400 f
->aligncomposer
= A_RIGHT
;
401 f
->notespacingfactor
= 1.414;
402 f
->stemheight
= STEM
;
403 f
->dateformat
= strdup("\\%b \\%e, \\%Y \\%H:\\%M");
404 f
->gracespace
= (65 << 16) | (80 << 8) | 120; /* left-inside-right - unit 1/10 pt */
405 f
->textoption
= T_LEFT
;
406 f
->ndfont
= FONT_DYN
;
407 fontspec(&f
->font_tb
[ANNOTATIONFONT
], "Helvetica", 0, 12.0);
408 fontspec(&f
->font_tb
[COMPOSERFONT
], "Times-Italic", 0, 14.0);
409 fontspec(&f
->font_tb
[FOOTERFONT
], "Times-Roman", 0, 12.0); /* not scaled */
410 fontspec(&f
->font_tb
[GCHORDFONT
], "Helvetica", 0, 12.0);
411 fontspec(&f
->font_tb
[HEADERFONT
], "Times-Roman", 0, 12.0); /* not scaled */
412 fontspec(&f
->font_tb
[HISTORYFONT
], "Times-Roman", 0, 16.0);
413 fontspec(&f
->font_tb
[INFOFONT
], "Times-Italic", 0, 14.0); /* same as composer by default */
414 fontspec(&f
->font_tb
[MEASUREFONT
], "Times-Italic", 0, 14.0);
415 fontspec(&f
->font_tb
[PARTSFONT
], "Times-Roman", 0, 15.0);
416 fontspec(&f
->font_tb
[REPEATFONT
], "Times-Roman", 0, 13.0);
417 fontspec(&f
->font_tb
[SUBTITLEFONT
], "Times-Roman", 0, 16.0);
418 fontspec(&f
->font_tb
[TEMPOFONT
], "Times-Bold", 0, 15.0);
419 fontspec(&f
->font_tb
[TEXTFONT
], "Times-Roman", 0, 16.0);
420 fontspec(&f
->font_tb
[TITLEFONT
], "Times-Roman", 0, 20.0);
421 fontspec(&f
->font_tb
[VOCALFONT
], "Times-Bold", 0, 13.0);
422 fontspec(&f
->font_tb
[VOICEFONT
], "Times-Bold", 0, 13.0);
423 fontspec(&f
->font_tb
[WORDSFONT
], "Times-Roman", 0, 16.0);
424 set_infoname("R \"Rhythm: \"");
425 set_infoname("B \"Book: \"");
426 set_infoname("S \"Source: \"");
427 set_infoname("D \"Discography: \"");
428 set_infoname("N \"Notes: \"");
429 set_infoname("Z \"Transcription: \"");
430 set_infoname("H \"History: \"");
433 /* -- print the current format -- */
434 void print_format(void)
437 static char yn
[2][5]={"no","yes"};
439 for (fd
= format_tb
; fd
->name
; fd
++) {
440 printf(" %-13s ", fd
->name
);
443 switch (fd
->subtype
) {
445 printf("%d\n", *((int *) fd
->v
));
447 case 1: /* encoding */
448 printf("%s\n", enc_name
[*((int *) fd
->v
)]);
450 case 3: /* tuplets */
453 (cfmt
.tuplets
>> 4) & 0x0f,
454 cfmt
.tuplets
& 0x0f);
456 case 5: /* gracespace */
457 printf("%d.%d %d.%d %d.%d\n",
458 (cfmt
.gracespace
>> 16) / 10,
459 (cfmt
.gracespace
>> 16) % 10,
460 ((cfmt
.gracespace
>> 8) & 0xff) / 10,
461 ((cfmt
.gracespace
>> 8) & 0xff) % 10,
462 (cfmt
.gracespace
& 0xff) / 10,
463 (cfmt
.gracespace
& 0xff) % 10);
468 printf("%.2f\n", *((float *) fd
->v
));
473 s
= (struct FONTSPEC
*) fd
->v
;
474 printf("%s", fontnames
[s
->fnum
]);
475 if (font_enc
[s
->fnum
] != cfmt
.encoding
)
477 enc_name
[(unsigned) font_enc
[s
->fnum
]]);
478 printf(" %.1f", s
->size
);
479 if ((fd
->subtype
== 1 && cfmt
.partsbox
)
480 || (fd
->subtype
== 2 && cfmt
.measurebox
)
481 || (fd
->subtype
== 3 && cfmt
.gchordbox
))
487 if (fd
->subtype
== 0)
488 printf("%.2fcm\n", *((float *) fd
->v
) / (1 CM
));
489 else printf("%.2fcm\n",
496 printf("%s\n", yn
[*((int *) fd
->v
)]);
499 printf("\"%s\"\n", *((char **) fd
->v
) != 0 ? *((char **) fd
->v
) : "");
505 /* -- get an encoding -- */
506 static int get_encoding(char *p
)
512 while (p
[l
] != '\0' && !isspace((unsigned char) p
[l
]))
514 if (strncasecmp(p
, "ASCII", l
) == 0) /* backward compatibility */
518 if (strncmp(p
, *e
, l
) == 0)
522 || e
>= &enc_name
[sizeof enc_name
]) {
523 if (e
>= &enc_name
[sizeof enc_name
- 1]) {
524 error(1, 0, "Too many encodings");
527 *e
= (char *) malloc(l
+ 1);
535 /* -- get the option for text -- */
536 int get_textopt(char *p
)
542 || strncmp(p
, "obeylines", 9) == 0)
544 else if (strncmp(p
, "align", 5) == 0
545 || strncmp(p
, "justify", 7) == 0)
547 else if (strncmp(p
, "ragged", 6) == 0
548 || strncmp(p
, "fill", 4) == 0)
550 else if (strncmp(p
, "center", 6) == 0)
552 else if (strncmp(p
, "skip", 4) == 0)
554 else if (strncmp(p
, "right", 5) == 0)
560 /* -- get a boolean value -- */
561 static int g_logv(char *p
)
579 "++++ Unknown logical '%s' - false assumed\n", p
);
585 /* -- get a float variable, no units -- */
586 static float g_fltv(char *p
)
591 /* -- get a font specifier -- */
592 static void g_fspc(char *p
,
599 p
= get_str(fname
, p
, sizeof fname
);
600 if (!isdigit((unsigned char) *p
)) {
602 encoding
= font_enc
[f
->fnum
];
603 else encoding
= get_encoding(p
);
604 while (*p
!= '\0' && !isspace((unsigned char) *p
))
606 while (isspace((unsigned char) *p
))
608 } else encoding
= -1;
609 fsize
= *p
!= '\0' && *p
!= '*' ? g_fltv(p
) : f
->size
;
611 strcmp(fname
, "*") != 0 ? fname
: 0,
614 if (!file_initialized
)
615 used_font
[f
->fnum
] = 1;
616 if (f
- cfmt
.font_tb
== outft
)
620 /* -- parse a 'tablature' definition -- */
622 * [#<nunmber (1..MAXTBLT)>]
623 * [pitch=<instrument pitch (<note> # | b)>]
631 struct tblt_s
*tblt_parse(char *p
)
636 static char notes_tb
[14] = "CDEFGABcdefgab";
637 static char pitch_tb
[14] = {60, 62, 64, 65, 67, 69, 71,
638 72, 74, 76, 77, 79, 81, 83};
644 if ((unsigned) n
>= MAXTBLT
645 || (*p
!= '\0' && *p
!= ' ')) {
646 error(1, 0, "Invalid number in %%%%tablature");
651 while (isspace((unsigned char) *p
))
656 tblt
= malloc(sizeof *tblt
);
657 memset(tblt
, 0, sizeof *tblt
);
658 if (strncmp(p
, "pitch=", 6) == 0) {
660 if (*p
== '^' || *p
== '_') {
663 tblt
->instr
[1] = '#';
666 tblt
->instr
[1] = 'b';
670 if (*p
== '\0' || (q
= strchr(notes_tb
, *p
)) == 0) {
671 error(1, 0, "Invalid pitch in %%%%tablature");
674 tblt
->pitch
+= pitch_tb
[q
- notes_tb
];
675 tblt
->instr
[0] = toupper(*p
++);
676 while (*p
== '\'' || *p
== ',') {
679 else tblt
->pitch
-= 12;
681 if (*p
== '#' || *p
== 'b') {
685 tblt
->instr
[1] = *p
++;
687 while (*p
== '\'' || *p
== ',') {
690 else tblt
->pitch
-= 12;
692 while (isspace((unsigned char) *p
))
696 /* width and heights */
698 error(1, 0, "Invalid width/height in %%%%tablature");
701 tblt
->hu
= scan_u(p
);
702 while (*p
!= '\0' && !isspace((unsigned char) *p
))
704 while (isspace((unsigned char) *p
))
708 tblt
->hu
= scan_u(p
);
709 while (*p
!= '\0' && !isspace((unsigned char) *p
))
711 while (isspace((unsigned char) *p
))
716 tblt
->hu
= scan_u(p
);
717 while (*p
!= '\0' && !isspace((unsigned char) *p
))
719 while (isspace((unsigned char) *p
))
729 while (*p
!= '\0' && !isspace((unsigned char) *p
))
734 while (isspace((unsigned char) *p
))
737 while (*p
!= '\0' && !isspace((unsigned char) *p
))
741 while (isspace((unsigned char) *p
))
744 while (*p
!= '\0' && !isspace((unsigned char) *p
))
750 /* memorize the definition */
755 error(1, 0, "Wrong values in %%%%tablature");
759 /* -- parse a format line -- */
760 void interpret_fmt_line(char *w
, /* keyword */
761 char *p
, /* argument */
768 if (strcmp(w
, "barnumbers") == 0)
772 if (strcmp(w
, "deco") == 0) {
778 if (strcmp(w
, "font") == 0) {
782 p
= get_str(fname
, p
, sizeof fname
);
784 encoding
= cfmt
.encoding
;
785 else encoding
= get_encoding(p
);
786 fnum
= get_font(fname
, encoding
);
787 def_font_enc
[fnum
] = encoding
;
791 if (strcmp(w
, "format") == 0) {
792 if (read_fmt_file(p
) < 0)
793 error(1, 0, "No such format file '%s'", p
);
798 if (strcmp(w
, "infoname") == 0) {
799 if (*p
< 'A' || *p
> 'Z') {
800 error(1, 0, "Bad info type '%c' in %%%%infoname",
809 if (strcmp(w
, "postscript") == 0) {
810 if (!file_initialized
)
818 if (strcmp(w
, "tablature") == 0) {
824 for (fd
= format_tb
; fd
->name
; fd
++)
825 if (strcmp(w
, fd
->name
) == 0)
829 if (fd
->lock
&& !lock
)
834 if (fd
->subtype
== 3) { /* tuplets */
837 if (sscanf(p
, "%d %d %d", &i1
, &i2
, &i3
) != 3
838 || i1
> 2 || i2
> 2 || i3
> 2) {
840 "Bad 'tuplets' values '%s' - ignored",
844 cfmt
.tuplets
= (i1
<< 8) | (i2
<< 4) | i3
;
847 if (fd
->subtype
== 5) { /* gracespace */
851 if (sscanf(p
, "%f %f %f", &f1
, &f2
, &f3
) != 3
852 || f1
> 256 || f2
> 256 || f3
> 256) {
854 "Bad 'gracespace' values '%s' - ignored",
861 cfmt
.gracespace
= (i1
<< 16) | (i2
<< 8) | i3
;
864 if (fd
->subtype
== 1 && !isdigit(*p
)) /* 'encoding' */
865 cfmt
.encoding
= get_encoding(p
);
866 else if (fd
->subtype
== 4 && !isdigit(*p
)) /* 'textoption' */
867 cfmt
.textoption
= get_textopt(p
);
868 else sscanf(p
, "%d", (int *) fd
->v
);
869 switch (fd
->subtype
) {
870 case 1: /* 'encoding' */
872 && (unsigned) cfmt
.encoding
> MAXENC
) {
874 "Bad encoding value %d - reset to 0",
880 for (i
= 0; i
< nfontnames
; i
++) {
881 if (font_enc
[i
] == 0)
882 def_font_enc
[i
] = font_enc
[i
]
888 nbar
= nbar_rep
= cfmt
.measurefirst
;
890 case 4: /* 'textoption' */
891 if (cfmt
.textoption
< 0) {
893 "Bad 'textoption' value '%s'",
895 cfmt
.textoption
= T_LEFT
;
901 *((float *) fd
->v
) = g_fltv(p
);
902 if (fd
->subtype
== 1) { /* note spacing factor */
906 if (cfmt
.notespacingfactor
<= 0) {
908 "Bad value for 'notespacingfactor'\n");
909 cfmt
.notespacingfactor
= 1;
912 i
= C_XFLAGS
; /* crotchet index */
914 for ( ; --i
>= 0; ) {
915 w
/= cfmt
.notespacingfactor
;
920 for ( ; ++i
< NFLAGS_SZ
; ) {
921 w
*= cfmt
.notespacingfactor
;
929 g_fspc(p
, (struct FONTSPEC
*) fd
->v
);
930 b
= strstr(p
, "box") != 0;
931 switch (fd
->subtype
) {
945 *((float *) fd
->v
) = scan_u(p
);
946 if (fd
->subtype
== 1) {
949 rmargin
= (cfmt
.landscape
? cfmt
.pageheight
: cfmt
.pagewidth
)
950 - staffwidth
- cfmt
.leftmargin
;
952 fprintf(stderr
, "'staffwidth' too big\n");
953 cfmt
.rightmargin
= rmargin
;
957 *((int *) fd
->v
) = g_logv(p
);
963 *((char **) fd
->v
) = getarena(l
);
965 get_str(*((char **) fd
->v
), p
, l
);
966 else strcpy(*((char **) fd
->v
), p
);
972 /* -- remove the spaces and comments of a format line -- */
973 static char *clean_line(char *p
)
978 while (isspace((unsigned char) *p
))
983 if ((c
= *p
++) == '%') {
984 if (i
> 0 && p
[-2] != '\\')
995 if (!isspace((unsigned char) c
)) {
1003 /* -- lock a format -- */
1004 void lock_fmt(void *fmt
)
1008 for (fd
= format_tb
; fd
->name
; fd
++)
1016 /* -- open a file for reading -- */
1017 FILE *open_file(char *fn
, /* file name */
1018 char *ext
, /* file type */
1019 char *rfn
) /* real file name */
1026 if ((fp
= fopen(rfn
, "r")) != 0)
1029 if ((fp
= fopen(rfn
, "r")) != 0)
1032 && (p
= strrchr(in_fname
, DIRSEP
)) != 0) {
1033 l
= p
- in_fname
+ 1;
1034 strncpy(rfn
, in_fname
, l
);
1035 strcpy(&rfn
[l
], fn
);
1036 if ((fp
= fopen(rfn
, "r")) != 0)
1038 strext(&rfn
[l
], ext
);
1039 if ((fp
= fopen(rfn
, "r")) != 0)
1044 sprintf(rfn
, "%s%c%s", styd
, DIRSEP
, fn
);
1045 if ((fp
= fopen(rfn
, "r")) != 0)
1048 if ((fp
= fopen(rfn
, "r")) != 0)
1053 /* -- read a format file -- */
1054 int read_fmt_file(char *fn
)
1057 char line
[BSIZE
], *p
, *q
;
1060 if ((fp
= open_file(fn
, "fmt", &line
[1])) == 0)
1062 if (strcmp(&line
[strlen(line
) - 3], ".ps") == 0) {
1063 if (!file_initialized
)
1066 error(0, 0, "Cannot include the file %s", &line
[1]);
1072 if (!fgets(p
, sizeof line
, fp
))
1077 if (strcmp(p
, "beginps") == 0) {
1080 if (!fgets(p
, sizeof line
, fp
))
1090 if (!isspace((unsigned char) c
)) {
1101 if (strcmp(p
, "endps") == 0)
1103 if (!file_initialized
)
1110 if (strcmp(p
, "end") == 0)
1113 while (*p
!= '\0' && !isspace((unsigned char) *p
))
1117 while (isspace((unsigned char) *p
))
1120 interpret_fmt_line(q
, p
, 0);
1126 /* -- start a new font -- */
1127 void set_font(int ft
)
1130 struct FONTSPEC
*f
, *f2
;
1134 f
= &cfmt
.font_tb
[ft
];
1135 f2
= &cfmt
.font_tb
[outft
];
1137 if (f
->fnum
== f2
->fnum
&& f
->size
== f2
->size
)
1140 if (!used_font
[fnum
]) {
1142 "Font \"%s\" not predefined; using first in list",
1147 error(0, 0, "Font \"%s\" with a null size",
1149 PUT2("%.1f F%d ", f
->size
, fnum
);