diff --git a/i3bar/include/common.h b/i3bar/include/common.h index 59fcc44a..6f8a7b2d 100644 --- a/i3bar/include/common.h +++ b/i3bar/include/common.h @@ -11,6 +11,7 @@ #include #include #include +#include "libi3.h" #include "queue.h" typedef struct rect_t rect; @@ -29,15 +30,10 @@ struct rect_t { /* This data structure represents one JSON dictionary, multiple of these make * up one status line. */ struct status_block { - char *full_text; + i3String *full_text; char *color; - /* full_text, but converted to UCS-2. This variable is only temporarily - * used in refresh_statusline(). */ - xcb_char2b_t *ucs2_full_text; - size_t glyph_count_full_text; - /* The amount of pixels necessary to render this block. This variable is * only temporarily used in refresh_statusline(). */ uint32_t width; diff --git a/i3bar/include/workspaces.h b/i3bar/include/workspaces.h index dfd93d9b..1c77b0b3 100644 --- a/i3bar/include/workspaces.h +++ b/i3bar/include/workspaces.h @@ -32,9 +32,7 @@ void free_workspaces(); struct i3_ws { int num; /* The internal number of the ws */ - char *name; /* The name (in utf8) of the ws */ - xcb_char2b_t *ucs2_name; /* The name (in ucs2) of the ws */ - int name_glyphs; /* The length (in glyphs) of the name */ + i3String *name; /* The name of the ws */ int name_width; /* The rendered width of the name */ bool visible; /* If the ws is currently visible on an output */ bool focused; /* If the ws is currently focused */ diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 51f5fe82..5cbae6a5 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -116,7 +116,7 @@ static int stdin_string(void *context, const unsigned char *val, unsigned int le #endif parser_ctx *ctx = context; if (strcasecmp(ctx->last_map_key, "full_text") == 0) { - sasprintf(&(ctx->block.full_text), "%.*s", len, val); + ctx->block.full_text = i3string_from_utf8_with_length((const char *)val, len); } if (strcasecmp(ctx->last_map_key, "color") == 0) { sasprintf(&(ctx->block.color), "%.*s", len, val); @@ -131,7 +131,7 @@ static int stdin_end_map(void *context) { /* Ensure we have a full_text set, so that when it is missing (or null), * i3bar doesn’t crash and the user gets an annoying message. */ if (!new_block->full_text) - new_block->full_text = sstrdup("SPEC VIOLATION (null)"); + new_block->full_text = i3string_from_utf8("SPEC VIOLATION (null)"); TAILQ_INSERT_TAIL(&statusline_head, new_block, blocks); return 1; } @@ -140,7 +140,7 @@ static int stdin_end_array(void *context) { DLOG("dumping statusline:\n"); struct status_block *current; TAILQ_FOREACH(current, &statusline_head, blocks) { - DLOG("full_text = %s\n", current->full_text); + DLOG("full_text = %s\n", i3string_as_utf8(current->full_text)); DLOG("color = %s\n", current->color); } DLOG("end of dump\n"); @@ -221,13 +221,13 @@ void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { } else { struct status_block *first = TAILQ_FIRST(&statusline_head); /* Clear the old buffer if any. */ - FREE(first->full_text); + I3STRING_FREE(first->full_text); /* Remove the trailing newline and terminate the string at the same * time. */ if (buffer[rec-1] == '\n' || buffer[rec-1] == '\r') buffer[rec-1] = '\0'; else buffer[rec] = '\0'; - first->full_text = (char*)buffer; + first->full_text = i3string_from_utf8((const char *)buffer); } draw_bars(); } diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c index 5df1899f..c77103f3 100644 --- a/i3bar/src/workspaces.c +++ b/i3bar/src/workspaces.c @@ -114,23 +114,17 @@ static int workspaces_string_cb(void *params_, const unsigned char *val, unsigne if (!strcmp(params->cur_key, "name")) { /* Save the name */ - params->workspaces_walk->name = smalloc(sizeof(const unsigned char) * (len + 1)); - strncpy(params->workspaces_walk->name, (const char*) val, len); - params->workspaces_walk->name[len] = '\0'; + params->workspaces_walk->name = i3string_from_utf8_with_length((const char *)val, len); /* Convert the name to ucs2, save its length in glyphs and calculate its rendered width */ - size_t ucs2_len; - xcb_char2b_t *ucs2_name = (xcb_char2b_t*) convert_utf8_to_ucs2(params->workspaces_walk->name, &ucs2_len); - params->workspaces_walk->ucs2_name = ucs2_name; - params->workspaces_walk->name_glyphs = ucs2_len; params->workspaces_walk->name_width = - predict_text_width((char *)params->workspaces_walk->ucs2_name, - params->workspaces_walk->name_glyphs, true); + predict_text_width((char *)i3string_as_ucs2(params->workspaces_walk->name), + i3string_get_num_glyphs(params->workspaces_walk->name), true); - DLOG("Got Workspace %s, name_width: %d, glyphs: %d\n", - params->workspaces_walk->name, + DLOG("Got Workspace %s, name_width: %d, glyphs: %zu\n", + i3string_as_utf8(params->workspaces_walk->name), params->workspaces_walk->name_width, - params->workspaces_walk->name_glyphs); + i3string_get_num_glyphs(params->workspaces_walk->name)); FREE(params->cur_key); return 1; @@ -279,8 +273,7 @@ void free_workspaces() { SLIST_FOREACH(outputs_walk, outputs, slist) { if (outputs_walk->workspaces != NULL && !TAILQ_EMPTY(outputs_walk->workspaces)) { TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) { - FREE(ws_walk->name); - FREE(ws_walk->ucs2_name); + I3STRING_FREE(ws_walk->name); } FREE_TAILQ(outputs_walk->workspaces, i3_ws); } diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 419a4723..be3ca35a 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -114,14 +114,12 @@ void refresh_statusline() { uint32_t old_statusline_width = statusline_width; statusline_width = 0; - /* Convert all blocks from UTF-8 to UCS-2 and predict the text width (in - * pixels). */ + /* Predict the text width of all blocks (in pixels). */ TAILQ_FOREACH(block, &statusline_head, blocks) { - if (strlen(block->full_text) == 0) + if (i3string_get_num_bytes(block->full_text) == 0) continue; - block->ucs2_full_text = (xcb_char2b_t*)convert_utf8_to_ucs2(block->full_text, &(block->glyph_count_full_text)); - block->width = predict_text_width((char*)block->ucs2_full_text, block->glyph_count_full_text, true); + block->width = predict_text_width((char *)i3string_as_ucs2(block->full_text), i3string_get_num_glyphs(block->full_text), true); /* If this is not the last block, add some pixels for a separator. */ if (TAILQ_NEXT(block, blocks) != NULL) block->width += 9; @@ -141,12 +139,12 @@ void refresh_statusline() { /* Draw the text of each block. */ uint32_t x = 0; TAILQ_FOREACH(block, &statusline_head, blocks) { - if (strlen(block->full_text) == 0) + if (i3string_get_num_bytes(block->full_text) == 0) continue; uint32_t colorpixel = (block->color ? get_colorpixel(block->color) : colors.bar_fg); set_font_colors(statusline_ctx, colorpixel, colors.bar_bg); - draw_text((char*)block->ucs2_full_text, block->glyph_count_full_text, + draw_text((char *)i3string_as_ucs2(block->full_text), i3string_get_num_glyphs(block->full_text), true, statusline_pm, statusline_ctx, x, 0, block->width); x += block->width; @@ -157,8 +155,6 @@ void refresh_statusline() { statusline_ctx, 2, (xcb_point_t[]){ { x - 5, 2 }, { x - 5, font.height - 2 } }); } - - FREE(block->ucs2_full_text); } } @@ -326,7 +322,8 @@ void handle_button(xcb_button_press_event_t *event) { * buffer, then we copy character by character. */ int num_quotes = 0; size_t namelen = 0; - for (char *walk = cur_ws->name; *walk != '\0'; walk++) { + const char *utf8_name = i3string_as_utf8(cur_ws->name); + for (const char *walk = utf8_name; *walk != '\0'; walk++) { if (*walk == '"') num_quotes++; /* While we’re looping through the name anyway, we can save one @@ -341,11 +338,11 @@ void handle_button(xcb_button_press_event_t *event) { for (inpos = 0, outpos = strlen("workspace \""); inpos < namelen; inpos++, outpos++) { - if (cur_ws->name[inpos] == '"') { + if (utf8_name[inpos] == '"') { buffer[outpos] = '\\'; outpos++; } - buffer[outpos] = cur_ws->name[inpos]; + buffer[outpos] = utf8_name[inpos]; } buffer[outpos] = '"'; i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, buffer); @@ -1468,7 +1465,7 @@ void draw_bars() { bool has_urgent = false, walks_away = true; TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) { - DLOG("Drawing Button for WS %s at x = %d, len = %d\n", ws_walk->name, i, ws_walk->name_width); + DLOG("Drawing Button for WS %s at x = %d, len = %d\n", i3string_as_utf8(ws_walk->name), i, ws_walk->name_width); uint32_t fg_color = colors.inactive_ws_fg; uint32_t bg_color = colors.inactive_ws_bg; uint32_t border_color = colors.inactive_ws_border; @@ -1481,19 +1478,19 @@ void draw_bars() { fg_color = colors.focus_ws_fg; bg_color = colors.focus_ws_bg; border_color = colors.focus_ws_border; - if (last_urgent_ws && strcmp(ws_walk->name, last_urgent_ws) == 0) + if (last_urgent_ws && strcmp(i3string_as_utf8(ws_walk->name), last_urgent_ws) == 0) walks_away = false; } } if (ws_walk->urgent) { - DLOG("WS %s is urgent!\n", ws_walk->name); + DLOG("WS %s is urgent!\n", i3string_as_utf8(ws_walk->name)); fg_color = colors.urgent_ws_fg; bg_color = colors.urgent_ws_bg; border_color = colors.urgent_ws_border; has_urgent = true; if (!ws_walk->focused) { FREE(last_urgent_ws); - last_urgent_ws = sstrdup(ws_walk->name); + last_urgent_ws = sstrdup(i3string_as_utf8(ws_walk->name)); } /* The urgent-hint should get noticed, so we unhide the bars shortly */ unhide_bars(); @@ -1522,7 +1519,7 @@ void draw_bars() { 1, &rect); set_font_colors(outputs_walk->bargc, fg_color, bg_color); - draw_text((char*)ws_walk->ucs2_name, ws_walk->name_glyphs, true, + draw_text((char*)i3string_as_ucs2(ws_walk->name), i3string_get_num_glyphs(ws_walk->name), true, outputs_walk->buffer, outputs_walk->bargc, i + 5, 2, ws_walk->name_width); i += 10 + ws_walk->name_width + 1; }