diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/background-image.c | 220 | ||||
-rw-r--r-- | common/gesture.c | 32 | ||||
-rw-r--r-- | common/ipc-client.c | 1 | ||||
-rw-r--r-- | common/log.c | 1 | ||||
-rw-r--r-- | common/loop.c | 1 | ||||
-rw-r--r-- | common/meson.build | 2 | ||||
-rw-r--r-- | common/pango.c | 20 | ||||
-rw-r--r-- | common/stringop.c | 34 | ||||
-rw-r--r-- | common/util.c | 1 |
9 files changed, 44 insertions, 268 deletions
diff --git a/common/background-image.c b/common/background-image.c deleted file mode 100644 index 994a0805..00000000 --- a/common/background-image.c +++ /dev/null | |||
@@ -1,220 +0,0 @@ | |||
1 | #include <assert.h> | ||
2 | #include "background-image.h" | ||
3 | #include "cairo_util.h" | ||
4 | #include "log.h" | ||
5 | #if HAVE_GDK_PIXBUF | ||
6 | #include <gdk-pixbuf/gdk-pixbuf.h> | ||
7 | #endif | ||
8 | |||
9 | enum background_mode parse_background_mode(const char *mode) { | ||
10 | if (strcmp(mode, "stretch") == 0) { | ||
11 | return BACKGROUND_MODE_STRETCH; | ||
12 | } else if (strcmp(mode, "fill") == 0) { | ||
13 | return BACKGROUND_MODE_FILL; | ||
14 | } else if (strcmp(mode, "fit") == 0) { | ||
15 | return BACKGROUND_MODE_FIT; | ||
16 | } else if (strcmp(mode, "center") == 0) { | ||
17 | return BACKGROUND_MODE_CENTER; | ||
18 | } else if (strcmp(mode, "tile") == 0) { | ||
19 | return BACKGROUND_MODE_TILE; | ||
20 | } else if (strcmp(mode, "solid_color") == 0) { | ||
21 | return BACKGROUND_MODE_SOLID_COLOR; | ||
22 | } | ||
23 | sway_log(SWAY_ERROR, "Unsupported background mode: %s", mode); | ||
24 | return BACKGROUND_MODE_INVALID; | ||
25 | } | ||
26 | |||
27 | #if HAVE_GDK_PIXBUF | ||
28 | static cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf( | ||
29 | const GdkPixbuf *gdkbuf) { | ||
30 | int chan = gdk_pixbuf_get_n_channels(gdkbuf); | ||
31 | if (chan < 3) { | ||
32 | return NULL; | ||
33 | } | ||
34 | |||
35 | const guint8* gdkpix = gdk_pixbuf_read_pixels(gdkbuf); | ||
36 | if (!gdkpix) { | ||
37 | return NULL; | ||
38 | } | ||
39 | gint w = gdk_pixbuf_get_width(gdkbuf); | ||
40 | gint h = gdk_pixbuf_get_height(gdkbuf); | ||
41 | int stride = gdk_pixbuf_get_rowstride(gdkbuf); | ||
42 | |||
43 | cairo_format_t fmt = (chan == 3) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32; | ||
44 | cairo_surface_t * cs = cairo_image_surface_create (fmt, w, h); | ||
45 | cairo_surface_flush (cs); | ||
46 | if ( !cs || cairo_surface_status(cs) != CAIRO_STATUS_SUCCESS) { | ||
47 | return NULL; | ||
48 | } | ||
49 | |||
50 | int cstride = cairo_image_surface_get_stride(cs); | ||
51 | unsigned char * cpix = cairo_image_surface_get_data(cs); | ||
52 | |||
53 | if (chan == 3) { | ||
54 | int i; | ||
55 | for (i = h; i; --i) { | ||
56 | const guint8 *gp = gdkpix; | ||
57 | unsigned char *cp = cpix; | ||
58 | const guint8* end = gp + 3*w; | ||
59 | while (gp < end) { | ||
60 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN | ||
61 | cp[0] = gp[2]; | ||
62 | cp[1] = gp[1]; | ||
63 | cp[2] = gp[0]; | ||
64 | #else | ||
65 | cp[1] = gp[0]; | ||
66 | cp[2] = gp[1]; | ||
67 | cp[3] = gp[2]; | ||
68 | #endif | ||
69 | gp += 3; | ||
70 | cp += 4; | ||
71 | } | ||
72 | gdkpix += stride; | ||
73 | cpix += cstride; | ||
74 | } | ||
75 | } else { | ||
76 | /* premul-color = alpha/255 * color/255 * 255 = (alpha*color)/255 | ||
77 | * (z/255) = z/256 * 256/255 = z/256 (1 + 1/255) | ||
78 | * = z/256 + (z/256)/255 = (z + z/255)/256 | ||
79 | * # recurse once | ||
80 | * = (z + (z + z/255)/256)/256 | ||
81 | * = (z + z/256 + z/256/255) / 256 | ||
82 | * # only use 16bit uint operations, loose some precision, | ||
83 | * # result is floored. | ||
84 | * -> (z + z>>8)>>8 | ||
85 | * # add 0x80/255 = 0.5 to convert floor to round | ||
86 | * => (z+0x80 + (z+0x80)>>8 ) >> 8 | ||
87 | * ------ | ||
88 | * tested as equal to lround(z/255.0) for uint z in [0..0xfe02] | ||
89 | */ | ||
90 | #define PREMUL_ALPHA(x,a,b,z) \ | ||
91 | G_STMT_START { z = a * b + 0x80; x = (z + (z >> 8)) >> 8; } \ | ||
92 | G_STMT_END | ||
93 | int i; | ||
94 | for (i = h; i; --i) { | ||
95 | const guint8 *gp = gdkpix; | ||
96 | unsigned char *cp = cpix; | ||
97 | const guint8* end = gp + 4*w; | ||
98 | guint z1, z2, z3; | ||
99 | while (gp < end) { | ||
100 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN | ||
101 | PREMUL_ALPHA(cp[0], gp[2], gp[3], z1); | ||
102 | PREMUL_ALPHA(cp[1], gp[1], gp[3], z2); | ||
103 | PREMUL_ALPHA(cp[2], gp[0], gp[3], z3); | ||
104 | cp[3] = gp[3]; | ||
105 | #else | ||
106 | PREMUL_ALPHA(cp[1], gp[0], gp[3], z1); | ||
107 | PREMUL_ALPHA(cp[2], gp[1], gp[3], z2); | ||
108 | PREMUL_ALPHA(cp[3], gp[2], gp[3], z3); | ||
109 | cp[0] = gp[3]; | ||
110 | #endif | ||
111 | gp += 4; | ||
112 | cp += 4; | ||
113 | } | ||
114 | gdkpix += stride; | ||
115 | cpix += cstride; | ||
116 | } | ||
117 | #undef PREMUL_ALPHA | ||
118 | } | ||
119 | cairo_surface_mark_dirty(cs); | ||
120 | return cs; | ||
121 | } | ||
122 | #endif // HAVE_GDK_PIXBUF | ||
123 | |||
124 | cairo_surface_t *load_background_image(const char *path) { | ||
125 | cairo_surface_t *image; | ||
126 | #if HAVE_GDK_PIXBUF | ||
127 | GError *err = NULL; | ||
128 | GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &err); | ||
129 | if (!pixbuf) { | ||
130 | sway_log(SWAY_ERROR, "Failed to load background image (%s).", | ||
131 | err->message); | ||
132 | return NULL; | ||
133 | } | ||
134 | image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); | ||
135 | g_object_unref(pixbuf); | ||
136 | #else | ||
137 | image = cairo_image_surface_create_from_png(path); | ||
138 | #endif // HAVE_GDK_PIXBUF | ||
139 | if (!image) { | ||
140 | sway_log(SWAY_ERROR, "Failed to read background image."); | ||
141 | return NULL; | ||
142 | } | ||
143 | if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) { | ||
144 | sway_log(SWAY_ERROR, "Failed to read background image: %s." | ||
145 | #if !HAVE_GDK_PIXBUF | ||
146 | "\nSway was compiled without gdk_pixbuf support, so only" | ||
147 | "\nPNG images can be loaded. This is the likely cause." | ||
148 | #endif // !HAVE_GDK_PIXBUF | ||
149 | , cairo_status_to_string(cairo_surface_status(image))); | ||
150 | return NULL; | ||
151 | } | ||
152 | return image; | ||
153 | } | ||
154 | |||
155 | void render_background_image(cairo_t *cairo, cairo_surface_t *image, | ||
156 | enum background_mode mode, int buffer_width, int buffer_height) { | ||
157 | double width = cairo_image_surface_get_width(image); | ||
158 | double height = cairo_image_surface_get_height(image); | ||
159 | |||
160 | cairo_save(cairo); | ||
161 | switch (mode) { | ||
162 | case BACKGROUND_MODE_STRETCH: | ||
163 | cairo_scale(cairo, | ||
164 | (double)buffer_width / width, | ||
165 | (double)buffer_height / height); | ||
166 | cairo_set_source_surface(cairo, image, 0, 0); | ||
167 | break; | ||
168 | case BACKGROUND_MODE_FILL: { | ||
169 | double window_ratio = (double)buffer_width / buffer_height; | ||
170 | double bg_ratio = width / height; | ||
171 | |||
172 | if (window_ratio > bg_ratio) { | ||
173 | double scale = (double)buffer_width / width; | ||
174 | cairo_scale(cairo, scale, scale); | ||
175 | cairo_set_source_surface(cairo, image, | ||
176 | 0, (double)buffer_height / 2 / scale - height / 2); | ||
177 | } else { | ||
178 | double scale = (double)buffer_height / height; | ||
179 | cairo_scale(cairo, scale, scale); | ||
180 | cairo_set_source_surface(cairo, image, | ||
181 | (double)buffer_width / 2 / scale - width / 2, 0); | ||
182 | } | ||
183 | break; | ||
184 | } | ||
185 | case BACKGROUND_MODE_FIT: { | ||
186 | double window_ratio = (double)buffer_width / buffer_height; | ||
187 | double bg_ratio = width / height; | ||
188 | |||
189 | if (window_ratio > bg_ratio) { | ||
190 | double scale = (double)buffer_height / height; | ||
191 | cairo_scale(cairo, scale, scale); | ||
192 | cairo_set_source_surface(cairo, image, | ||
193 | (double)buffer_width / 2 / scale - width / 2, 0); | ||
194 | } else { | ||
195 | double scale = (double)buffer_width / width; | ||
196 | cairo_scale(cairo, scale, scale); | ||
197 | cairo_set_source_surface(cairo, image, | ||
198 | 0, (double)buffer_height / 2 / scale - height / 2); | ||
199 | } | ||
200 | break; | ||
201 | } | ||
202 | case BACKGROUND_MODE_CENTER: | ||
203 | cairo_set_source_surface(cairo, image, | ||
204 | (double)buffer_width / 2 - width / 2, | ||
205 | (double)buffer_height / 2 - height / 2); | ||
206 | break; | ||
207 | case BACKGROUND_MODE_TILE: { | ||
208 | cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); | ||
209 | cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); | ||
210 | cairo_set_source(cairo, pattern); | ||
211 | break; | ||
212 | } | ||
213 | case BACKGROUND_MODE_SOLID_COLOR: | ||
214 | case BACKGROUND_MODE_INVALID: | ||
215 | assert(0); | ||
216 | break; | ||
217 | } | ||
218 | cairo_paint(cairo); | ||
219 | cairo_restore(cairo); | ||
220 | } | ||
diff --git a/common/gesture.c b/common/gesture.c index 8c2efe99..272aa837 100644 --- a/common/gesture.c +++ b/common/gesture.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include "gesture.h" | 1 | #include "gesture.h" |
3 | 2 | ||
4 | #include <math.h> | 3 | #include <math.h> |
@@ -12,23 +11,6 @@ | |||
12 | 11 | ||
13 | const uint8_t GESTURE_FINGERS_ANY = 0; | 12 | const uint8_t GESTURE_FINGERS_ANY = 0; |
14 | 13 | ||
15 | // Helper to easily allocate and format string | ||
16 | static char *strformat(const char *format, ...) { | ||
17 | va_list args; | ||
18 | va_start(args, format); | ||
19 | int length = vsnprintf(NULL, 0, format, args) + 1; | ||
20 | va_end(args); | ||
21 | |||
22 | char *result = malloc(length); | ||
23 | if (result) { | ||
24 | va_start(args, format); | ||
25 | vsnprintf(result, length, format, args); | ||
26 | va_end(args); | ||
27 | } | ||
28 | |||
29 | return result; | ||
30 | } | ||
31 | |||
32 | char *gesture_parse(const char *input, struct gesture *output) { | 14 | char *gesture_parse(const char *input, struct gesture *output) { |
33 | // Clear output in case of failure | 15 | // Clear output in case of failure |
34 | output->type = GESTURE_TYPE_NONE; | 16 | output->type = GESTURE_TYPE_NONE; |
@@ -38,7 +20,7 @@ char *gesture_parse(const char *input, struct gesture *output) { | |||
38 | // Split input type, fingers and directions | 20 | // Split input type, fingers and directions |
39 | list_t *split = split_string(input, ":"); | 21 | list_t *split = split_string(input, ":"); |
40 | if (split->length < 1 || split->length > 3) { | 22 | if (split->length < 1 || split->length > 3) { |
41 | return strformat( | 23 | return format_str( |
42 | "expected <gesture>[:<fingers>][:direction], got %s", | 24 | "expected <gesture>[:<fingers>][:direction], got %s", |
43 | input); | 25 | input); |
44 | } | 26 | } |
@@ -51,8 +33,8 @@ char *gesture_parse(const char *input, struct gesture *output) { | |||
51 | } else if (strcmp(split->items[0], "swipe") == 0) { | 33 | } else if (strcmp(split->items[0], "swipe") == 0) { |
52 | output->type = GESTURE_TYPE_SWIPE; | 34 | output->type = GESTURE_TYPE_SWIPE; |
53 | } else { | 35 | } else { |
54 | return strformat("expected hold|pinch|swipe, got %s", | 36 | return format_str("expected hold|pinch|swipe, got %s", |
55 | split->items[0]); | 37 | (const char *)split->items[0]); |
56 | } | 38 | } |
57 | 39 | ||
58 | // Parse optional arguments | 40 | // Parse optional arguments |
@@ -67,7 +49,7 @@ char *gesture_parse(const char *input, struct gesture *output) { | |||
67 | next = split->length == 3 ? split->items[2] : NULL; | 49 | next = split->length == 3 ? split->items[2] : NULL; |
68 | } else if (split->length == 3) { | 50 | } else if (split->length == 3) { |
69 | // Fail here if argument can only be finger count | 51 | // Fail here if argument can only be finger count |
70 | return strformat("expected 1-9, got %s", next); | 52 | return format_str("expected 1-9, got %s", next); |
71 | } | 53 | } |
72 | 54 | ||
73 | // If there is an argument left, try to parse as direction | 55 | // If there is an argument left, try to parse as direction |
@@ -95,7 +77,7 @@ char *gesture_parse(const char *input, struct gesture *output) { | |||
95 | } else if (strcmp(item, "counterclockwise") == 0) { | 77 | } else if (strcmp(item, "counterclockwise") == 0) { |
96 | output->directions |= GESTURE_DIRECTION_COUNTERCLOCKWISE; | 78 | output->directions |= GESTURE_DIRECTION_COUNTERCLOCKWISE; |
97 | } else { | 79 | } else { |
98 | return strformat("expected direction, got %s", item); | 80 | return format_str("expected direction, got %s", item); |
99 | } | 81 | } |
100 | } | 82 | } |
101 | list_free_items_and_destroy(directions); | 83 | list_free_items_and_destroy(directions); |
@@ -163,7 +145,7 @@ static char *gesture_directions_to_string(uint32_t directions) { | |||
163 | if (!result) { | 145 | if (!result) { |
164 | result = strdup(name); | 146 | result = strdup(name); |
165 | } else { | 147 | } else { |
166 | char *new = strformat("%s+%s", result, name); | 148 | char *new = format_str("%s+%s", result, name); |
167 | free(result); | 149 | free(result); |
168 | result = new; | 150 | result = new; |
169 | } | 151 | } |
@@ -179,7 +161,7 @@ static char *gesture_directions_to_string(uint32_t directions) { | |||
179 | 161 | ||
180 | char *gesture_to_string(struct gesture *gesture) { | 162 | char *gesture_to_string(struct gesture *gesture) { |
181 | char *directions = gesture_directions_to_string(gesture->directions); | 163 | char *directions = gesture_directions_to_string(gesture->directions); |
182 | char *result = strformat("%s:%u:%s", | 164 | char *result = format_str("%s:%u:%s", |
183 | gesture_type_string(gesture->type), | 165 | gesture_type_string(gesture->type), |
184 | gesture->fingers, directions); | 166 | gesture->fingers, directions); |
185 | free(directions); | 167 | free(directions); |
diff --git a/common/ipc-client.c b/common/ipc-client.c index d30212d2..a0be2b2d 100644 --- a/common/ipc-client.c +++ b/common/ipc-client.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <stdio.h> | 1 | #include <stdio.h> |
3 | #include <stdint.h> | 2 | #include <stdint.h> |
4 | #include <stdlib.h> | 3 | #include <stdlib.h> |
diff --git a/common/log.c b/common/log.c index 483420e7..3eacdb34 100644 --- a/common/log.c +++ b/common/log.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #define _POSIX_C_SOURCE 200112L | ||
2 | #include <signal.h> | 1 | #include <signal.h> |
3 | #include <stdarg.h> | 2 | #include <stdarg.h> |
4 | #include <stdio.h> | 3 | #include <stdio.h> |
diff --git a/common/loop.c b/common/loop.c index 80fe18ea..b99c6d55 100644 --- a/common/loop.c +++ b/common/loop.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #define _POSIX_C_SOURCE 200112L | ||
2 | #include <limits.h> | 1 | #include <limits.h> |
3 | #include <string.h> | 2 | #include <string.h> |
4 | #include <stdbool.h> | 3 | #include <stdbool.h> |
diff --git a/common/meson.build b/common/meson.build index 3756075a..c0ce1f68 100644 --- a/common/meson.build +++ b/common/meson.build | |||
@@ -1,7 +1,6 @@ | |||
1 | lib_sway_common = static_library( | 1 | lib_sway_common = static_library( |
2 | 'sway-common', | 2 | 'sway-common', |
3 | files( | 3 | files( |
4 | 'background-image.c', | ||
5 | 'cairo.c', | 4 | 'cairo.c', |
6 | 'gesture.c', | 5 | 'gesture.c', |
7 | 'ipc-client.c', | 6 | 'ipc-client.c', |
@@ -14,7 +13,6 @@ lib_sway_common = static_library( | |||
14 | ), | 13 | ), |
15 | dependencies: [ | 14 | dependencies: [ |
16 | cairo, | 15 | cairo, |
17 | gdk_pixbuf, | ||
18 | pango, | 16 | pango, |
19 | pangocairo, | 17 | pangocairo, |
20 | wayland_client.partial_dependency(compile_args: true) | 18 | wayland_client.partial_dependency(compile_args: true) |
diff --git a/common/pango.c b/common/pango.c index e04bf80f..288569b3 100644 --- a/common/pango.c +++ b/common/pango.c | |||
@@ -84,18 +84,11 @@ void get_text_size(cairo_t *cairo, const PangoFontDescription *desc, int *width, | |||
84 | int *baseline, double scale, bool markup, const char *fmt, ...) { | 84 | int *baseline, double scale, bool markup, const char *fmt, ...) { |
85 | va_list args; | 85 | va_list args; |
86 | va_start(args, fmt); | 86 | va_start(args, fmt); |
87 | // Add one since vsnprintf excludes null terminator. | 87 | char *buf = vformat_str(fmt, args); |
88 | int length = vsnprintf(NULL, 0, fmt, args) + 1; | ||
89 | va_end(args); | 88 | va_end(args); |
90 | |||
91 | char *buf = malloc(length); | ||
92 | if (buf == NULL) { | 89 | if (buf == NULL) { |
93 | sway_log(SWAY_ERROR, "Failed to allocate memory"); | ||
94 | return; | 90 | return; |
95 | } | 91 | } |
96 | va_start(args, fmt); | ||
97 | vsnprintf(buf, length, fmt, args); | ||
98 | va_end(args); | ||
99 | 92 | ||
100 | PangoLayout *layout = get_pango_layout(cairo, desc, buf, scale, markup); | 93 | PangoLayout *layout = get_pango_layout(cairo, desc, buf, scale, markup); |
101 | pango_cairo_update_layout(cairo, layout); | 94 | pango_cairo_update_layout(cairo, layout); |
@@ -104,6 +97,7 @@ void get_text_size(cairo_t *cairo, const PangoFontDescription *desc, int *width, | |||
104 | *baseline = pango_layout_get_baseline(layout) / PANGO_SCALE; | 97 | *baseline = pango_layout_get_baseline(layout) / PANGO_SCALE; |
105 | } | 98 | } |
106 | g_object_unref(layout); | 99 | g_object_unref(layout); |
100 | |||
107 | free(buf); | 101 | free(buf); |
108 | } | 102 | } |
109 | 103 | ||
@@ -125,18 +119,11 @@ void render_text(cairo_t *cairo, const PangoFontDescription *desc, | |||
125 | double scale, bool markup, const char *fmt, ...) { | 119 | double scale, bool markup, const char *fmt, ...) { |
126 | va_list args; | 120 | va_list args; |
127 | va_start(args, fmt); | 121 | va_start(args, fmt); |
128 | // Add one since vsnprintf excludes null terminator. | 122 | char *buf = vformat_str(fmt, args); |
129 | int length = vsnprintf(NULL, 0, fmt, args) + 1; | ||
130 | va_end(args); | 123 | va_end(args); |
131 | |||
132 | char *buf = malloc(length); | ||
133 | if (buf == NULL) { | 124 | if (buf == NULL) { |
134 | sway_log(SWAY_ERROR, "Failed to allocate memory"); | ||
135 | return; | 125 | return; |
136 | } | 126 | } |
137 | va_start(args, fmt); | ||
138 | vsnprintf(buf, length, fmt, args); | ||
139 | va_end(args); | ||
140 | 127 | ||
141 | PangoLayout *layout = get_pango_layout(cairo, desc, buf, scale, markup); | 128 | PangoLayout *layout = get_pango_layout(cairo, desc, buf, scale, markup); |
142 | cairo_font_options_t *fo = cairo_font_options_create(); | 129 | cairo_font_options_t *fo = cairo_font_options_create(); |
@@ -146,5 +133,6 @@ void render_text(cairo_t *cairo, const PangoFontDescription *desc, | |||
146 | pango_cairo_update_layout(cairo, layout); | 133 | pango_cairo_update_layout(cairo, layout); |
147 | pango_cairo_show_layout(cairo, layout); | 134 | pango_cairo_show_layout(cairo, layout); |
148 | g_object_unref(layout); | 135 | g_object_unref(layout); |
136 | |||
149 | free(buf); | 137 | free(buf); |
150 | } | 138 | } |
diff --git a/common/stringop.c b/common/stringop.c index 7fb3fe12..16d04917 100644 --- a/common/stringop.c +++ b/common/stringop.c | |||
@@ -1,5 +1,5 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <ctype.h> | 1 | #include <ctype.h> |
2 | #include <stdarg.h> | ||
3 | #include <stdbool.h> | 3 | #include <stdbool.h> |
4 | #include <stdio.h> | 4 | #include <stdio.h> |
5 | #include <stdlib.h> | 5 | #include <stdlib.h> |
@@ -328,3 +328,35 @@ bool expand_path(char **path) { | |||
328 | wordfree(&p); | 328 | wordfree(&p); |
329 | return true; | 329 | return true; |
330 | } | 330 | } |
331 | |||
332 | char *vformat_str(const char *fmt, va_list args) { | ||
333 | char *str = NULL; | ||
334 | va_list args_copy; | ||
335 | va_copy(args_copy, args); | ||
336 | |||
337 | int len = vsnprintf(NULL, 0, fmt, args); | ||
338 | if (len < 0) { | ||
339 | sway_log_errno(SWAY_ERROR, "vsnprintf(\"%s\") failed", fmt); | ||
340 | goto out; | ||
341 | } | ||
342 | |||
343 | str = malloc(len + 1); | ||
344 | if (str == NULL) { | ||
345 | sway_log_errno(SWAY_ERROR, "malloc() failed"); | ||
346 | goto out; | ||
347 | } | ||
348 | |||
349 | vsnprintf(str, len + 1, fmt, args_copy); | ||
350 | |||
351 | out: | ||
352 | va_end(args_copy); | ||
353 | return str; | ||
354 | } | ||
355 | |||
356 | char *format_str(const char *fmt, ...) { | ||
357 | va_list args; | ||
358 | va_start(args, fmt); | ||
359 | char *str = vformat_str(fmt, args); | ||
360 | va_end(args); | ||
361 | return str; | ||
362 | } | ||
diff --git a/common/util.c b/common/util.c index 5d4c0673..7c492bcb 100644 --- a/common/util.c +++ b/common/util.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <ctype.h> | 1 | #include <ctype.h> |
3 | #include <fcntl.h> | 2 | #include <fcntl.h> |
4 | #include <math.h> | 3 | #include <math.h> |