lorid

convert chordpro to pdf
git clone git://git.relim.de/lorid.git
Log | Files | Refs | README | LICENSE

commit 2b7aede1b996d407008e432da94aaf535b79ad5a
parent 1372caa85cb72bba0e6d5e45153207fc102521e8
Author: nibo <nibo@relim.de>
Date:   Sun, 29 Dec 2024 12:09:38 +0100

Refactor different things

Diffstat:
Mchordpro.c | 487+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mchordpro.h | 327++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mout_pdf.h | 44++++++++++++++++++++++----------------------
3 files changed, 437 insertions(+), 421 deletions(-)

diff --git a/chordpro.c b/chordpro.c @@ -3036,7 +3036,7 @@ cho_line_free(struct ChoLine *line) /* TODO: Does this still work? */ static int -cho_line_compute_chord_position(struct ChoLine *line, int ly, int te) +cho_line_compute_text_above_position(struct ChoLine *line, int ly, int te) { if (ly == 0) { return te; @@ -3697,7 +3697,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) int atn = 0; int atv = 0; int ann = 0; - int chord_pos; + int text_above_pos; int transpose; int th = 0; int dia = 0; @@ -3709,14 +3709,16 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) enum AttrValueSyntax avs = AVS_NO; struct ChoDirective *directive = NULL; struct ChoMetadata *metadata = NULL; + struct ChoLine ***lines; struct ChoSong **songs = emalloc(sizeof(struct ChoSong *)); songs[so] = cho_song_new(); songs[so]->sections = emalloc((se+1) * sizeof(struct ChoSection *)); songs[so]->sections[se] = cho_section_new(); songs[so]->sections[se]->lines = emalloc(sizeof(struct ChoLine *)); songs[so]->sections[se]->lines[li] = cho_line_new(); - songs[so]->sections[se]->lines[li]->items = emalloc(sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); + lines = &songs[so]->sections[se]->lines; + (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); struct Tag **tags = NULL; struct ChoStyle *tag_style; struct StyleProperty sprop; @@ -3750,11 +3752,11 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) break; } if (buf == '<') { - if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) { - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = erealloc(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text[te] = 0; - if (strlen(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text) == 0) { - cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]); + if ((*lines)[li]->items[ly]->is_text) { + (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); + (*lines)[li]->items[ly]->u.text->text[te] = 0; + if (strlen((*lines)[li]->items[ly]->u.text->text) == 0) { + cho_line_item_free((*lines)[li]->items[ly]); } else { ly++; } @@ -3762,8 +3764,8 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) ly++; } te = 0; - songs[so]->sections[se]->lines[li]->items = erealloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); + (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); prev_state = STATE_LYRICS; state = STATE_MARKUP_TAG; break; @@ -3778,22 +3780,22 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) cho_log(LOG_ERR, "Tag has to be closed on same line."); return NULL; } - if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) { - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = erealloc(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text[te] = 0; - if (strlen(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text) == 0) { - cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]); + if ((*lines)[li]->items[ly]->is_text) { + (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); + (*lines)[li]->items[ly]->u.text->text[te] = 0; + if (strlen((*lines)[li]->items[ly]->u.text->text) == 0) { + cho_line_item_free((*lines)[li]->items[ly]); if (ly == 0) { if ( - !songs[so]->sections[se]->lines[li]->text_above && - songs[so]->sections[se]->lines[li]->btype == BT_LINE + !(*lines)[li]->text_above && + (*lines)[li]->btype == BT_LINE ) { - free(songs[so]->sections[se]->lines[li]->items); - free(songs[so]->sections[se]->lines[li]); - songs[so]->sections[se]->lines = erealloc(songs[so]->sections[se]->lines, (li+1) * sizeof(struct ChoLine *)); - songs[so]->sections[se]->lines[li] = cho_line_new(); - songs[so]->sections[se]->lines[li]->items = erealloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); + free((*lines)[li]->items); + free((*lines)[li]); + *lines = erealloc(*lines, (li+1) * sizeof(struct ChoLine *)); + (*lines)[li] = cho_line_new(); + (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); break; } } @@ -3803,22 +3805,22 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) } else { ly++; } - songs[so]->sections[se]->lines[li]->items = erealloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = NULL; + (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = NULL; ly = 0; te = 0; - songs[so]->sections[se]->lines[li]->text_above = erealloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); - songs[so]->sections[se]->lines[li]->text_above[c] = NULL; + (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); + (*lines)[li]->text_above[c] = NULL; c = 0; li++; - songs[so]->sections[se]->lines = erealloc(songs[so]->sections[se]->lines, (li+1) * sizeof(struct ChoLine *)); - songs[so]->sections[se]->lines[li] = cho_line_new(); - songs[so]->sections[se]->lines[li]->items = erealloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); + *lines = erealloc(*lines, (li+1) * sizeof(struct ChoLine *)); + (*lines)[li] = cho_line_new(); + (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); break; } - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = erealloc(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text[te] = buf; + (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); + (*lines)[li]->items[ly]->u.text->text[te] = buf; te++; break; case STATE_DIRECTIVE_NAME: @@ -3839,20 +3841,21 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) memset(custom_directive, 0, sizeof(custom_directive)); strcpy(custom_directive, &directive_name[9]); } - cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]); - free(songs[so]->sections[se]->lines[li]->items); + cho_line_item_free((*lines)[li]->items[ly]); + free((*lines)[li]->items); ly = 0; - free(songs[so]->sections[se]->lines[li]); - songs[so]->sections[se]->lines[li] = NULL; + free((*lines)[li]); + (*lines)[li] = NULL; se++; songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *)); songs[so]->sections[se] = cho_section_new(); songs[so]->sections[se]->type = directive->stype; li = 0; - songs[so]->sections[se]->lines = emalloc(sizeof(struct ChoLine *)); - songs[so]->sections[se]->lines[li] = cho_line_new(); - songs[so]->sections[se]->lines[li]->items = emalloc(sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); + lines = &songs[so]->sections[se]->lines; + *lines = emalloc(sizeof(struct ChoLine *)); + (*lines)[li] = cho_line_new(); + (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); break; case POS_END: if (directive->stype == songs[so]->sections[se]->type) { @@ -3861,19 +3864,20 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) break; } } - cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]); - free(songs[so]->sections[se]->lines[li]->items); + cho_line_item_free((*lines)[li]->items[ly]); + free((*lines)[li]->items); ly = 0; - free(songs[so]->sections[se]->lines[li]); - songs[so]->sections[se]->lines[li] = NULL; + free((*lines)[li]); + (*lines)[li] = NULL; se++; songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *)); songs[so]->sections[se] = cho_section_new(); li = 0; - songs[so]->sections[se]->lines = emalloc(sizeof(struct ChoLine *)); - songs[so]->sections[se]->lines[li] = cho_line_new(); - songs[so]->sections[se]->lines[li]->items = emalloc(sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); + lines = &songs[so]->sections[se]->lines; + *lines = emalloc(sizeof(struct ChoLine *)); + (*lines)[li] = cho_line_new(); + (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); } break; case POS_EMPTY: @@ -3881,20 +3885,20 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) chorus = cho_find_previous_chorus(songs[so]->sections, se); if (chorus) { if (config->output->chorus->quote) { - if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) { - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = erealloc(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text[te] = 0; + if ((*lines)[li]->items[ly]->is_text) { + (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); + (*lines)[li]->items[ly]->u.text->text[te] = 0; } ly++; - songs[so]->sections[se]->lines[li]->items = erealloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = NULL; + (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = NULL; ly = 0; te = 0; - songs[so]->sections[se]->lines[li]->text_above = erealloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); - songs[so]->sections[se]->lines[li]->text_above[c] = NULL; + (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); + (*lines)[li]->text_above[c] = NULL; c = 0; - cho_line_free(songs[so]->sections[se]->lines[li]); - songs[so]->sections[se]->lines[li] = NULL; + cho_line_free((*lines)[li]); + (*lines)[li] = NULL; li = 0; se++; songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *)); @@ -3902,33 +3906,34 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) se++; songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *)); songs[so]->sections[se] = cho_section_new(); - songs[so]->sections[se]->lines = emalloc(sizeof(struct ChoLine *)); - songs[so]->sections[se]->lines[li] = cho_line_new(); - songs[so]->sections[se]->lines[li]->items = emalloc(sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); + lines = &songs[so]->sections[se]->lines; + *lines = emalloc(sizeof(struct ChoLine *)); + (*lines)[li] = cho_line_new(); + (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); } else { if (chorus->label) { label = strdup(chorus->label->text); } else { label = strdup(config->output->chorus->label); } - if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) { - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = erealloc(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text[te] = 0; - if (strlen(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text) == 0) { - cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]); + if ((*lines)[li]->items[ly]->is_text) { + (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); + (*lines)[li]->items[ly]->u.text->text[te] = 0; + if (strlen((*lines)[li]->items[ly]->u.text->text) == 0) { + cho_line_item_free((*lines)[li]->items[ly]); } else { ly++; } } else { ly++; } - songs[so]->sections[se]->lines[li]->items = erealloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); - cho_style_free(songs[so]->sections[se]->lines[li]->items[ly]->u.text->style); + (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); + cho_style_free((*lines)[li]->items[ly]->u.text->style); g_current_ftype = SF_LABEL; - songs[so]->sections[se]->lines[li]->items[ly]->u.text->style = cho_style_new_default(); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = label; + (*lines)[li]->items[ly]->u.text->style = cho_style_new_default(); + (*lines)[li]->items[ly]->u.text->text = label; te += strlen(label); } } else { @@ -3936,23 +3941,23 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) cho_log(LOG_WARN, "Can't quote chorus because it's not defined previously."); } label = strdup(config->output->chorus->label); - if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) { - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = erealloc(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text[te] = 0; - if (strlen(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text) == 0) { - cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]); + if ((*lines)[li]->items[ly]->is_text) { + (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); + (*lines)[li]->items[ly]->u.text->text[te] = 0; + if (strlen((*lines)[li]->items[ly]->u.text->text) == 0) { + cho_line_item_free((*lines)[li]->items[ly]); } else { ly++; } } else { ly++; } - songs[so]->sections[se]->lines[li]->items = erealloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); - cho_style_free(songs[so]->sections[se]->lines[li]->items[ly]->u.text->style); + (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); + cho_style_free((*lines)[li]->items[ly]->u.text->style); g_current_ftype = SF_LABEL; - songs[so]->sections[se]->lines[li]->items[ly]->u.text->style = cho_style_new_default(); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = label; + (*lines)[li]->items[ly]->u.text->style = cho_style_new_default(); + (*lines)[li]->items[ly]->u.text->text = label; te += strlen(label); } break; @@ -3972,10 +3977,10 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) return NULL; case DT_PREAMBLE: // INFO: The only preamble directive is 'new_song' - cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]); - free(songs[so]->sections[se]->lines[li]->items); - free(songs[so]->sections[se]->lines[li]); - songs[so]->sections[se]->lines[li] = NULL; + cho_line_item_free((*lines)[li]->items[ly]); + free((*lines)[li]->items); + free((*lines)[li]); + (*lines)[li] = NULL; songs[so]->metadata = erealloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *)); songs[so]->metadata[m] = NULL; se++; @@ -3997,10 +4002,11 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) dia = 0; songs[so]->sections = emalloc((se+1) * sizeof(struct ChoSection *)); songs[so]->sections[se] = cho_section_new(); - songs[so]->sections[se]->lines = erealloc(songs[so]->sections[se]->lines, (li+1) * sizeof(struct ChoLine *)); - songs[so]->sections[se]->lines[li] = cho_line_new(); - songs[so]->sections[se]->lines[li]->items = emalloc(sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); + lines = &songs[so]->sections[se]->lines; + *lines = erealloc(*lines, (li+1) * sizeof(struct ChoLine *)); + (*lines)[li] = cho_line_new(); + (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); break; case DT_FONT: sprop.ftype = directive->ftype; @@ -4037,7 +4043,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) break; case DT_OUTPUT: if (directive->btype != BT_EMPTY) { - songs[so]->sections[se]->lines[li]->btype = directive->btype; + (*lines)[li]->btype = directive->btype; } break; case DT_CUSTOM: @@ -4088,11 +4094,11 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) memset(custom_directive, 0, sizeof(custom_directive)); strcpy(custom_directive, &directive_name[9]); } - cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]); - free(songs[so]->sections[se]->lines[li]->items); + cho_line_item_free((*lines)[li]->items[ly]); + free((*lines)[li]->items); ly = 0; - free(songs[so]->sections[se]->lines[li]); - songs[so]->sections[se]->lines[li] = NULL; + free((*lines)[li]); + (*lines)[li] = NULL; se++; songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *)); songs[so]->sections[se] = cho_section_new(); @@ -4111,26 +4117,28 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) } songs[so]->sections[se]->label->style = cho_style_new_from_config(SF_LABEL); li = 0; - songs[so]->sections[se]->lines = emalloc(sizeof(struct ChoLine *)); - songs[so]->sections[se]->lines[li] = cho_line_new(); - songs[so]->sections[se]->lines[li]->items = emalloc(sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); + lines = &songs[so]->sections[se]->lines; + *lines = emalloc(sizeof(struct ChoLine *)); + (*lines)[li] = cho_line_new(); + (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); break; case POS_END: if (directive->stype == songs[so]->sections[se]->type) { - cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]); - free(songs[so]->sections[se]->lines[li]->items); + cho_line_item_free((*lines)[li]->items[ly]); + free((*lines)[li]->items); ly = 0; - free(songs[so]->sections[se]->lines[li]); - songs[so]->sections[se]->lines[li] = NULL; + free((*lines)[li]); + (*lines)[li] = NULL; se++; songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *)); songs[so]->sections[se] = cho_section_new(); li = 0; - songs[so]->sections[se]->lines = emalloc(sizeof(struct ChoLine *)); - songs[so]->sections[se]->lines[li] = cho_line_new(); - songs[so]->sections[se]->lines[li]->items = emalloc(sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); + lines = &songs[so]->sections[se]->lines; + *lines = emalloc(sizeof(struct ChoLine *)); + (*lines)[li] = cho_line_new(); + (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); } break; case POS_EMPTY: @@ -4139,21 +4147,21 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) chorus = cho_find_previous_chorus(songs[so]->sections, se); if (chorus) { if (config->output->chorus->quote) { - if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) { - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = erealloc(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text[te] = 0; + if ((*lines)[li]->items[ly]->is_text) { + (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); + (*lines)[li]->items[ly]->u.text->text[te] = 0; } ly++; - songs[so]->sections[se]->lines[li]->items = erealloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = NULL; + (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = NULL; ly = 0; te = 0; - songs[so]->sections[se]->lines[li]->text_above = erealloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); - songs[so]->sections[se]->lines[li]->text_above[c] = NULL; + (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); + (*lines)[li]->text_above[c] = NULL; c = 0; - cho_line_free(songs[so]->sections[se]->lines[li]); + cho_line_free((*lines)[li]); // songs[so]->sections[se]->lines = erealloc(songs[so]->sections[se]->lines, (li+1) * sizeof(struct ChoLine *)); - songs[so]->sections[se]->lines[li] = NULL; + (*lines)[li] = NULL; li = 0; se++; songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *)); @@ -4169,51 +4177,52 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) se++; songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *)); songs[so]->sections[se] = cho_section_new(); - songs[so]->sections[se]->lines = emalloc(sizeof(struct ChoLine *)); - songs[so]->sections[se]->lines[li] = cho_line_new(); - songs[so]->sections[se]->lines[li]->items = emalloc(sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); + lines = &songs[so]->sections[se]->lines; + *lines = emalloc(sizeof(struct ChoLine *)); + (*lines)[li] = cho_line_new(); + (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); } else { - if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) { - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = erealloc(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text[te] = 0; - if (strlen(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text) == 0) { - cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]); + if ((*lines)[li]->items[ly]->is_text) { + (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); + (*lines)[li]->items[ly]->u.text->text[te] = 0; + if (strlen((*lines)[li]->items[ly]->u.text->text) == 0) { + cho_line_item_free((*lines)[li]->items[ly]); } else { ly++; } } else { ly++; } - songs[so]->sections[se]->lines[li]->items = erealloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); - cho_style_free(songs[so]->sections[se]->lines[li]->items[ly]->u.text->style); + (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); + cho_style_free((*lines)[li]->items[ly]->u.text->style); g_current_ftype = SF_LABEL; - songs[so]->sections[se]->lines[li]->items[ly]->u.text->style = cho_style_new_default(); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = label; + (*lines)[li]->items[ly]->u.text->style = cho_style_new_default(); + (*lines)[li]->items[ly]->u.text->text = label; te += strlen(label); } } else { if (config->output->chorus->quote) { cho_log(LOG_WARN, "Can't quote chorus because it's not defined previously."); } - if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) { - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = erealloc(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text[te] = 0; - if (strlen(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text) == 0) { - cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]); + if ((*lines)[li]->items[ly]->is_text) { + (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); + (*lines)[li]->items[ly]->u.text->text[te] = 0; + if (strlen((*lines)[li]->items[ly]->u.text->text) == 0) { + cho_line_item_free((*lines)[li]->items[ly]); } else { ly++; } } else { ly++; } - songs[so]->sections[se]->lines[li]->items = erealloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); - cho_style_free(songs[so]->sections[se]->lines[li]->items[ly]->u.text->style); + (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); + cho_style_free((*lines)[li]->items[ly]->u.text->style); g_current_ftype = SF_LABEL; - songs[so]->sections[se]->lines[li]->items[ly]->u.text->style = cho_style_new_default(); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = label; + (*lines)[li]->items[ly]->u.text->style = cho_style_new_default(); + (*lines)[li]->items[ly]->u.text->text = label; te += strlen(label); } break; @@ -4269,23 +4278,23 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) } break; case DT_FORMATTING: - if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) { - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = erealloc(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text[te] = 0; - if (strlen(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text) == 0) { - cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]); + if ((*lines)[li]->items[ly]->is_text) { + (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); + (*lines)[li]->items[ly]->u.text->text[te] = 0; + if (strlen((*lines)[li]->items[ly]->u.text->text) == 0) { + cho_line_item_free((*lines)[li]->items[ly]); } else { ly++; } } else { ly++; } - songs[so]->sections[se]->lines[li]->items = erealloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); - cho_style_free(songs[so]->sections[se]->lines[li]->items[ly]->u.text->style); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->style = cho_style_copy(directive->style); + (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); + cho_style_free((*lines)[li]->items[ly]->u.text->style); + (*lines)[li]->items[ly]->u.text->style = cho_style_copy(directive->style); char *trimmed_directive_value = str_remove_leading_whitespace(directive_value); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = trimmed_directive_value; + (*lines)[li]->items[ly]->u.text->text = trimmed_directive_value; te += strlen(trimmed_directive_value); break; case DT_IMAGE: @@ -4304,17 +4313,17 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) g_image_assets[g_ia] = image; g_ia++; } else { - if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) { - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = erealloc(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text[te] = 0; + if ((*lines)[li]->items[ly]->is_text) { + (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); + (*lines)[li]->items[ly]->u.text->text[te] = 0; te = 0; } ly++; - songs[so]->sections[se]->lines[li]->items = erealloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); - cho_text_free(songs[so]->sections[se]->lines[li]->items[ly]->u.text); - songs[so]->sections[se]->lines[li]->items[ly]->is_text = false; - songs[so]->sections[se]->lines[li]->items[ly]->u.image = image; + (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); + cho_text_free((*lines)[li]->items[ly]->u.text); + (*lines)[li]->items[ly]->is_text = false; + (*lines)[li]->items[ly]->u.image = image; } break; case DT_PREAMBLE: @@ -4425,24 +4434,24 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) g_prev_ftype = g_current_ftype; g_current_ftype = SF_CHORD; if (is_chord_already_initialized) { - chord_pos = cho_line_compute_chord_position(songs[so]->sections[se]->lines[li], ly, te); - songs[so]->sections[se]->lines[li]->text_above[c]->position = chord_pos; + text_above_pos = cho_line_compute_text_above_position(songs[so]->sections[se]->lines[li], ly, te); + (*lines)[li]->text_above[c]->position = text_above_pos; tmp_chord = cho_chord_parse(chord); - cho_chord_complete(songs[so]->sections[se]->lines[li]->text_above[c]->u.chord, tmp_chord); - if (!songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->is_canonical) { - cho_log(LOG_INFO, "Didn't recognize the chord '%s'.", songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->name); + cho_chord_complete((*lines)[li]->text_above[c]->u.chord, tmp_chord); + if (!(*lines)[li]->text_above[c]->u.chord->is_canonical) { + cho_log(LOG_INFO, "Didn't recognize the chord '%s'.", (*lines)[li]->text_above[c]->u.chord->name); } cho_chord_free(tmp_chord); is_chord_already_initialized = false; } else { - songs[so]->sections[se]->lines[li]->text_above = erealloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); - songs[so]->sections[se]->lines[li]->text_above[c] = emalloc(sizeof(struct ChoLineItemAbove)); - songs[so]->sections[se]->lines[li]->text_above[c]->is_chord = true; - chord_pos = cho_line_compute_chord_position(songs[so]->sections[se]->lines[li], ly, te); - songs[so]->sections[se]->lines[li]->text_above[c]->position = chord_pos; - songs[so]->sections[se]->lines[li]->text_above[c]->u.chord = cho_chord_parse(chord); - if (!songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->is_canonical) { - cho_log(LOG_INFO, "Didn't recognize the chord '%s'.", songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->name); + (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); + (*lines)[li]->text_above[c] = emalloc(sizeof(struct ChoLineItemAbove)); + (*lines)[li]->text_above[c]->is_chord = true; + text_above_pos = cho_line_compute_text_above_position((*lines)[li], ly, te); + (*lines)[li]->text_above[c]->position = text_above_pos; + (*lines)[li]->text_above[c]->u.chord = cho_chord_parse(chord); + if (!(*lines)[li]->text_above[c]->u.chord->is_canonical) { + cho_log(LOG_INFO, "Didn't recognize the chord '%s'.", (*lines)[li]->text_above[c]->u.chord->name); } } memset(chord, 0, strlen(chord)); @@ -4454,12 +4463,12 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) if (prev_buf == '[' && buf == '*') { g_prev_ftype = g_current_ftype; g_current_ftype = SF_ANNOT; - songs[so]->sections[se]->lines[li]->text_above = erealloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); - songs[so]->sections[se]->lines[li]->text_above[c] = emalloc(sizeof(struct ChoLineItemAbove)); - songs[so]->sections[se]->lines[li]->text_above[c]->is_chord = false; - chord_pos = cho_line_compute_chord_position(songs[so]->sections[se]->lines[li], ly, te); - songs[so]->sections[se]->lines[li]->text_above[c]->position = chord_pos; - songs[so]->sections[se]->lines[li]->text_above[c]->u.annot = cho_text_new(); + (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); + (*lines)[li]->text_above[c] = emalloc(sizeof(struct ChoLineItemAbove)); + (*lines)[li]->text_above[c]->is_chord = false; + text_above_pos = cho_line_compute_text_above_position((*lines)[li], ly, te); + (*lines)[li]->text_above[c]->position = text_above_pos; + (*lines)[li]->text_above[c]->u.annot = cho_text_new(); state = STATE_ANNOTATION; break; } @@ -4473,10 +4482,10 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) } if (buf == '<') { if (prev_buf == '[') { - songs[so]->sections[se]->lines[li]->text_above = erealloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); - songs[so]->sections[se]->lines[li]->text_above[c] = emalloc(sizeof(struct ChoLineItemAbove)); - songs[so]->sections[se]->lines[li]->text_above[c]->is_chord = true; - songs[so]->sections[se]->lines[li]->text_above[c]->u.chord = cho_chord_new(); + (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); + (*lines)[li]->text_above[c] = emalloc(sizeof(struct ChoLineItemAbove)); + (*lines)[li]->text_above[c]->is_chord = true; + (*lines)[li]->text_above[c]->u.chord = cho_chord_new(); is_chord_already_initialized = true; } prev_state = STATE_CHORD; @@ -4488,8 +4497,8 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) break; case STATE_ANNOTATION: if (buf == ']') { - songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text = erealloc(songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text, (ann+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text[ann] = 0; + (*lines)[li]->text_above[c]->u.annot->text = erealloc((*lines)[li]->text_above[c]->u.annot->text, (ann+1) * sizeof(char)); + (*lines)[li]->text_above[c]->u.annot->text[ann] = 0; ann = 0; c++; g_current_ftype = g_prev_ftype; @@ -4505,8 +4514,8 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) cho_log(LOG_ERR, "Newline character inside an annotation is invalid."); return NULL; } - songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text = erealloc(songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text, (ann+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text[ann] = buf; + (*lines)[li]->text_above[c]->u.annot->text = erealloc((*lines)[li]->text_above[c]->u.annot->text, (ann+1) * sizeof(char)); + (*lines)[li]->text_above[c]->u.annot->text[ann] = buf; ann++; break; case STATE_MARKUP_TAG_START: @@ -4527,27 +4536,27 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) tags[ta]->style = tag_style; switch (prev_state) { case STATE_LYRICS: - cho_style_free(songs[so]->sections[se]->lines[li]->items[ly]->u.text->style); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->style = cho_style_copy(tag_style); + cho_style_free((*lines)[li]->items[ly]->u.text->style); + (*lines)[li]->items[ly]->u.text->style = cho_style_copy(tag_style); break; case STATE_CHORD: - cho_style_free(songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->style); - songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->style = cho_style_copy(tag_style); + cho_style_free((*lines)[li]->text_above[c]->u.chord->style); + (*lines)[li]->text_above[c]->u.chord->style = cho_style_copy(tag_style); break; case STATE_ANNOTATION: if (ann > 0) { - songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text = erealloc(songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text, (ann+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text[ann] = 0; + (*lines)[li]->text_above[c]->u.annot->text = erealloc((*lines)[li]->text_above[c]->u.annot->text, (ann+1) * sizeof(char)); + (*lines)[li]->text_above[c]->u.annot->text[ann] = 0; ann = 0; c++; - songs[so]->sections[se]->lines[li]->text_above = erealloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); - songs[so]->sections[se]->lines[li]->text_above[c] = emalloc(sizeof(struct ChoLineItemAbove)); - songs[so]->sections[se]->lines[li]->text_above[c]->is_chord = false; - songs[so]->sections[se]->lines[li]->text_above[c]->position = chord_pos; - songs[so]->sections[se]->lines[li]->text_above[c]->u.annot = cho_text_new(); + (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); + (*lines)[li]->text_above[c] = emalloc(sizeof(struct ChoLineItemAbove)); + (*lines)[li]->text_above[c]->is_chord = false; + (*lines)[li]->text_above[c]->position = text_above_pos; + (*lines)[li]->text_above[c]->u.annot = cho_text_new(); } - cho_style_free(songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->style); - songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->style = cho_style_copy(tag_style); + cho_style_free((*lines)[li]->text_above[c]->u.annot->style); + (*lines)[li]->text_above[c]->u.annot->style = cho_style_copy(tag_style); break; default: cho_log(LOG_ERR, "Invalid prev_state '%s'.", state_enums[prev_state]); @@ -4646,17 +4655,17 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) cho_tag_attr_free(tags[ta]->attrs[at]); tags[ta]->attrs[at] = NULL; if (!strcmp(tags[ta]->name, "img")) { - cho_text_free(songs[so]->sections[se]->lines[li]->items[ly]->u.text); - songs[so]->sections[se]->lines[li]->items[ly]->is_text = false; + cho_text_free((*lines)[li]->items[ly]->u.text); + (*lines)[li]->items[ly]->is_text = false; image = cho_image_tag_parse(tags[ta]->attrs); if (!image) { LOG_DEBUG("cho_image_tag_parse failed."); return NULL; } - songs[so]->sections[se]->lines[li]->items[ly]->u.image = image; + (*lines)[li]->items[ly]->u.image = image; ly++; - songs[so]->sections[se]->lines[li]->items = erealloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); + (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); } else { tag_style = cho_style_parse(tag_start, tags[ta]->attrs, cho_tag_style_inherit(tags, ta-1)); if (!tag_style) { @@ -4666,16 +4675,16 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) tags[ta]->style = tag_style; switch (prev_state) { case STATE_LYRICS: - cho_style_free(songs[so]->sections[se]->lines[li]->items[ly]->u.text->style); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->style = cho_style_copy(tag_style); + cho_style_free((*lines)[li]->items[ly]->u.text->style); + (*lines)[li]->items[ly]->u.text->style = cho_style_copy(tag_style); break; case STATE_CHORD: - cho_style_free(songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->style); - songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->style = cho_style_copy(tag_style); + cho_style_free((*lines)[li]->text_above[c]->u.chord->style); + (*lines)[li]->text_above[c]->u.chord->style = cho_style_copy(tag_style); break; case STATE_ANNOTATION: - cho_style_free(songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->style); - songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->style = cho_style_copy(tag_style); + cho_style_free((*lines)[li]->text_above[c]->u.annot->style); + (*lines)[li]->text_above[c]->u.annot->style = cho_style_copy(tag_style); break; default: cho_log(LOG_ERR, "Invalid prev_state '%s'.", state_enums[prev_state]); @@ -4736,17 +4745,17 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) tags[ta]->attrs = erealloc(tags[ta]->attrs, (at+1) * sizeof(struct Attr *)); tags[ta]->attrs[at] = NULL; if (!strcmp(tags[ta]->name, "img")) { - cho_text_free(songs[so]->sections[se]->lines[li]->items[ly]->u.text); - songs[so]->sections[se]->lines[li]->items[ly]->is_text = false; + cho_text_free((*lines)[li]->items[ly]->u.text); + (*lines)[li]->items[ly]->is_text = false; image = cho_image_tag_parse(tags[ta]->attrs); if (!image) { LOG_DEBUG("cho_image_tag_parse failed."); return NULL; } - songs[so]->sections[se]->lines[li]->items[ly]->u.image = image; + (*lines)[li]->items[ly]->u.image = image; ly++; - songs[so]->sections[se]->lines[li]->items = erealloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new(); + (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = cho_line_item_new(); } else { tag_style = cho_style_parse(tag_start, tags[ta]->attrs, cho_tag_style_inherit(tags, ta-1)); if (!tag_style) { @@ -4756,16 +4765,16 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) tags[ta]->style = tag_style; switch (prev_state) { case STATE_LYRICS: - cho_style_free(songs[so]->sections[se]->lines[li]->items[ly]->u.text->style); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->style = cho_style_copy(tag_style); + cho_style_free((*lines)[li]->items[ly]->u.text->style); + (*lines)[li]->items[ly]->u.text->style = cho_style_copy(tag_style); break; case STATE_CHORD: - cho_style_free(songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->style); - songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->style = cho_style_copy(tag_style); + cho_style_free((*lines)[li]->text_above[c]->u.chord->style); + (*lines)[li]->text_above[c]->u.chord->style = cho_style_copy(tag_style); break; case STATE_ANNOTATION: - cho_style_free(songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->style); - songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->style = cho_style_copy(tag_style); + cho_style_free((*lines)[li]->text_above[c]->u.annot->style); + (*lines)[li]->text_above[c]->u.annot->style = cho_style_copy(tag_style); break; default: cho_log(LOG_ERR, "Invalid prev_state '%s'.", state_enums[prev_state]); @@ -4815,24 +4824,24 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) e++; } free(tags); - if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) { - if (songs[so]->sections[se]->lines[li]->items[ly]->u.text->text) { - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = erealloc(songs[so]->sections[se]->lines[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); - songs[so]->sections[se]->lines[li]->items[ly]->u.text->text[te] = 0; + if ((*lines)[li]->items[ly]->is_text) { + if ((*lines)[li]->items[ly]->u.text->text) { + (*lines)[li]->items[ly]->u.text->text = erealloc((*lines)[li]->items[ly]->u.text->text, (te+1) * sizeof(char)); + (*lines)[li]->items[ly]->u.text->text[te] = 0; ly++; - songs[so]->sections[se]->lines[li]->items = erealloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); - songs[so]->sections[se]->lines[li]->items[ly] = NULL; - songs[so]->sections[se]->lines[li]->text_above = erealloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); - songs[so]->sections[se]->lines[li]->text_above[c] = NULL; + (*lines)[li]->items = erealloc((*lines)[li]->items, (ly+1) * sizeof(struct ChoLineItem *)); + (*lines)[li]->items[ly] = NULL; + (*lines)[li]->text_above = erealloc((*lines)[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *)); + (*lines)[li]->text_above[c] = NULL; li++; - songs[so]->sections[se]->lines = erealloc(songs[so]->sections[se]->lines, (li+1) * sizeof(struct ChoLine *)); - songs[so]->sections[se]->lines[li] = NULL; + *lines = erealloc(*lines, (li+1) * sizeof(struct ChoLine *)); + (*lines)[li] = NULL; } else { - cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]); - free(songs[so]->sections[se]->lines[li]->items); - free(songs[so]->sections[se]->lines[li]->text_above); - free(songs[so]->sections[se]->lines[li]); - songs[so]->sections[se]->lines[li] = NULL; + cho_line_item_free((*lines)[li]->items[ly]); + free((*lines)[li]->items); + free((*lines)[li]->text_above); + free((*lines)[li]); + (*lines)[li] = NULL; } } if (!cho_style_reset_default()) { @@ -4849,13 +4858,19 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) so++; songs = erealloc(songs, (so+1) * sizeof(struct ChoSong *)); songs[so] = NULL; + g_current_ftype = SF_TEXT; + g_prev_ftype = SF_TEXT; + g_config = NULL; + g_chordpro_filepath = NULL; free(g_transpose_history); g_transpose_history = NULL; + g_transpose = NULL; g_line_number = 1; for (e = 0; e<g_ia; e++) { cho_image_free(g_image_assets[e]); } free(g_image_assets); + g_image_assets = NULL; g_ia = 0; bool exist_title = false; for (so = 0; songs[so]; so++) { diff --git a/chordpro.h b/chordpro.h @@ -12,6 +12,40 @@ #define URL_MAX_LEN 2000 #define FONT_NAME_MAX 100 +enum Alignment { + A_LEFT, + A_CENTER, + A_RIGHT +}; + +enum Anchor { + AN_PAPER, + AN_PAGE, + AN_COLUMN, + AN_LINE, + AN_FLOAT +}; + +enum AttrValueSyntax { + AVS_NO, + AVS_QUOTATION_MARK, + AVS_APOSTROPHE, + AVS_UNQUOTED +}; + +enum BreakType { + BT_EMPTY, + BT_LINE, + BT_PAGE, + BT_COLUMN +}; + +enum ChordDiagramContent { + CDC_EMPTY, + CDC_STRING, + CDC_KEYBOARD +}; + enum ChordDiagramState { CDS_NAME, CDS_OPTION_NAME, @@ -21,19 +55,29 @@ enum ChordDiagramState { CDS_KEYS }; -enum ChordDiagramContent { - CDC_EMPTY, - CDC_STRING, - CDC_KEYBOARD +enum ChordDirective { + TRANSPOSE, DEFINE /* , CHORD */ }; -enum MetadataDirective { - TITLE, - SUBTITLE +enum ChordQualifier { + CQ_EMPTY, + CQ_MIN, + CQ_MAJ, + CQ_AUG, + CQ_DIM }; -enum ChordDirective { - TRANSPOSE, DEFINE /* , CHORD */ +enum DirectiveType { + DT_EMPTY, + DT_ENVIRONMENT, + DT_METADATA, + DT_FORMATTING, + DT_IMAGE, + DT_PREAMBLE, + DT_FONT, + DT_CHORD, + DT_OUTPUT, + DT_CUSTOM }; enum FontFamily { @@ -57,14 +101,6 @@ enum FontWeight { FW_EMPTY }; -struct Font { - char *name; - enum FontFamily family; - enum FontStyle style; - enum FontWeight weight; - double size; -}; - enum LineStyle { LS_SINGLE, LS_DOUBLE, @@ -72,52 +108,9 @@ enum LineStyle { LS_EMPTY }; -struct RGBColor { - uint8_t red; - uint8_t green; - uint8_t blue; -}; - -struct ChoStyle { - struct Font *font; - struct RGBColor *foreground_color; - struct RGBColor *background_color; - enum LineStyle underline_style; - struct RGBColor *underline_color; - enum LineStyle overline_style; - struct RGBColor *overline_color; - bool strikethrough; - struct RGBColor *strikethrough_color; - bool boxed; - struct RGBColor *boxed_color; - double rise; - char *href; -}; - -struct Attr { - char *name; - char *value; -}; - -struct Tag { - char *name; - struct ChoStyle *style; - struct Attr **attrs; - bool is_closed; -}; - -enum Alignment { - A_LEFT, - A_CENTER, - A_RIGHT -}; - -enum Anchor { - AN_PAPER, - AN_PAGE, - AN_COLUMN, - AN_LINE, - AN_FLOAT +enum MetadataDirective { + TITLE, + SUBTITLE }; enum OptionState { @@ -125,47 +118,21 @@ enum OptionState { OS_VALUE }; -struct ChoImage { - bool is_asset; - char *id; - char *src; - struct Size *width; - struct Size *height; - struct Size *width_scale; - struct Size *height_scale; - enum Alignment align; - double border; - struct Size *spread_space; - char *href; - struct Size *x; - struct Size *y; - enum Anchor anchor; - struct Size *dx; - struct Size *dy; - struct Size *w; - struct Size *h; - bool bbox; -}; - -enum AttrValueSyntax { - AVS_NO, - AVS_QUOTATION_MARK, - AVS_APOSTROPHE, - AVS_UNQUOTED +enum Position { + POS_EMPTY, + POS_START, + POS_END }; -enum State { - STATE_LYRICS, - STATE_DIRECTIVE_NAME, - STATE_DIRECTIVE_VALUE, - STATE_CHORD, - STATE_ANNOTATION, - STATE_MARKUP_TAG_START, - STATE_MARKUP_TAG_END, - STATE_MARKUP_TAG, - STATE_MARKUP_ATTR_NAME, - STATE_MARKUP_ATTR_VALUE, - STATE_COMMENT +enum SectionType { + ST_EMPTY, + ST_NEWSONG, + ST_CHORUS, + ST_VERSE, + ST_BRIDGE, + ST_TAB, + ST_GRID, + ST_CUSTOM }; enum SongFragmentType { @@ -183,6 +150,20 @@ enum SongFragmentType { SF_LABEL }; +enum State { + STATE_LYRICS, + STATE_DIRECTIVE_NAME, + STATE_DIRECTIVE_VALUE, + STATE_CHORD, + STATE_ANNOTATION, + STATE_MARKUP_TAG_START, + STATE_MARKUP_TAG_END, + STATE_MARKUP_TAG, + STATE_MARKUP_ATTR_NAME, + STATE_MARKUP_ATTR_VALUE, + STATE_COMMENT +}; + enum StylePropertyType { SPT_EMPTY, SPT_FONT, @@ -190,61 +171,49 @@ enum StylePropertyType { SPT_COLOR }; -union StylePropertyValue { - char *font_name; - double font_size; - struct RGBColor *foreground_color; -}; - -struct StyleProperty { - enum SongFragmentType ftype; - enum StylePropertyType type; - union StylePropertyValue u; -}; - -enum DirectiveType { - DT_EMPTY, - DT_ENVIRONMENT, - DT_METADATA, - DT_FORMATTING, - DT_IMAGE, - DT_PREAMBLE, - DT_FONT, - DT_CHORD, - DT_OUTPUT, - DT_CUSTOM +struct Attr { + char *name; + char *value; }; -enum SectionType { - ST_EMPTY, - ST_NEWSONG, - ST_CHORUS, - ST_VERSE, - ST_BRIDGE, - ST_TAB, - ST_GRID, - ST_CUSTOM +struct Font { + char *name; + enum FontFamily family; + enum FontStyle style; + enum FontWeight weight; + double size; }; -enum Position { - POS_EMPTY, - POS_START, - POS_END +struct RGBColor { + uint8_t red; + uint8_t green; + uint8_t blue; }; -enum ChordQualifier { - CQ_EMPTY, - CQ_MIN, - CQ_MAJ, - CQ_AUG, - CQ_DIM +struct ChoStyle { + struct Font *font; + struct RGBColor *foreground_color; + struct RGBColor *background_color; + enum LineStyle underline_style; + struct RGBColor *underline_color; + enum LineStyle overline_style; + struct RGBColor *overline_color; + bool strikethrough; + struct RGBColor *strikethrough_color; + bool boxed; + struct RGBColor *boxed_color; + double rise; + char *href; }; -enum BreakType { - BT_EMPTY, - BT_LINE, - BT_PAGE, - BT_COLUMN +struct ChoChord { + struct ChoStyle *style; + bool is_canonical; + char *name; + char *root; + enum ChordQualifier qual; + char *ext; + char *bass; }; /* @@ -264,20 +233,26 @@ struct ChoDirective { struct ChoStyle *style; }; -struct ChoMetadata { - char *name; - char *value; - struct ChoStyle *style; -}; - -struct ChoChord { - struct ChoStyle *style; - bool is_canonical; - char *name; - char *root; - enum ChordQualifier qual; - char *ext; - char *bass; +struct ChoImage { + bool is_asset; + char *id; + char *src; + struct Size *width; + struct Size *height; + struct Size *width_scale; + struct Size *height_scale; + enum Alignment align; + double border; + struct Size *spread_space; + char *href; + struct Size *x; + struct Size *y; + enum Anchor anchor; + struct Size *dx; + struct Size *dy; + struct Size *w; + struct Size *h; + bool bbox; }; struct ChoText { @@ -308,6 +283,12 @@ struct ChoLine { enum BreakType btype; }; +struct ChoMetadata { + char *name; + char *value; + struct ChoStyle *style; +}; + struct ChoSection { enum SectionType type; struct ChoText *label; @@ -320,6 +301,26 @@ struct ChoSong { struct ChordDiagram **diagrams; }; +union StylePropertyValue { + char *font_name; + double font_size; + struct RGBColor *foreground_color; +}; + +struct StyleProperty { + enum SongFragmentType ftype; + enum StylePropertyType type; + union StylePropertyValue u; +}; + +struct Tag { + char *name; + struct ChoStyle *style; + struct Attr **attrs; + bool is_closed; +}; + + struct ChoSong **cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config); int cho_song_count(struct ChoSong **songs); int cho_song_compare(const void *a, const void *b); diff --git a/out_pdf.h b/out_pdf.h @@ -19,27 +19,21 @@ enum LineLocation { LL_UNDER }; -struct Obj { - char *name; - pdfio_obj_t *value; -}; - -struct SpaceNeeded { +struct CharPosition { int line_item_index; int text_index; - int text_above_index; - double amount; }; -struct CharPosition { - int line_item_index; - int text_index; +struct Obj { + char *name; + pdfio_obj_t *value; }; -struct TocEntry { - int page_index; - double page_y; - char *title; +struct PDFText { + char *text; + struct ChoStyle *style; + double x; + double y; }; struct PDFImage { @@ -51,13 +45,6 @@ struct PDFImage { pdfio_obj_t *obj; }; -struct PDFText { - char *text; - struct ChoStyle *style; - double x; - double y; -}; - struct PDFPage { struct PDFText **texts; struct PDFImage **images; @@ -65,11 +52,24 @@ struct PDFPage { struct ChordDiagram **diagrams; }; +struct TocEntry { + int page_index; + double page_y; + char *title; +}; + struct PDFContent { struct PDFPage **pages; struct TocEntry **toc; }; +struct SpaceNeeded { + int line_item_index; + int text_index; + int text_above_index; + double amount; +}; + struct PDFContext { struct PDFContent *content; double x;