diff options
-rw-r--r-- | common/pango.c | 73 | ||||
-rw-r--r-- | include/pango.h | 11 | ||||
-rw-r--r-- | sway/tree/view.c | 21 |
3 files changed, 99 insertions, 6 deletions
diff --git a/common/pango.c b/common/pango.c index 658d2876..9437c60d 100644 --- a/common/pango.c +++ b/common/pango.c | |||
@@ -8,6 +8,68 @@ | |||
8 | #include <string.h> | 8 | #include <string.h> |
9 | #include "log.h" | 9 | #include "log.h" |
10 | 10 | ||
11 | int escape_markup_text(const char *src, char *dest, int dest_length) { | ||
12 | int length = 0; | ||
13 | |||
14 | while (src[0]) { | ||
15 | switch (src[0]) { | ||
16 | case '&': | ||
17 | length += 5; | ||
18 | if (dest && dest_length - length >= 0) { | ||
19 | dest += sprintf(dest, "%s", "&"); | ||
20 | } else { | ||
21 | dest_length = -1; | ||
22 | } | ||
23 | break; | ||
24 | case '<': | ||
25 | length += 4; | ||
26 | if (dest && dest_length - length >= 0) { | ||
27 | dest += sprintf(dest, "%s", "<"); | ||
28 | } else { | ||
29 | dest_length = -1; | ||
30 | } | ||
31 | break; | ||
32 | case '>': | ||
33 | length += 4; | ||
34 | if (dest && dest_length - length >= 0) { | ||
35 | dest += sprintf(dest, "%s", ">"); | ||
36 | } else { | ||
37 | dest_length = -1; | ||
38 | } | ||
39 | break; | ||
40 | case '\'': | ||
41 | length += 6; | ||
42 | if (dest && dest_length - length >= 0) { | ||
43 | dest += sprintf(dest, "%s", "'"); | ||
44 | } else { | ||
45 | dest_length = -1; | ||
46 | } | ||
47 | break; | ||
48 | case '"': | ||
49 | length += 6; | ||
50 | if (dest && dest_length - length >= 0) { | ||
51 | dest += sprintf(dest, "%s", """); | ||
52 | } else { | ||
53 | dest_length = -1; | ||
54 | } | ||
55 | break; | ||
56 | default: | ||
57 | length += 1; | ||
58 | if (dest && dest_length - length >= 0) { | ||
59 | *(dest++) = *src; | ||
60 | } else { | ||
61 | dest_length = -1; | ||
62 | } | ||
63 | } | ||
64 | src++; | ||
65 | } | ||
66 | // if we could not fit the escaped string in dest, return -1 | ||
67 | if (dest && dest_length == -1) { | ||
68 | return -1; | ||
69 | } | ||
70 | return length; | ||
71 | } | ||
72 | |||
11 | PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, | 73 | PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, |
12 | const char *text, int32_t scale, bool markup) { | 74 | const char *text, int32_t scale, bool markup) { |
13 | PangoLayout *layout = pango_cairo_create_layout(cairo); | 75 | PangoLayout *layout = pango_cairo_create_layout(cairo); |
@@ -15,13 +77,14 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, | |||
15 | if (markup) { | 77 | if (markup) { |
16 | char *buf; | 78 | char *buf; |
17 | GError *error = NULL; | 79 | GError *error = NULL; |
18 | if (!sway_assert(pango_parse_markup( | 80 | bool result = pango_parse_markup(text, -1, 0, &attrs, &buf, |
19 | text, -1, 0, &attrs, &buf, NULL, &error), | 81 | NULL, &error); |
20 | "pango_parse_markup '%s' -> error %s", text, | 82 | if (result) { |
21 | error ? error->message : NULL)) { | 83 | wlr_log(L_ERROR, "pango_parse_markup '%s' -> error %s", text, |
84 | error->message); | ||
22 | return NULL; | 85 | return NULL; |
23 | } | 86 | } |
24 | pango_layout_set_markup(layout, buf, -1); | 87 | pango_layout_set_markup(layout, text, -1); |
25 | free(buf); | 88 | free(buf); |
26 | } else { | 89 | } else { |
27 | attrs = pango_attr_list_new(); | 90 | attrs = pango_attr_list_new(); |
diff --git a/include/pango.h b/include/pango.h index f6325f28..d8263f9e 100644 --- a/include/pango.h +++ b/include/pango.h | |||
@@ -6,6 +6,17 @@ | |||
6 | #include <cairo/cairo.h> | 6 | #include <cairo/cairo.h> |
7 | #include <pango/pangocairo.h> | 7 | #include <pango/pangocairo.h> |
8 | 8 | ||
9 | /* Utility function which escape characters a & < > ' ". | ||
10 | * | ||
11 | * If the dest parameter is NULL, then the function returns the length of | ||
12 | * of the escaped src string. The dest_length doesn't matter. | ||
13 | * | ||
14 | * If the dest parameter is not NULL then the fuction escapes the src string | ||
15 | * an puts the escaped string in dest and returns the lenght of the escaped string. | ||
16 | * The dest_length parameter is the size of dest array. If the size of dest is not | ||
17 | * enough, then the function returns -1. | ||
18 | */ | ||
19 | int escape_markup_text(const char *src, char *dest, int dest_length); | ||
9 | PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, | 20 | PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, |
10 | const char *text, int32_t scale, bool markup); | 21 | const char *text, int32_t scale, bool markup); |
11 | void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, | 22 | void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, |
diff --git a/sway/tree/view.c b/sway/tree/view.c index e2cb8a7a..9bdc5198 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include "sway/tree/layout.h" | 14 | #include "sway/tree/layout.h" |
15 | #include "sway/tree/view.h" | 15 | #include "sway/tree/view.h" |
16 | #include "sway/tree/workspace.h" | 16 | #include "sway/tree/workspace.h" |
17 | #include "sway/config.h" | ||
18 | #include "pango.h" | ||
17 | 19 | ||
18 | void view_init(struct sway_view *view, enum sway_view_type type, | 20 | void view_init(struct sway_view *view, enum sway_view_type type, |
19 | const struct sway_view_impl *impl) { | 21 | const struct sway_view_impl *impl) { |
@@ -612,6 +614,19 @@ static size_t parse_title_format(struct sway_view *view, char *buffer) { | |||
612 | return len; | 614 | return len; |
613 | } | 615 | } |
614 | 616 | ||
617 | static char *escape_title(char *buffer) { | ||
618 | int length = escape_markup_text(buffer, NULL, 0); | ||
619 | char *escaped_title = calloc(length + 1, sizeof(char)); | ||
620 | int result = escape_markup_text(buffer, escaped_title, length); | ||
621 | if (result != length) { | ||
622 | wlr_log(L_ERROR, "Could not escape title: %s", buffer); | ||
623 | free(escaped_title); | ||
624 | return buffer; | ||
625 | } | ||
626 | free(buffer); | ||
627 | return escaped_title; | ||
628 | } | ||
629 | |||
615 | void view_update_title(struct sway_view *view, bool force) { | 630 | void view_update_title(struct sway_view *view, bool force) { |
616 | if (!view->swayc) { | 631 | if (!view->swayc) { |
617 | return; | 632 | return; |
@@ -631,11 +646,15 @@ void view_update_title(struct sway_view *view, bool force) { | |||
631 | free(view->swayc->formatted_title); | 646 | free(view->swayc->formatted_title); |
632 | if (title) { | 647 | if (title) { |
633 | size_t len = parse_title_format(view, NULL); | 648 | size_t len = parse_title_format(view, NULL); |
634 | char *buffer = calloc(len + 1, 1); | 649 | char *buffer = calloc(len + 1, sizeof(char)); |
635 | if (!sway_assert(buffer, "Unable to allocate title string")) { | 650 | if (!sway_assert(buffer, "Unable to allocate title string")) { |
636 | return; | 651 | return; |
637 | } | 652 | } |
638 | parse_title_format(view, buffer); | 653 | parse_title_format(view, buffer); |
654 | // now we have the title, but needs to be escaped when using pango markup | ||
655 | if (config->pango_markup) { | ||
656 | buffer = escape_title(buffer); | ||
657 | } | ||
639 | 658 | ||
640 | view->swayc->name = strdup(title); | 659 | view->swayc->name = strdup(title); |
641 | view->swayc->formatted_title = buffer; | 660 | view->swayc->formatted_title = buffer; |