mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-04-04 07:15:55 -04:00
Refactor after upstream changes; harden get_name_from_tag_number
This commit is contained in:
parent
9bfe2f08dd
commit
c3a0c11adc
8 changed files with 67 additions and 54 deletions
|
|
@ -351,7 +351,7 @@ static void dwl_ipc_output_frame(void *data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((i - 1) > tag_count)
|
if (i == 0 || (i - 1) > tag_count)
|
||||||
die("bad tagset %s", tagset);
|
die("bad tagset %s", tagset);
|
||||||
|
|
||||||
zdwl_ipc_output_v2_set_tags(dwl_ipc_output, mask, 0);
|
zdwl_ipc_output_v2_set_tags(dwl_ipc_output, mask, 0);
|
||||||
|
|
@ -381,7 +381,7 @@ static void dwl_ipc_output_frame(void *data,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((i - 1) > tag_count)
|
if (i == 0 || (i - 1) > tag_count)
|
||||||
die("bad client tagset %s", client_tags);
|
die("bad client tagset %s", client_tags);
|
||||||
|
|
||||||
zdwl_ipc_output_v2_set_client_tags(dwl_ipc_output, and, xor);
|
zdwl_ipc_output_v2_set_client_tags(dwl_ipc_output, and, xor);
|
||||||
|
|
@ -400,7 +400,8 @@ static void dwl_ipc_output_frame(void *data,
|
||||||
|
|
||||||
printf("%s clients %u\n", output_name, total_clients);
|
printf("%s clients %u\n", output_name, total_clients);
|
||||||
|
|
||||||
char occ_str[tag_count + 1], seltags_str[tag_count + 1], urg_str[tag_count + 1];
|
char occ_str[tag_count + 1], seltags_str[tag_count + 1],
|
||||||
|
urg_str[tag_count + 1];
|
||||||
|
|
||||||
bin_str_nbits(occ_str, occ, tag_count);
|
bin_str_nbits(occ_str, occ, tag_count);
|
||||||
bin_str_nbits(seltags_str, seltags, tag_count);
|
bin_str_nbits(seltags_str, seltags, tag_count);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,11 @@
|
||||||
#define SYSCONFDIR "/etc"
|
#define SYSCONFDIR "/etc"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool config_initialized = false;
|
// We don't want to allow config hot-reloading to change the tag_count and we
|
||||||
|
// want to require a compositor reload. The code to support hot-reloading a
|
||||||
|
// change in tag_count is a lot more involved than this minimal solution we have
|
||||||
|
// for configuring the number of tags available in Mango.
|
||||||
|
static uint32_t active_tag_count = 0;
|
||||||
|
|
||||||
// Clamps value in range while preserving numeric type
|
// Clamps value in range while preserving numeric type
|
||||||
#define CLAMP(x, min, max) \
|
#define CLAMP(x, min, max) \
|
||||||
|
|
@ -1136,7 +1140,7 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value,
|
||||||
|
|
||||||
while (token != NULL) {
|
while (token != NULL) {
|
||||||
int32_t num = atoi(token);
|
int32_t num = atoi(token);
|
||||||
if (num > 0 && num <= tag_count) {
|
if (num > 0 && num <= config.tag_count) {
|
||||||
mask |= (1 << (num - 1));
|
mask |= (1 << (num - 1));
|
||||||
}
|
}
|
||||||
token = strtok_r(NULL, "|", &saveptr);
|
token = strtok_r(NULL, "|", &saveptr);
|
||||||
|
|
@ -1604,14 +1608,17 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
config->default_nmaster = atoi(value);
|
config->default_nmaster = atoi(value);
|
||||||
} else if (strcmp(key, "tag_count") == 0) {
|
} else if (strcmp(key, "tag_count") == 0) {
|
||||||
uint32_t requested = CLAMP(atoi(value), 1, 32);
|
uint32_t requested = CLAMP(atoi(value), 1, 32);
|
||||||
config->tag_count = requested;
|
bool is_initial_config_load = active_tag_count == 0;
|
||||||
if (!config_initialized) {
|
if (is_initial_config_load) {
|
||||||
tag_count = requested;
|
config->tag_count = requested;
|
||||||
} else if (tag_count != requested) {
|
} else {
|
||||||
wlr_log(WLR_INFO,
|
config->tag_count = active_tag_count;
|
||||||
"tag_count change requires restart (current: %u, "
|
if (active_tag_count != requested) {
|
||||||
"requested: %u)",
|
wlr_log(WLR_INFO,
|
||||||
tag_count, requested);
|
"tag_count change requires restart (current: %u, "
|
||||||
|
"requested: %u)",
|
||||||
|
active_tag_count, requested);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (strcmp(key, "center_master_overspread") == 0) {
|
} else if (strcmp(key, "center_master_overspread") == 0) {
|
||||||
config->center_master_overspread = atoi(value);
|
config->center_master_overspread = atoi(value);
|
||||||
|
|
@ -1936,7 +1943,7 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
trim_whitespace(val);
|
trim_whitespace(val);
|
||||||
|
|
||||||
if (strcmp(key, "id") == 0) {
|
if (strcmp(key, "id") == 0) {
|
||||||
rule->id = CLAMP_INT(atoi(val), 0, tag_count);
|
rule->id = CLAMP_INT(atoi(val), 0, config->tag_count);
|
||||||
} else if (strcmp(key, "layout_name") == 0) {
|
} else if (strcmp(key, "layout_name") == 0) {
|
||||||
rule->layout_name = strdup(val);
|
rule->layout_name = strdup(val);
|
||||||
} else if (strcmp(key, "monitor_name") == 0) {
|
} else if (strcmp(key, "monitor_name") == 0) {
|
||||||
|
|
@ -3527,7 +3534,7 @@ bool parse_config(void) {
|
||||||
config.scroller_proportion_preset_count = 0;
|
config.scroller_proportion_preset_count = 0;
|
||||||
config.circle_layout = NULL;
|
config.circle_layout = NULL;
|
||||||
config.circle_layout_count = 0;
|
config.circle_layout_count = 0;
|
||||||
config.tag_count = 9;
|
config.tag_count = 0;
|
||||||
config.tag_rules = NULL;
|
config.tag_rules = NULL;
|
||||||
config.tag_rules_count = 0;
|
config.tag_rules_count = 0;
|
||||||
config.cursor_theme = NULL;
|
config.cursor_theme = NULL;
|
||||||
|
|
@ -3561,7 +3568,6 @@ bool parse_config(void) {
|
||||||
parse_correct = parse_config_file(&config, filename, true);
|
parse_correct = parse_config_file(&config, filename, true);
|
||||||
set_default_key_bindings(&config);
|
set_default_key_bindings(&config);
|
||||||
override_config();
|
override_config();
|
||||||
config_initialized = true;
|
|
||||||
return parse_correct;
|
return parse_correct;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3729,7 +3735,7 @@ void reapply_master(void) {
|
||||||
|
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
Monitor *m = NULL;
|
Monitor *m = NULL;
|
||||||
for (i = 0; i <= tag_count; i++) {
|
for (i = 0; i <= config.tag_count; i++) {
|
||||||
wl_list_for_each(m, &mons, link) {
|
wl_list_for_each(m, &mons, link) {
|
||||||
if (!m->wlr_output->enabled) {
|
if (!m->wlr_output->enabled) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -3808,7 +3814,7 @@ void parse_tagrule(Monitor *m) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 1; i <= tag_count; i++) {
|
for (i = 1; i <= config.tag_count; i++) {
|
||||||
wl_list_for_each(c, &clients, link) {
|
wl_list_for_each(c, &clients, link) {
|
||||||
if ((c->tags & (1 << (i - 1)) & TAGMASK) && ISTILED(c)) {
|
if ((c->tags & (1 << (i - 1)) & TAGMASK) && ISTILED(c)) {
|
||||||
if (m->pertag->mfacts[i] > 0.0f)
|
if (m->pertag->mfacts[i] > 0.0f)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
#define MODKEY WLR_MODIFIER_ALT
|
#define MODKEY WLR_MODIFIER_ALT
|
||||||
|
|
||||||
static const char *tags[] = {
|
|
||||||
"1", "2", "3", "4", "5", "6", "7", "8", "9",
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct xkb_rule_names xkb_fallback_rules = {
|
static const struct xkb_rule_names xkb_fallback_rules = {
|
||||||
.layout = "us",
|
.layout = "us",
|
||||||
|
|
|
||||||
|
|
@ -1539,10 +1539,10 @@ int32_t viewtoright_have_client(const Arg *arg) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current >= tag_count)
|
if (current >= config.tag_count)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (n = current + 1; n <= tag_count; n++) {
|
for (n = current + 1; n <= config.tag_count; n++) {
|
||||||
if (get_tag_status(n, selmon)) {
|
if (get_tag_status(n, selmon)) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ void dwl_ipc_manager_bind(struct wl_client *client, void *data,
|
||||||
&dwl_manager_implementation, NULL,
|
&dwl_manager_implementation, NULL,
|
||||||
dwl_ipc_manager_destroy);
|
dwl_ipc_manager_destroy);
|
||||||
|
|
||||||
zdwl_ipc_manager_v2_send_tags(manager_resource, tag_count);
|
zdwl_ipc_manager_v2_send_tags(manager_resource, config.tag_count);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < LENGTH(layouts); i++)
|
for (uint32_t i = 0; i < LENGTH(layouts); i++)
|
||||||
zdwl_ipc_manager_v2_send_layout(manager_resource, layouts[i].symbol);
|
zdwl_ipc_manager_v2_send_layout(manager_resource, layouts[i].symbol);
|
||||||
|
|
@ -118,7 +118,7 @@ void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output) {
|
||||||
focused = focustop(monitor);
|
focused = focustop(monitor);
|
||||||
zdwl_ipc_output_v2_send_active(ipc_output->resource, monitor == selmon);
|
zdwl_ipc_output_v2_send_active(ipc_output->resource, monitor == selmon);
|
||||||
|
|
||||||
for (tag_idx = 0; tag_idx < tag_count; tag_idx++) {
|
for (tag_idx = 0; tag_idx < config.tag_count; tag_idx++) {
|
||||||
numclients = state = focused_client = 0;
|
numclients = state = focused_client = 0;
|
||||||
tagmask = 1 << tag_idx;
|
tagmask = 1 << tag_idx;
|
||||||
if ((tagmask & monitor->tagset[monitor->seltags]) != 0)
|
if ((tagmask & monitor->tagset[monitor->seltags]) != 0)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
#include "wlr_ext_workspace_v1.h"
|
#include "wlr_ext_workspace_v1.h"
|
||||||
|
|
||||||
#define WORKSPACE_NAME_MAX_SIZE 12
|
|
||||||
|
|
||||||
#define EXT_WORKSPACE_ENABLE_CAPS \
|
#define EXT_WORKSPACE_ENABLE_CAPS \
|
||||||
EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_ACTIVATE | \
|
EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_ACTIVATE | \
|
||||||
EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_DEACTIVATE
|
EXT_WORKSPACE_HANDLE_V1_WORKSPACE_CAPABILITIES_DEACTIVATE
|
||||||
|
|
@ -10,8 +8,8 @@ typedef struct Monitor Monitor;
|
||||||
|
|
||||||
struct workspace {
|
struct workspace {
|
||||||
struct wl_list link; // Link in global workspaces list
|
struct wl_list link; // Link in global workspaces list
|
||||||
uint32_t tag; // Identifier (tag number) in [0=overview, tag_count]
|
uint32_t tag; // Identifier (tag number) in [0=overview, tag_count]
|
||||||
Monitor *m; // Associated monitor
|
Monitor *m; // Associated monitor
|
||||||
struct wlr_ext_workspace_handle_v1 *ext_workspace; // Protocol object
|
struct wlr_ext_workspace_handle_v1 *ext_workspace; // Protocol object
|
||||||
/* Event listeners */
|
/* Event listeners */
|
||||||
struct wl_listener activate;
|
struct wl_listener activate;
|
||||||
|
|
@ -71,14 +69,22 @@ static void handle_ext_workspace_deactivate(struct wl_listener *listener,
|
||||||
wlr_log(WLR_INFO, "ext deactivating workspace %d", workspace->tag);
|
wlr_log(WLR_INFO, "ext deactivating workspace %d", workspace->tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_name_from_tag_number(char *dst_buf, size_t dst_len,
|
// Returns the size_t that would have been written to dst_buf if dst_len was
|
||||||
uint32_t tag_number) {
|
// large enough. Safe usage of this function is to call it with
|
||||||
if (tag_number > tag_count)
|
// dst_buf == NULL and dst_len == 0, then use the returned value to allocate the
|
||||||
die("tag_number %u exceeds tag_count %u", tag_number, tag_count);
|
// destination buffer, then call it again passing in the buffer and size.
|
||||||
|
static size_t get_name_from_tag_number(char *dst_buf, size_t dst_len,
|
||||||
|
uint32_t tag_number) {
|
||||||
|
if (tag_number > config.tag_count)
|
||||||
|
die("tag_number %u exceeds tag_count %u", tag_number, config.tag_count);
|
||||||
|
int n;
|
||||||
if (tag_number == 0)
|
if (tag_number == 0)
|
||||||
snprintf(dst_buf, dst_len, "overview");
|
n = snprintf(dst_buf, dst_len, "overview");
|
||||||
else
|
else
|
||||||
snprintf(dst_buf, dst_len, "%u", tag_number);
|
n = snprintf(dst_buf, dst_len, "%u", tag_number);
|
||||||
|
if (n < 0)
|
||||||
|
die("snprintf failed for tag_number %u", tag_number);
|
||||||
|
return (size_t)(n + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_workspace(struct workspace *workspace) {
|
void destroy_workspace(struct workspace *workspace) {
|
||||||
|
|
@ -109,8 +115,9 @@ static void remove_workspace_by_tag(uint32_t tag, Monitor *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_workspace_by_tag(uint32_t tag, Monitor *m) {
|
static void add_workspace_by_tag(uint32_t tag, Monitor *m) {
|
||||||
char name[WORKSPACE_NAME_MAX_SIZE];
|
size_t name_len = get_name_from_tag_number(NULL, 0, tag);
|
||||||
get_name_from_tag_number(name, sizeof(name), tag);
|
char name[name_len];
|
||||||
|
get_name_from_tag_number(name, name_len, tag);
|
||||||
|
|
||||||
struct workspace *workspace = ecalloc(1, sizeof(*workspace));
|
struct workspace *workspace = ecalloc(1, sizeof(*workspace));
|
||||||
wl_list_append(&workspaces, &workspace->link);
|
wl_list_append(&workspaces, &workspace->link);
|
||||||
|
|
@ -172,13 +179,13 @@ void refresh_monitors_workspaces_status(Monitor *m) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
if (m->isoverview) {
|
if (m->isoverview) {
|
||||||
for (i = 1; i <= tag_count; i++) {
|
for (i = 1; i <= config.tag_count; i++) {
|
||||||
remove_workspace_by_tag(i, m);
|
remove_workspace_by_tag(i, m);
|
||||||
}
|
}
|
||||||
add_workspace_by_tag(0, m);
|
add_workspace_by_tag(0, m);
|
||||||
} else {
|
} else {
|
||||||
remove_workspace_by_tag(0, m);
|
remove_workspace_by_tag(0, m);
|
||||||
for (i = 1; i <= tag_count; i++) {
|
for (i = 1; i <= config.tag_count; i++) {
|
||||||
add_workspace_by_tag(i, m);
|
add_workspace_by_tag(i, m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,14 +57,14 @@ uint32_t get_tags_first_tag_num(uint32_t source_tags) {
|
||||||
return selmon->pertag->curtag;
|
return selmon->pertag->curtag;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; !(tag & 1) && source_tags != 0 && i < tag_count; i++) {
|
for (i = 0; !(tag & 1) && source_tags != 0 && i < config.tag_count; i++) {
|
||||||
tag = source_tags >> i;
|
tag = source_tags >> i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == 1) {
|
if (i == 1) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (i > tag_count) {
|
} else if (i > config.tag_count) {
|
||||||
return tag_count;
|
return config.tag_count;
|
||||||
} else {
|
} else {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
@ -79,14 +79,14 @@ uint32_t get_tags_first_tag(uint32_t source_tags) {
|
||||||
return selmon->pertag->curtag;
|
return selmon->pertag->curtag;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; !(tag & 1) && source_tags != 0 && i < tag_count; i++) {
|
for (i = 0; !(tag & 1) && source_tags != 0 && i < config.tag_count; i++) {
|
||||||
tag = source_tags >> i;
|
tag = source_tags >> i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == 1) {
|
if (i == 1) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (i > tag_count) {
|
} else if (i > config.tag_count) {
|
||||||
return 1 << (tag_count - 1);
|
return 1 << (config.tag_count - 1);
|
||||||
} else {
|
} else {
|
||||||
return 1 << (i - 1);
|
return 1 << (i - 1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
20
src/mango.c
20
src/mango.c
|
|
@ -117,7 +117,7 @@
|
||||||
((C) && (M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags]))
|
((C) && (M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags]))
|
||||||
#define LENGTH(X) (sizeof X / sizeof X[0])
|
#define LENGTH(X) (sizeof X / sizeof X[0])
|
||||||
#define END(A) ((A) + LENGTH(A))
|
#define END(A) ((A) + LENGTH(A))
|
||||||
#define TAGMASK (tag_count == 32 ? ~0u : ((1u << tag_count) - 1))
|
#define TAGMASK (config.tag_count == 32 ? ~0u : ((1u << config.tag_count) - 1))
|
||||||
#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L)))
|
#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L)))
|
||||||
#define ISFULLSCREEN(A) \
|
#define ISFULLSCREEN(A) \
|
||||||
((A)->isfullscreen || (A)->ismaximizescreen || \
|
((A)->isfullscreen || (A)->ismaximizescreen || \
|
||||||
|
|
@ -3041,14 +3041,16 @@ void createmon(struct wl_listener *listener, void *data) {
|
||||||
wlr_output_state_finish(&state);
|
wlr_output_state_finish(&state);
|
||||||
|
|
||||||
wl_list_insert(&mons, &m->link);
|
wl_list_insert(&mons, &m->link);
|
||||||
|
if (active_tag_count == 0)
|
||||||
|
active_tag_count = config.tag_count;
|
||||||
m->pertag = calloc(1, sizeof(Pertag));
|
m->pertag = calloc(1, sizeof(Pertag));
|
||||||
if (!m->pertag)
|
if (!m->pertag)
|
||||||
die("pertag calloc failed");
|
die("pertag calloc failed");
|
||||||
m->pertag->nmasters = calloc(tag_count + 1, sizeof(int32_t));
|
m->pertag->nmasters = calloc(config.tag_count + 1, sizeof(int32_t));
|
||||||
m->pertag->mfacts = calloc(tag_count + 1, sizeof(float));
|
m->pertag->mfacts = calloc(config.tag_count + 1, sizeof(float));
|
||||||
m->pertag->no_hide = calloc(tag_count + 1, sizeof(bool));
|
m->pertag->no_hide = calloc(config.tag_count + 1, sizeof(bool));
|
||||||
m->pertag->no_render_border = calloc(tag_count + 1, sizeof(bool));
|
m->pertag->no_render_border = calloc(config.tag_count + 1, sizeof(bool));
|
||||||
m->pertag->ltidxs = calloc(tag_count + 1, sizeof(const Layout *));
|
m->pertag->ltidxs = calloc(config.tag_count + 1, sizeof(const Layout *));
|
||||||
if (!m->pertag->nmasters || !m->pertag->mfacts || !m->pertag->no_hide ||
|
if (!m->pertag->nmasters || !m->pertag->mfacts || !m->pertag->no_hide ||
|
||||||
!m->pertag->no_render_border || !m->pertag->ltidxs)
|
!m->pertag->no_render_border || !m->pertag->ltidxs)
|
||||||
die("pertag member calloc failed");
|
die("pertag member calloc failed");
|
||||||
|
|
@ -3103,7 +3105,7 @@ void createmon(struct wl_listener *listener, void *data) {
|
||||||
ext_manager, EXT_WORKSPACE_ENABLE_CAPS);
|
ext_manager, EXT_WORKSPACE_ENABLE_CAPS);
|
||||||
wlr_ext_workspace_group_handle_v1_output_enter(m->ext_group, m->wlr_output);
|
wlr_ext_workspace_group_handle_v1_output_enter(m->ext_group, m->wlr_output);
|
||||||
|
|
||||||
for (i = 1; i <= tag_count; i++) {
|
for (i = 1; i <= config.tag_count; i++) {
|
||||||
add_workspace_by_tag(i, m);
|
add_workspace_by_tag(i, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6307,10 +6309,10 @@ void view_in_mon(const Arg *arg, bool want_animation, Monitor *m,
|
||||||
if (arg->ui == (~0 & TAGMASK))
|
if (arg->ui == (~0 & TAGMASK))
|
||||||
m->pertag->curtag = 0;
|
m->pertag->curtag = 0;
|
||||||
else {
|
else {
|
||||||
for (i = 0; !(arg->ui & 1 << i) && i < tag_count && arg->ui != 0;
|
for (i = 0; !(arg->ui & 1u << i) && i < config.tag_count && arg->ui != 0;
|
||||||
i++)
|
i++)
|
||||||
;
|
;
|
||||||
m->pertag->curtag = i >= tag_count ? tag_count : i + 1;
|
m->pertag->curtag = i >= config.tag_count ? config.tag_count : i + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
m->pertag->prevtag =
|
m->pertag->prevtag =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue