lorid

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

commit b589ffd2a01350f88c5676b737b0da0280978838
parent 9d9c20021fc5f2537a7057cc906a04f6155781e4
Author: nibo <nibo@relim.de>
Date:   Tue, 11 Jun 2024 21:28:56 +0200

Work

Diffstat:
Mchordpro.c | 113++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mchordpro.h | 42+++++++++---------------------------------
Mlorid.c | 73++++++++++++++++++++++++++++++++++++++++---------------------------------
3 files changed, 120 insertions(+), 108 deletions(-)

diff --git a/chordpro.c b/chordpro.c @@ -46,8 +46,6 @@ static const char *the_state(enum State state) return "STATE_MARKUP_TAG_BEGIN"; case STATE_MARKUP_TAG_END: return "STATE_MARKUP_TAG_END"; - case STATE_MARKUP_TAG_INSIDE: - return "STATE_MARKUP_TAG_INSIDE"; case STATE_MARKUP_TAG: return "STATE_MARKUP_TAG"; case STATE_MARKUP_ATTR_NAME: @@ -78,8 +76,6 @@ const char *the_dtype(enum DirectiveType dtype) const char *the_stype(enum SectionType stype) { switch (stype) { - case ST_NOTHING: - return "ST_NOTHING"; case ST_CHORUS: return "ST_CHORUS"; case ST_VERSE: @@ -99,10 +95,8 @@ const char *the_stype(enum SectionType stype) const char *the_pos(enum Position pos) { switch (pos) { - case POS_NOTHING: - return "POS_NOTHING"; - case POS_BEGIN: - return "POS_BEGIN"; + case POS_START: + return "POS_START"; case POS_END: return "POS_END"; } @@ -386,13 +380,13 @@ struct Style *cho_style_duplicate(struct Style *style) return copy; } -struct Style *cho_style_get(const char *tag_name, struct Attr **attrs, struct Style *prev_style) +struct Style *cho_style_get(const char *tag_name, struct Attr **attrs, struct Style *inherited_style) { size_t value_len, last_char; struct RGBColor *rgb_color; struct Style *style; - if (prev_style) - style = cho_style_duplicate(prev_style); + if (inherited_style) + style = cho_style_duplicate(inherited_style); else style = cho_style_new(); if (strcmp(tag_name, "span") == 0) { @@ -708,7 +702,7 @@ void cho_tag_close_last_unclosed(const char *tag_name, struct Tag **tags, int la { int i = last_index; while (i >= 0) { - if (strcmp(tags[i]->name, tag_name) == 0) { + if (strcmp(tags[i]->name, tag_name) == 0 && !tags[i]->is_closed) { tags[i]->is_closed = true; return; } @@ -717,6 +711,24 @@ void cho_tag_close_last_unclosed(const char *tag_name, struct Tag **tags, int la fprintf(stderr, "INFO: Didn't find a start tag for the end tag '%s'.\n", tag_name); } +struct Style *cho_tag_style_inherit(struct Tag **tags, int prev_index) +{ + int i = prev_index; + while (i >= 0) { + if (!tags[i]->is_closed) { + return tags[i]->style; + } + i--; + } + /* + Doesn't mean there is an error. + If no style can be inherited the + default style should be used. + */ + printf("cho_tag_style_inherit: Return NULL\n"); + return NULL; +} + void cho_directive_free(struct ChoDirective *directive) { cho_style_free(directive->style); @@ -805,7 +817,7 @@ void cho_line_item_free(struct ChoLineItem *item) struct ChoSection *cho_section_new(void) { struct ChoSection *section = malloc(sizeof(struct ChoSection)); - section->type = ST_NOTHING; + section->type = -1; section->name = NULL; section->lines = NULL; return section; @@ -883,7 +895,7 @@ struct ChoDirective *directive_parse(const char *name) strcmp(name, environment_directives[1]) == 0 ) { directive->dtype = DT_ENVIRONMENT; - directive->position = POS_BEGIN; + directive->position = POS_START; directive->stype = ST_CHORUS; goto END; } else if ( @@ -899,7 +911,7 @@ struct ChoDirective *directive_parse(const char *name) strcmp(name, environment_directives[6]) == 0 ) { directive->dtype = DT_ENVIRONMENT; - directive->position = POS_BEGIN; + directive->position = POS_START; directive->stype = ST_VERSE; goto END; } else if ( @@ -915,7 +927,7 @@ struct ChoDirective *directive_parse(const char *name) strcmp(name, environment_directives[10]) == 0 ) { directive->dtype = DT_ENVIRONMENT; - directive->position = POS_BEGIN; + directive->position = POS_START; directive->stype = ST_BRIDGE; goto END; } else if ( @@ -931,7 +943,7 @@ struct ChoDirective *directive_parse(const char *name) strcmp(name, environment_directives[14]) == 0 ) { directive->dtype = DT_ENVIRONMENT; - directive->position = POS_BEGIN; + directive->position = POS_START; directive->stype = ST_TAB; goto END; } else if ( @@ -947,7 +959,7 @@ struct ChoDirective *directive_parse(const char *name) strcmp(name, environment_directives[18]) == 0 ) { directive->dtype = DT_ENVIRONMENT; - directive->position = POS_BEGIN; + directive->position = POS_START; directive->stype = ST_GRID; goto END; } else if ( @@ -962,8 +974,8 @@ struct ChoDirective *directive_parse(const char *name) while (metadata_directives[i] != NULL) { if (strcmp(metadata_directives[i], name) == 0) { directive->dtype = DT_METADATA; - directive->stype = ST_NOTHING; - directive->position = POS_NOTHING; + directive->stype = -1; + directive->position = -1; goto END; } i++; @@ -976,8 +988,8 @@ struct ChoDirective *directive_parse(const char *name) ) { directive->style->background_color = cho_rgbcolor_new(228, 228, 228); directive->dtype = DT_FORMATTING; - directive->stype = ST_NOTHING; - directive->position = POS_NOTHING; + directive->stype = -1; + directive->position = -1; goto END; } else if ( strcmp(formatting_directives[3], name) == 0 || @@ -985,8 +997,8 @@ struct ChoDirective *directive_parse(const char *name) ) { directive->style->font_style = FS_ITALIC; directive->dtype = DT_FORMATTING; - directive->stype = ST_NOTHING; - directive->position = POS_NOTHING; + directive->stype = -1; + directive->position = -1; goto END; } else if ( strcmp(formatting_directives[5], name) == 0 || @@ -994,22 +1006,22 @@ struct ChoDirective *directive_parse(const char *name) ) { directive->style->boxed = true; directive->dtype = DT_FORMATTING; - directive->stype = ST_NOTHING; - directive->position = POS_NOTHING; + directive->stype = -1; + directive->position = -1; goto END; } while (preamble_directives[i] != NULL) { if (strcmp(preamble_directives[i], name) == 0) { directive->dtype = DT_PREAMBLE; directive->stype = ST_NEWSONG; - directive->position = POS_NOTHING; + directive->position = -1; goto END; } i++; } directive->dtype = DT_CUSTOM; - directive->stype = ST_NOTHING; - directive->position = POS_NOTHING; + directive->stype = -1; + directive->position = -1; END: return directive; } @@ -1032,8 +1044,6 @@ struct ChoSong **cho_parse(FILE *fp) int m = 0; int ly = 0; int t = 0; - int an = 0; - int av = 0; int so = 0; int se = 0; int li = 0; @@ -1055,7 +1065,6 @@ struct ChoSong **cho_parse(FILE *fp) songs[so]->sections[se]->lines[li]->lyrics = malloc(sizeof(struct ChoLineItem *)); songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new(); struct Tag **tags = NULL; - struct Style *prev_style; struct Style *tag_style; while (feof(fp) == 0) { read = fread(&buf, 1, 1, fp); @@ -1074,6 +1083,7 @@ struct ChoSong **cho_parse(FILE *fp) if (buf == '<') { songs[so]->sections[se]->lines[li]->lyrics[ly]->text = realloc(songs[so]->sections[se]->lines[li]->lyrics[ly]->text, (te+1) * sizeof(char)); songs[so]->sections[se]->lines[li]->lyrics[ly]->text[te] = 0; + te = 0; ly++; songs[so]->sections[se]->lines[li]->lyrics = realloc(songs[so]->sections[se]->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *)); songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new(); @@ -1084,11 +1094,26 @@ struct ChoSong **cho_parse(FILE *fp) if (buf == '\n') { songs[so]->sections[se]->lines[li]->lyrics[ly]->text = realloc(songs[so]->sections[se]->lines[li]->lyrics[ly]->text, (te+1) * sizeof(char)); songs[so]->sections[se]->lines[li]->lyrics[ly]->text[te] = 0; - te = 0; - ly++; + if (strlen(songs[so]->sections[se]->lines[li]->lyrics[ly]->text) == 0) { + cho_line_item_free(songs[so]->sections[se]->lines[li]->lyrics[ly]); + if (ly == 0) { + if (!songs[so]->sections[se]->lines[li]->chords) { + free(songs[so]->sections[se]->lines[li]->lyrics); + free(songs[so]->sections[se]->lines[li]); + songs[so]->sections[se]->lines = realloc(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]->lyrics = realloc(songs[so]->sections[se]->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *)); + songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new(); + break; + } + } + } else { + ly++; + } songs[so]->sections[se]->lines[li]->lyrics = realloc(songs[so]->sections[se]->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *)); songs[so]->sections[se]->lines[li]->lyrics[ly] = NULL; ly = 0; + te = 0; songs[so]->sections[se]->lines[li]->chords = realloc(songs[so]->sections[se]->lines[li]->chords, (c+1) * sizeof(struct ChoChord *)); songs[so]->sections[se]->lines[li]->chords[c] = NULL; c = 0; @@ -1115,7 +1140,7 @@ struct ChoSong **cho_parse(FILE *fp) switch (directive->dtype) { case DT_ENVIRONMENT: switch (directive->position) { - case POS_BEGIN: + case POS_START: cho_line_item_free(songs[so]->sections[se]->lines[li]->lyrics[ly]); free(songs[so]->sections[se]->lines[li]->lyrics); ly = 0; @@ -1210,7 +1235,7 @@ struct ChoSong **cho_parse(FILE *fp) switch (directive->dtype) { case DT_ENVIRONMENT: switch (directive->position) { - case POS_BEGIN: + case POS_START: cho_line_item_free(songs[so]->sections[se]->lines[li]->lyrics[ly]); free(songs[so]->sections[se]->lines[li]->lyrics); ly = 0; @@ -1263,13 +1288,17 @@ struct ChoSong **cho_parse(FILE *fp) } break; case DT_FORMATTING: + songs[so]->sections[se]->lines[li]->lyrics[ly]->text = realloc(songs[so]->sections[se]->lines[li]->lyrics[ly]->text, (te+1) * sizeof(char)); + songs[so]->sections[se]->lines[li]->lyrics[ly]->text[te] = 0; ly++; songs[so]->sections[se]->lines[li]->lyrics = realloc(songs[so]->sections[se]->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *)); songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new(); cho_style_free(songs[so]->sections[se]->lines[li]->lyrics[ly]->style); songs[so]->sections[se]->lines[li]->lyrics[ly]->style = cho_style_duplicate(directive->style); - songs[so]->sections[se]->lines[li]->lyrics[ly]->text = string_remove_leading_whitespace(directive_value); - te = 0; + char *trimmed_directive_value = string_remove_leading_whitespace(directive_value); + songs[so]->sections[se]->lines[li]->lyrics[ly]->text = trimmed_directive_value; + te += strlen(trimmed_directive_value); + // te = 0; break; case DT_PREAMBLE: fprintf(stderr, "INFO: Preamble directive '%s' can't have a value.\n", directive_name); @@ -1308,7 +1337,7 @@ struct ChoSong **cho_parse(FILE *fp) tag_begin[t] = 0; t = 0; tags[ta]->name = strdup(tag_begin); - tag_style = cho_style_get(tag_begin, NULL, ta == 0 ? NULL : tags[ta-1]->style); + tag_style = cho_style_get(tag_begin, NULL, cho_tag_style_inherit(tags, ta-1)); if (tag_style == NULL) { fprintf(stderr, "cho_style_get failed.\n"); return NULL; @@ -1345,7 +1374,7 @@ struct ChoSong **cho_parse(FILE *fp) tags = realloc(tags, (ta+1) * sizeof(struct Tag *)); tags[ta] = cho_tag_new(); state = STATE_MARKUP_TAG_BEGIN; - // If we not use 'goto' we loose the first character of the begin tag name + // If we don't use 'goto' we loose the first character of the begin tag name goto MARKUP_TAG_BEGIN; case STATE_MARKUP_TAG_END: if (buf == '>') { @@ -1397,7 +1426,7 @@ struct ChoSong **cho_parse(FILE *fp) if (tags[ta]->attrs[at-1]->value) { cho_tag_attr_free(tags[ta]->attrs[at]); tags[ta]->attrs[at] = NULL; - tag_style = cho_style_get(tag_begin, tags[ta]->attrs, ta == 0 ? NULL : tags[ta-1]->style); + tag_style = cho_style_get(tag_begin, tags[ta]->attrs, cho_tag_style_inherit(tags, ta-1)); if (tag_style == NULL) { fprintf(stderr, "cho_style_get failed.\n"); return NULL; @@ -1454,7 +1483,7 @@ struct ChoSong **cho_parse(FILE *fp) at++; tags[ta]->attrs = realloc(tags[ta]->attrs, (at+1) * sizeof(struct Attr *)); tags[ta]->attrs[at] = NULL; - tag_style = cho_style_get(tag_begin, tags[ta]->attrs, ta == 0 ? NULL : tags[ta-1]->style); + tag_style = cho_style_get(tag_begin, tags[ta]->attrs, cho_tag_style_inherit(tags, ta-1)); if (tag_style == NULL) { fprintf(stderr, "cho_style_get failed.\n"); return NULL; diff --git a/chordpro.h b/chordpro.h @@ -55,26 +55,6 @@ struct Style { char *href; }; -/* struct StyleHelper { - bool exist_font; - bool exist_font_family; - bool exist_font_size; - bool exist_font_style; - bool exist_font_weight; - bool exist_foreground_color; - bool exist_background_color; - bool exist_underline_style; - bool exist_underline_color; - bool exist_overline_style; - bool exist_overline_color; - bool exist_strikethrough; - bool exist_strikethrough_color; - bool exist_boxed; - bool exist_boxed_color; - bool exist_rise; - bool exist_href; -}; */ - struct Attr { char *name; char *value; @@ -101,7 +81,6 @@ enum State { STATE_CHORD, STATE_MARKUP_TAG_BEGIN, STATE_MARKUP_TAG_END, - STATE_MARKUP_TAG_INSIDE, STATE_MARKUP_TAG, STATE_MARKUP_ATTR_NAME, STATE_MARKUP_ATTR_VALUE @@ -117,7 +96,6 @@ enum DirectiveType { enum SectionType { ST_NEWSONG, - ST_NOTHING, ST_CHORUS, ST_VERSE, ST_BRIDGE, @@ -126,18 +104,10 @@ enum SectionType { }; enum Position { - POS_NOTHING, - POS_BEGIN, // rename to POS_START + POS_START, POS_END }; -/* enum LineStyle { - LS_NORMAL, - LS_GREY_BACKGROUND, - LS_ITALIC, - LS_BOX -}; */ - struct ChoDirective { enum DirectiveType dtype; enum SectionType stype; @@ -162,9 +132,7 @@ struct ChoLineItem { }; struct ChoLine { - // enum LineStyle style; struct ChoChord **chords; - // char *lyrics; struct ChoLineItem **lyrics; }; @@ -181,6 +149,14 @@ struct ChoSong { struct ChoSong **cho_parse(FILE *fp); void cho_songs_free(struct ChoSong **song); +void cho_style_print(struct Style *style); + +/* Debugging */ const char *the_dtype(enum DirectiveType dtype); const char *the_stype(enum SectionType stype); const char *the_pos(enum Position pos); +const char *the_font_family(enum FontFamily font_family); +const char *the_font_style(enum FontStyle style); +const char *the_font_weight(enum FontWeight weight); +const char *the_rgb_color(struct RGBColor *color); +const char *the_line_style(enum LineStyle style); diff --git a/lorid.c b/lorid.c @@ -46,39 +46,46 @@ int main(int argc, char *argv[]) /* m++;*/ /*}*/ /*printf("---- END METADATA ------\n");*/ - /*char *lyrics;*/ - /*struct ChoChord **chords;*/ - /*enum SectionType stype;*/ - /*enum LineStyle style;*/ - /*int s = 0;*/ - /*int li = 0;*/ - /*int c = 0;*/ - /*while (song->sections[s] != NULL) {*/ - /* printf("---- BEGIN SECTION ----\n");*/ - /* stype = song->sections[s]->type;*/ - /* printf("stype: %s\n", the_stype(stype));*/ - /* if (song->sections[s]->name) {*/ - /* printf("name: %s\n", song->sections[s]->name);*/ - /* }*/ - /* while (song->sections[s]->lines[li] != NULL) {*/ - /* chords = song->sections[s]->lines[li]->chords;*/ - /* while (chords[c] != NULL) {*/ - /* printf("index: %d, chord: %s | ", chords[c]->index_in_lyrics, chords[c]->chord);*/ - /* c++;*/ - /* }*/ - /* printf("\n");*/ - /* c = 0;*/ - /* style = song->sections[s]->lines[li]->style;*/ - /* lyrics = song->sections[s]->lines[li]->lyrics;*/ - /* if (strlen(lyrics) > 0) {*/ - /* printf("style %s, line %s\n", the_style(style), lyrics);*/ - /* }*/ - /* li++;*/ - /* }*/ - /* li = 0;*/ - /* s++;*/ - /* printf("---- END SECTION ------\n");*/ - /*}*/ + // struct ChoChord **chords; + enum SectionType stype; + struct ChoLineItem *line_item; + int s = 0; + int li = 0; + // int c = 0; + int ly = 0; + struct ChoSong *song = songs[0]; + while (song->sections[s] != NULL) { + printf("---- BEGIN SECTION ----\n"); + stype = song->sections[s]->type; + printf("stype: %s\n", the_stype(stype)); + if (song->sections[s]->name) { + printf("name: %s\n", song->sections[s]->name); + } + while (song->sections[s]->lines[li] != NULL) { + printf("---- BEGIN LINE ----\n"); + /* chords = song->sections[s]->lines[li]->chords; + while (chords[c] != NULL) { + printf("index: %d, chord: %s | ", chords[c]->index_in_lyrics, chords[c]->chord); + c++; + } + printf("\n"); + c = 0; */ + while (song->sections[s]->lines[li]->lyrics[ly] != NULL) { + line_item = song->sections[s]->lines[li]->lyrics[ly]; + if (strlen(line_item->text) > 0) { + printf("text: %s\n", line_item->text); + cho_style_print(line_item->style); + } + ly++; + } + ly = 0; + li++; + printf("---- END LINE ------\n"); + } + li = 0; + s++; + printf("---- END SECTION ------\n"); + } cho_songs_free(songs); fclose(fp); return 0;