/* -- write a title -- */ void write_title(struct SYMBOL *s) { char *p; p = &s->as.text[2]; while (isspace((unsigned char) *p)) p++; if (*p == '\0') return; p = trim_title(p, s == info['T' - 'A']); if (s == info['T' - 'A']) { bskip(cfmt.titlespace + cfmt.font_tb[TITLEFONT].size); set_font(TITLEFONT); } else { bskip(cfmt.subtitlespace + cfmt.font_tb[SUBTITLEFONT].size); set_font(SUBTITLEFONT); } if (cfmt.titleleft) PUT0("0 0 M("); else PUT1("%.1f 0 M(", 0.5 * ((cfmt.landscape ? cfmt.pageheight : cfmt.pagewidth) - cfmt.leftmargin - cfmt.rightmargin) / cfmt.scale); tex_str(p); PUT2("%s)show%s\n", tex_buf, cfmt.titleleft ? "" : "c"); }
/* -- convert a date -- */ static void cnv_date(time_t *ltime) { char buf[TEX_BUF_SZ]; tex_str(cfmt.dateformat); strcpy(buf, tex_buf); strftime(tex_buf, TEX_BUF_SZ, buf, localtime(ltime)); }
/* -- write heading with format -- */ static void write_headform(float lwidth) { char *p, *q; struct SYMBOL *s; struct FONTSPEC *f; int align, i, j; float x, y, xa[3], ya[3], sz, yb[3]; char inf_nb[26]; INFO inf_s; char inf_ft[26]; float inf_sz[26]; char fmt[64]; memset(inf_nb, 0, sizeof inf_nb); memset(inf_ft, HISTORYFONT, sizeof inf_ft); inf_ft['A' - 'A'] = INFOFONT; inf_ft['C' - 'A'] = COMPOSERFONT; inf_ft['O' - 'A'] = COMPOSERFONT; inf_ft['P' - 'A'] = PARTSFONT; inf_ft['Q' - 'A'] = TEMPOFONT; inf_ft['R' - 'A'] = INFOFONT; inf_ft['T' - 'A'] = TITLEFONT; inf_ft['X' - 'A'] = TITLEFONT; memcpy(inf_s, info, sizeof inf_s); memset(inf_sz, 0, sizeof inf_sz); inf_sz['A' - 'A'] = cfmt.infospace; inf_sz['C' - 'A'] = cfmt.composerspace; inf_sz['O' - 'A'] = cfmt.composerspace; inf_sz['R' - 'A'] = cfmt.infospace; p = cfmt.titleformat; j = 0; for (;;) { while (isspace((unsigned char) *p)) p++; if (*p == '\0') break; i = *p - 'A'; if ((unsigned) i < 26) { inf_nb[i]++; switch (p[1]) { default: align = A_CENTER; break; case '1': align = A_RIGHT; p++; break; case '-': align = A_LEFT; p++; break; } if (j < sizeof fmt - 4) { fmt[j++] = i; fmt[j++] = align; } } else if (*p == ',') { if (j < sizeof fmt - 3) fmt[j++] = 126; /* next line */ } else if (*p == '+') { if (j > 0 && fmt[j - 1] < 125 && j < sizeof fmt - 3) fmt[j++] = 125; /* concatenate */ /*new fixme: add free text "..." ?*/ } p++; } fmt[j++] = 126; /* newline */ fmt[j] = 127; /* end of format */ ya[0] = ya[1] = ya[2] = cfmt.titlespace;; xa[0] = 0; xa[1] = lwidth * 0.5; xa[2] = lwidth; p = fmt; for (;;) { yb[0] = yb[1] = yb[2] = y = 0; q = p; for (;;) { i = *q++; if (i >= 126) /* if newline */ break; align = *q++; if (yb[align + 1] != 0) continue; s = inf_s[i]; if (s == 0 || inf_nb[i] == 0) continue; j = inf_ft[i]; f = &cfmt.font_tb[j]; sz = f->size * 1.1 + inf_sz[i]; if (y < sz) y = sz; yb[align + 1] = sz; /*fixme:should count the height of the concatenated field*/ if (*q == 125) q++; } for (i = 0; i < 3; i++) ya[i] += y - yb[i]; for (;;) { i = *p++; if (i >= 126) /* if newline */ break; align = *p++; s = inf_s[i]; if (s == 0 || inf_nb[i] == 0) continue; j = inf_ft[i]; str_font(j); x = xa[align + 1]; f = &cfmt.font_tb[j]; sz = f->size * 1.1 + inf_sz[i]; y = ya[align + 1] + sz; PUT2("%.1f %.1f M ", x, -y); if (*p == 125) { /* concatenate */ p++; /*fixme: do it work with different fields*/ if (*p == i && p[1] == align && s->next != 0) { char buf[256], *r; q = s->as.text; if (q[1] == ':') q += 2; while (isspace((unsigned char) *q)) q++; if (i == 'T' - 'A') q = trim_title(q, s == inf_s['T' - 'A']); strncpy(buf, q, sizeof buf - 1); buf[sizeof buf - 1] = '\0'; j = strlen(buf); if (j < sizeof buf - 1) { buf[j] = ' '; buf[j + 1] = '\0'; } s = s->next; q = s->as.text; if (q[1] == ':') q += 2; while (isspace((unsigned char) *q)) q++; if (s->as.text[0] == 'T' && s->as.text[1] == ':') q = trim_title(q, 0); r = buf + strlen(buf); strncpy(r, q, buf + sizeof buf - r - 1); tex_str(buf); str_out(tex_buf, align); PUT0("\n"); inf_nb[i]--; p += 2; } } else if (i == 'Q' - 'A') { /* special case for tempo */ if (align != A_LEFT) { float w; w = tempo_width(s); if (align == A_CENTER) PUT1("-%.1f 0 RM ", w * 0.5); else PUT1("-%.1f 0 RM ", w); } write_tempo(s, 0, 0.75); } else put_inf2r(s, 0, align); if (inf_s[i] == info['T' - 'A']) { inf_ft[i] = SUBTITLEFONT; str_font(SUBTITLEFONT); f = &cfmt.font_tb[SUBTITLEFONT]; inf_sz[i] = cfmt.subtitlespace; sz = f->size * 1.1 + inf_sz[i]; } s = s->next; if (inf_nb[i] == 1) { while (s != 0) { y += sz; PUT2("%.1f %.1f M ", x, -y); put_inf2r(s, 0, align); s = s->next; } } inf_s[i] = s; inf_nb[i]--; ya[align + 1] = y; } if (ya[1] > ya[0]) ya[0] = ya[1]; if (ya[2] > ya[0]) ya[0] = ya[2]; if (*p == 127) { bskip(ya[0]); break; } ya[1] = ya[2] = ya[0]; } }
/* -- add text to a block -- */ void add_to_text_block(char *s, int job) { float baseskip, lw; char *p, sep; struct FONTSPEC *f; /* if first line, set the fonts */ if (strtw < 0) { str_font(TEXTFONT); strlw = ((cfmt.landscape ? cfmt.pageheight : cfmt.pagewidth) - cfmt.leftmargin - cfmt.rightmargin) / cfmt.scale; } if (curft > 0) f = &cfmt.font_tb[curft]; else f = &cfmt.font_tb[defft]; baseskip = f->size * cfmt.lineskipfac; /* follow lines */ if (job == T_LEFT || job == T_CENTER || job == T_RIGHT) { if (*s != '\0') { bskip(baseskip); if (job == T_LEFT) { PUT0("0 0 M "); put_str(s, A_LEFT); } else if (job == T_CENTER) { PUT1("%.1f 0 M ", strlw * 0.5); put_str(s, A_CENTER); } else { PUT1("%.1f 0 M ", strlw); put_str(s, A_RIGHT); } } else { bskip(baseskip * 0.5); buffer_eob(); } strtw = 0; return; } /* fill or justify lines */ if (strtw < 0) { /* if first line */ curft = defft; bskip(baseskip); PUT0("0 0 M "); if (job == T_FILL) strop = "show"; else { PUT0("/str{"); outft = -1; strop = "strop"; } strns = 0; strtw = 0; } if (*s == '\0') { /* empty line */ if (strtx) { PUT1(")%s", strop); strtx = 0; } if (job == T_JUSTIFY) PUT0("}def\n" "/strop/show load def str\n"); else PUT0("\n"); bskip(f->size * cfmt.lineskipfac * 1.5); buffer_eob(); PUT0("0 0 M "); if (job == T_JUSTIFY) { PUT0("/str{"); outft = -1; } strns = 0; strtw = 0; return; } p = s; for (;;) { while (*p != ' ' && *p != '\0') p++; sep = *p; *p = '\0'; lw = tex_str(s); if (strtw + lw > strlw) { if (strtx) { PUT1(")%s ", strop); strtx = 0; } if (job == T_JUSTIFY) { if (strns == 0) strns = 1; PUT2("}def\n" "/strop/strw load def/w 0 def str" "/w %.1f w sub %d div def" "/strop/jshow load def str ", strlw, strns); strns = 0; } bskip(cfmt.font_tb[curft].size * cfmt.lineskipfac); PUT0("0 0 M "); if (job == T_JUSTIFY) { PUT0("/str{"); outft = -1; } strtw = 0; } if (strtw != 0) { str_ft_out(" ", 0); strtw += cwid(' ') * cfmt.font_tb[curft].swfac; strns++; } str_ft_out(tex_buf, 0); strtw += lw; *p = sep; while (*p == ' ') p++; if (*p == '\0') break; s = p; } }
/* -- output a string with TeX translation -- */ void put_str(char *str, int action) { tex_str(str); str_out(tex_buf, action); PUT0("\n"); }
/* -- output the header or footer -- */ static float headfooter(int header, float pwidth, float pheight) { char tmp[2048], str[TEX_BUF_SZ + 512]; char *p, *q, *r, *outbuf_sav, *mbf_sav; float size, y, wsize; struct FONTSPEC *f, f_sav; int cft_sav, dft_sav, outbufsz_sav; if (header) { p = cfmt.header; f = &cfmt.font_tb[HEADERFONT]; size = f->size; y = -size; } else { p = cfmt.footer; f = &cfmt.font_tb[FOOTERFONT]; size = f->size; y = - (pheight - cfmt.topmargin - cfmt.botmargin) + size; } if (*p == '-') { if (pagenum == 1) return 0; p++; } get_str_font(&cft_sav, &dft_sav); memcpy(&f_sav, &cfmt.font_tb[0], sizeof f_sav); str_font(f - cfmt.font_tb); output(fout, "%.1f F%d ", size, f->fnum); outft = f - cfmt.font_tb; /* may have 2 lines */ wsize = size; if ((r = strstr(p, "\\n")) != NULL) { if (!header) y += size; wsize += size; *r = '\0'; } mbf_sav = mbf; outbuf_sav = outbuf; outbufsz_sav = outbufsz; outbuf = tmp; outbufsz = sizeof tmp; for (;;) { tex_str(p); strcpy(tmp, tex_buf); format_hf(str, tmp); /* left side */ p = str; if ((q = strchr(p, '\t')) != NULL) { if (q != p) { *q = '\0'; output(fout, "%.1f %.1f M ", p_fmt->leftmargin, y); mbf = tmp; str_out(p, A_LEFT); a2b("\n"); if (svg) svg_write(tmp, strlen(tmp)); else fputs(tmp, fout); } p = q + 1; } if ((q = strchr(p, '\t')) != NULL) *q = '\0'; /* center */ if (q != p) { output(fout, "%.1f %.1f M ", pwidth * 0.5, y); mbf = tmp; str_out(p, A_CENTER); a2b("\n"); if (svg) svg_write(tmp, strlen(tmp)); else fputs(tmp, fout); } /* right side */ if (q) { p = q + 1; if (*p != '\0') { output(fout, "%.1f %.1f M ", pwidth - p_fmt->rightmargin, y); mbf = tmp; str_out(p, A_RIGHT); a2b("\n"); if (svg) svg_write(tmp, strlen(tmp)); else fputs(tmp, fout); } } if (!r) break; *r = '\\'; p = r + 2; r = NULL; y -= size; } /* restore the buffer and fonts */ outbuf = outbuf_sav; outbufsz = outbufsz_sav; mbf = mbf_sav; memcpy(&cfmt.font_tb[0], &f_sav, sizeof cfmt.font_tb[0]); set_str_font(cft_sav, dft_sav); return wsize; }
/* -- output a header/footer element -- */ static void format_hf(char *d, char *p) { char *q; time_t ltime; for (;;) { if (*p == '\0') break; if ((q = strchr(p, '$')) != NULL) *q = '\0'; d += sprintf(d, "%s", p); if (!q) break; p = q + 1; switch (*p) { case 'd': ltime = mtime; goto dput; case 'D': time(<ime); dput: cnv_date(<ime); d += sprintf(d, "%s", tex_buf); break; case 'F': /* ABC file name */ #if DIRSEP!='\\' d += sprintf(d, "%s", in_fname); #else { int i; q = in_fname; i = TEX_BUF_SZ; for (;;) { if (--i <= 0 || *q == '\0') break; if ((*d++ = *q++) == '\\') { i--; *d++ = '\\'; } } *d = '\0'; } #endif break; case 'I': /* information field */ p++; if (*p < 'A' || *p > 'Z' || !info[*p - 'A']) break; d += sprintf(d, "%s", &info[*p - 'A']->text[2]); break; case 'P': /* page number */ if (p[1] == '0') { p++; if (pagenum & 1) break; } else if (p[1] == '1') { p++; if ((pagenum & 1) == 0) break; } d += sprintf(d, "%d", pagenum); break; case 'T': /* tune title */ q = &info['T' - 'A']->text[2]; tex_str(q); d += sprintf(d, "%s", tex_buf); break; case 'V': d += sprintf(d,"abcm2ps-" VERSION); break; default: continue; } p++; } *d = '\0'; /* in case of empty string */ }