commit 9e08b6cb16c8a7d76cdacae1bab328df2cd0e091
parent e50e80b8700cdb60c19e1b349f531acb6a9b4015
Author: nibo <nibo@relim.de>
Date: Mon, 14 Oct 2024 13:49:20 +0200
Finish cho_image_option_parse()
Diffstat:
| M | chordpro.c | | | 112 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- |
| M | chordpro.h | | | 12 | ++++++------ |
| M | util.c | | | 27 | +++++++++++++++++++++++++++ |
| M | util.h | | | 9 | +++++++++ |
4 files changed, 136 insertions(+), 24 deletions(-)
diff --git a/chordpro.c b/chordpro.c
@@ -1982,15 +1982,15 @@ static struct ChoImage *cho_image_new(void)
struct ChoImage *image = malloc(sizeof(struct ChoImage));
image->id = NULL;
image->src = NULL;
- image->width = EMPTY;
- image->height = EMPTY;
- image->scale = EMPTY;
+ image->width = NULL;
+ image->height = NULL;
+ image->scale = NULL;
image->align = A_CENTER;
image->border = EMPTY;
- image->spread_space = EMPTY;
+ image->spread_space = NULL;
image->href = NULL;
- image->x = EMPTY;
- image->y = EMPTY;
+ image->x = NULL;
+ image->y = NULL;
image->anchor = AN_FLOAT;
image->dx = EMPTY;
image->dy = EMPTY;
@@ -2003,13 +2003,32 @@ static void cho_image_free(struct ChoImage *image)
{
free(image->id);
free(image->src);
+ if (image->width) {
+ free(image->width);
+ }
+ if (image->height) {
+ free(image->height);
+ }
+ if (image->scale) {
+ free(image->scale);
+ }
+ if (image->spread_space) {
+ free(image->spread_space);
+ }
+ if (image->x) {
+ free(image->x);
+ }
+ if (image->y) {
+ free(image->y);
+ }
free(image->href);
free(image);
}
-static bool cho_image_option_check(struct ChoImage *image, const char *name, const char *value)
+static bool cho_image_option_parse(struct ChoImage *image, const char *name, const char *value)
{
- size_t value_len = strlen(value);
+ char *endptr;
+ // size_t value_len = strlen(value);
if (!strcmp(name, "id")) {
image->id = strdup(value);
} else
@@ -2017,33 +2036,90 @@ static bool cho_image_option_check(struct ChoImage *image, const char *name, con
image->src = strdup(value);
} else
if (!strcmp(name, "width")) {
- if (value[value_len-1] == '%') {
- short p = str_parse_as_percent(value);
- if (p == -1) {
- LOG_DEBUG("str_parse_as_percent failed.");
- cho_log(LOG_ERR, "Invalid percentage.");
- return false;
- }
- printf("p: %d\n", p);
+ image->width = double_or_percent_create(value);
+ if (!image->width) {
+ cho_log(LOG_ERR, "Invalid value in option 'width' in image directive.");
+ return false;
}
} else
if (!strcmp(name, "height")) {
+ image->height = double_or_percent_create(value);
+ if (!image->height) {
+ cho_log(LOG_ERR, "Invalid value in option 'height' in image directive.");
+ return false;
+ }
} else
if (!strcmp(name, "scale")) {
+ image->scale = double_or_percent_create(value);
+ if (!image->scale) {
+ cho_log(LOG_ERR, "Invalid value in option 'scale' in image directive.");
+ return false;
+ }
} else
if (!strcmp(name, "align")) {
+ if (!strcmp(value, "left")) {
+ image->align = A_LEFT;
+ } else
+ if (!strcmp(value, "right")) {
+ image->align = A_RIGHT;
+ } else
+ if (!strcmp(value, "center")) {
+ image->align = A_CENTER;
+ } else {
+ cho_log(LOG_ERR, "Invalid value in option 'align' in image directive.");
+ return false;
+ }
} else
if (!strcmp(name, "border")) {
+ image->border = strtod(value, &endptr);
+ if (value == endptr || errno == ERANGE) {
+ LOG_DEBUG("strtod failed.");
+ return false;
+ }
} else
if (!strcmp(name, "spread")) {
+ image->spread_space = double_or_percent_create(value);
+ if (!image->spread_space) {
+ cho_log(LOG_ERR, "Invalid value in option 'spread' in image directive.");
+ return false;
+ }
} else
if (!strcmp(name, "href")) {
+ image->href = strdup(value);
} else
if (!strcmp(name, "x")) {
+ image->x = double_or_percent_create(value);
+ if (!image->x) {
+ cho_log(LOG_ERR, "Invalid value in option 'x' in image directive.");
+ return false;
+ }
} else
if (!strcmp(name, "y")) {
+ image->y = double_or_percent_create(value);
+ if (!image->y) {
+ cho_log(LOG_ERR, "Invalid value in option 'y' in image directive.");
+ return false;
+ }
} else
if (!strcmp(name, "anchor")) {
+ if (!strcmp(value, "paper")) {
+ image->anchor = AN_PAPER;
+ } else
+ if (!strcmp(value, "page")) {
+ image->anchor = AN_PAGE;
+ } else
+ if (!strcmp(value, "column")) {
+ image->anchor = AN_COLUMN;
+ } else
+ if (!strcmp(value, "line")) {
+ image->anchor = AN_LINE;
+ } else
+ if (!strcmp(value, "float")) {
+ image->anchor = AN_FLOAT;
+ } else {
+ cho_log(LOG_ERR, "Invalid value in option 'anchor' in image directive.");
+ return false;
+ }
}
return true;
}
@@ -2116,7 +2192,7 @@ static struct ChoImage *cho_image_directive_parse(const char *str)
) {
value[v] = 0;
printf("'%s' -> '%s'\n", name, value);
- if (!cho_image_option_check(image, name, value)) {
+ if (!cho_image_option_parse(image, name, value)) {
LOG_DEBUG("cho_image_option_check failed.");
return NULL;
}
@@ -2136,7 +2212,7 @@ static struct ChoImage *cho_image_directive_parse(const char *str)
if (avs == AVS_UNQUOTED) {
value[v] = 0;
printf("'%s' -> '%s'\n", name, value);
- if (!cho_image_option_check(image, name, value)) {
+ if (!cho_image_option_parse(image, name, value)) {
LOG_DEBUG("cho_image_option_check failed.");
return NULL;
}
diff --git a/chordpro.h b/chordpro.h
@@ -141,15 +141,15 @@ enum OptionState {
struct ChoImage {
char *id;
char *src;
- double width;
- double height;
- double scale;
+ struct DoubleOrPercent *width;
+ struct DoubleOrPercent *height;
+ struct DoubleOrPercent *scale;
enum Alignment align;
double border;
- double spread_space;
+ struct DoubleOrPercent *spread_space;
char *href;
- double x;
- double y;
+ struct DoubleOrPercent *x;
+ struct DoubleOrPercent *y;
enum Anchor anchor;
double dx;
double dy;
diff --git a/util.c b/util.c
@@ -264,3 +264,30 @@ char *filepath_dirname(const char *path)
dirname[i] = 0;
return dirname;
}
+
+struct DoubleOrPercent *
+double_or_percent_create(const char *str)
+{
+ struct DoubleOrPercent *dop = malloc(sizeof(struct DoubleOrPercent));
+ size_t len = strlen(str);
+ if (str[len-1] == '%') {
+ short p = str_parse_as_percent(str);
+ if (p == -1) {
+ LOG_DEBUG("str_parse_as_percent failed.");
+ return NULL;
+ }
+ dop->u.p = p;
+ dop->is_percent = true;
+ } else {
+ char *endptr;
+ double d;
+ d = strtod(str, &endptr);
+ if (str == endptr || errno == ERANGE) {
+ LOG_DEBUG("strtod failed.");
+ return NULL;
+ }
+ dop->u.d = d;
+ dop->is_percent = false;
+ }
+ return dop;
+}
diff --git a/util.h b/util.h
@@ -17,6 +17,14 @@ enum FileType {
F_OTHER
};
+struct DoubleOrPercent {
+ bool is_percent;
+ union {
+ double d;
+ short p;
+ } u;
+};
+
void util_log(enum LogLevel level, const char *msg, ...);
bool str_starts_with(const char *str, const char *part);
@@ -32,3 +40,4 @@ char *filepath_add_ending_slash_if_missing(const char *path);
char *filepath_basename(const char *path);
char *filepath_dirname(const char *path);
+struct DoubleOrPercent *double_or_percent_create(const char *str);