Skip to content

Commit

Permalink
layout_description and image are caller frees
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-courtis committed Dec 9, 2024
1 parent b26038b commit 40046c2
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 48 deletions.
6 changes: 4 additions & 2 deletions inc/layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ struct Box {
};

// return a river layout name
const char *layout_description(const struct Demand *demand, const struct Tag *tag);
// caller frees
char *layout_description(const struct Demand *demand, const struct Tag *tag);

// populate views with Box for river layout push dimensions, caller frees
struct SList *layout(const struct Demand *demand, const struct Tag *tag);
Expand All @@ -31,7 +32,8 @@ struct SList *layout(const struct Demand *demand, const struct Tag *tag);
void push(const struct SList *views, struct river_layout_v3 *river_layout_v3, const uint32_t serial);

// layout image
const char *layout_image(const struct Demand* const demand, const struct Tag* const tag);
// caller frees
char *layout_image(const struct Demand* const demand, const struct Tag* const tag);

// fully rendered layout
const char *description_info(const struct Demand* const demand, const struct Tag* const tag);
Expand Down
61 changes: 32 additions & 29 deletions src/layout.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,64 +16,66 @@

#include "layout.h"

const char *layout_image(const struct Demand* const demand, const struct Tag* const tag) {
static char image[20];
char *layout_image(const struct Demand* const demand, const struct Tag* const tag) {
char *image = calloc(20, sizeof(char));

switch(tag->layout_cur) {
case LEFT:
if (tag->count_master == 0 ) {
snprintf(image, sizeof(image), "│├──┤");
snprintf(image, 20, "│├──┤");
} else {
snprintf(image, sizeof(image), "│ ├─┤");
snprintf(image, 20, "│ ├─┤");
}
break;
case RIGHT:
if (tag->count_master == 0 ) {
snprintf(image, sizeof(image), "├──┤│");
snprintf(image, 20, "├──┤│");
} else {
snprintf(image, sizeof(image), "├─┤ │");
snprintf(image, 20, "├─┤ │");
}
break;
case TOP:
snprintf(image, sizeof(image), "├─┬─┤");
snprintf(image, 20, "├─┬─┤");
break;
case BOTTOM:
snprintf(image, sizeof(image), "├─┴─┤");
snprintf(image, 20, "├─┴─┤");
break;
case MONOCLE:
if (demand->view_count > 1) {
snprintf(image, sizeof(image), "│ %u │", demand->view_count);
snprintf(image, 20, "│ %u │", demand->view_count);
} else {
snprintf(image, sizeof(image), "│ │");
snprintf(image, 20, "│ │");
}
break;
case WIDE:
if (tag->count_wide_left == 0) {
snprintf(image, sizeof(image), "││ ├─┤");
snprintf(image, 20, "││ ├─┤");
} else {
snprintf(image, sizeof(image), "├─┤ ├─┤");
snprintf(image, 20, "├─┤ ├─┤");
}
break;
default:
return NULL;
free(image);
image = NULL;
break;
}

return image;
}

const char *layout_description(const struct Demand* const demand, const struct Tag* const tag) {
char *layout_description(const struct Demand* const demand, const struct Tag* const tag) {
if (!demand || !tag)
return "";

// escapes
const struct STable *replacements = stable_init(8, 8, true);
stable_put(replacements, "\\n", "\n");
stable_put(replacements, "\\t", "\t");
stable_put(replacements, "\\r", "\r");
stable_put(replacements, "\\v", "\v");

// layout details
char ratio[4], count[3];
char ratio[13], count[3];
switch(tag->layout_cur) {
case LEFT:
case RIGHT:
Expand Down Expand Up @@ -102,25 +104,26 @@ const char *layout_description(const struct Demand* const demand, const struct T
break;
}

// layout
stable_put(replacements, "{l}", layout_image(demand, tag));
stable_put(replacements, "{n}", layout_name(tag->layout_cur));
// layout info
char *image = layout_image(demand, tag);
if (image) {
stable_put(replacements, "{l}", image);
}

const char *name = layout_name(tag->layout_cur);
if (name) {
stable_put(replacements, "{n}", name);
}

// perform all replacements
char *res = strdup(cfg->layout_format);
char *desc = strdup(cfg->layout_format);
for (const struct STableIter *i = stable_iter(replacements); i; i = stable_next(i)) {
if (i->val) {
char *next = string_replace(res, i->key, i->val);
free(res);
res = next;
}
char *next = string_replace(desc, i->key, i->val);
free(desc);
desc = next;
}

// populate the output
static char desc[LAYOUT_FORMAT_LEN + 5];
strncpy(desc, res, LAYOUT_FORMAT_LEN + 5);
free(res);

free(image);
stable_free(replacements);

return desc;
Expand Down
4 changes: 3 additions & 1 deletion src/listener_river_layout.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,15 @@ static void layout_handle_layout_demand(void *data,
slist_free_vals(&boxes, NULL);

// river layout name
const char *layout_name = layout_description(&demand, tag);
char *layout_name = layout_description(&demand, tag);

// commit
river_layout_v3_commit(output->river_layout, layout_name, serial);

// maybe style
displ_request_style(output, tag, view_count);

free(layout_name);
}

static void layout_handle_namespace_in_use(void *data,
Expand Down
82 changes: 66 additions & 16 deletions tst/tst-layout.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,58 +28,84 @@ int after_each(void **state) {
void layout_image__left(void **state) {
struct Demand demand = { 0 };
struct Tag tag = { .layout_cur = LEFT, };
char *actual;

tag.count_master = 0;
assert_str_equal(layout_image(&demand, &tag), "│├──┤");
actual = layout_image(&demand, &tag);
assert_str_equal(actual, "│├──┤");
free(actual);

tag.count_master = 1;
assert_str_equal(layout_image(&demand, &tag), "│ ├─┤");
actual = layout_image(&demand, &tag);
assert_str_equal(actual, "│ ├─┤");
free(actual);
}

void layout_image__right(void **state) {
struct Demand demand = { 0 };
struct Tag tag = { .layout_cur = RIGHT, };
char *actual;

tag.count_master = 0;
assert_str_equal(layout_image(&demand, &tag), "├──┤│");
actual = layout_image(&demand, &tag);
assert_str_equal(actual, "├──┤│");
free(actual);

tag.count_master = 1;
assert_str_equal(layout_image(&demand, &tag), "├─┤ │");
actual = layout_image(&demand, &tag);
assert_str_equal(actual, "├─┤ │");
free(actual);
}

void layout_image__top(void **state) {
struct Demand demand = { 0 };
struct Tag tag = { .layout_cur = TOP, };
char *actual;

assert_str_equal(layout_image(&demand, &tag), "├─┬─┤");
actual = layout_image(&demand, &tag);
assert_str_equal(actual, "├─┬─┤");
free(actual);
}

void layout_image__bottom(void **state) {
struct Demand demand = { 0 };
struct Tag tag = { .layout_cur = BOTTOM, };
char *actual;

assert_str_equal(layout_image(&demand, &tag), "├─┴─┤");
actual = layout_image(&demand, &tag);
assert_str_equal(actual, "├─┴─┤");
free(actual);
}

void layout_image__wide(void **state) {
struct Demand demand = { 0 };
struct Tag tag = { .layout_cur = WIDE, };
char *actual;

tag.count_wide_left = 0;
assert_str_equal(layout_image(&demand, &tag), "││ ├─┤");
actual = layout_image(&demand, &tag);
assert_str_equal(actual, "││ ├─┤");
free(actual);

tag.count_wide_left = 1;
assert_str_equal(layout_image(&demand, &tag), "├─┤ ├─┤");
actual = layout_image(&demand, &tag);
assert_str_equal(actual, "├─┤ ├─┤");
free(actual);
}

void layout_image__monocle(void **state) {
struct Tag tag = { .layout_cur = MONOCLE, };
char *actual;

struct Demand demand1 = { .view_count = 1 };
assert_str_equal(layout_image(&demand1, &tag), "│ │");
actual = layout_image(&demand1, &tag);
assert_str_equal(actual, "│ │");
free(actual);

struct Demand demand2 = { .view_count = 2 };
assert_str_equal(layout_image(&demand2, &tag), "│ 2 │");
actual = layout_image(&demand2, &tag);
assert_str_equal(actual, "│ 2 │");
free(actual);
}

void layout_image__invalid(void **state) {
Expand All @@ -98,7 +124,11 @@ void layout_description_info__none(void **state) {

assert_true(cfg_set_layout_format("{c}{l}{r}{n}"));

assert_str_equal(layout_description(&demand, &tag), "{c}{l}{r}{n}");
char *actual = layout_description(&demand, &tag);

assert_str_equal(actual, "{c}{l}{r}{n}");

free(actual);
}

void layout_description_info__monocle(void **state) {
Expand All @@ -107,8 +137,12 @@ void layout_description_info__monocle(void **state) {

assert_true(cfg_set_layout_format("image: {l} count: {c} ratio: {r} name: {n} end"));

char *actual = layout_description(&demand, &tag);

// TODO #21 remove the monocle count
assert_str_equal(layout_description(&demand, &tag), "image: │ 9 │ count: 9 ratio: 1 name: monocle end");
// assert_str_equal(actual, "image: │ 9 │ count: 9 ratio: 1 name: monocle end");

free(actual);
}

void layout_description_info__lrtb(void **state) {
Expand All @@ -117,7 +151,11 @@ void layout_description_info__lrtb(void **state) {

assert_true(cfg_set_layout_format("image: {l} count: {c} ratio: {r} name: {n} end"));

assert_str_equal(layout_description(&demand, &tag), "image: │ ├─┤ count: 2 ratio: 0.4 name: left end");
char *actual = layout_description(&demand, &tag);

assert_str_equal(actual, "image: │ ├─┤ count: 2 ratio: 0.4 name: left end");

free(actual);
}

void layout_description_info__wide(void **state) {
Expand All @@ -126,7 +164,11 @@ void layout_description_info__wide(void **state) {

assert_true(cfg_set_layout_format("image: {l} count: {c} ratio: {r} name: {n} end"));

assert_str_equal(layout_description(&demand, &tag), "image: ├─┤ ├─┤ count: 3 ratio: 0.5 name: wide end");
char *actual = layout_description(&demand, &tag);

assert_str_equal(actual, "image: ├─┤ ├─┤ count: 3 ratio: 0.5 name: wide end");

free(actual);
}

void layout_description_info__invalids(void **state) {
Expand All @@ -136,7 +178,11 @@ void layout_description_info__invalids(void **state) {
// manually set an invalid layout
strcpy(((struct Cfg*)cfg)->layout_format, "image: {foo} count: {c c} ratio: {rATIO} end");

assert_str_equal(layout_description(&demand, &tag), "image: {foo} count: {c c} ratio: {rATIO} end");
char *actual = layout_description(&demand, &tag);

assert_str_equal(actual, "image: {foo} count: {c c} ratio: {rATIO} end");

free(actual);
}

void layout_description_info__escapes(void **state) {
Expand All @@ -145,7 +191,11 @@ void layout_description_info__escapes(void **state) {

assert_true(cfg_set_layout_format("i: {l}\\ncount:\\t{c}\\rratio:\\v{r} end"));

assert_str_equal(layout_description(&demand, &tag), "i: ├─┤ ├─┤\ncount:\t3\rratio:\v0.5 end");
char *actual = layout_description(&demand, &tag);

assert_str_equal(actual, "i: ├─┤ ├─┤\ncount:\t3\rratio:\v0.5 end");

free(actual);
}

int main(void) {
Expand Down

0 comments on commit 40046c2

Please sign in to comment.