commit fdafe328e5c6b9b4c4cc7d300cde2f922753e84b
parent 983d4d0ada2f4230ec7c4d70f4e5766c628e1136
Author: nibo <nibo@relim.de>
Date: Tue, 22 Oct 2024 10:46:16 +0200
Change struct 'ChoLineItem' to contain either text or an image
The struct 'ChoLineItem' is the fundamental type for this
project. Changing its definition meant changing a lot of
code in the whole project.
Also create a basis type for styled text 'ChoText'. This type
can be then used in different places. Every text in this
chordpro implementation should have a corresponding style.
Diffstat:
| M | chordpro.c | | | 859 | ++++++++++++++++++++++++++++++++++++++++++------------------------------------- |
| M | chordpro.h | | | 34 | +++++++++------------------------- |
| M | out_pdf.c | | | 69 | ++++++++++++++++++++++++++++++++++++++++----------------------------- |
| M | util.c | | | 14 | ++++++++++++++ |
| M | util.h | | | 1 | + |
5 files changed, 521 insertions(+), 456 deletions(-)
diff --git a/chordpro.c b/chordpro.c
@@ -1930,266 +1930,6 @@ cho_chord_name_generate(struct ChoChord *chord)
return strdup(chord->name);
}
-static struct ChoAnnotation *
-cho_annotation_new(void)
-{
- struct ChoAnnotation *annot = malloc(sizeof(struct ChoAnnotation));
- annot->style = cho_style_new_default();
- annot->text = NULL;
- return annot;
-}
-
-static void
-cho_annotation_free(struct ChoAnnotation *annot)
-{
- cho_style_free(annot->style);
- free(annot->text);
- free(annot);
-}
-
-static struct ChoAnnotation *
-cho_annotation_copy(struct ChoAnnotation *annot)
-{
- struct ChoAnnotation *copy = malloc(sizeof(struct ChoAnnotation));
- copy->style = cho_style_copy(annot->style);
- copy->text = strdup(annot->text);
- return copy;
-}
-
-int
-cho_text_above_count(struct ChoLineItemAbove **text_above)
-{
- int i = 0;
- while (text_above[i] != NULL)
- i++;
- return i;
-}
-
-static void
-cho_text_above_free(struct ChoLineItemAbove *text_above)
-{
- if (text_above->is_chord) {
- cho_chord_free(text_above->u.chord);
- } else {
- cho_annotation_free(text_above->u.annot);
- }
- free(text_above);
-}
-
-static struct ChoLineItemAbove *
-cho_text_above_copy(struct ChoLineItemAbove *text_above)
-{
- struct ChoLineItemAbove *copy = malloc(sizeof(struct ChoLineItemAbove));
- copy->position = text_above->position;
- copy->is_chord = text_above->is_chord;
- if (copy->is_chord) {
- copy->u.chord = cho_chord_copy(text_above->u.chord);
- } else {
- copy->u.annot = cho_annotation_copy(text_above->u.annot);
- }
- return copy;
-}
-
-static struct ChoLineItem *
-cho_line_item_new(void)
-{
- struct ChoLineItem *item = malloc(sizeof(struct ChoLineItem));
- item->style = cho_style_new_default();
- item->text = NULL;
- return item;
-}
-
-static void
-cho_line_item_free(struct ChoLineItem *item)
-{
- cho_style_free(item->style);
- free(item->text);
- free(item);
-}
-
-static struct ChoLineItem *
-cho_line_item_copy(struct ChoLineItem *item)
-{
- struct ChoLineItem *copy = malloc(sizeof(struct ChoLineItem));
- copy->style = cho_style_copy(item->style);
- copy->text = strdup(item->text);
- return copy;
-}
-
-int
-cho_line_item_count(struct ChoLineItem **items)
-{
- int i = 0;
- while (items[i] != NULL)
- i++;
- return i;
-}
-
-static struct ChoLine *
-cho_line_new(void)
-{
- struct ChoLine *line = malloc(sizeof(struct ChoLine));
- line->text_above = NULL;
- line->lyrics = NULL;
- line->btype = BT_LINE;
- return line;
-}
-
-static void
-cho_line_free(struct ChoLine *line)
-{
- struct ChoLineItem **start_lyrics = line->lyrics;
- while (*line->lyrics) {
- cho_line_item_free(*line->lyrics);
- line->lyrics++;
- }
- struct ChoLineItemAbove **start_text_above = line->text_above;
- while (*line->text_above) {
- cho_text_above_free(*line->text_above);
- line->text_above++;
- }
- free(start_lyrics);
- free(start_text_above);
- free(line);
-}
-
-static int
-cho_line_compute_chord_position(struct ChoLine *line, int ly, int te)
-{
- if (ly == 0)
- return te;
- ly--;
- size_t lyrics_len = 0;
- while (ly >= 0) {
- lyrics_len += strlen(line->lyrics[ly]->text);
- ly--;
- }
- return lyrics_len + te;
-}
-
-static struct ChoLabel *
-cho_section_label_copy(struct ChoLabel *label)
-{
- struct ChoLabel *copy = malloc(sizeof(struct ChoLabel));
- copy->name = strdup(label->name);
- copy->style = cho_style_copy(label->style);
- return copy;
-}
-
-static void
-cho_section_label_free(struct ChoLabel *label)
-{
- free(label->name);
- cho_style_free(label->style);
- free(label);
-}
-
-static struct ChoSection *
-cho_section_new(void)
-{
- struct ChoSection *section = malloc(sizeof(struct ChoSection));
- section->type = ST_EMPTY;
- section->label = NULL;
- section->lines = NULL;
- return section;
-}
-
-static void
-cho_section_free(struct ChoSection *section)
-{
- if (section->label) {
- cho_section_label_free(section->label);
- }
- struct ChoLine **start_lines = section->lines;
- while (*section->lines) {
- cho_line_free(*section->lines);
- section->lines++;
- }
- free(start_lines);
- free(section);
-}
-
-static struct ChoSection *
-cho_section_copy(struct ChoSection *section)
-{
- struct ChoSection *copy = malloc(sizeof(struct ChoSection));
- copy->type = section->type;
- if (section->label) {
- copy->label = cho_section_label_copy(section->label);
- } else {
- copy->label = NULL;
- }
- copy->lines = NULL;
- int li, c, ly;
- for (li = 0; section->lines[li]; li++) {
- copy->lines = realloc(copy->lines, (li+1) * sizeof(struct ChoLine *));
- copy->lines[li] = cho_line_new();
- copy->lines[li]->btype = section->lines[li]->btype;
- for (c = 0; section->lines[li]->text_above[c]; c++) {
- copy->lines[li]->text_above = realloc(copy->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
- copy->lines[li]->text_above[c] = cho_text_above_copy(section->lines[li]->text_above[c]);
- }
- copy->lines[li]->text_above = realloc(copy->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
- copy->lines[li]->text_above[c] = NULL;
- for (ly = 0; section->lines[li]->lyrics[ly]; ly++) {
- copy->lines[li]->lyrics = realloc(copy->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *));
- copy->lines[li]->lyrics[ly] = cho_line_item_copy(section->lines[li]->lyrics[ly]);
- }
- copy->lines[li]->lyrics = realloc(copy->lines[li]->lyrics, (ly+1) * sizeof(struct ChoLineItem *));
- copy->lines[li]->lyrics[ly] = NULL;
- }
- copy->lines = realloc(copy->lines, (li+1) * sizeof(struct ChoLine *));
- copy->lines[li] = NULL;
- return copy;
-}
-
-static struct ChoSong *
-cho_song_new(void)
-{
- struct ChoSong *song = malloc(sizeof(struct ChoSong));
- song->metadata = NULL;
- song->sections = NULL;
- return song;
-}
-
-int
-cho_song_count(struct ChoSong **songs)
-{
- int i = 0;
- while (songs[i] != NULL)
- i++;
- return i;
-}
-
-static void
-cho_song_free(struct ChoSong *song)
-{
- struct ChoMetadata **start_meta = song->metadata;
- struct ChoSection **start_section = song->sections;
- while (*song->metadata) {
- cho_metadata_free(*song->metadata);
- song->metadata++;
- }
- while (*song->sections) {
- cho_section_free(*song->sections);
- song->sections++;
- }
- free(start_meta);
- free(start_section);
- free(song);
-}
-
-void
-cho_songs_free(struct ChoSong **songs)
-{
- struct ChoSong **start_song = songs;
- while (*songs) {
- cho_song_free(*songs);
- songs++;
- }
- free(start_song);
-}
-
static struct ChoImage *
cho_image_new(void)
{
@@ -2242,6 +1982,30 @@ cho_image_free(struct ChoImage *image)
}
static struct ChoImage *
+cho_image_copy(struct ChoImage *image)
+{
+ struct ChoImage *copy = malloc(sizeof(struct ChoImage));
+ copy->is_asset = image->is_asset;
+ copy->id = strdup(image->id);
+ copy->src = strdup(image->src);
+ copy->width = double_or_percent_copy(image->width);
+ copy->height = double_or_percent_copy(image->height);
+ copy->scale = double_or_percent_copy(image->scale);
+ copy->align = image->align;
+ copy->border = image->border;
+ copy->spread_space = double_or_percent_copy(image->spread_space);
+ copy->href = strdup(image->href);
+ copy->x = double_or_percent_copy(image->x);
+ copy->y = double_or_percent_copy(image->y);
+ copy->anchor = image->anchor;
+ copy->dx = image->dx;
+ copy->dy = image->dy;
+ copy->w = image->w;
+ copy->h = image->h;
+ return copy;
+}
+
+static struct ChoImage *
cho_image_find_asset(const char *id)
{
int i;
@@ -2531,6 +2295,252 @@ cho_image_directive_parse(const char *str)
{
} */
+static struct ChoText *
+cho_text_new(void)
+{
+ struct ChoText *text = malloc(sizeof(struct ChoText));
+ text->style = cho_style_new_default();
+ text->text = NULL;
+ return text;
+}
+
+static void
+cho_text_free(struct ChoText *text)
+{
+ cho_style_free(text->style);
+ free(text->text);
+ free(text);
+}
+
+static struct ChoText *
+cho_text_copy(struct ChoText *text)
+{
+ struct ChoText *copy = malloc(sizeof(struct ChoText));
+ copy->style = cho_style_copy(text->style);
+ copy->text = strdup(text->text);
+ return copy;
+}
+
+int
+cho_text_above_count(struct ChoLineItemAbove **text_above)
+{
+ int i = 0;
+ while (text_above[i] != NULL)
+ i++;
+ return i;
+}
+
+static void
+cho_text_above_free(struct ChoLineItemAbove *text_above)
+{
+ if (text_above->is_chord) {
+ cho_chord_free(text_above->u.chord);
+ } else {
+ cho_text_free(text_above->u.annot);
+ }
+ free(text_above);
+}
+
+static struct ChoLineItemAbove *
+cho_text_above_copy(struct ChoLineItemAbove *text_above)
+{
+ struct ChoLineItemAbove *copy = malloc(sizeof(struct ChoLineItemAbove));
+ copy->position = text_above->position;
+ copy->is_chord = text_above->is_chord;
+ if (copy->is_chord) {
+ copy->u.chord = cho_chord_copy(text_above->u.chord);
+ } else {
+ copy->u.annot = cho_text_copy(text_above->u.annot);
+ }
+ return copy;
+}
+
+static struct ChoLineItem *
+cho_line_item_new(void)
+{
+ struct ChoLineItem *item = malloc(sizeof(struct ChoLineItem));
+ item->is_text = true;
+ item->u.text = cho_text_new();
+ return item;
+}
+
+static void
+cho_line_item_free(struct ChoLineItem *item)
+{
+ if (item->is_text) {
+ cho_text_free(item->u.text);
+ } else {
+ cho_image_free(item->u.image);
+ }
+ free(item);
+}
+
+static struct ChoLineItem *
+cho_line_item_copy(struct ChoLineItem *item)
+{
+ struct ChoLineItem *copy = malloc(sizeof(struct ChoLineItem));
+ if (item->is_text) {
+ copy->is_text = true;
+ copy->u.text = cho_text_copy(item->u.text);
+ } else {
+ copy->is_text = false;
+ copy->u.image = cho_image_copy(item->u.image);
+ }
+ return copy;
+}
+
+static struct ChoLine *
+cho_line_new(void)
+{
+ struct ChoLine *line = malloc(sizeof(struct ChoLine));
+ line->text_above = NULL;
+ line->items = NULL;
+ line->btype = BT_LINE;
+ return line;
+}
+
+static void
+cho_line_free(struct ChoLine *line)
+{
+ struct ChoLineItem **start_items = line->items;
+ while (*line->items) {
+ cho_line_item_free(*line->items);
+ line->items++;
+ }
+ struct ChoLineItemAbove **start_text_above = line->text_above;
+ while (*line->text_above) {
+ cho_text_above_free(*line->text_above);
+ line->text_above++;
+ }
+ free(start_items);
+ free(start_text_above);
+ free(line);
+}
+
+/* TODO: Does this still work? */
+static int
+cho_line_compute_chord_position(struct ChoLine *line, int ly, int te)
+{
+ if (ly == 0) {
+ return te;
+ }
+ ly--;
+ size_t lyrics_len = 0;
+ while (ly >= 0) {
+ if (line->items[ly]->is_text) {
+ lyrics_len += strlen(line->items[ly]->u.text->text);
+ }
+ ly--;
+ }
+ return lyrics_len + te;
+}
+
+static struct ChoSection *
+cho_section_new(void)
+{
+ struct ChoSection *section = malloc(sizeof(struct ChoSection));
+ section->type = ST_EMPTY;
+ section->label = NULL;
+ section->lines = NULL;
+ return section;
+}
+
+static void
+cho_section_free(struct ChoSection *section)
+{
+ if (section->label) {
+ cho_text_free(section->label);
+ }
+ struct ChoLine **start_lines = section->lines;
+ while (*section->lines) {
+ cho_line_free(*section->lines);
+ section->lines++;
+ }
+ free(start_lines);
+ free(section);
+}
+
+static struct ChoSection *
+cho_section_copy(struct ChoSection *section)
+{
+ struct ChoSection *copy = malloc(sizeof(struct ChoSection));
+ copy->type = section->type;
+ if (section->label) {
+ copy->label = cho_text_copy(section->label);
+ } else {
+ copy->label = NULL;
+ }
+ copy->lines = NULL;
+ int li, c, ly;
+ for (li = 0; section->lines[li]; li++) {
+ copy->lines = realloc(copy->lines, (li+1) * sizeof(struct ChoLine *));
+ copy->lines[li] = cho_line_new();
+ copy->lines[li]->btype = section->lines[li]->btype;
+ for (c = 0; section->lines[li]->text_above[c]; c++) {
+ copy->lines[li]->text_above = realloc(copy->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
+ copy->lines[li]->text_above[c] = cho_text_above_copy(section->lines[li]->text_above[c]);
+ }
+ copy->lines[li]->text_above = realloc(copy->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
+ copy->lines[li]->text_above[c] = NULL;
+ for (ly = 0; section->lines[li]->items[ly]; ly++) {
+ copy->lines[li]->items = realloc(copy->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
+ copy->lines[li]->items[ly] = cho_line_item_copy(section->lines[li]->items[ly]);
+ }
+ copy->lines[li]->items = realloc(copy->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
+ copy->lines[li]->items[ly] = NULL;
+ }
+ copy->lines = realloc(copy->lines, (li+1) * sizeof(struct ChoLine *));
+ copy->lines[li] = NULL;
+ return copy;
+}
+
+static struct ChoSong *
+cho_song_new(void)
+{
+ struct ChoSong *song = malloc(sizeof(struct ChoSong));
+ song->metadata = NULL;
+ song->sections = NULL;
+ return song;
+}
+
+int
+cho_song_count(struct ChoSong **songs)
+{
+ int i = 0;
+ while (songs[i] != NULL)
+ i++;
+ return i;
+}
+
+static void
+cho_song_free(struct ChoSong *song)
+{
+ struct ChoMetadata **start_meta = song->metadata;
+ struct ChoSection **start_section = song->sections;
+ while (*song->metadata) {
+ cho_metadata_free(*song->metadata);
+ song->metadata++;
+ }
+ while (*song->sections) {
+ cho_section_free(*song->sections);
+ song->sections++;
+ }
+ free(start_meta);
+ free(start_section);
+ free(song);
+}
+
+void
+cho_songs_free(struct ChoSong **songs)
+{
+ struct ChoSong **start_song = songs;
+ while (*songs) {
+ cho_song_free(*songs);
+ songs++;
+ }
+ free(start_song);
+}
+
static struct ChoSection *
cho_find_previous_chorus(struct ChoSection **sections, int se)
{
@@ -2985,8 +2995,8 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
songs[so]->sections[se] = cho_section_new();
songs[so]->sections[se]->lines = malloc(sizeof(struct ChoLine *));
songs[so]->sections[se]->lines[li] = cho_line_new();
- songs[so]->sections[se]->lines[li]->lyrics = malloc(sizeof(struct ChoLineItem *));
- songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new();
+ songs[so]->sections[se]->lines[li]->items = malloc(sizeof(struct ChoLineItem *));
+ songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new();
struct Tag **tags = NULL;
struct Style *tag_style;
struct StyleProperty sprop;
@@ -3018,16 +3028,20 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
break;
}
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;
- 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 (songs[so]->sections[se]->lines[li]->items[ly]->is_text) {
+ songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = realloc(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;
+ 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]);
+ } else {
+ ly++;
+ }
} 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] = cho_line_item_new();
+ songs[so]->sections[se]->lines[li]->items = realloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
+ songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new();
prev_state = STATE_LYRICS;
state = STATE_MARKUP_TAG;
break;
@@ -3042,29 +3056,33 @@ 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;
}
- 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;
- 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]->text_above &&
- songs[so]->sections[se]->lines[li]->btype == BT_LINE
- ) {
- 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;
+ if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) {
+ songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = realloc(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 (ly == 0) {
+ if (
+ !songs[so]->sections[se]->lines[li]->text_above &&
+ songs[so]->sections[se]->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 = 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]->items = realloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
+ songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new();
+ break;
+ }
}
+ } else {
+ ly++;
}
} 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;
+ songs[so]->sections[se]->lines[li]->items = realloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
+ songs[so]->sections[se]->lines[li]->items[ly] = NULL;
ly = 0;
te = 0;
songs[so]->sections[se]->lines[li]->text_above = realloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
@@ -3073,12 +3091,12 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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();
+ songs[so]->sections[se]->lines[li]->items = realloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
+ songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new();
break;
}
- 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] = buf;
+ songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = realloc(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;
te++;
break;
case STATE_DIRECTIVE_NAME:
@@ -3099,8 +3117,8 @@ 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]->lyrics[ly]);
- free(songs[so]->sections[se]->lines[li]->lyrics);
+ cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]);
+ free(songs[so]->sections[se]->lines[li]->items);
ly = 0;
free(songs[so]->sections[se]->lines[li]);
songs[so]->sections[se]->lines[li] = NULL;
@@ -3111,8 +3129,8 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
li = 0;
songs[so]->sections[se]->lines = malloc(sizeof(struct ChoLine *));
songs[so]->sections[se]->lines[li] = cho_line_new();
- songs[so]->sections[se]->lines[li]->lyrics = malloc(sizeof(struct ChoLineItem *));
- songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new();
+ songs[so]->sections[se]->lines[li]->items = malloc(sizeof(struct ChoLineItem *));
+ songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new();
break;
case POS_END:
if (directive->stype == songs[so]->sections[se]->type) {
@@ -3121,8 +3139,8 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
break;
}
}
- cho_line_item_free(songs[so]->sections[se]->lines[li]->lyrics[ly]);
- free(songs[so]->sections[se]->lines[li]->lyrics);
+ cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]);
+ free(songs[so]->sections[se]->lines[li]->items);
ly = 0;
free(songs[so]->sections[se]->lines[li]);
songs[so]->sections[se]->lines[li] = NULL;
@@ -3132,8 +3150,8 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
li = 0;
songs[so]->sections[se]->lines = malloc(sizeof(struct ChoLine *));
songs[so]->sections[se]->lines[li] = cho_line_new();
- songs[so]->sections[se]->lines[li]->lyrics = malloc(sizeof(struct ChoLineItem *));
- songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new();
+ songs[so]->sections[se]->lines[li]->items = malloc(sizeof(struct ChoLineItem *));
+ songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new();
}
break;
case POS_EMPTY:
@@ -3141,11 +3159,13 @@ 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) {
- 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;
+ if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) {
+ songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = realloc(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;
+ }
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;
+ songs[so]->sections[se]->lines[li]->items = realloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
+ songs[so]->sections[se]->lines[li]->items[ly] = NULL;
ly = 0;
te = 0;
songs[so]->sections[se]->lines[li]->text_above = realloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
@@ -3163,27 +3183,31 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
songs[so]->sections[se] = cho_section_new();
songs[so]->sections[se]->lines = malloc(sizeof(struct ChoLine *));
songs[so]->sections[se]->lines[li] = cho_line_new();
- songs[so]->sections[se]->lines[li]->lyrics = malloc(sizeof(struct ChoLineItem *));
- songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new();
+ songs[so]->sections[se]->lines[li]->items = malloc(sizeof(struct ChoLineItem *));
+ songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new();
} else {
if (chorus->label) {
- label = strdup(chorus->label->name);
+ label = strdup(chorus->label->text);
} else {
label = strdup(config->output->chorus->label);
}
- 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;
- 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 (songs[so]->sections[se]->lines[li]->items[ly]->is_text) {
+ songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = realloc(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]);
+ } else {
+ ly++;
+ }
} 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] = cho_line_item_new();
- cho_style_free(songs[so]->sections[se]->lines[li]->lyrics[ly]->style);
+ songs[so]->sections[se]->lines[li]->items = realloc(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);
g_current_ftype = SF_LABEL;
- songs[so]->sections[se]->lines[li]->lyrics[ly]->style = cho_style_new_default();
- songs[so]->sections[se]->lines[li]->lyrics[ly]->text = 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;
te += strlen(label);
}
} else {
@@ -3191,19 +3215,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);
- 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;
- 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 (songs[so]->sections[se]->lines[li]->items[ly]->is_text) {
+ songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = realloc(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]);
+ } else {
+ ly++;
+ }
} 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] = cho_line_item_new();
- cho_style_free(songs[so]->sections[se]->lines[li]->lyrics[ly]->style);
+ songs[so]->sections[se]->lines[li]->items = realloc(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);
g_current_ftype = SF_LABEL;
- songs[so]->sections[se]->lines[li]->lyrics[ly]->style = cho_style_new_default();
- songs[so]->sections[se]->lines[li]->lyrics[ly]->text = 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;
te += strlen(label);
}
break;
@@ -3228,8 +3256,8 @@ 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]->lyrics[ly]);
- free(songs[so]->sections[se]->lines[li]->lyrics);
+ 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;
songs[so]->metadata = realloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *));
@@ -3252,8 +3280,8 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
songs[so]->sections[se] = cho_section_new();
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 = malloc(sizeof(struct ChoLineItem *));
- songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new();
+ songs[so]->sections[se]->lines[li]->items = malloc(sizeof(struct ChoLineItem *));
+ songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new();
break;
case DT_FONT:
sprop.ftype = directive->ftype;
@@ -3335,8 +3363,8 @@ 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]->lyrics[ly]);
- free(songs[so]->sections[se]->lines[li]->lyrics);
+ cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]);
+ free(songs[so]->sections[se]->lines[li]->items);
ly = 0;
free(songs[so]->sections[se]->lines[li]);
songs[so]->sections[se]->lines[li] = NULL;
@@ -3344,7 +3372,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
songs[so]->sections = realloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *));
songs[so]->sections[se] = cho_section_new();
songs[so]->sections[se]->type = directive->stype;
- songs[so]->sections[se]->label = malloc(sizeof(struct ChoLabel));
+ songs[so]->sections[se]->label = malloc(sizeof(struct ChoText));
if (strstr(directive_value, "=")) {
label = cho_directive_label_parse(directive_name, directive_value);
if (!label) {
@@ -3352,21 +3380,21 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
cho_log(LOG_ERR, "Failed to parse the section label. You have to ways of specifying a label:\n\t\t\t1. {start_of_*: label=\"Label name\"}\n\t\t\t2. {start_of*: Label name}");
return NULL;
}
- songs[so]->sections[se]->label->name = label;
+ songs[so]->sections[se]->label->text = label;
} else {
- songs[so]->sections[se]->label->name = str_remove_leading_whitespace(directive_value);
+ songs[so]->sections[se]->label->text = str_remove_leading_whitespace(directive_value);
}
songs[so]->sections[se]->label->style = cho_style_new_from_config(SF_LABEL);
li = 0;
songs[so]->sections[se]->lines = malloc(sizeof(struct ChoLine *));
songs[so]->sections[se]->lines[li] = cho_line_new();
- songs[so]->sections[se]->lines[li]->lyrics = malloc(sizeof(struct ChoLineItem *));
- songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new();
+ songs[so]->sections[se]->lines[li]->items = malloc(sizeof(struct ChoLineItem *));
+ songs[so]->sections[se]->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]->lyrics[ly]);
- free(songs[so]->sections[se]->lines[li]->lyrics);
+ cho_line_item_free(songs[so]->sections[se]->lines[li]->items[ly]);
+ free(songs[so]->sections[se]->lines[li]->items);
ly = 0;
free(songs[so]->sections[se]->lines[li]);
songs[so]->sections[se]->lines[li] = NULL;
@@ -3376,8 +3404,8 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
li = 0;
songs[so]->sections[se]->lines = malloc(sizeof(struct ChoLine *));
songs[so]->sections[se]->lines[li] = cho_line_new();
- songs[so]->sections[se]->lines[li]->lyrics = malloc(sizeof(struct ChoLineItem *));
- songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new();
+ songs[so]->sections[se]->lines[li]->items = malloc(sizeof(struct ChoLineItem *));
+ songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new();
}
break;
case POS_EMPTY:
@@ -3386,11 +3414,13 @@ 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) {
- 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;
+ if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) {
+ songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = realloc(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;
+ }
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;
+ songs[so]->sections[se]->lines[li]->items = realloc(songs[so]->sections[se]->lines[li]->items, (ly+1) * sizeof(struct ChoLineItem *));
+ songs[so]->sections[se]->lines[li]->items[ly] = NULL;
ly = 0;
te = 0;
songs[so]->sections[se]->lines[li]->text_above = realloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
@@ -3404,10 +3434,10 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
songs[so]->sections = realloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *));
songs[so]->sections[se] = cho_section_copy(chorus);
if (songs[so]->sections[se]->label) {
- free(songs[so]->sections[se]->label->name);
- songs[so]->sections[se]->label->name = label;
+ free(songs[so]->sections[se]->label->text);
+ songs[so]->sections[se]->label->text = label;
} else {
- songs[so]->sections[se]->label = malloc(sizeof(struct ChoLabel));
+ songs[so]->sections[se]->label = malloc(sizeof(struct ChoText));
g_current_ftype = SF_LABEL;
songs[so]->sections[se]->label->style = cho_style_new_default();
}
@@ -3416,41 +3446,49 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
songs[so]->sections[se] = cho_section_new();
songs[so]->sections[se]->lines = malloc(sizeof(struct ChoLine *));
songs[so]->sections[se]->lines[li] = cho_line_new();
- songs[so]->sections[se]->lines[li]->lyrics = malloc(sizeof(struct ChoLineItem *));
- songs[so]->sections[se]->lines[li]->lyrics[ly] = cho_line_item_new();
+ songs[so]->sections[se]->lines[li]->items = malloc(sizeof(struct ChoLineItem *));
+ songs[so]->sections[se]->lines[li]->items[ly] = cho_line_item_new();
} else {
- 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;
- 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 (songs[so]->sections[se]->lines[li]->items[ly]->is_text) {
+ songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = realloc(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]);
+ } else {
+ ly++;
+ }
} 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] = cho_line_item_new();
- cho_style_free(songs[so]->sections[se]->lines[li]->lyrics[ly]->style);
+ songs[so]->sections[se]->lines[li]->items = realloc(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);
g_current_ftype = SF_LABEL;
- songs[so]->sections[se]->lines[li]->lyrics[ly]->style = cho_style_new_default();
- songs[so]->sections[se]->lines[li]->lyrics[ly]->text = 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;
te += strlen(label);
}
} else {
if (config->output->chorus->quote) {
cho_log(LOG_WARN, "Can't quote chorus because it's not defined previously.");
}
- 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;
- 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 (songs[so]->sections[se]->lines[li]->items[ly]->is_text) {
+ songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = realloc(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]);
+ } else {
+ ly++;
+ }
} 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] = cho_line_item_new();
- cho_style_free(songs[so]->sections[se]->lines[li]->lyrics[ly]->style);
+ songs[so]->sections[se]->lines[li]->items = realloc(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);
g_current_ftype = SF_LABEL;
- songs[so]->sections[se]->lines[li]->lyrics[ly]->style = cho_style_new_default();
- songs[so]->sections[se]->lines[li]->lyrics[ly]->text = 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;
te += strlen(label);
}
break;
@@ -3490,19 +3528,23 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
}
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;
- 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 (songs[so]->sections[se]->lines[li]->items[ly]->is_text) {
+ songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = realloc(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]);
+ } else {
+ ly++;
+ }
} 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] = 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_copy(directive->style);
+ songs[so]->sections[se]->lines[li]->items = realloc(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);
char *trimmed_directive_value = str_remove_leading_whitespace(directive_value);
- songs[so]->sections[se]->lines[li]->lyrics[ly]->text = trimmed_directive_value;
+ songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = trimmed_directive_value;
te += strlen(trimmed_directive_value);
break;
case DT_IMAGE:
@@ -3522,8 +3564,18 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
g_ia++;
} else {
// Add image to ChoSong somehow
- cho_debug_image_print(image);
- cho_image_free(image);
+ if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) {
+ songs[so]->sections[se]->lines[li]->items[ly]->u.text->text = realloc(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;
+ te = 0;
+ }
+ ly++;
+ songs[so]->sections[se]->lines[li]->items = realloc(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;
+ // cho_debug_image_print(image);
}
break;
case DT_PREAMBLE:
@@ -3651,7 +3703,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
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_annotation_new();
+ songs[so]->sections[se]->lines[li]->text_above[c]->u.annot = cho_text_new();
state = STATE_ANNOTATION;
break;
}
@@ -3698,7 +3750,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
songs[so]->sections[se]->lines[li]->text_above[c] = malloc(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_annotation_new();
+ songs[so]->sections[se]->lines[li]->text_above[c]->u.annot = cho_text_new();
}
prev_state = STATE_ANNOTATION;
state = STATE_MARKUP_TAG;
@@ -3726,8 +3778,8 @@ 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]->lyrics[ly]->style);
- songs[so]->sections[se]->lines[li]->lyrics[ly]->style = cho_style_copy(tag_style);
+ 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);
break;
case STATE_CHORD:
cho_style_free(songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->style);
@@ -3841,8 +3893,8 @@ 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]->lyrics[ly]->style);
- songs[so]->sections[se]->lines[li]->lyrics[ly]->style = cho_style_copy(tag_style);
+ 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);
break;
case STATE_CHORD:
cho_style_free(songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->style);
@@ -3917,8 +3969,8 @@ 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]->lyrics[ly]->style);
- songs[so]->sections[se]->lines[li]->lyrics[ly]->style = cho_style_copy(tag_style);
+ 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);
break;
case STATE_CHORD:
cho_style_free(songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->style);
@@ -3976,23 +4028,26 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config)
e++;
}
free(tags);
- if (songs[so]->sections[se]->lines[li]->lyrics[ly]->text) {
- 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] = NULL;
- songs[so]->sections[se]->lines[li]->text_above = realloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
- songs[so]->sections[se]->lines[li]->text_above[c] = NULL;
- li++;
- songs[so]->sections[se]->lines = realloc(songs[so]->sections[se]->lines, (li+1) * sizeof(struct ChoLine *));
- songs[so]->sections[se]->lines[li] = NULL;
- } else {
- cho_line_item_free(songs[so]->sections[se]->lines[li]->lyrics[ly]);
- free(songs[so]->sections[se]->lines[li]->lyrics);
- free(songs[so]->sections[se]->lines[li]->text_above);
- free(songs[so]->sections[se]->lines[li]);
- songs[so]->sections[se]->lines[li] = NULL;
+ 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 = realloc(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;
+ ly++;
+ songs[so]->sections[se]->lines[li]->items = realloc(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 = realloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
+ songs[so]->sections[se]->lines[li]->text_above[c] = NULL;
+ li++;
+ songs[so]->sections[se]->lines = realloc(songs[so]->sections[se]->lines, (li+1) * sizeof(struct ChoLine *));
+ songs[so]->sections[se]->lines[li] = NULL;
+ } else {
+ // cho_text_free(songs[so]->sections[se]->lines[li]->items[ly]->u.text);
+ 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;
+ }
}
if (!cho_style_reset_default()) {
LOG_DEBUG("cho_style_reset_default failed.");
diff --git a/chordpro.h b/chordpro.h
@@ -293,14 +293,17 @@ struct ChoChord {
char *bass;
};
-struct ChoAnnotation {
+struct ChoText {
struct Style *style;
char *text;
};
struct ChoLineItem {
- struct Style *style;
- char *text;
+ bool is_text;
+ union {
+ struct ChoImage *image;
+ struct ChoText *text;
+ } u;
};
struct ChoLineItemAbove {
@@ -308,38 +311,19 @@ struct ChoLineItemAbove {
bool is_chord;
union {
struct ChoChord *chord;
- struct ChoAnnotation *annot;
+ struct ChoText *annot;
} u;
};
struct ChoLine {
struct ChoLineItemAbove **text_above;
- struct ChoLineItem **lyrics;
- enum BreakType btype;
-};
-
-/* struct ChoSongLine {
- struct ChoLineItemAbove **text_above;
- struct ChoLineItem **lyrics;
+ struct ChoLineItem **items;
enum BreakType btype;
};
-struct ChoLine {
- bool is_song_line;
- union {
- struct ChoSongLine *s;
- struct ChoImage *i;
- } u;
-}; */
-
-struct ChoLabel {
- char *name;
- struct Style *style;
-};
-
struct ChoSection {
enum SectionType type;
- struct ChoLabel *label;
+ struct ChoText *label;
struct ChoLine **lines;
};
diff --git a/out_pdf.c b/out_pdf.c
@@ -133,10 +133,12 @@ out_pdf_font_get_all(struct ChoSong **songs, struct Config *config)
ch++;
}
ch = 0;
- while (songs[so]->sections[se]->lines[li]->lyrics[ly] != NULL) {
- style = songs[so]->sections[se]->lines[li]->lyrics[ly]->style;
- if (style->font->name) {
- out_pdf_add_fonts(style->font, &fonts);
+ while (songs[so]->sections[se]->lines[li]->items[ly] != NULL) {
+ if (songs[so]->sections[se]->lines[li]->items[ly]->is_text) {
+ style = songs[so]->sections[se]->lines[li]->items[ly]->u.text->style;
+ if (style->font->name) {
+ out_pdf_add_fonts(style->font, &fonts);
+ }
}
ly++;
}
@@ -660,6 +662,7 @@ out_pdf_text_show(pdfio_stream_t *stream, struct TextLineItem *item, double y)
return true;
}
+/* TODO: Does this still work? */
static double
line_width_until_chord(struct ChoLine *line, struct ChoLineItemAbove *text_above, struct SpaceNeeded *space)
{
@@ -670,8 +673,8 @@ line_width_until_chord(struct ChoLine *line, struct ChoLineItemAbove *text_above
char *name;
double width = 0.0;
pdfio_obj_t *font_obj;
- for (ly = 0; line->lyrics[ly]; ly++) {
- for (i = 0; line->lyrics[ly]->text[i]; i++) {
+ for (ly = 0; line->items[ly]; ly++) {
+ for (i = 0; line->items[ly]->u.text->text[i]; i++) {
if (pos == text_above->position) {
last_ly = ly;
last_i = i;
@@ -688,22 +691,26 @@ line_width_until_chord(struct ChoLine *line, struct ChoLineItemAbove *text_above
space->line_item_index = last_ly;
space->text_index = last_i;
}
- for (ly = 0; line->lyrics[ly] && ly <= last_ly; ly++) {
- name = out_pdf_fnt_name_create(line->lyrics[ly]->style->font);
- font_obj = out_pdf_fnt_obj_get_by_name(name);
- if (!font_obj) {
- LOG_DEBUG("out_pdf_fnt_obj_get_by_name failed.");
- return EMPTY;
- }
- if (ly == last_ly) {
- char tmp[strlen(line->lyrics[ly]->text)+1];
- strcpy((char *)&tmp, line->lyrics[ly]->text);
- tmp[last_i] = 0;
- width += pdfioContentTextMeasure(font_obj, (const char *)&tmp, line->lyrics[ly]->style->font->size);
+ for (ly = 0; line->items[ly] && ly <= last_ly; ly++) {
+ if (line->items[ly]->is_text) {
+ name = out_pdf_fnt_name_create(line->items[ly]->u.text->style->font);
+ font_obj = out_pdf_fnt_obj_get_by_name(name);
+ if (!font_obj) {
+ LOG_DEBUG("out_pdf_fnt_obj_get_by_name failed.");
+ return EMPTY;
+ }
+ if (ly == last_ly) {
+ char tmp[strlen(line->items[ly]->u.text->text)+1];
+ strcpy((char *)&tmp, line->items[ly]->u.text->text);
+ tmp[last_i] = 0;
+ width += pdfioContentTextMeasure(font_obj, (const char *)&tmp, line->items[ly]->u.text->style->font->size);
+ } else {
+ width += pdfioContentTextMeasure(font_obj, line->items[ly]->u.text->text, line->items[ly]->u.text->style->font->size);
+ }
+ free(name);
} else {
- width += pdfioContentTextMeasure(font_obj, line->lyrics[ly]->text, line->lyrics[ly]->style->font->size);
+ // TODO: calculate width of image and append to 'width' var.
}
- free(name);
}
return width;
}
@@ -894,7 +901,7 @@ text_create(struct ChoSong **songs, struct Config *config)
tl++;
for (se = 0; songs[so]->sections[se]; se++) {
if (songs[so]->sections[se]->label) {
- fits = text_fits(songs[so]->sections[se]->label->name, songs[so]->sections[se]->label->style);
+ fits = text_fits(songs[so]->sections[se]->label->text, songs[so]->sections[se]->label->style);
if (fits == B_ERROR) {
LOG_DEBUG("text_fits failed.");
return NULL;
@@ -904,7 +911,7 @@ text_create(struct ChoSong **songs, struct Config *config)
text[t]->lines[tl] = malloc(sizeof(struct TextLine));
text[t]->lines[tl]->items = malloc(2 * sizeof(struct TextLineItem *));
text[t]->lines[tl]->items[0] = malloc(sizeof(struct TextLineItem));
- text[t]->lines[tl]->items[0]->text = strdup(songs[so]->sections[se]->label->name);
+ text[t]->lines[tl]->items[0]->text = strdup(songs[so]->sections[se]->label->text);
text[t]->lines[tl]->items[0]->style = cho_style_copy(songs[so]->sections[se]->label->style);
text[t]->lines[tl]->items[0]->x = MARGIN_HORIZONTAL;
text[t]->lines[tl]->items[1] = NULL;
@@ -918,7 +925,7 @@ text_create(struct ChoSong **songs, struct Config *config)
tl++;
} else {
util_log(LOG_WARN, "Section name doesn't fit on one line.");
- text_lines = text_split_by_whitespace(songs[so]->sections[se]->label->name, songs[so]->sections[se]->label->style);
+ text_lines = text_split_by_whitespace(songs[so]->sections[se]->label->text, songs[so]->sections[se]->label->style);
for (int i = 0; text_lines[i]; i++) {
width = text_width(text_lines[i]->items[0]);
if (width == EMPTY) {
@@ -1046,7 +1053,11 @@ text_create(struct ChoSong **songs, struct Config *config)
text[t]->lines = realloc(text[t]->lines, (tl+1) * sizeof(struct TextLine *));
text[t]->lines[tl] = malloc(sizeof(struct TextLine));
text[t]->lines[tl]->items = NULL;
- for (ly = 0; lines[li]->lyrics[ly]; ly++) {
+ for (ly = 0; lines[li]->items[ly]; ly++) {
+ if (!lines[li]->items[ly]->is_text) {
+ printf("src: %s\n", lines[li]->items[ly]->u.image->src);
+ continue;
+ }
// out_pdf_text_find_fitting_length(lines[li]->lyrics[ly]);
int ii;
double last_text_line_item_width;
@@ -1054,7 +1065,7 @@ text_create(struct ChoSong **songs, struct Config *config)
text[t]->lines[tl]->items = realloc(text[t]->lines[tl]->items, (tli+1) * sizeof(struct TextLineItem *));
text[t]->lines[tl]->items[tli] = malloc(sizeof(struct TextLineItem));
text[t]->lines[tl]->items[tli]->text = NULL;
- text[t]->lines[tl]->items[tli]->style = cho_style_copy(lines[li]->lyrics[ly]->style);
+ text[t]->lines[tl]->items[tli]->style = cho_style_copy(lines[li]->items[ly]->u.text->style);
if (ly == 0) {
text[t]->lines[tl]->items[tli]->x = MARGIN_HORIZONTAL;
} else {
@@ -1066,10 +1077,10 @@ text_create(struct ChoSong **songs, struct Config *config)
text[t]->lines[tl]->items[tli]->x = text[t]->lines[tl]->items[tli-1]->x + last_text_line_item_width;
}
int tlii = 0;
- for (ii = 0; lines[li]->lyrics[ly]->text[ii] != 0; ii++) {
+ for (ii = 0; lines[li]->items[ly]->u.text->text[ii] != 0; ii++) {
if (spaces && (sp = needs_space(spaces, ly, ii))) {
text[t]->lines[tl]->items[tli]->text = realloc(text[t]->lines[tl]->items[tli]->text, (tlii+1) * sizeof(char));
- text[t]->lines[tl]->items[tli]->text[tlii] = lines[li]->lyrics[ly]->text[ii];
+ text[t]->lines[tl]->items[tli]->text[tlii] = lines[li]->items[ly]->u.text->text[ii];
tlii++;
text[t]->lines[tl]->items[tli]->text = realloc(text[t]->lines[tl]->items[tli]->text, (tlii+1) * sizeof(char));
text[t]->lines[tl]->items[tli]->text[tlii] = 0;
@@ -1078,7 +1089,7 @@ text_create(struct ChoSong **songs, struct Config *config)
text[t]->lines[tl]->items = realloc(text[t]->lines[tl]->items, (tli+1) * sizeof(struct TextLineItem *));
text[t]->lines[tl]->items[tli] = malloc(sizeof(struct TextLineItem));
text[t]->lines[tl]->items[tli]->text = NULL;
- text[t]->lines[tl]->items[tli]->style = cho_style_copy(lines[li]->lyrics[ly]->style);
+ text[t]->lines[tl]->items[tli]->style = cho_style_copy(lines[li]->items[ly]->u.text->style);
last_text_line_item_width = text_width(text[t]->lines[tl]->items[tli-1]);
if (last_text_line_item_width == EMPTY) {
LOG_DEBUG("text_width failed.");
@@ -1087,7 +1098,7 @@ text_create(struct ChoSong **songs, struct Config *config)
text[t]->lines[tl]->items[tli]->x = text[t]->lines[tl]->items[tli-1]->x + last_text_line_item_width + sp->amount;
} else {
text[t]->lines[tl]->items[tli]->text = realloc(text[t]->lines[tl]->items[tli]->text, (tlii+1) * sizeof(char));
- text[t]->lines[tl]->items[tli]->text[tlii] = lines[li]->lyrics[ly]->text[ii];
+ text[t]->lines[tl]->items[tli]->text[tlii] = lines[li]->items[ly]->u.text->text[ii];
tlii++;
}
}
diff --git a/util.c b/util.c
@@ -293,6 +293,20 @@ double_or_percent_to_string(struct DoubleOrPercent *dop)
}
struct DoubleOrPercent *
+double_or_percent_copy(struct DoubleOrPercent *dop)
+{
+ struct DoubleOrPercent *copy = malloc(sizeof(struct DoubleOrPercent));
+ if (dop->is_percent) {
+ copy->is_percent = true;
+ copy->u.p = dop->u.p;
+ } else {
+ copy->is_percent = false;
+ copy->u.d = dop->u.d;
+ }
+ return copy;
+}
+
+struct DoubleOrPercent *
double_or_percent_create(const char *str)
{
struct DoubleOrPercent *dop = malloc(sizeof(struct DoubleOrPercent));
diff --git a/util.h b/util.h
@@ -49,4 +49,5 @@ char *filepath_basename(const char *path);
char *filepath_dirname(const char *path);
const char *double_or_percent_to_string(struct DoubleOrPercent *dop);
+struct DoubleOrPercent *double_or_percent_copy(struct DoubleOrPercent *dop);
struct DoubleOrPercent *double_or_percent_create(const char *str);