2023-03-02 11:40:52 +01:00
|
|
|
|
void
|
2023-03-16 10:09:51 +01:00
|
|
|
|
drawhighlights(struct item *item, int x, int y, int w)
|
2023-03-02 11:40:52 +01:00
|
|
|
|
{
|
2023-03-16 11:58:38 +01:00
|
|
|
|
int i, indent;
|
|
|
|
|
char *highlight;
|
|
|
|
|
char c;
|
2023-03-08 19:20:18 +01:00
|
|
|
|
|
2023-03-24 03:14:24 +01:00
|
|
|
|
if (columns > 5 && lines > 1) return;
|
2023-03-21 22:24:50 +01:00
|
|
|
|
|
2023-03-16 11:58:38 +01:00
|
|
|
|
char *itemtext = item->text;
|
2023-03-08 19:20:18 +01:00
|
|
|
|
|
2023-03-24 03:14:24 +01:00
|
|
|
|
if (!(strlen(itemtext) && strlen(text))) return;
|
2023-03-16 11:58:38 +01:00
|
|
|
|
|
|
|
|
|
drw_setscheme(drw, scheme[item == sel
|
|
|
|
|
? SchemeSelHighlight
|
|
|
|
|
: SchemeNormHighlight]);
|
|
|
|
|
for (i = 0, highlight = itemtext; *highlight && text[i];) {
|
2023-03-16 17:22:14 +01:00
|
|
|
|
if (((fuzzy && !fstrncmp(&(*highlight), &text[i], 1)) || (!fuzzy && *highlight == text[i]))) {
|
2023-03-16 11:58:38 +01:00
|
|
|
|
c = *highlight;
|
|
|
|
|
*highlight = '\0';
|
|
|
|
|
indent = TEXTW(itemtext) - lrpad;
|
|
|
|
|
*highlight = c;
|
|
|
|
|
|
2023-03-16 16:54:36 +01:00
|
|
|
|
// highlight character
|
2023-03-16 11:58:38 +01:00
|
|
|
|
c = highlight[1];
|
|
|
|
|
highlight[1] = '\0';
|
|
|
|
|
drw_text(
|
|
|
|
|
drw,
|
|
|
|
|
x + indent + (lrpad / 2),
|
|
|
|
|
y,
|
|
|
|
|
MIN(w - indent - lrpad, TEXTW(highlight) - lrpad),
|
|
|
|
|
bh, 0, highlight, 0, pango_highlight ? True : False);
|
|
|
|
|
highlight[1] = c;
|
|
|
|
|
i++;
|
2023-03-02 11:40:52 +01:00
|
|
|
|
}
|
2023-03-16 11:58:38 +01:00
|
|
|
|
highlight++;
|
2023-03-02 11:40:52 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
drawitem(struct item *item, int x, int y, int w)
|
|
|
|
|
{
|
2023-03-18 13:07:15 +01:00
|
|
|
|
char buffer[MAXITEMLENGTH];
|
2023-03-02 11:40:52 +01:00
|
|
|
|
Clr scm[3];
|
2023-03-16 16:54:36 +01:00
|
|
|
|
int lp = lrpad / 2; // padding
|
2023-03-02 11:40:52 +01:00
|
|
|
|
int wr, rd;
|
2023-03-16 16:54:36 +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
|
|
|
|
}
|
|
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
|
drw_setscheme(drw, scm); // set scheme
|
2023-03-02 11:40:52 +01:00
|
|
|
|
|
2023-03-16 16:54:36 +01:00
|
|
|
|
// parse item text
|
2023-03-02 11:40:52 +01:00
|
|
|
|
for (wr = 0, rd = 0; item->text[rd]; rd++) {
|
|
|
|
|
if (item->text[rd] == '' && item->text[rd + 1] == '[') {
|
2023-03-24 03:48:56 +01:00
|
|
|
|
size_t alen = strspn(item->text + rd + 2, "0123456789;");
|
2023-03-16 10:09:51 +01:00
|
|
|
|
if (item->text[rd + alen + 2] == 'm') { // last character in sequence is always 'm'
|
|
|
|
|
buffer[wr] = '\0';
|
2023-03-02 11:40:52 +01:00
|
|
|
|
|
2023-03-04 19:59:36 +01:00
|
|
|
|
apply_fribidi(buffer);
|
2023-03-08 22:51:00 +01:00
|
|
|
|
rw = MIN(w, TEXTW(buffer) - lrpad);
|
2023-03-04 19:59:36 +01:00
|
|
|
|
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-16 10:09:51 +01:00
|
|
|
|
orw += rw; // width of all colored text, we add this to the full width later
|
2023-03-02 11:40:52 +01:00
|
|
|
|
ib = 1;
|
2023-03-16 10:09:51 +01:00
|
|
|
|
lp = 0;
|
2023-03-02 11:40:52 +01:00
|
|
|
|
|
|
|
|
|
char *ep = item->text + rd + 1;
|
|
|
|
|
|
2023-03-16 16:54:36 +01:00
|
|
|
|
// parse hex colors in scm
|
2023-03-02 11:40:52 +01:00
|
|
|
|
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;
|
|
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
|
drw_setscheme(drw, scm); // set scheme
|
2023-03-02 11:40:52 +01:00
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buffer[wr++] = item->text[rd];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buffer[wr] = '\0';
|
|
|
|
|
|
2023-03-08 22:49:04 +01:00
|
|
|
|
w -= orw;
|
|
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
|
// now draw any non-colored text
|
2023-03-02 11:40:52 +01:00
|
|
|
|
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-16 10:09:51 +01:00
|
|
|
|
if (!hidehighlight && !ib) drawhighlights(item, x, y, w);
|
2023-03-02 11:40:52 +01:00
|
|
|
|
|
2023-03-24 03:48:56 +01:00
|
|
|
|
// this should allow us to use it for tab completion
|
|
|
|
|
item->clntext = malloc(sizeof(buffer));
|
|
|
|
|
memcpy(item->clntext, buffer, sizeof(buffer));
|
|
|
|
|
|
2023-03-02 11:40:52 +01:00
|
|
|
|
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;
|
2023-03-09 17:26:56 +01:00
|
|
|
|
#if USEIMAGE
|
2023-03-21 16:30:30 +01:00
|
|
|
|
int ox = 0; // original x position
|
2023-03-09 17:26:56 +01:00
|
|
|
|
#endif
|
2023-03-21 16:30:30 +01:00
|
|
|
|
char *censort; // censor text (password)
|
|
|
|
|
plw = hidepowerline ? 0 : drw->font->h / 2 + 1; // powerline size
|
2023-03-02 11:40:52 +01:00
|
|
|
|
|
2023-03-21 16:30:30 +01:00
|
|
|
|
// draw menu first using menu scheme
|
2023-03-02 11:40:52 +01:00
|
|
|
|
drw_setscheme(drw, scheme[SchemeMenu]);
|
|
|
|
|
drw_rect(drw, 0, 0, mw, mh, 1, 1);
|
|
|
|
|
|
2023-03-02 17:51:25 +01:00
|
|
|
|
int numberWidth = 0;
|
|
|
|
|
int modeWidth = 0;
|
|
|
|
|
int larrowWidth = 0;
|
|
|
|
|
int rarrowWidth = 0;
|
|
|
|
|
|
2023-03-21 16:30:30 +01:00
|
|
|
|
// add width
|
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) {
|
2023-03-11 13:24:20 +01:00
|
|
|
|
drw_setscheme(drw, scheme[SchemePrompt]);
|
2023-03-02 11:40:52 +01:00
|
|
|
|
|
2023-03-09 17:26:56 +01:00
|
|
|
|
#if USEIMAGE
|
2023-03-03 17:12:38 +01:00
|
|
|
|
ox = x;
|
2023-03-09 17:26:56 +01:00
|
|
|
|
#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);
|
2023-03-21 16:30:30 +01:00
|
|
|
|
|
|
|
|
|
drw_settrans(drw, scheme[SchemePrompt], scheme[SchemeMenu]);
|
|
|
|
|
drw_arrow(drw, x, 0, plw, bh, 1, 0);
|
|
|
|
|
|
|
|
|
|
x += plw;
|
2023-03-02 11:40:52 +01:00
|
|
|
|
}
|
2023-03-16 11:58:38 +01:00
|
|
|
|
|
|
|
|
|
// draw input
|
2023-03-02 11:40:52 +01:00
|
|
|
|
w = (lines > 0 || !matches) ? mw - x : inputw;
|
|
|
|
|
drw_setscheme(drw, scheme[SchemeInput]);
|
2023-03-02 18:10:37 +01:00
|
|
|
|
if (passwd && !hideprompt) {
|
2023-03-02 18:43:09 +01:00
|
|
|
|
censort = ecalloc(pango_input ? TEXTWM(password) : TEXTW(password), sizeof(text));
|
|
|
|
|
memset(censort, *password, strlen(text));
|
2023-03-02 17:51:25 +01:00
|
|
|
|
|
2023-03-02 11:40:52 +01:00
|
|
|
|
apply_fribidi(censort);
|
2023-03-02 17:51:25 +01:00
|
|
|
|
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 18:43:09 +01:00
|
|
|
|
|
2023-03-02 11:40:52 +01:00
|
|
|
|
free(censort);
|
2023-03-02 18:10:37 +01:00
|
|
|
|
} else if (!passwd && !hideprompt) {
|
2023-03-02 11:40:52 +01:00
|
|
|
|
apply_fribidi(text);
|
2023-03-02 17:51:25 +01:00
|
|
|
|
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
|
|
|
|
|
2023-03-02 17:51:25 +01:00
|
|
|
|
curpos = TEXTW(text) - TEXTW(&text[cursor]);
|
2023-03-02 11:40:52 +01:00
|
|
|
|
}
|
|
|
|
|
|
2023-03-02 18:10:37 +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);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-02 18:10:37 +01:00
|
|
|
|
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 18:10:37 +01:00
|
|
|
|
}
|
2023-03-02 11:40:52 +01:00
|
|
|
|
|
2023-03-11 13:24:20 +01:00
|
|
|
|
// draw items and image
|
2023-03-02 11:40:52 +01:00
|
|
|
|
if (lines > 0) {
|
2023-03-11 13:24:20 +01:00
|
|
|
|
int i = 0;
|
2023-03-24 04:04:37 +01:00
|
|
|
|
int rx = 0;
|
2023-03-02 18:10:37 +01:00
|
|
|
|
|
2023-03-11 13:24:20 +01:00
|
|
|
|
// 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-24 04:04:37 +01:00
|
|
|
|
rx = ox;
|
|
|
|
|
rx += (imagegaps * 2) + imagewidth;
|
|
|
|
|
} else
|
2023-03-02 11:40:52 +01:00
|
|
|
|
#endif
|
2023-03-24 04:04:37 +01:00
|
|
|
|
if (!indentitems) {
|
|
|
|
|
rx = 0;
|
|
|
|
|
} else {
|
|
|
|
|
rx = x;
|
|
|
|
|
}
|
2023-03-02 18:10:37 +01:00
|
|
|
|
|
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,
|
2023-03-24 04:04:37 +01:00
|
|
|
|
rx + ((i / lines) * ((mw - rx) / columns)),
|
2023-03-02 11:40:52 +01:00
|
|
|
|
y + (((i % lines) + 1) * bh),
|
2023-03-24 04:04:37 +01:00
|
|
|
|
(mw - rx) / columns
|
2023-03-02 11:40:52 +01:00
|
|
|
|
);
|
2023-03-13 22:45:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
|
// horizontal list
|
2023-03-02 11:40:52 +01:00
|
|
|
|
} else if (matches) {
|
|
|
|
|
x += inputw;
|
2023-03-02 18:10:37 +01:00
|
|
|
|
w = larrowWidth;
|
|
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
|
if (curr->left && !hidelarrow) { // draw left arrow
|
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 18:10:37 +01:00
|
|
|
|
|
2023-03-02 11:40:52 +01:00
|
|
|
|
x += w;
|
2023-03-02 18:10:37 +01:00
|
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
|
for (item = curr; item != next; item = item->right) // draw items
|
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:10:37 +01:00
|
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
|
if (next && !hiderarrow) { // draw right arrow
|
2023-03-02 18:10:37 +01:00
|
|
|
|
w = rarrowWidth;
|
2023-03-02 11:40:52 +01:00
|
|
|
|
drw_setscheme(drw, scheme[SchemeRArrow]);
|
|
|
|
|
|
2023-03-02 18:10:37 +01:00
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
|
if (!hidematchcount) { // draw match count
|
2023-03-02 11:40:52 +01:00
|
|
|
|
drw_setscheme(drw, scheme[SchemeNumber]);
|
2023-03-21 16:40:11 +01:00
|
|
|
|
|
2023-03-21 17:10:16 +01:00
|
|
|
|
drw_text(drw, mw - numberWidth - modeWidth, 0, numberWidth, bh, lrpad / 2 + plw / 2, numbers, 0, pango_numbers ? True : False);
|
2023-03-21 16:40:11 +01:00
|
|
|
|
|
|
|
|
|
// draw powerline for match count
|
|
|
|
|
if (!hidepowerline) {
|
|
|
|
|
drw_settrans(drw, scheme[SchemeNumber], scheme[SchemeMenu]);
|
|
|
|
|
drw_arrow(drw, mw - numberWidth - modeWidth, 0, plw, bh, 0, 0);
|
|
|
|
|
|
|
|
|
|
x += plw;
|
|
|
|
|
}
|
2023-03-02 11:40:52 +01:00
|
|
|
|
}
|
|
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
|
if (!hidemode) { // draw mode indicator
|
2023-03-02 11:40:52 +01:00
|
|
|
|
drw_setscheme(drw, scheme[SchemeMode]);
|
2023-03-21 16:40:11 +01:00
|
|
|
|
|
2023-03-21 17:10:16 +01:00
|
|
|
|
drw_text(drw, mw - modeWidth, 0, modeWidth, bh, lrpad / 2 + plw / 2, modetext, 0, pango_mode ? True : False);
|
2023-03-21 16:40:11 +01:00
|
|
|
|
|
|
|
|
|
// draw powerline for match count
|
|
|
|
|
if (!hidepowerline) {
|
|
|
|
|
drw_settrans(drw, scheme[SchemeMode], hidematchcount ? scheme[SchemeMenu] : scheme[SchemeNumber]);
|
|
|
|
|
drw_arrow(drw, mw - modeWidth, 0, plw, bh, 0, 0);
|
|
|
|
|
|
|
|
|
|
x += plw;
|
|
|
|
|
}
|
2023-03-02 11:40:52 +01:00
|
|
|
|
}
|
|
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
|
// map the drawing
|
2023-03-02 11:40:52 +01:00
|
|
|
|
drw_map(drw, win, 0, 0, mw, mh);
|
|
|
|
|
}
|