Remove tags

This commit is contained in:
Alex Kotov 2021-11-20 19:28:50 +05:00
parent 84ba2de1b8
commit 54de29ead6
Signed by: kotovalexarian
GPG Key ID: 553C0EBBEB5D5F08
9 changed files with 17 additions and 420 deletions

View File

@ -26,7 +26,6 @@ MODULES_SRC = \
src/menu.c \
src/settings.c \
src/spawn.c \
src/tags.c \
src/unit.c \
src/util.c

View File

@ -40,11 +40,8 @@ Applied patches
* alwayscenter
* fakefullscreen
* focusonclick
* hide_vacant_tags
* movestack
* nametag
* nmaxmaster
* pertag
* resetnmaster
* smartborders
* swallow

View File

@ -17,35 +17,12 @@ maximised to the screen size. In floating layout windows can be resized and
moved freely. Dialog windows are always managed floating, regardless of the
layout applied.
.P
Windows are grouped by tags. Each window can be tagged with one or multiple
tags. Selecting certain tags displays all windows with these tags.
.P
Each screen contains a small status bar which displays all available tags and
the layout. The selected tags are indicated with a different color. The tags of
the focused window are indicated with a filled square in the top left corner.
The tags which are applied to one or more windows are indicated with an empty
square in the top left corner.
.P
PolytreeWM draws a small border around windows to indicate the focus state.
.SH OPTIONS
.TP
.B \-v
prints version information to stderr, then exits.
.SH USAGE
.SS Status bar
.TP
.B Button1
click on a tag label to display all windows with that tag, click on the layout
label toggles between tiled and floating layout.
.TP
.B Button3
click on a tag label adds/removes all windows with that tag to/from the view.
.TP
.B Mod1\-Button1
click on a tag label applies that tag to the focused window.
.TP
.B Mod1\-Button3
click on a tag label adds/removes that tag to/from the focused window.
.SS Keyboard commands
.TP
.B Mod1\-/
@ -119,27 +96,6 @@ Close focused window.
.B Mod1\-Shift\-space
Toggle focused window between tiled and floating state.
.TP
.B Mod1\-Tab
Toggles to the previously selected tags.
.TP
.B Mod1\-Shift\-[1..n]
Apply nth tag to focused window.
.TP
.B Mod1\-Shift\-0
Apply all tags to focused window.
.TP
.B Mod1\-Control\-Shift\-[1..n]
Add/remove nth tag to/from focused window.
.TP
.B Mod1\-[1..n]
View all windows with nth tag.
.TP
.B Mod1\-0
View all windows with any tag.
.TP
.B Mod1\-Control\-[1..n]
Add/remove all windows with nth tag to/from the view.
.TP
.B Mod1\-Shift\-q
Quit PolytreeWM.
.SS Mouse commands

View File

@ -21,9 +21,9 @@ static const Rule rules[] = {
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class, instance, title, tags mask, isfloating, isterminal, noswallow, monitor */
{ "alacritty", NULL, NULL, 0, 0, 1, 0, -1 },
{ NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, // xev
/* class, instance, title, isfloating, isterminal, noswallow, monitor */
{ "alacritty", NULL, NULL, 0, 1, 0, -1 },
{ NULL, NULL, "Event Tester", 0, 0, 1, -1 }, // xev
};
/* layout(s) */
@ -40,10 +40,6 @@ static const Layout layouts[] = {
/* key definitions */
#define MODKEY Mod4Mask
#define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} },
static Key keys[] = {
// WM
@ -53,20 +49,6 @@ static Key keys[] = {
{ MODKEY, XK_bracketright, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_bracketleft, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_bracketright, tagmon, {.i = +1 } },
// Tag
{ MODKEY, XK_n, nametag, {0} },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
TAGKEYS( XK_4, 3)
TAGKEYS( XK_5, 4)
TAGKEYS( XK_6, 5)
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY|ShiftMask, XK_h, viewrel, {.i = -1 } },
{ MODKEY|ShiftMask, XK_l, viewrel, {.i = +1 } },
// Layout
{ MODKEY, XK_m, setlayout, {.v = &layouts[0]} }, // Monocle
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, // Floating

227
src/dwm.c
View File

@ -4,7 +4,6 @@
#include "menu.h"
#include "settings.h"
#include "spawn.h"
#include "tags.h"
#include "unit.h"
#include "util.h"
@ -46,7 +45,7 @@
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
* MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
#define ISVISIBLE(C) (true)
#define LENGTH(X) (sizeof X / sizeof X[0])
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
@ -63,7 +62,6 @@ enum { ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
typedef struct Monitor Monitor;
typedef struct Client Client;
typedef struct Pertag Pertag;
typedef union {
int i;
@ -87,7 +85,6 @@ struct Client {
int oldx, oldy, oldw, oldh;
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int bw, oldbw;
unsigned int tags;
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow;
pid_t pid;
Client *next;
@ -120,15 +117,12 @@ struct Monitor {
Unit unit;
Bar bar;
Pertag *pertag;
char ltsymbol[16];
int nmaster;
int num;
int mx, my, mw, mh; /* screen size */
int wx, wy, ww, wh; /* window area */
unsigned int seltags;
unsigned int sellt;
unsigned int tagset[2];
Client *clients;
Client *sel;
Client *stack;
@ -143,21 +137,12 @@ typedef struct {
const char *class;
const char *instance;
const char *title;
unsigned int tags;
int isfloating;
int isterminal;
int noswallow;
int monitor;
} Rule;
struct Pertag {
Unit units[TAGS_COUNT + 1];
unsigned int curtag, prevtag; /* current and previous tag */
int nmasters[TAGS_COUNT + 1]; /* number of windows in master area */
unsigned int sellts[TAGS_COUNT + 1]; /* selected layouts */
const Layout *ltidxs[TAGS_COUNT + 1][2]; /* matrix of tags and layouts indexes */
};
/*************************
* function declarations *
*************************/
@ -192,7 +177,6 @@ static void killclient(const Arg *arg);
static void manage(Window w, XWindowAttributes *wa);
static void movemouse(const Arg *arg);
static void movestack(const Arg *arg);
static void nametag(const Arg *arg);
static Client *nexttiled(Client *c);
static void pop(Client *);
static void quit(const Arg *arg);
@ -217,10 +201,8 @@ static void showhide(Client *c);
static void sigchld(int unused);
static void spawn(const Arg *arg);
static void spawn_callback();
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static void togglefloating(const Arg *arg);
static void toggleview(const Arg *arg);
static void unfocus(Client *c, int setfocus);
static void unmanage(Client *c, int destroyed);
static void updateclientlist(void);
@ -230,8 +212,6 @@ static void updatesizehints(Client *c);
static void updatetitle(Client *c);
static void updatewindowtype(Client *c);
static void updatewmhints(Client *c);
static void view(const Arg *arg);
static void viewrel(const Arg *arg);
static Client *wintoclient(Window w);
static Monitor *wintomon(Window w);
static void zoom(const Arg *arg);
@ -348,7 +328,6 @@ applyrules(Client *c)
/* rule matching */
c->isfloating = 0;
c->tags = 0;
XGetClassHint(dpy, c->win, &ch);
class = ch.res_class ? ch.res_class : broken;
instance = ch.res_name ? ch.res_name : broken;
@ -362,7 +341,6 @@ applyrules(Client *c)
c->isterminal = r->isterminal;
c->noswallow = r->noswallow;
c->isfloating = r->isfloating;
c->tags |= r->tags;
for (m = mons; m && m->num != r->monitor; m = m->next);
if (m)
c->mon = m;
@ -372,7 +350,6 @@ applyrules(Client *c)
XFree(ch.res_class);
if (ch.res_name)
XFree(ch.res_name);
c->tags = c->tags & TAGS_MASK ? c->tags & TAGS_MASK : c->mon->tagset[c->mon->seltags];
}
int
@ -545,12 +522,10 @@ checkotherwm(void)
void
cleanup(void)
{
Arg a = {.ui = ~0};
Layout foo = { NULL, NULL };
Monitor *m;
size_t i;
view(&a);
selmon->lt[selmon->sellt] = &foo;
for (m = mons; m; m = m->next)
while (m->stack)
@ -584,10 +559,6 @@ cleanupmon(Monitor *mon)
m->next = mon->next;
}
for (int i = 0; i <= TAGS_COUNT; ++i) {
UNIT_DELETE(mon->pertag->units[i]);
}
free(mon->pertag);
{
XUnmapWindow(dpy, mon->bar->barwin);
XDestroyWindow(dpy, mon->bar->barwin);
@ -634,7 +605,6 @@ createmon(void)
memset(m->bar, 0, sizeof(struct Bar));
m->bar->bh = drw->fonts->h + 2;
m->tagset[0] = m->tagset[1] = 1;
m->nmaster = settings_get_default_clients_in_master();
m->bar->topbar = settings_get_bar_on_top_by_default();
m->lt[0] = &layouts[0];
@ -648,40 +618,11 @@ createmon(void)
0
);
if (!(m->pertag = ecalloc(1, sizeof(Pertag)))) goto fail_without_pertag;
m->pertag->curtag = m->pertag->prevtag = 1;
for (int i = 0; i <= TAGS_COUNT; ++i) {
m->pertag->units[i] = NULL;
}
for (int i = 0; i <= TAGS_COUNT; i++) {
if (!(m->pertag->units[i] = unit_new(UNIT_TAG, m->unit))) {
goto fail_other;
}
m->pertag->nmasters[i] = m->nmaster;
m->pertag->ltidxs[i][0] = m->lt[0];
m->pertag->ltidxs[i][1] = m->lt[1];
m->pertag->sellts[i] = m->sellt;
}
// actual state
m->show_bar = unit_get_show_bar(m->pertag->units[m->pertag->curtag]);
m->show_bar = unit_get_show_bar(m->unit);
return m;
fail_other:
for (int i = 0; i <= TAGS_COUNT; ++i) {
if (m->pertag->units[i]) {
UNIT_DELETE(m->pertag->units[i]);
}
}
free(m->pertag);
fail_without_pertag:
free(m->bar);
fail_without_bar:
UNIT_DELETE(m->unit);
fail_without_unit:
@ -931,7 +872,7 @@ incnmaster(const Arg *arg)
const int max_clients_in_master = settings_get_max_clients_in_master();
const int new_clients_in_master = MAX(0, selmon->nmaster + arg->i);
selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] =
selmon->nmaster =
max_clients_in_master == 0
? new_clients_in_master
: MIN(new_clients_in_master, max_clients_in_master);
@ -990,7 +931,6 @@ manage(Window w, XWindowAttributes *wa)
if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
c->mon = t->mon;
c->tags = t->tags;
} else {
c->mon = selmon;
applyrules(c);
@ -1172,22 +1112,6 @@ movemouse(__attribute__((unused)) const Arg *arg)
}
}
// TODO: this function really needs to be refactored
void
nametag(__attribute__((unused)) const Arg *arg) {
char name[TAGS_CUSTOM_NAME_SIZE];
if (!menu_run(name, TAGS_CUSTOM_NAME_SIZE, "Tag name")) return;
for (int i = 0; i < TAGS_COUNT; ++i) {
if (selmon->tagset[selmon->seltags] & (1 << i)) {
tags_rename(i, name);
}
}
drawbars();
}
void
movestack(const Arg *arg) {
Client *c = NULL, *p = NULL, *pc = NULL, *i;
@ -1279,7 +1203,7 @@ resetnmaster(const Arg *arg)
const int max_clients_in_master = settings_get_max_clients_in_master();
const int new_clients_in_master = arg->i == 0 ? 0 : settings_get_default_clients_in_master();
selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] =
selmon->nmaster =
max_clients_in_master == 0
? new_clients_in_master
: MIN(new_clients_in_master, max_clients_in_master);
@ -1459,7 +1383,6 @@ sendmon(Client *c, Monitor *m)
detach(c);
detachstack(c);
c->mon = m;
c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
attach(c);
attachstack(c);
focus(NULL);
@ -1534,12 +1457,11 @@ void
setlayout(const Arg *arg)
{
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) {
selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1;
selmon->sellt ^= 1;
}
if (arg && arg->v) {
const Layout *const new_layout = arg->v;
selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = new_layout;
selmon->lt[selmon->sellt] = new_layout;
}
@ -1568,10 +1490,7 @@ setmfact(const Arg *arg)
{
if (!arg) return;
unit_inc_master_area_factor(
selmon->pertag->units[selmon->pertag->curtag],
arg->f
);
unit_inc_master_area_factor(selmon->unit, arg->f);
for (Monitor *m = mons; m; m = m->next) {
arrange(m);
@ -1728,16 +1647,6 @@ spawn_callback()
}
}
void
tag(const Arg *arg)
{
if (selmon->sel && arg->ui & TAGS_MASK) {
selmon->sel->tags = arg->ui & TAGS_MASK;
focus(NULL);
arrange(selmon);
}
}
void
tagmon(const Arg *arg)
{
@ -1770,44 +1679,6 @@ togglefloating(__attribute__((unused)) const Arg *arg)
arrange(selmon);
}
void
toggleview(const Arg *arg)
{
unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGS_MASK);
int i;
if (newtagset) {
selmon->tagset[selmon->seltags] = newtagset;
if (newtagset == ~0u) {
selmon->pertag->prevtag = selmon->pertag->curtag;
selmon->pertag->curtag = 0;
}
/* test if the user did not select the same tag */
if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) {
selmon->pertag->prevtag = selmon->pertag->curtag;
for (i = 0; !(newtagset & 1 << i); i++) ;
selmon->pertag->curtag = i + 1;
}
/* apply settings for this view */
selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
if (selmon->show_bar !=
unit_get_show_bar(selmon->pertag->units[selmon->pertag->curtag]))
{
updatebar(selmon);
}
focus(NULL);
arrange(selmon);
}
}
void
unfocus(Client *c, int setfocus)
{
@ -2054,92 +1925,6 @@ updatewmhints(Client *c)
}
}
void
view(const Arg *arg)
{
const unsigned int old_tagset = selmon->tagset[selmon->seltags] & TAGS_MASK;
const unsigned int new_tagset = arg->ui & TAGS_MASK;
if (new_tagset == old_tagset) return;
selmon->seltags ^= 1; /* toggle sel tagset */
if (new_tagset == 0) {
unsigned int tmptag = selmon->pertag->prevtag;
selmon->pertag->prevtag = selmon->pertag->curtag;
selmon->pertag->curtag = tmptag;
} else {
selmon->tagset[selmon->seltags] = new_tagset;
selmon->pertag->prevtag = selmon->pertag->curtag;
if (arg->ui == ~0u) {
selmon->pertag->curtag = 0;
} else {
int i = 0;
while (!(new_tagset & 1 << i)) ++i;
selmon->pertag->curtag = i + 1;
}
}
selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
selmon->lt[selmon->sellt ^ 1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt ^ 1];
if (selmon->show_bar !=
unit_get_show_bar(selmon->pertag->units[selmon->pertag->curtag]))
{
updatebar(selmon);
}
focus(NULL);
arrange(selmon);
}
void
viewrel(const Arg *arg)
{
const int shift = arg->i;
if (shift == 0) return;
const unsigned int old_tagset = selmon->tagset[selmon->seltags] & TAGS_MASK;
const unsigned int new_tagset = (shift > 0 ? (old_tagset << shift) : (old_tagset >> (-shift))) & TAGS_MASK;
if (new_tagset == old_tagset) return;
if (new_tagset == 0) {
unsigned int tmptag = selmon->pertag->prevtag;
selmon->pertag->prevtag = selmon->pertag->curtag;
selmon->pertag->curtag = tmptag;
} else {
selmon->tagset[selmon->seltags] = new_tagset;
selmon->pertag->prevtag = selmon->pertag->curtag;
if (new_tagset == (~0 & TAGS_MASK)) {
selmon->pertag->curtag = 0;
} else {
int i = 0;
while (!(new_tagset & 1 << i)) ++i;
selmon->pertag->curtag = i + 1;
}
}
selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
selmon->lt[selmon->sellt ^ 1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt ^ 1];
if (selmon->show_bar !=
unit_get_show_bar(selmon->pertag->units[selmon->pertag->curtag]))
{
updatebar(selmon);
}
focus(NULL);
arrange(selmon);
}
Client *
wintoclient(Window w)
{

View File

@ -38,31 +38,11 @@ createbars(void)
void
drawbar(Monitor *m)
{
int x, w, tw = 0;
unsigned int i, occ = 0, urg = 0;
Client *c;
for (c = m->clients; c; c = c->next) {
occ |= c->tags == 255 ? 0 : c->tags;
if (c->isurgent)
urg |= c->tags;
}
x = 0;
for (i = 0; i < TAGS_COUNT; i++) {
/* do not draw vacant tags */
if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i || tags_get(i)->has_custom_name))
continue;
w = TEXTW(tags_get(i)->name.cstr);
drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
drw_text(drw, x, 0, w, m->bar->bh, lrpad / 2, tags_get(i)->name.cstr, urg & 1 << i);
x += w;
}
w = TEXTW(m->ltsymbol);
int w = TEXTW(m->ltsymbol);
drw_setscheme(drw, scheme[SchemeNorm]);
x = drw_text(drw, x, 0, w, m->bar->bh, lrpad / 2, m->ltsymbol, 0);
const int x = drw_text(drw, 0, 0, w, m->bar->bh, lrpad / 2, m->ltsymbol, 0);
if ((w = m->ww - tw - x) > m->bar->bh) {
if ((w = m->ww - x) > m->bar->bh) {
drw_setscheme(drw, scheme[SchemeNorm]);
drw_rect(drw, x, 0, w, m->bar->bh, 1, 1);
}
@ -81,7 +61,7 @@ drawbars(void)
void
togglebar(const Arg *arg)
{
unit_toggle_show_bar(selmon->pertag->units[selmon->pertag->curtag]);
unit_toggle_show_bar(selmon->unit);
updatebars();
}
@ -89,7 +69,7 @@ togglebar(const Arg *arg)
void
updatebar(Monitor *m)
{
m->show_bar = unit_get_show_bar(m->pertag->units[m->pertag->curtag]);
m->show_bar = unit_get_show_bar(m->unit);
updatebarpos(m);
XMoveResizeWindow(dpy, selmon->bar->barwin, selmon->wx, selmon->bar->by, selmon->ww, m->bar->bh);

View File

@ -8,8 +8,7 @@ centeredmaster(Monitor *m)
for (Client *c = nexttiled(m->clients); c; c = nexttiled(c->next), ++n);
if (n == 0) return;
const float master_area_factor =
unit_get_master_area_factor(m->pertag->units[m->pertag->curtag]);
const float master_area_factor = unit_get_master_area_factor(m->unit);
unsigned int mx = 0;
unsigned int mw = m->ww;
@ -111,8 +110,7 @@ horizontile(Monitor *m)
for (Client *c = nexttiled(m->clients); c; c = nexttiled(c->next), ++n);
if (n == 0) return;
const float master_area_factor =
unit_get_master_area_factor(m->pertag->units[m->pertag->curtag]);
const float master_area_factor = unit_get_master_area_factor(m->unit);
const bool is_fullscreen = m->sel == NULL ? false : m->sel->isfullscreen;
@ -208,8 +206,7 @@ tile(Monitor *m)
for (Client *c = nexttiled(m->clients); c; c = nexttiled(c->next), ++n);
if (n == 0) return;
const float master_area_factor =
unit_get_master_area_factor(m->pertag->units[m->pertag->curtag]);
const float master_area_factor = unit_get_master_area_factor(m->unit);
const bool is_fullscreen = m->sel == NULL ? false : m->sel->isfullscreen;

View File

@ -1,67 +0,0 @@
#include "tags.h"
#include <stddef.h>
#include <string.h>
static struct Tag tags[TAGS_COUNT] = {
[0] = {
.has_custom_name = false,
.name = { .structured = { .number = '1', .colon_or_eol = '\0' } },
},
[1] = {
.has_custom_name = false,
.name = { .structured = { .number = '2', .colon_or_eol = '\0' } },
},
[2] = {
.has_custom_name = false,
.name = { .structured = { .number = '3', .colon_or_eol = '\0' } },
},
[3] = {
.has_custom_name = false,
.name = { .structured = { .number = '4', .colon_or_eol = '\0' } },
},
[4] = {
.has_custom_name = false,
.name = { .structured = { .number = '5', .colon_or_eol = '\0' } },
},
[5] = {
.has_custom_name = false,
.name = { .structured = { .number = '6', .colon_or_eol = '\0' } },
},
[6] = {
.has_custom_name = false,
.name = { .structured = { .number = '7', .colon_or_eol = '\0' } },
},
[7] = {
.has_custom_name = false,
.name = { .structured = { .number = '8', .colon_or_eol = '\0' } },
},
[8] = {
.has_custom_name = false,
.name = { .structured = { .number = '9', .colon_or_eol = '\0' } },
},
};
const struct Tag *tags_get(const unsigned int index)
{
// TODO: assert here
if (index >= TAGS_COUNT) return NULL;
return &tags[index];
}
void tags_rename(const unsigned int index, const char *const new_custom_name)
{
// TODO: assert here
if (index >= TAGS_COUNT) return;
if (new_custom_name == NULL || new_custom_name[0] == '\0') {
tags[index].has_custom_name = false;
tags[index].name.structured.colon_or_eol = '\0';
} else {
tags[index].has_custom_name = true;
tags[index].name.structured.colon_or_eol = ':';
strncpy(tags[index].name.structured.custom_name, new_custom_name, TAGS_CUSTOM_NAME_SIZE);
tags[index].name.structured.custom_name[TAGS_CUSTOM_NAME_SIZE - 1] = '\0';
}
}

View File

@ -1,32 +0,0 @@
#ifndef _TAGS_H
#define _TAGS_H
#include <stdbool.h>
#define TAGS_COUNT (9)
#define TAGS_MASK ((1 << TAGS_COUNT) - 1)
#define TAGS_CUSTOM_NAME_SLEN (13)
#define TAGS_CUSTOM_NAME_SIZE ((TAGS_CUSTOM_NAME_SLEN) + 1)
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[TAGS_COUNT > 31 ? -1 : 1]; };
struct __attribute__((packed)) TagName {
char number;
char colon_or_eol;
char custom_name[TAGS_CUSTOM_NAME_SIZE];
};
struct Tag {
bool has_custom_name;
union {
char cstr[sizeof(struct TagName) / sizeof(char)];
struct TagName structured;
} name;
};
const struct Tag *tags_get(unsigned int index);
void tags_rename(unsigned int index, const char *new_custom_name);
#endif // _TAGS_H