summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/CMakeLists.txt15
-rw-r--r--common/background-image.c119
-rw-r--r--common/cairo.c127
-rw-r--r--common/ipc-client.c34
-rw-r--r--common/log.c151
-rw-r--r--common/meson.build23
-rw-r--r--common/pango.c72
-rw-r--r--common/readline.c4
-rw-r--r--common/unicode.c101
-rw-r--r--common/util.c24
10 files changed, 487 insertions, 183 deletions
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
deleted file mode 100644
index 4fa71f3a..00000000
--- a/common/CMakeLists.txt
+++ /dev/null
@@ -1,15 +0,0 @@
1include_directories(
2 ${WLC_INCLUDE_DIRS}
3 ${XKBCOMMON_INCLUDE_DIRS}
4)
5
6add_library(sway-common STATIC
7 ipc-client.c
8 list.c
9 log.c
10 util.c
11 readline.c
12 stringop.c
13)
14
15target_link_libraries(sway-common m)
diff --git a/common/background-image.c b/common/background-image.c
new file mode 100644
index 00000000..e5fb4433
--- /dev/null
+++ b/common/background-image.c
@@ -0,0 +1,119 @@
1#include <assert.h>
2#include <stdbool.h>
3#include <wlr/util/log.h>
4#include "background-image.h"
5#include "cairo.h"
6
7enum background_mode parse_background_mode(const char *mode) {
8 if (strcmp(mode, "stretch") == 0) {
9 return BACKGROUND_MODE_STRETCH;
10 } else if (strcmp(mode, "fill") == 0) {
11 return BACKGROUND_MODE_FILL;
12 } else if (strcmp(mode, "fit") == 0) {
13 return BACKGROUND_MODE_FIT;
14 } else if (strcmp(mode, "center") == 0) {
15 return BACKGROUND_MODE_CENTER;
16 } else if (strcmp(mode, "tile") == 0) {
17 return BACKGROUND_MODE_TILE;
18 } else if (strcmp(mode, "solid_color") == 0) {
19 return BACKGROUND_MODE_SOLID_COLOR;
20 }
21 wlr_log(L_ERROR, "Unsupported background mode: %s", mode);
22 return BACKGROUND_MODE_INVALID;
23}
24
25cairo_surface_t *load_background_image(const char *path) {
26 cairo_surface_t *image;
27#ifdef HAVE_GDK_PIXBUF
28 GError *err = NULL;
29 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &err);
30 if (!pixbuf) {
31 wlr_log(L_ERROR, "Failed to load background image (%s).",
32 err->message);
33 return false;
34 }
35 image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf);
36 g_object_unref(pixbuf);
37#else
38 image = cairo_image_surface_create_from_png(path);
39#endif //HAVE_GDK_PIXBUF
40 if (!image) {
41 wlr_log(L_ERROR, "Failed to read background image.");
42 return NULL;
43 }
44 if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) {
45 wlr_log(L_ERROR, "Failed to read background image: %s."
46#ifndef HAVE_GDK_PIXBUF
47 "\nSway was compiled without gdk_pixbuf support, so only"
48 "\nPNG images can be loaded. This is the likely cause."
49#endif //HAVE_GDK_PIXBUF
50 , cairo_status_to_string(cairo_surface_status(image)));
51 return NULL;
52 }
53 return image;
54}
55
56void render_background_image(cairo_t *cairo, cairo_surface_t *image,
57 enum background_mode mode, int buffer_width, int buffer_height) {
58 double width = cairo_image_surface_get_width(image);
59 double height = cairo_image_surface_get_height(image);
60
61 switch (mode) {
62 case BACKGROUND_MODE_STRETCH:
63 cairo_scale(cairo,
64 (double)buffer_width / width,
65 (double)buffer_height / height);
66 cairo_set_source_surface(cairo, image, 0, 0);
67 break;
68 case BACKGROUND_MODE_FILL: {
69 double window_ratio = (double)buffer_width / buffer_height;
70 double bg_ratio = width / height;
71
72 if (window_ratio > bg_ratio) {
73 double scale = (double)buffer_width / width;
74 cairo_scale(cairo, scale, scale);
75 cairo_set_source_surface(cairo, image,
76 0, (double)buffer_height / 2 / scale - height / 2);
77 } else {
78 double scale = (double)buffer_height / height;
79 cairo_scale(cairo, scale, scale);
80 cairo_set_source_surface(cairo, image,
81 (double)buffer_width / 2 / scale - width / 2, 0);
82 }
83 break;
84 }
85 case BACKGROUND_MODE_FIT: {
86 double window_ratio = (double)buffer_width / buffer_height;
87 double bg_ratio = width / height;
88
89 if (window_ratio > bg_ratio) {
90 double scale = (double)buffer_height / height;
91 cairo_scale(cairo, scale, scale);
92 cairo_set_source_surface(cairo, image,
93 (double)buffer_width / 2 / scale - width / 2, 0);
94 } else {
95 double scale = (double)buffer_width / width;
96 cairo_scale(cairo, scale, scale);
97 cairo_set_source_surface(cairo, image,
98 0, (double)buffer_height / 2 / scale - height / 2);
99 }
100 break;
101 }
102 case BACKGROUND_MODE_CENTER:
103 cairo_set_source_surface(cairo, image,
104 (double)buffer_width / 2 - width / 2,
105 (double)buffer_height / 2 - height / 2);
106 break;
107 case BACKGROUND_MODE_TILE: {
108 cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image);
109 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
110 cairo_set_source(cairo, pattern);
111 break;
112 }
113 case BACKGROUND_MODE_SOLID_COLOR:
114 case BACKGROUND_MODE_INVALID:
115 assert(0);
116 break;
117 }
118 cairo_paint(cairo);
119}
diff --git a/common/cairo.c b/common/cairo.c
new file mode 100644
index 00000000..c267c77c
--- /dev/null
+++ b/common/cairo.c
@@ -0,0 +1,127 @@
1#include <stdint.h>
2#include <cairo/cairo.h>
3#include "cairo.h"
4#ifdef HAVE_GDK_PIXBUF
5#include <gdk-pixbuf/gdk-pixbuf.h>
6#endif
7
8void cairo_set_source_u32(cairo_t *cairo, uint32_t color) {
9 cairo_set_source_rgba(cairo,
10 (color >> (3*8) & 0xFF) / 255.0,
11 (color >> (2*8) & 0xFF) / 255.0,
12 (color >> (1*8) & 0xFF) / 255.0,
13 (color >> (0*8) & 0xFF) / 255.0);
14}
15
16cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image,
17 int width, int height) {
18 int image_width = cairo_image_surface_get_width(image);
19 int image_height = cairo_image_surface_get_height(image);
20
21 cairo_surface_t *new =
22 cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
23 cairo_t *cairo = cairo_create(new);
24 cairo_scale(cairo, (double)width / image_width,
25 (double)height / image_height);
26 cairo_set_source_surface(cairo, image, 0, 0);
27
28 cairo_paint(cairo);
29 cairo_destroy(cairo);
30 return new;
31}
32
33#ifdef HAVE_GDK_PIXBUF
34cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdkbuf) {
35 int chan = gdk_pixbuf_get_n_channels(gdkbuf);
36 if (chan < 3) {
37 return NULL;
38 }
39
40 const guint8* gdkpix = gdk_pixbuf_read_pixels(gdkbuf);
41 if (!gdkpix) {
42 return NULL;
43 }
44 gint w = gdk_pixbuf_get_width(gdkbuf);
45 gint h = gdk_pixbuf_get_height(gdkbuf);
46 int stride = gdk_pixbuf_get_rowstride(gdkbuf);
47
48 cairo_format_t fmt = (chan == 3) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32;
49 cairo_surface_t * cs = cairo_image_surface_create (fmt, w, h);
50 cairo_surface_flush (cs);
51 if ( !cs || cairo_surface_status(cs) != CAIRO_STATUS_SUCCESS) {
52 return NULL;
53 }
54
55 int cstride = cairo_image_surface_get_stride(cs);
56 unsigned char * cpix = cairo_image_surface_get_data(cs);
57
58 if (chan == 3) {
59 int i;
60 for (i = h; i; --i) {
61 const guint8 *gp = gdkpix;
62 unsigned char *cp = cpix;
63 const guint8* end = gp + 3*w;
64 while (gp < end) {
65#if G_BYTE_ORDER == G_LITTLE_ENDIAN
66 cp[0] = gp[2];
67 cp[1] = gp[1];
68 cp[2] = gp[0];
69#else
70 cp[1] = gp[0];
71 cp[2] = gp[1];
72 cp[3] = gp[2];
73#endif
74 gp += 3;
75 cp += 4;
76 }
77 gdkpix += stride;
78 cpix += cstride;
79 }
80 } else {
81 /* premul-color = alpha/255 * color/255 * 255 = (alpha*color)/255
82 * (z/255) = z/256 * 256/255 = z/256 (1 + 1/255)
83 * = z/256 + (z/256)/255 = (z + z/255)/256
84 * # recurse once
85 * = (z + (z + z/255)/256)/256
86 * = (z + z/256 + z/256/255) / 256
87 * # only use 16bit uint operations, loose some precision,
88 * # result is floored.
89 * -> (z + z>>8)>>8
90 * # add 0x80/255 = 0.5 to convert floor to round
91 * => (z+0x80 + (z+0x80)>>8 ) >> 8
92 * ------
93 * tested as equal to lround(z/255.0) for uint z in [0..0xfe02]
94 */
95#define PREMUL_ALPHA(x,a,b,z) \
96 G_STMT_START { z = a * b + 0x80; x = (z + (z >> 8)) >> 8; } \
97 G_STMT_END
98 int i;
99 for (i = h; i; --i) {
100 const guint8 *gp = gdkpix;
101 unsigned char *cp = cpix;
102 const guint8* end = gp + 4*w;
103 guint z1, z2, z3;
104 while (gp < end) {
105#if G_BYTE_ORDER == G_LITTLE_ENDIAN
106 PREMUL_ALPHA(cp[0], gp[2], gp[3], z1);
107 PREMUL_ALPHA(cp[1], gp[1], gp[3], z2);
108 PREMUL_ALPHA(cp[2], gp[0], gp[3], z3);
109 cp[3] = gp[3];
110#else
111 PREMUL_ALPHA(cp[1], gp[0], gp[3], z1);
112 PREMUL_ALPHA(cp[2], gp[1], gp[3], z2);
113 PREMUL_ALPHA(cp[3], gp[2], gp[3], z3);
114 cp[0] = gp[3];
115#endif
116 gp += 4;
117 cp += 4;
118 }
119 gdkpix += stride;
120 cpix += cstride;
121 }
122#undef PREMUL_ALPHA
123 }
124 cairo_surface_mark_dirty(cs);
125 return cs;
126}
127#endif //HAVE_GDK_PIXBUF
diff --git a/common/ipc-client.c b/common/ipc-client.c
index 1ab6627b..117e9910 100644
--- a/common/ipc-client.c
+++ b/common/ipc-client.c
@@ -1,4 +1,4 @@
1#define _POSIX_C_SOURCE 2 1#define _POSIX_C_SOURCE 200809L
2#include <stdio.h> 2#include <stdio.h>
3#include <stdint.h> 3#include <stdint.h>
4#include <stdlib.h> 4#include <stdlib.h>
@@ -14,13 +14,31 @@ static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'};
14static const size_t ipc_header_size = sizeof(ipc_magic)+8; 14static const size_t ipc_header_size = sizeof(ipc_magic)+8;
15 15
16char *get_socketpath(void) { 16char *get_socketpath(void) {
17 FILE *fp = popen("sway --get-socketpath", "r"); 17 const char *swaysock = getenv("SWAYSOCK");
18 if (!fp) { 18 if (swaysock) {
19 return NULL; 19 return strdup(swaysock);
20 } 20 }
21 char *line = read_line(fp); 21 FILE *fp = popen("sway --get-socketpath 2>/dev/null", "r");
22 pclose(fp); 22 if (fp) {
23 return line; 23 char *line = read_line(fp);
24 pclose(fp);
25 if (line && *line) {
26 return line;
27 }
28 }
29 const char *i3sock = getenv("I3SOCK");
30 if (i3sock) {
31 return strdup(i3sock);
32 }
33 fp = popen("i3 --get-socketpath 2>/dev/null", "r");
34 if (fp) {
35 char *line = read_line(fp);
36 pclose(fp);
37 if (line && *line) {
38 return line;
39 }
40 }
41 return NULL;
24} 42}
25 43
26int ipc_open_socket(const char *socket_path) { 44int ipc_open_socket(const char *socket_path) {
@@ -79,7 +97,7 @@ struct ipc_response *ipc_recv_response(int socketfd) {
79error_2: 97error_2:
80 free(response); 98 free(response);
81error_1: 99error_1:
82 sway_log(L_ERROR, "Unable to allocate memory for IPC response"); 100 wlr_log(L_ERROR, "Unable to allocate memory for IPC response");
83 return NULL; 101 return NULL;
84} 102}
85 103
diff --git a/common/log.c b/common/log.c
index 6dc9d743..2cc7289c 100644
--- a/common/log.c
+++ b/common/log.c
@@ -1,167 +1,26 @@
1#define _POSIX_C_SOURCE 199506L
2#include <errno.h>
3#include <libgen.h>
4#include <signal.h> 1#include <signal.h>
5#include <stdarg.h> 2#include <stdarg.h>
6#include <stdio.h>
7#include <stdlib.h> 3#include <stdlib.h>
8#include <unistd.h>
9#include <string.h>
10#include <time.h>
11#include "log.h" 4#include "log.h"
12#include "sway.h"
13#include "readline.h"
14 5
15static int colored = 1; 6void sway_terminate(int code);
16static log_importance_t loglevel_default = L_ERROR;
17static log_importance_t v = L_SILENT;
18 7
19static const char *verbosity_colors[] = { 8void _sway_abort(const char *format, ...) {
20 [L_SILENT] = "",
21 [L_ERROR ] = "\x1B[1;31m",
22 [L_INFO ] = "\x1B[1;34m",
23 [L_DEBUG ] = "\x1B[1;30m",
24};
25static const char verbosity_chars[] = {
26 [L_SILENT] = '\0',
27 [L_ERROR ] = 'E',
28 [L_INFO ] = 'I',
29 [L_DEBUG ] = 'D',
30};
31
32void init_log(log_importance_t verbosity) {
33 if (verbosity != L_DEBUG) {
34 // command "debuglog" needs to know the user specified log level when
35 // turning off debug logging.
36 loglevel_default = verbosity;
37 }
38 v = verbosity;
39}
40
41void set_log_level(log_importance_t verbosity) {
42 v = verbosity;
43}
44
45log_importance_t get_log_level(void) {
46 return v;
47}
48
49void reset_log_level(void) {
50 v = loglevel_default;
51}
52
53bool toggle_debug_logging(void) {
54 v = (v == L_DEBUG) ? loglevel_default : L_DEBUG;
55 return (v == L_DEBUG);
56}
57
58void sway_log_colors(int mode) {
59 colored = (mode == 1) ? 1 : 0;
60}
61
62void _sway_vlog(const char *filename, int line, log_importance_t verbosity,
63 const char *format, va_list args) {
64 if (verbosity <= v) {
65 // prefix the time to the log message
66 static struct tm result;
67 static time_t t;
68 static struct tm *tm_info;
69 char buffer[26];
70
71 unsigned int c = verbosity;
72 if (c > sizeof(verbosity_colors) / sizeof(char *) - 1) {
73 c = sizeof(verbosity_colors) / sizeof(char *) - 1;
74 }
75
76 // First, if not printing color, show the log level
77 if (!(colored && isatty(STDERR_FILENO)) && c != L_SILENT) {
78 fprintf(stderr, "%c: ", verbosity_chars[c]);
79 }
80
81 // get current time
82 t = time(NULL);
83 // convert time to local time (determined by the locale)
84 tm_info = localtime_r(&t, &result);
85 // generate time prefix
86 strftime(buffer, sizeof(buffer), "%x %X - ", tm_info);
87 fprintf(stderr, "%s", buffer);
88
89 if (colored && isatty(STDERR_FILENO)) {
90 fprintf(stderr, "%s", verbosity_colors[c]);
91 }
92
93 if (filename && line) {
94 const char *file = filename + strlen(filename);
95 while (file != filename && *file != '/') {
96 --file;
97 }
98 if (*file == '/') {
99 ++file;
100 }
101 fprintf(stderr, "[%s:%d] ", file, line);
102 }
103
104 vfprintf(stderr, format, args);
105
106 if (colored && isatty(STDERR_FILENO)) {
107 fprintf(stderr, "\x1B[0m");
108 }
109 fprintf(stderr, "\n");
110 }
111}
112
113void _sway_log(const char *filename, int line, log_importance_t verbosity, const char* format, ...) {
114 va_list args;
115 va_start(args, format);
116 _sway_vlog(filename, line, verbosity, format, args);
117 va_end(args);
118}
119
120
121void _sway_abort(const char *filename, int line, const char* format, ...) {
122 va_list args; 9 va_list args;
123 va_start(args, format); 10 va_start(args, format);
124 _sway_vlog(filename, line, L_ERROR, format, args); 11 _wlr_vlog(L_ERROR, format, args);
125 va_end(args); 12 va_end(args);
126 sway_terminate(EXIT_FAILURE); 13 sway_terminate(EXIT_FAILURE);
127} 14}
128 15
129void sway_log_errno(log_importance_t verbosity, char* format, ...) { 16bool _sway_assert(bool condition, const char *format, ...) {
130 if (verbosity <= v) {
131 unsigned int c = verbosity;
132 if (c > sizeof(verbosity_colors) / sizeof(char *) - 1) {
133 c = sizeof(verbosity_colors) / sizeof(char *) - 1;
134 }
135
136 if (colored && isatty(STDERR_FILENO)) {
137 fprintf(stderr, "%s", verbosity_colors[c]);
138 } else if (c != L_SILENT) {
139 fprintf(stderr, "%c: ", verbosity_chars[c]);
140 }
141
142 va_list args;
143 va_start(args, format);
144 vfprintf(stderr, format, args);
145 va_end(args);
146
147 fprintf(stderr, ": ");
148 fprintf(stderr, "%s", strerror(errno));
149
150 if (colored && isatty(STDERR_FILENO)) {
151 fprintf(stderr, "\x1B[0m");
152 }
153 fprintf(stderr, "\n");
154 }
155}
156
157bool _sway_assert(bool condition, const char *filename, int line, const char* format, ...) {
158 if (condition) { 17 if (condition) {
159 return true; 18 return true;
160 } 19 }
161 20
162 va_list args; 21 va_list args;
163 va_start(args, format); 22 va_start(args, format);
164 _sway_vlog(filename, line, L_ERROR, format, args); 23 _wlr_vlog(L_ERROR, format, args);
165 va_end(args); 24 va_end(args);
166 25
167#ifndef NDEBUG 26#ifndef NDEBUG
diff --git a/common/meson.build b/common/meson.build
new file mode 100644
index 00000000..44a29508
--- /dev/null
+++ b/common/meson.build
@@ -0,0 +1,23 @@
1lib_sway_common = static_library(
2 'sway-common',
3 files(
4 'background-image.c',
5 'cairo.c',
6 'ipc-client.c',
7 'log.c',
8 'list.c',
9 'pango.c',
10 'readline.c',
11 'stringop.c',
12 'unicode.c',
13 'util.c'
14 ),
15 dependencies: [
16 cairo,
17 gdk_pixbuf,
18 pango,
19 pangocairo,
20 wlroots
21 ],
22 include_directories: sway_inc
23)
diff --git a/common/pango.c b/common/pango.c
new file mode 100644
index 00000000..658d2876
--- /dev/null
+++ b/common/pango.c
@@ -0,0 +1,72 @@
1#include <cairo/cairo.h>
2#include <pango/pangocairo.h>
3#include <stdarg.h>
4#include <stdbool.h>
5#include <stdint.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include "log.h"
10
11PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
12 const char *text, int32_t scale, bool markup) {
13 PangoLayout *layout = pango_cairo_create_layout(cairo);
14 PangoAttrList *attrs;
15 if (markup) {
16 char *buf;
17 GError *error = NULL;
18 if (!sway_assert(pango_parse_markup(
19 text, -1, 0, &attrs, &buf, NULL, &error),
20 "pango_parse_markup '%s' -> error %s", text,
21 error ? error->message : NULL)) {
22 return NULL;
23 }
24 pango_layout_set_markup(layout, buf, -1);
25 free(buf);
26 } else {
27 attrs = pango_attr_list_new();
28 pango_layout_set_text(layout, text, -1);
29 }
30 pango_attr_list_insert(attrs, pango_attr_scale_new(scale));
31 PangoFontDescription *desc = pango_font_description_from_string(font);
32 pango_layout_set_font_description(layout, desc);
33 pango_layout_set_single_paragraph_mode(layout, 1);
34 pango_layout_set_attributes(layout, attrs);
35 pango_attr_list_unref(attrs);
36 pango_font_description_free(desc);
37 return layout;
38}
39
40void get_text_size(cairo_t *cairo, const char *font, int *width, int *height,
41 int32_t scale, bool markup, const char *fmt, ...) {
42 static char buf[2048];
43
44 va_list args;
45 va_start(args, fmt);
46 if (vsnprintf(buf, 2048, fmt, args) >= 2048) {
47 strcpy(buf, "[buffer overflow]");
48 }
49 va_end(args);
50
51 PangoLayout *layout = get_pango_layout(cairo, font, buf, scale, markup);
52 pango_cairo_update_layout(cairo, layout);
53 pango_layout_get_pixel_size(layout, width, height);
54 g_object_unref(layout);
55}
56
57void pango_printf(cairo_t *cairo, const char *font,
58 int32_t scale, bool markup, const char *fmt, ...) {
59 static char buf[2048];
60
61 va_list args;
62 va_start(args, fmt);
63 if (vsnprintf(buf, 2048, fmt, args) >= 2048) {
64 strcpy(buf, "[buffer overflow]");
65 }
66 va_end(args);
67
68 PangoLayout *layout = get_pango_layout(cairo, font, buf, scale, markup);
69 pango_cairo_update_layout(cairo, layout);
70 pango_cairo_show_layout(cairo, layout);
71 g_object_unref(layout);
72}
diff --git a/common/readline.c b/common/readline.c
index cc40a2cc..ed5801de 100644
--- a/common/readline.c
+++ b/common/readline.c
@@ -8,7 +8,7 @@ char *read_line(FILE *file) {
8 char *string = malloc(size); 8 char *string = malloc(size);
9 char lastChar = '\0'; 9 char lastChar = '\0';
10 if (!string) { 10 if (!string) {
11 sway_log(L_ERROR, "Unable to allocate memory for read_line"); 11 wlr_log(L_ERROR, "Unable to allocate memory for read_line");
12 return NULL; 12 return NULL;
13 } 13 }
14 while (1) { 14 while (1) {
@@ -29,7 +29,7 @@ char *read_line(FILE *file) {
29 char *new_string = realloc(string, size *= 2); 29 char *new_string = realloc(string, size *= 2);
30 if (!new_string) { 30 if (!new_string) {
31 free(string); 31 free(string);
32 sway_log(L_ERROR, "Unable to allocate memory for read_line"); 32 wlr_log(L_ERROR, "Unable to allocate memory for read_line");
33 return NULL; 33 return NULL;
34 } 34 }
35 string = new_string; 35 string = new_string;
diff --git a/common/unicode.c b/common/unicode.c
new file mode 100644
index 00000000..38a9b48e
--- /dev/null
+++ b/common/unicode.c
@@ -0,0 +1,101 @@
1#include <stdint.h>
2#include <stddef.h>
3#include "unicode.h"
4
5size_t utf8_chsize(uint32_t ch) {
6 if (ch < 0x80) {
7 return 1;
8 } else if (ch < 0x800) {
9 return 2;
10 } else if (ch < 0x10000) {
11 return 3;
12 }
13 return 4;
14}
15
16static const uint8_t masks[] = {
17 0x7F,
18 0x1F,
19 0x0F,
20 0x07,
21 0x03,
22 0x01
23};
24
25uint32_t utf8_decode(const char **char_str) {
26 uint8_t **s = (uint8_t **)char_str;
27
28 uint32_t cp = 0;
29 if (**s < 128) {
30 // shortcut
31 cp = **s;
32 ++*s;
33 return cp;
34 }
35 int size = utf8_size((char *)*s);
36 if (size == -1) {
37 ++*s;
38 return UTF8_INVALID;
39 }
40 uint8_t mask = masks[size - 1];
41 cp = **s & mask;
42 ++*s;
43 while (--size) {
44 cp <<= 6;
45 cp |= **s & 0x3f;
46 ++*s;
47 }
48 return cp;
49}
50
51size_t utf8_encode(char *str, uint32_t ch) {
52 size_t len = 0;
53 uint8_t first;
54
55 if (ch < 0x80) {
56 first = 0;
57 len = 1;
58 } else if (ch < 0x800) {
59 first = 0xc0;
60 len = 2;
61 } else if (ch < 0x10000) {
62 first = 0xe0;
63 len = 3;
64 } else {
65 first = 0xf0;
66 len = 4;
67 }
68
69 for (size_t i = len - 1; i > 0; --i) {
70 str[i] = (ch & 0x3f) | 0x80;
71 ch >>= 6;
72 }
73
74 str[0] = ch | first;
75 return len;
76}
77
78
79static const struct {
80 uint8_t mask;
81 uint8_t result;
82 int octets;
83} sizes[] = {
84 { 0x80, 0x00, 1 },
85 { 0xE0, 0xC0, 2 },
86 { 0xF0, 0xE0, 3 },
87 { 0xF8, 0xF0, 4 },
88 { 0xFC, 0xF8, 5 },
89 { 0xFE, 0xF8, 6 },
90 { 0x80, 0x80, -1 },
91};
92
93int utf8_size(const char *s) {
94 uint8_t c = (uint8_t)*s;
95 for (size_t i = 0; i < sizeof(sizes) / 2; ++i) {
96 if ((c & sizes[i].mask) == sizes[i].result) {
97 return sizes[i].octets;
98 }
99 }
100 return -1;
101}
diff --git a/common/util.c b/common/util.c
index d6369853..fb7f9454 100644
--- a/common/util.c
+++ b/common/util.c
@@ -8,8 +8,8 @@
8#include <stdlib.h> 8#include <stdlib.h>
9#include <string.h> 9#include <string.h>
10#include <strings.h> 10#include <strings.h>
11#include <wlc/wlc.h>
12#include <xkbcommon/xkbcommon-names.h> 11#include <xkbcommon/xkbcommon-names.h>
12#include <wlr/types/wlr_keyboard.h>
13#include "log.h" 13#include "log.h"
14#include "readline.h" 14#include "readline.h"
15#include "util.h" 15#include "util.h"
@@ -29,16 +29,16 @@ static struct modifier_key {
29 char *name; 29 char *name;
30 uint32_t mod; 30 uint32_t mod;
31} modifiers[] = { 31} modifiers[] = {
32 { XKB_MOD_NAME_SHIFT, WLC_BIT_MOD_SHIFT }, 32 { XKB_MOD_NAME_SHIFT, WLR_MODIFIER_SHIFT },
33 { XKB_MOD_NAME_CAPS, WLC_BIT_MOD_CAPS }, 33 { XKB_MOD_NAME_CAPS, WLR_MODIFIER_CAPS },
34 { XKB_MOD_NAME_CTRL, WLC_BIT_MOD_CTRL }, 34 { XKB_MOD_NAME_CTRL, WLR_MODIFIER_CTRL },
35 { "Ctrl", WLC_BIT_MOD_CTRL }, 35 { "Ctrl", WLR_MODIFIER_CTRL },
36 { XKB_MOD_NAME_ALT, WLC_BIT_MOD_ALT }, 36 { XKB_MOD_NAME_ALT, WLR_MODIFIER_ALT },
37 { "Alt", WLC_BIT_MOD_ALT }, 37 { "Alt", WLR_MODIFIER_ALT },
38 { XKB_MOD_NAME_NUM, WLC_BIT_MOD_MOD2 }, 38 { XKB_MOD_NAME_NUM, WLR_MODIFIER_MOD2 },
39 { "Mod3", WLC_BIT_MOD_MOD3 }, 39 { "Mod3", WLR_MODIFIER_MOD3 },
40 { XKB_MOD_NAME_LOGO, WLC_BIT_MOD_LOGO }, 40 { XKB_MOD_NAME_LOGO, WLR_MODIFIER_LOGO },
41 { "Mod5", WLC_BIT_MOD_MOD5 }, 41 { "Mod5", WLR_MODIFIER_MOD5 },
42}; 42};
43 43
44uint32_t get_modifier_mask_by_name(const char *name) { 44uint32_t get_modifier_mask_by_name(const char *name) {
@@ -113,7 +113,7 @@ uint32_t parse_color(const char *color) {
113 113
114 int len = strlen(color); 114 int len = strlen(color);
115 if (len != 6 && len != 8) { 115 if (len != 6 && len != 8) {
116 sway_log(L_DEBUG, "Invalid color %s, defaulting to color 0xFFFFFFFF", color); 116 wlr_log(L_DEBUG, "Invalid color %s, defaulting to color 0xFFFFFFFF", color);
117 return 0xFFFFFFFF; 117 return 0xFFFFFFFF;
118 } 118 }
119 uint32_t res = (uint32_t)strtoul(color, NULL, 16); 119 uint32_t res = (uint32_t)strtoul(color, NULL, 16);