spmenu/libs/draw.c

287 lines
7.6 KiB
C
Raw Normal View History

2023-03-02 11:40:52 +01:00
void
drawhighlights(struct item *item, int x, int y, int maxw)
{
2023-03-08 19:20:18 +01:00
char restorechar, tokens[sizeof text], *highlight, *token;
int indentx, highlightlen;
char *itemtext = item->text;
2023-03-02 11:40:52 +01:00
drw_setscheme(drw, scheme[item == sel ? SchemeSelHighlight : SchemeNormHighlight]);
2023-03-08 19:20:18 +01:00
strcpy(tokens, text);
for (token = strtok(tokens, " "); token; token = strtok(NULL, " ")) {
highlight = fstrstr(itemtext, token);
while (highlight) {
highlightlen = highlight - itemtext;
restorechar = *highlight;
itemtext[highlightlen] = '\0';
indentx = TEXTW(itemtext);
itemtext[highlightlen] = restorechar;
restorechar = highlight[strlen(token)];
highlight[strlen(token)] = '\0';
if (indentx - (lrpad / 2) - 1 < maxw)
drw_text(drw, x + indentx - (lrpad / 2) - 1, y, MIN(maxw - indentx, TEXTW(highlight) - lrpad), bh, 0, highlight, 0, pango_highlight ? True : False);
highlight[strlen(token)] = restorechar;
if (strlen(highlight) - strlen(token) < strlen(token))
break;
highlight = fstrstr(highlight + strlen(token), token);
2023-03-02 11:40:52 +01:00
}
}
}
int
drawitem(struct item *item, int x, int y, int w)
{
char buffer[sizeof(item->text) + lrpad / 2];
Clr scm[3];
int lp = lrpad / 2; /* padding */
int wr, rd;
2023-03-06 21:19:12 +01:00
int rw = 0; /* width of text */
2023-03-08 22:49:04 +01:00
int orw = 0;
2023-03-02 11:40:52 +01:00
int fg = 7;
int bg = 0;
int bgfg = 0;
2023-03-04 02:07:06 +01:00
int ignore = 0;
2023-03-02 11:40:52 +01:00
int ib = 0;
if (item == sel) {
memcpy(scm, scheme[SchemeItemSel], sizeof(scm));
2023-03-09 10:10:29 +01:00
if (item->hp)
memcpy(scm, scheme[SchemeItemSelPri], sizeof(scm));
2023-03-02 11:40:52 +01:00
} else {
memcpy(scm, scheme[SchemeItemNorm], sizeof(scm));
2023-03-09 10:10:29 +01:00
if (item->hp)
memcpy(scm, scheme[SchemeItemNormPri], sizeof(scm));
2023-03-02 11:40:52 +01:00
}
/* set scheme */
drw_setscheme(drw, scm);
/* parse item text */
for (wr = 0, rd = 0; item->text[rd]; rd++) {
if (item->text[rd] == '' && item->text[rd + 1] == '[') {
size_t alen = strspn(item->text + rd + 2,
"0123456789;");
if (item->text[rd + alen + 2] == 'm') { /* character is 'm' which is the last character in the sequence */
buffer[wr] = '\0'; /* clear out character */
apply_fribidi(buffer);
2023-03-08 22:51:00 +01:00
rw = MIN(w, TEXTW(buffer) - lrpad);
drw_text(drw, x, y, rw + lp, bh, lp, isrtl ? fribidi_text : buffer, 0, pango_item ? True : False);
2023-03-02 11:40:52 +01:00
x += rw + lp;
2023-03-08 22:49:04 +01:00
orw += rw;
2023-03-02 11:40:52 +01:00
ib = 1;
lp = 0; /* no padding */
char *ep = item->text + rd + 1;
/* parse hex colors in scm */
while (*ep != 'm') {
unsigned v = strtoul(ep + 1, &ep, 10);
2023-03-04 02:07:06 +01:00
if (ignore)
continue;
if (bgfg) {
if (bgfg < 4 && v == 5) {
bgfg <<= 1;
continue;
}
if (bgfg == 4)
scm[0] = textclrs[fg = v];
else if (bgfg == 6)
scm[1] = textclrs[bg = v];
ignore = 1;
continue;
}
2023-03-02 11:40:52 +01:00
if (v == 1) {
fg |= 8;
scm[0] = textclrs[fg];
} else if (v == 22) {
fg &= ~8;
scm[0] = textclrs[fg];
} else if (v >= 30 && v <= 37) {
fg = v % 10 | (fg & 8);
scm[0] = textclrs[fg];
} else if (v == 38) {
bgfg = 2;
} else if (v >= 40 && v <= 47) {
bg = v % 10;
scm[1] = textclrs[bg];
} else if (v == 48) {
bgfg = 3;
}
}
rd += alen + 2;
wr = 0;
drw_setscheme(drw, scm);
continue;
}
}
buffer[wr++] = item->text[rd];
}
buffer[wr] = '\0';
2023-03-08 22:49:04 +01:00
w -= orw;
2023-03-02 11:40:52 +01:00
/* draw any text that doesn't use sgr sequences */
apply_fribidi(buffer);
2023-03-08 22:49:04 +01:00
int r = drw_text(drw, x, y, w, bh, lp, isrtl ? fribidi_text : buffer, 0, pango_item ? True : False);
2023-03-02 11:40:52 +01:00
if (!hidehighlight && !ib) drawhighlights(item, x, y, w - rw);
return r;
}
void
drawmenu(void)
{
2023-03-06 21:19:12 +01:00
unsigned int curpos = 0;
2023-03-02 11:40:52 +01:00
struct item *item;
int x = 0, y = 0, fh = drw->font->h, w;
#if USEIMAGE
2023-03-03 17:12:38 +01:00
int ox = 0;
#endif
2023-03-02 11:40:52 +01:00
char *censort;
drw_setscheme(drw, scheme[SchemeMenu]);
drw_rect(drw, 0, 0, mw, mh, 1, 1);
int numberWidth = 0;
int modeWidth = 0;
int larrowWidth = 0;
int rarrowWidth = 0;
2023-03-02 18:25:28 +01:00
if (!hidemode) modeWidth = pango_mode ? TEXTWM(modetext) : TEXTW(modetext);
if (!hidelarrow) larrowWidth = pango_leftarrow ? TEXTWM(leftarrow) : TEXTW(leftarrow);
if (!hiderarrow) rarrowWidth = pango_rightarrow ? TEXTWM(rightarrow) : TEXTW(rightarrow);
2023-03-02 11:40:52 +01:00
if (prompt && *prompt) {
drw_setscheme(drw, scheme[SchemePrompt]);
2023-03-02 11:40:52 +01:00
#if USEIMAGE
2023-03-03 17:12:38 +01:00
ox = x;
#endif
2023-03-02 11:40:52 +01:00
x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0, pango_prompt ? True : False);
}
/* draw input field */
w = (lines > 0 || !matches) ? mw - x : inputw;
drw_setscheme(drw, scheme[SchemeInput]);
if (passwd && !hideprompt) {
censort = ecalloc(pango_input ? TEXTWM(password) : TEXTW(password), sizeof(text));
memset(censort, *password, strlen(text));
2023-03-02 11:40:52 +01:00
apply_fribidi(censort);
drw_text(drw, x, 0, w, bh, lrpad / 2, isrtl ? fribidi_text : censort, 0, pango_password ? True : False);
curpos = TEXTW(censort) - TEXTW(&text[cursor]);
2023-03-02 11:40:52 +01:00
free(censort);
} else if (!passwd && !hideprompt) {
2023-03-02 11:40:52 +01:00
apply_fribidi(text);
drw_text(drw, x, 0, w, bh, lrpad / 2, isrtl ? fribidi_text : text, 0, pango_input ? True : False);
2023-03-02 18:25:28 +01:00
curpos = TEXTW(text) - TEXTW(&text[cursor]);
2023-03-02 11:40:52 +01:00
}
if ((curpos += lrpad / 2 - 1) < w && !hidecursor && !hideprompt) {
2023-03-02 11:40:52 +01:00
drw_setscheme(drw, scheme[SchemeCaret]);
drw_rect(drw, x + curpos, 2 + (bh - fh) / 2, 2, fh - 4, 1, 0);
}
/* get match count */
if (!hidematchcount) {
recalculatenumbers();
numberWidth = TEXTW(numbers);
2023-03-12 21:03:35 +01:00
// mode indicator is always going to be at the right
if (hidemode) {
numberWidth += 2 * sp + borderwidth;
} else {
modeWidth += 2 * sp + borderwidth;
}
}
2023-03-02 11:40:52 +01:00
// draw items and image
2023-03-02 11:40:52 +01:00
if (lines > 0) {
int i = 0;
int xpad = 0;
// indent items to prompt width?
if (indentitems) {
xpad = 0; // x -= 0
} else {
xpad = promptw; // x -= prompt width so no indentation to prompt width
}
// draw image first
2023-03-02 11:40:52 +01:00
#if USEIMAGE
2023-03-02 16:22:59 +01:00
if (!hideimage && longestedge != 0) {
2023-03-03 17:12:38 +01:00
x = ox;
x += (imagegaps * 2) + imagewidth;
x += xpad;
2023-03-02 11:40:52 +01:00
}
#endif
2023-03-13 22:45:04 +01:00
for (item = curr; item != next; item = item->right, i++) {
2023-03-02 11:40:52 +01:00
drawitem(
item,
x + ((i / lines) * ((mw - x) / columns)) - xpad,
2023-03-02 11:40:52 +01:00
y + (((i % lines) + 1) * bh),
(mw - x) / columns
);
2023-03-13 22:45:04 +01:00
}
if (lines > i) {
lines = i;
resizeclient();
}
2023-03-02 11:40:52 +01:00
} else if (matches) {
/* draw horizontal list */
x += inputw;
w = larrowWidth;
2023-03-02 18:25:28 +01:00
if (curr->left && !hidelarrow) {
2023-03-02 11:40:52 +01:00
drw_setscheme(drw, scheme[SchemeLArrow]);
drw_text(drw, x, 0, w, bh, lrpad / 2, leftarrow, 0, pango_leftarrow ? True : False);
}
2023-03-02 11:40:52 +01:00
x += w;
2023-03-02 11:40:52 +01:00
for (item = curr; item != next; item = item->right)
2023-03-02 21:37:08 +01:00
x = drawitem(item, x, 0, MIN(pango_item ? TEXTWM(item->text) : TEXTW(item->text), mw - x - rarrowWidth - numberWidth - modeWidth));
2023-03-02 18:25:28 +01:00
if (next && !hiderarrow) {
w = rarrowWidth;
2023-03-02 11:40:52 +01:00
drw_setscheme(drw, scheme[SchemeRArrow]);
drw_text(drw, mw - w - numberWidth - modeWidth, 0, w, bh, lrpad / 2, rightarrow, 0, pango_rightarrow ? True : False);
2023-03-02 11:40:52 +01:00
}
}
if (!hidematchcount) {
drw_setscheme(drw, scheme[SchemeNumber]);
drw_text(drw, mw - numberWidth - modeWidth, 0, numberWidth, bh, lrpad / 2, numbers, 0, pango_numbers ? True : False);
2023-03-02 11:40:52 +01:00
}
if (!hidemode) {
drw_setscheme(drw, scheme[SchemeMode]);
drw_text(drw, mw - modeWidth, 0, modeWidth, bh, lrpad / 2, modetext, 0, pango_mode ? True : False);
2023-03-02 11:40:52 +01:00
}
drw_map(drw, win, 0, 0, mw, mh);
}