mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Merge pull request #1935 from heghe/heghe/fix-pango-markup-crash
Fix crash when using pango markup font
This commit is contained in:
		
						commit
						4dfb0529f8
					
				
					 3 changed files with 99 additions and 6 deletions
				
			
		| 
						 | 
					@ -8,6 +8,68 @@
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int escape_markup_text(const char *src, char *dest, int dest_length) {
 | 
				
			||||||
 | 
						int length = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (src[0]) {
 | 
				
			||||||
 | 
							switch (src[0]) {
 | 
				
			||||||
 | 
							case '&':
 | 
				
			||||||
 | 
								length += 5;
 | 
				
			||||||
 | 
								if (dest && dest_length - length >= 0) {
 | 
				
			||||||
 | 
									dest += sprintf(dest, "%s", "&");
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									dest_length = -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '<':
 | 
				
			||||||
 | 
								length += 4;
 | 
				
			||||||
 | 
								if (dest && dest_length - length >= 0) {
 | 
				
			||||||
 | 
									dest += sprintf(dest, "%s", "<");
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									dest_length = -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '>':
 | 
				
			||||||
 | 
								length += 4;
 | 
				
			||||||
 | 
								if (dest && dest_length - length >= 0) {
 | 
				
			||||||
 | 
									dest += sprintf(dest, "%s", ">");
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									dest_length = -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '\'':
 | 
				
			||||||
 | 
								length += 6;
 | 
				
			||||||
 | 
								if (dest && dest_length - length >= 0) {
 | 
				
			||||||
 | 
									dest += sprintf(dest, "%s", "'");
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									dest_length = -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case '"':
 | 
				
			||||||
 | 
								length += 6;
 | 
				
			||||||
 | 
								if (dest && dest_length - length >= 0) {
 | 
				
			||||||
 | 
									dest += sprintf(dest, "%s", """);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									dest_length = -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								length += 1;
 | 
				
			||||||
 | 
								if (dest && dest_length - length >= 0) {
 | 
				
			||||||
 | 
									*(dest++) = *src;
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									dest_length = -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							src++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// if we could not fit the escaped string in dest, return -1
 | 
				
			||||||
 | 
						if (dest && dest_length == -1) {
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return length;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
 | 
					PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
 | 
				
			||||||
		const char *text, int32_t scale, bool markup) {
 | 
							const char *text, int32_t scale, bool markup) {
 | 
				
			||||||
	PangoLayout *layout = pango_cairo_create_layout(cairo);
 | 
						PangoLayout *layout = pango_cairo_create_layout(cairo);
 | 
				
			||||||
| 
						 | 
					@ -15,13 +77,14 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
 | 
				
			||||||
	if (markup) {
 | 
						if (markup) {
 | 
				
			||||||
		char *buf;
 | 
							char *buf;
 | 
				
			||||||
		GError *error = NULL;
 | 
							GError *error = NULL;
 | 
				
			||||||
		if (!sway_assert(pango_parse_markup(
 | 
							bool result = pango_parse_markup(text, -1, 0, &attrs, &buf,
 | 
				
			||||||
					text, -1, 0, &attrs, &buf, NULL, &error),
 | 
									NULL, &error);
 | 
				
			||||||
				"pango_parse_markup '%s' -> error %s", text,
 | 
							if (result) {
 | 
				
			||||||
				error ? error->message : NULL)) {
 | 
								wlr_log(L_ERROR, "pango_parse_markup '%s' -> error %s", text,
 | 
				
			||||||
 | 
										error->message);
 | 
				
			||||||
			return NULL;
 | 
								return NULL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		pango_layout_set_markup(layout, buf, -1);
 | 
							pango_layout_set_markup(layout, text, -1);
 | 
				
			||||||
		free(buf);
 | 
							free(buf);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		attrs = pango_attr_list_new();
 | 
							attrs = pango_attr_list_new();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,17 @@
 | 
				
			||||||
#include <cairo/cairo.h>
 | 
					#include <cairo/cairo.h>
 | 
				
			||||||
#include <pango/pangocairo.h>
 | 
					#include <pango/pangocairo.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Utility function which escape characters a & < > ' ".
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If the dest parameter is NULL, then the function returns the length of
 | 
				
			||||||
 | 
					 * of the escaped src string. The dest_length doesn't matter.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If the dest parameter is not NULL then the fuction escapes the src string
 | 
				
			||||||
 | 
					 * an puts the escaped string in dest and returns the lenght of the escaped string.
 | 
				
			||||||
 | 
					 * The dest_length parameter is the size of dest array. If the size of dest is not
 | 
				
			||||||
 | 
					 * enough, then the function returns -1.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int escape_markup_text(const char *src, char *dest, int dest_length);
 | 
				
			||||||
PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
 | 
					PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
 | 
				
			||||||
		const char *text, int32_t scale, bool markup);
 | 
							const char *text, int32_t scale, bool markup);
 | 
				
			||||||
void get_text_size(cairo_t *cairo, const char *font, int *width, int *height,
 | 
					void get_text_size(cairo_t *cairo, const char *font, int *width, int *height,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,8 @@
 | 
				
			||||||
#include "sway/tree/layout.h"
 | 
					#include "sway/tree/layout.h"
 | 
				
			||||||
#include "sway/tree/view.h"
 | 
					#include "sway/tree/view.h"
 | 
				
			||||||
#include "sway/tree/workspace.h"
 | 
					#include "sway/tree/workspace.h"
 | 
				
			||||||
 | 
					#include "sway/config.h"
 | 
				
			||||||
 | 
					#include "pango.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void view_init(struct sway_view *view, enum sway_view_type type,
 | 
					void view_init(struct sway_view *view, enum sway_view_type type,
 | 
				
			||||||
		const struct sway_view_impl *impl) {
 | 
							const struct sway_view_impl *impl) {
 | 
				
			||||||
| 
						 | 
					@ -612,6 +614,19 @@ static size_t parse_title_format(struct sway_view *view, char *buffer) {
 | 
				
			||||||
	return len;
 | 
						return len;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char *escape_title(char *buffer) {
 | 
				
			||||||
 | 
						int length = escape_markup_text(buffer, NULL, 0);
 | 
				
			||||||
 | 
						char *escaped_title = calloc(length + 1, sizeof(char));
 | 
				
			||||||
 | 
						int result = escape_markup_text(buffer, escaped_title, length);
 | 
				
			||||||
 | 
						if (result != length) {
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "Could not escape title: %s", buffer);
 | 
				
			||||||
 | 
							free(escaped_title);
 | 
				
			||||||
 | 
							return buffer;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(buffer);
 | 
				
			||||||
 | 
						return escaped_title;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void view_update_title(struct sway_view *view, bool force) {
 | 
					void view_update_title(struct sway_view *view, bool force) {
 | 
				
			||||||
	if (!view->swayc) {
 | 
						if (!view->swayc) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -631,11 +646,15 @@ void view_update_title(struct sway_view *view, bool force) {
 | 
				
			||||||
	free(view->swayc->formatted_title);
 | 
						free(view->swayc->formatted_title);
 | 
				
			||||||
	if (title) {
 | 
						if (title) {
 | 
				
			||||||
		size_t len = parse_title_format(view, NULL);
 | 
							size_t len = parse_title_format(view, NULL);
 | 
				
			||||||
		char *buffer = calloc(len + 1, 1);
 | 
							char *buffer = calloc(len + 1, sizeof(char));
 | 
				
			||||||
		if (!sway_assert(buffer, "Unable to allocate title string")) {
 | 
							if (!sway_assert(buffer, "Unable to allocate title string")) {
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		parse_title_format(view, buffer);
 | 
							parse_title_format(view, buffer);
 | 
				
			||||||
 | 
							// now we have the title, but needs to be escaped when using pango markup
 | 
				
			||||||
 | 
							if (config->pango_markup) {
 | 
				
			||||||
 | 
								buffer = escape_title(buffer);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		view->swayc->name = strdup(title);
 | 
							view->swayc->name = strdup(title);
 | 
				
			||||||
		view->swayc->formatted_title = buffer;
 | 
							view->swayc->formatted_title = buffer;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue