indent lots of code using vim gg=G

This commit is contained in:
speedie 2023-05-08 23:00:45 +02:00
parent fc8d12cd0a
commit 5efe236380
32 changed files with 2366 additions and 2365 deletions

View file

@ -22,9 +22,9 @@ static Key keys[] = {
{ -1, 0, XK_Right, movecursor, {.i = +1 } },
{ -1, Ctrl|Shift, XK_p, setprofile, {0} },
/* normal mode */
{ 0, 0, XK_i, switchmode, {0} },
{ 0, 0, XK_slash, switchmode, {0} },
/* normal mode */
{ 0, 0, XK_i, switchmode, {0} },
{ 0, 0, XK_slash, switchmode, {0} },
{ 0, Ctrl, XK_equal, setimgsize, {.i = +1 } },
{ 0, Ctrl, XK_minus, setimgsize, {.i = -1 } },
{ 0, 0, XK_equal, setimgsize, {.i = +10 } },
@ -43,20 +43,20 @@ static Key keys[] = {
{ 0, 0, XK_t, toggleimg, {0} },
{ 0, 0, XK_h, flipimg, {.i = 1 } },
{ 0, 0, XK_v, flipimg, {.i = 0 } },
{ 0, 0, XK_k, moveup, {0} },
{ 0, 0, XK_j, movedown, {0} },
{ 0, 0, XK_h, moveleft, {0} },
{ 0, 0, XK_l, moveright, {0} },
{ 0, Ctrl, XK_u, moveup, {.i = 5 } },
{ 0, Ctrl, XK_d, movedown, {.i = 5 } },
{ 0, Ctrl, XK_k, setlines, {.i = +1 } },
{ 0, Ctrl, XK_j, setlines, {.i = -1 } },
{ 0, Ctrl|Alt|Shift, XK_k, setlines, {.i = +5 } },
{ 0, Ctrl|Alt|Shift, XK_j, setlines, {.i = -5 } },
{ 0, Ctrl, XK_h, setcolumns, {.i = +1 } },
{ 0, Ctrl, XK_l, setcolumns, {.i = -1 } },
{ 0, Ctrl|Alt|Shift, XK_h, setcolumns, {.i = +5 } },
{ 0, Ctrl|Alt|Shift, XK_l, setcolumns, {.i = -5 } },
{ 0, 0, XK_k, moveup, {0} },
{ 0, 0, XK_j, movedown, {0} },
{ 0, 0, XK_h, moveleft, {0} },
{ 0, 0, XK_l, moveright, {0} },
{ 0, Ctrl, XK_u, moveup, {.i = 5 } },
{ 0, Ctrl, XK_d, movedown, {.i = 5 } },
{ 0, Ctrl, XK_k, setlines, {.i = +1 } },
{ 0, Ctrl, XK_j, setlines, {.i = -1 } },
{ 0, Ctrl|Alt|Shift, XK_k, setlines, {.i = +5 } },
{ 0, Ctrl|Alt|Shift, XK_j, setlines, {.i = -5 } },
{ 0, Ctrl, XK_h, setcolumns, {.i = +1 } },
{ 0, Ctrl, XK_l, setcolumns, {.i = -1 } },
{ 0, Ctrl|Alt|Shift, XK_h, setcolumns, {.i = +5 } },
{ 0, Ctrl|Alt|Shift, XK_l, setcolumns, {.i = -5 } },
{ 0, 0, XK_u, togglehighlight, {0} },
{ 0, Ctrl|Shift, XK_h, viewhist, {0} },
{ 0, 0, XK_d, clear, {0} },
@ -71,6 +71,6 @@ static Key keys[] = {
{ 0, Alt, XK_p, navhistory, {.i = -1 } },
{ 0, Alt, XK_n, navhistory, {.i = +1 } },
/* insert mode */
{ 1, 0, XK_Escape, switchmode, {0} },
/* insert mode */
{ 1, 0, XK_Escape, switchmode, {0} },
};

View file

@ -4,34 +4,34 @@ void moveleft(Arg *arg) {
int argu = arg->i ? arg->i : 1;
if (columns > 1) {
if (!sel)
return;
tmpsel = sel;
for (i = 0; i < lines; i++) {
if (!tmpsel->left || tmpsel->left->right != tmpsel) {
if (offscreen)
drawmenu();
return;
}
if (tmpsel == curr)
offscreen = 1;
tmpsel = tmpsel->left;
}
sel = tmpsel;
if (offscreen) {
if (!sel)
return;
tmpsel = sel;
for (i = 0; i < lines; i++) {
if (!tmpsel->left || tmpsel->left->right != tmpsel) {
if (offscreen)
drawmenu();
return;
}
if (tmpsel == curr)
offscreen = 1;
tmpsel = tmpsel->left;
}
sel = tmpsel;
if (offscreen) {
for (int j = 0; j < argu; j++) {
curr = prev;
}
}
}
drawmenu();
drawmenu();
calcoffsets();
}
}
if (cursor > 0 && (!sel || !sel->left || lines > 0)) {
cursor = nextrune(-1);
drawmenu();
}
if (cursor > 0 && (!sel || !sel->left || lines > 0)) {
cursor = nextrune(-1);
drawmenu();
}
}
void moveright(Arg *arg) {
@ -40,46 +40,46 @@ void moveright(Arg *arg) {
int argu = arg->i ? arg->i : 1;
if (columns > 1) {
if (!sel)
return;
tmpsel = sel;
for (i = 0; i < lines; i++) {
if (!tmpsel->right || tmpsel->right->left != tmpsel) {
if (offscreen)
drawmenu();
return;
}
tmpsel = tmpsel->right;
if (tmpsel == next)
offscreen = 1;
}
sel = tmpsel;
if (offscreen) {
if (!sel)
return;
tmpsel = sel;
for (i = 0; i < lines; i++) {
if (!tmpsel->right || tmpsel->right->left != tmpsel) {
if (offscreen)
drawmenu();
return;
}
tmpsel = tmpsel->right;
if (tmpsel == next)
offscreen = 1;
}
sel = tmpsel;
if (offscreen) {
for (int j = 0; j < argu; j++)
curr = next;
}
calcoffsets();
}
}
calcoffsets();
}
drawmenu();
drawmenu();
if (text[cursor] != '\0') {
cursor = nextrune(+1);
drawmenu();
}
if (text[cursor] != '\0') {
cursor = nextrune(+1);
drawmenu();
}
}
void movedown(Arg *arg) {
int argu = arg->i ? arg->i : 1;
for (int j = 0; j < argu; j++) {
if (sel && sel->right && (sel = sel->right) == next) {
curr = next;
}
if (sel && sel->right && (sel = sel->right) == next) {
curr = next;
}
}
calcoffsets();
drawmenu();
drawmenu();
}
void moveup(Arg *arg) {
@ -87,31 +87,31 @@ void moveup(Arg *arg) {
for (int j = 0; j < argu; j++) {
if (sel && sel->left && (sel = sel->left)->right == curr) {
curr = prev;
}
curr = prev;
}
}
calcoffsets();
calcoffsets();
drawmenu();
}
void complete(Arg *arg) {
if (hideitem) return;
strncpy(text, sel->clntext, sizeof text - 1);
text[sizeof text - 1] = '\0';
cursor = strlen(text);
strncpy(text, sel->clntext, sizeof text - 1);
text[sizeof text - 1] = '\0';
cursor = strlen(text);
match();
match();
drawmenu();
}
void movenext(Arg *arg) {
if (!next)
return;
if (!next)
return;
sel = curr = next;
calcoffsets();
sel = curr = next;
calcoffsets();
drawmenu();
}
@ -125,35 +125,35 @@ void moveprev(Arg *arg) {
}
void movestart(Arg *arg) {
if (sel == matches) {
cursor = 0;
if (sel == matches) {
cursor = 0;
drawmenu();
return;
}
}
sel = curr = matches;
calcoffsets();
sel = curr = matches;
calcoffsets();
drawmenu();
}
void moveend(Arg *arg) {
if (text[cursor] != '\0') {
cursor = strlen(text);
cursor = strlen(text);
drawmenu();
return;
}
}
if (next) {
curr = matchend;
calcoffsets();
curr = prev;
calcoffsets();
if (next) {
curr = matchend;
calcoffsets();
curr = prev;
calcoffsets();
while (next && (curr = curr->right))
calcoffsets();
}
while (next && (curr = curr->right))
calcoffsets();
}
sel = matchend;
sel = matchend;
drawmenu();
}
@ -166,8 +166,8 @@ void paste(Arg *arg) {
clipboard = clip;
}
XConvertSelection(dpy, clipboard, utf8, utf8, win, CurrentTime);
return;
XConvertSelection(dpy, clipboard, utf8, utf8, win, CurrentTime);
return;
}
@ -175,32 +175,32 @@ void viewhist(Arg *arg) {
int i;
if (histfile) {
if (!backup_items) {
backup_items = items;
items = calloc(histsz + 1, sizeof(struct item));
if (!backup_items) {
backup_items = items;
items = calloc(histsz + 1, sizeof(struct item));
if (!items) {
die("spmenu: cannot allocate memory");
}
if (!items) {
die("spmenu: cannot allocate memory");
}
for (i = 0; i < histsz; i++) {
items[i].text = history[i];
}
} else {
free(items);
items = backup_items;
backup_items = NULL;
}
}
for (i = 0; i < histsz; i++) {
items[i].text = history[i];
}
} else {
free(items);
items = backup_items;
backup_items = NULL;
}
}
match();
match();
drawmenu();
}
void deleteword(Arg *arg) {
if (cursor == 0) return;
while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) {
while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) {
insert(NULL, nextrune(-1) - cursor);
} while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) {
insert(NULL, nextrune(-1) - cursor);
@ -211,32 +211,32 @@ void deleteword(Arg *arg) {
void moveword(Arg *arg) {
if (arg->i < 0) { // move cursor to the start of the word
while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) {
cursor = nextrune(-1);
while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) {
cursor = nextrune(-1);
} while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) {
cursor = nextrune(-1);
cursor = nextrune(-1);
}
} else { // move cursor to the end of the word
while (text[cursor] && strchr(worddelimiters, text[cursor])) {
cursor = nextrune(+1);
} else { // move cursor to the end of the word
while (text[cursor] && strchr(worddelimiters, text[cursor])) {
cursor = nextrune(+1);
} while (text[cursor] && !strchr(worddelimiters, text[cursor])) {
cursor = nextrune(+1);
cursor = nextrune(+1);
}
}
}
drawmenu();
}
void movecursor(Arg *arg) {
if (arg->i < 0) {
if (cursor > 0) {
cursor = nextrune(-1);
if (cursor > 0) {
cursor = nextrune(-1);
}
} else {
if (text[cursor]) {
cursor = nextrune(+1);
} else {
if (text[cursor]) {
cursor = nextrune(+1);
}
}
}
drawmenu();
}
@ -272,8 +272,8 @@ void selectitem(Arg *arg) {
puts(selection);
savehistory(selection);
cleanup();
exit(0);
cleanup();
exit(0);
}
void navhistory(Arg *arg) {
@ -304,53 +304,53 @@ void clearins(Arg *arg) {
}
void quit(Arg *arg) {
cleanup();
exit(0);
cleanup();
exit(0);
}
void savehistory(char *input) {
unsigned int i;
FILE *fp;
unsigned int i;
FILE *fp;
if (!histfile ||
0 == maxhist ||
0 == strlen(input)) {
goto out;
}
if (!histfile ||
0 == maxhist ||
0 == strlen(input)) {
goto out;
}
fp = fopen(histfile, "w");
if (!fp) {
die("spmenu: failed to open %s", histfile);
}
for (i = histsz < maxhist ? 0 : histsz - maxhist; i < histsz; i++) {
if (0 >= fprintf(fp, "%s\n", history[i])) {
die("spmenu: failed to write to %s", histfile);
}
}
if (histsz == 0 || histdup || (histsz > 0 && strcmp(input, history[histsz-1]) != 0)) {
if (0 >= fputs(input, fp)) {
die("spmenu: failed to write to %s", histfile);
}
}
if (fclose(fp)) {
die("spmenu: failed to close file %s", histfile);
}
fp = fopen(histfile, "w");
if (!fp) {
die("spmenu: failed to open %s", histfile);
}
for (i = histsz < maxhist ? 0 : histsz - maxhist; i < histsz; i++) {
if (0 >= fprintf(fp, "%s\n", history[i])) {
die("spmenu: failed to write to %s", histfile);
}
}
if (histsz == 0 || histdup || (histsz > 0 && strcmp(input, history[histsz-1]) != 0)) {
if (0 >= fputs(input, fp)) {
die("spmenu: failed to write to %s", histfile);
}
}
if (fclose(fp)) {
die("spmenu: failed to close file %s", histfile);
}
out:
for (i = 0; i < histsz; i++) {
free(history[i]);
}
free(history);
for (i = 0; i < histsz; i++) {
free(history[i]);
}
free(history);
}
void setimgsize(Arg *arg) {
#if USEIMAGE
#if USEIMAGE
setimagesize(imagewidth + arg->i, imageheight + arg->i);
#endif
#endif
}
void flipimg(Arg *arg) {
#if USEIMAGE
#if USEIMAGE
if (!image) return;
@ -358,11 +358,11 @@ void flipimg(Arg *arg) {
drawmenu();
#endif
#endif
}
void setimgpos(Arg *arg) {
#if USEIMAGE
#if USEIMAGE
if (!image || hideimage) return;
if (imageposition < 3) {
@ -372,11 +372,11 @@ void setimgpos(Arg *arg) {
}
drawmenu();
#endif
#endif
}
void setimggaps(Arg *arg) {
#if USEIMAGE
#if USEIMAGE
imagegaps += arg->i;
if (!image || hideimage) return;
@ -389,32 +389,32 @@ void setimggaps(Arg *arg) {
imagegaps -= arg->i;
drawmenu();
#endif
#endif
}
void rotateimg(Arg *arg) {
#if USEIMAGE
#if USEIMAGE
if (!image || hideimage) return;
rotation += arg->i ? arg->i : 1;
drawmenu();
#endif
#endif
}
void toggleimg(Arg *arg) {
#if USEIMAGE
#if USEIMAGE
hideimage = !hideimage;
drawmenu();
#endif
#endif
}
void defaultimg(Arg *arg) {
#if USEIMAGE
#if USEIMAGE
if (hideimage || !image) return;
@ -425,7 +425,7 @@ void defaultimg(Arg *arg) {
}
drawmenu();
#endif
#endif
}
void setlines(Arg *arg) {

View file

@ -1,8 +1,8 @@
typedef union {
int i; // integer
unsigned int ui; // unsigned int
float f; // float
const void *v; // void
int i; // integer
unsigned int ui; // unsigned int
float f; // float
const void *v; // void
const char *c; // char
} Arg;

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
void prepare_window_size(void) {
// set horizontal and vertical padding
sp = menupaddingh;
vp = (menuposition == 1) ? menupaddingv : - menupaddingv;
vp = (menuposition == 1) ? menupaddingv : - menupaddingv;
return;
}
@ -10,9 +10,9 @@ void create_window(int x, int y, int w, int h) {
XSetWindowAttributes swa;
swa.override_redirect = managed ? False : True;
swa.background_pixel = 0;
swa.colormap = cmap;
swa.event_mask =
swa.background_pixel = 0;
swa.colormap = cmap;
swa.event_mask =
ExposureMask | // mapping the drawing
KeyPressMask | // keypresses
VisibilityChangeMask | // whether or not client is visible
@ -21,8 +21,8 @@ void create_window(int x, int y, int w, int h) {
// create client
win = XCreateWindow(dpy, root, x, y, w, h, borderwidth,
depth, InputOutput, visual,
CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &swa);
depth, InputOutput, visual,
CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &swa);
return;
@ -33,7 +33,7 @@ void set_window(void) {
// set border and class
XSetWindowBorder(dpy, win, scheme[SchemeBorder][ColBg].pixel);
XSetClassHint(dpy, win, &ch);
XSetClassHint(dpy, win, &ch);
return;
}
@ -46,13 +46,13 @@ void set_prop(void) {
void resizeclient(void) {
int omh = mh;
int x, y;
#if USEXINERAMA
#if USEXINERAMA
int j, di, a, n, area = 0;
XineramaScreenInfo *info;
Window pw;
Window pw;
unsigned int du;
Window w, dw, *dws;
#endif
#endif
XWindowAttributes wa;
struct item *item;
int itemCount = 0;
@ -62,36 +62,36 @@ void resizeclient(void) {
itemCount++;
bh = MAX(drw->font->h, drw->font->h + 2 + lineheight);
lines = MIN(itemCount, MAX(lines, 0));
lines = MIN(itemCount, MAX(lines, 0));
reallines = lines;
// resize client to image height
#if USEIMAGE
#if USEIMAGE
if (image) resizetoimageheight(imageheight);
#endif
#endif
mh = (lines + 1) * bh + 2 * menumarginv;
// init xinerama screens
#if USEXINERAMA
int i = 0;
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
XGetInputFocus(dpy, &w, &di);
if (mon >= 0 && mon < n) {
i = mon;
#if USEXINERAMA
int i = 0;
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
XGetInputFocus(dpy, &w, &di);
if (mon >= 0 && mon < n) {
i = mon;
} else if (w != root && w != PointerRoot && w != None) {
do {
if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
XFree(dws);
if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
XFree(dws);
} while (w != root && w != pw);
if (XGetWindowAttributes(dpy, pw, &wa)) {
for (j = 0; j < n; j++) {
if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
area = a;
i = j;
}
if (XGetWindowAttributes(dpy, pw, &wa)) {
for (j = 0; j < n; j++) {
if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
area = a;
i = j;
}
}
}
if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) {
for (i = 0; i < n; i++) {
@ -103,33 +103,33 @@ void resizeclient(void) {
}
// calculate x/y position
if (menuposition == 2) { // centered
mw = MIN(MAX(max_textw() + promptw, minwidth), info[i].width);
x = info[i].x_org + ((info[i].width - mw) / 2);
y = info[i].y_org + ((info[i].height - mh) / 2);
} else { // top or bottom
x = info[i].x_org + xpos;
y = info[i].y_org + (menuposition ? 0 : info[i].height - mh - ypos);
mw = (menuwidth>0 ? menuwidth : info[i].width);
}
if (menuposition == 2) { // centered
mw = MIN(MAX(max_textw() + promptw, minwidth), info[i].width);
x = info[i].x_org + ((info[i].width - mw) / 2);
y = info[i].y_org + ((info[i].height - mh) / 2);
} else { // top or bottom
x = info[i].x_org + xpos;
y = info[i].y_org + (menuposition ? 0 : info[i].height - mh - ypos);
mw = (menuwidth>0 ? menuwidth : info[i].width);
}
XFree(info);
} else
#endif
{
XFree(info);
} else
#endif
{
if (!XGetWindowAttributes(dpy, parentwin, &wa))
die("spmenu: could not get embedding window attributes: 0x%lx",
parentwin); // die because unable to get attributes for the parent window
if (menuposition == 2) { // centered
mw = MIN(MAX(max_textw() + promptw, minwidth), wa.width);
x = (wa.width - mw) / 2;
y = (wa.height - mh) / 2;
} else { // top or bottom
x = 0;
y = menuposition ? 0 : wa.height - mh - ypos;
mw = wa.width;
}
}
die("spmenu: could not get embedding window attributes: 0x%lx",
parentwin); // die because unable to get attributes for the parent window
if (menuposition == 2) { // centered
mw = MIN(MAX(max_textw() + promptw, minwidth), wa.width);
x = (wa.width - mw) / 2;
y = (wa.height - mh) / 2;
} else { // top or bottom
x = 0;
y = menuposition ? 0 : wa.height - mh - ypos;
mw = wa.width;
}
}
// why have an empty line? when there's nothing to draw there anyway?
if (hideprompt && hideinput && hidemode && hidematchcount)

View file

@ -1,17 +1,17 @@
// alpha array
static unsigned int alphas[][2] = {
// fg bg
[SchemeLArrow] = { 255, 200 },
[SchemeRArrow] = { 255, 200 },
[SchemeItemNorm] = { 255, 200 },
[SchemeItemSel] = { 255, 200 },
[SchemeItemNormPri] = { 255, 200 },
[SchemeItemSelPri] = { 255, 200 },
[SchemeMenu] = { 255, 200 },
// fg bg
[SchemeLArrow] = { 255, 200 },
[SchemeRArrow] = { 255, 200 },
[SchemeItemNorm] = { 255, 200 },
[SchemeItemSel] = { 255, 200 },
[SchemeItemNormPri] = { 255, 200 },
[SchemeItemSelPri] = { 255, 200 },
[SchemeMenu] = { 255, 200 },
[SchemeInput] = { 255, 200 },
[SchemePrompt] = { 255, 200 },
[SchemeNormHighlight] = { 255, 200 },
[SchemeSelHighlight] = { 255, 200 },
[SchemePrompt] = { 255, 200 },
[SchemeNormHighlight] = { 255, 200 },
[SchemeSelHighlight] = { 255, 200 },
[SchemeMode] = { 255, 200 },
[SchemeCaret] = { 255, 200 },
[SchemeNumber] = { 255, 200 },
@ -21,17 +21,17 @@ static unsigned int alphas[][2] = {
// colorscheme array
static char *colors[][2] = {
// fg bg
[SchemeLArrow] = { col_larrowfg, col_larrowbg },
[SchemeRArrow] = { col_rarrowfg, col_rarrowbg },
[SchemeItemNorm] = { col_itemnormfg, col_itemnormbg },
[SchemeItemSel] = { col_itemselfg, col_itemselbg },
[SchemeItemNormPri] = { col_itemnormprifg, col_itemnormpribg },
[SchemeItemSelPri] = { col_itemselprifg, col_itemselpribg },
// fg bg
[SchemeLArrow] = { col_larrowfg, col_larrowbg },
[SchemeRArrow] = { col_rarrowfg, col_rarrowbg },
[SchemeItemNorm] = { col_itemnormfg, col_itemnormbg },
[SchemeItemSel] = { col_itemselfg, col_itemselbg },
[SchemeItemNormPri] = { col_itemnormprifg, col_itemnormpribg },
[SchemeItemSelPri] = { col_itemselprifg, col_itemselpribg },
[SchemeInput] = { col_inputfg, col_inputbg, },
[SchemeMenu] = { NULL, col_menu },
[SchemeMenu] = { NULL, col_menu },
[SchemeCaps] = { col_capsfg, col_capsbg },
[SchemePrompt] = { col_promptfg, col_promptbg },
[SchemePrompt] = { col_promptfg, col_promptbg },
[SchemeNormHighlight] = { col_hlnormfg, col_hlnormbg },
[SchemeSelHighlight] = { col_hlselfg, col_hlselbg },
[SchemeCaret] = { col_caretfg, col_caretbg },
@ -42,22 +42,22 @@ static char *colors[][2] = {
// sgr color array, first 16 colors are defined in the config, the rest are 256 colors
static char *textcolors[] = {
col_sgr0,
col_sgr1,
col_sgr2,
col_sgr3,
col_sgr4,
col_sgr5,
col_sgr6,
col_sgr7,
col_sgr8,
col_sgr9,
col_sgr10,
col_sgr11,
col_sgr12,
col_sgr13,
col_sgr14,
col_sgr15,
col_sgr0,
col_sgr1,
col_sgr2,
col_sgr3,
col_sgr4,
col_sgr5,
col_sgr6,
col_sgr7,
col_sgr8,
col_sgr9,
col_sgr10,
col_sgr11,
col_sgr12,
col_sgr13,
col_sgr14,
col_sgr15,
"#00005f",
"#000087",
"#0000af",

View file

@ -32,11 +32,11 @@ void conf_init(void) {
sprintf(cfgfile, "%s/%s", xdg_conf, "spmenu/spmenu.conf");
}
} else { // custom config path
if (!(cfgfile = malloc(snprintf(NULL, 0, "%s", argconf) + 1))) {
die("spmenu: failed to malloc cfgfile");
}
if (!(cfgfile = malloc(snprintf(NULL, 0, "%s", argconf) + 1))) {
die("spmenu: failed to malloc cfgfile");
}
sprintf(cfgfile, "%s", argconf);
sprintf(cfgfile, "%s", argconf);
}
// don't bother trying to load if it doesn't exist.
@ -51,8 +51,8 @@ void conf_init(void) {
// attempt to read config file to cfg
if (!config_read_file(&cfg, cfgfile)) {
// invalid configuration, but let's try to read it anyway
fprintf(stdout, "spmenu: Invalid configuration.\n");
// invalid configuration, but let's try to read it anyway
fprintf(stdout, "spmenu: Invalid configuration.\n");
}
// load options spmenu.window

View file

@ -2,7 +2,7 @@
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
#define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \
&& MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org)))
&& MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org)))
#define LENGTH(X) (sizeof X / sizeof X[0])
#define TEXTW(X) (drw_font_getwidth(drw, (X), False) + lrpad)
#define TEXTWM(X) (drw_font_getwidth(drw, (X), True) + lrpad)

View file

@ -1,52 +1,52 @@
void
drawhighlights(struct item *item, int x, int y, int w, int p)
{
int i, indent;
char *highlight;
char c;
int i, indent;
char *highlight;
char c;
// limitation in order to prevent highlighting from drawing when the text isn't visible
if (columns > 5 && lines > 1) return;
char *itemtext = item->text;
char *itemtext = item->text;
if (!(strlen(itemtext) && strlen(text))) return;
if (!(strlen(itemtext) && strlen(text))) return;
drw_setscheme(drw, scheme[item == sel
? SchemeSelHighlight
: SchemeNormHighlight]);
for (i = 0, highlight = itemtext; *highlight && text[i];) {
drw_setscheme(drw, scheme[item == sel
? SchemeSelHighlight
: SchemeNormHighlight]);
for (i = 0, highlight = itemtext; *highlight && text[i];) {
if (((fuzzy && !fstrncmp(&(*highlight), &text[i], 1)) || (!fuzzy && *highlight == text[i]))) {
c = *highlight;
*highlight = '\0';
indent = TEXTW(itemtext) - lrpad;
*highlight = c;
c = *highlight;
*highlight = '\0';
indent = TEXTW(itemtext) - lrpad;
*highlight = c;
// highlight character
c = highlight[1];
highlight[1] = '\0';
drw_text(
drw,
x + indent + (p),
y,
MIN(w - indent - lrpad, TEXTW(highlight) - lrpad),
bh, 0, highlight, 0, pango_highlight ? True : False);
highlight[1] = c;
i++;
}
highlight++;
}
// highlight character
c = highlight[1];
highlight[1] = '\0';
drw_text(
drw,
x + indent + (p),
y,
MIN(w - indent - lrpad, TEXTW(highlight) - lrpad),
bh, 0, highlight, 0, pango_highlight ? True : False);
highlight[1] = c;
i++;
}
highlight++;
}
}
int
int
drawitemtext(struct item *item, int x, int y, int w)
{
char buffer[MAXITEMLENGTH]; // buffer containing item text
Clr scm[2]; // color scheme
int leftpadding = lrpad / 2; // padding
int wr, rd; // character
int fg = 7; // foreground
int bg = 0; // background
int fg = 7; // foreground
int bg = 0; // background
int bgfg = 0; // both
int ignore = 0; // ignore colors
int skiphighlight = 0; // skip highlighting
@ -86,63 +86,63 @@ drawitemtext(struct item *item, int x, int y, int w)
drw_setscheme(drw, scm); // set scheme
// 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' && sgr) { // last character in sequence is always 'm'
buffer[wr] = '\0';
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' && sgr) { // last character in sequence is always 'm'
buffer[wr] = '\0';
if (!lines) {
w -= item->text[rd + alen];
}
apply_fribidi(buffer);
drw_text(drw, x, y, MIN(w, TEXTW(buffer) - lrpad) + leftpadding, bh, leftpadding, isrtl ? fribidi_text : buffer, 0, pango_item ? True : False);
drw_text(drw, x, y, MIN(w, TEXTW(buffer) - lrpad) + leftpadding, bh, leftpadding, isrtl ? fribidi_text : buffer, 0, pango_item ? True : False);
// position and width
x += MIN(w, TEXTW(buffer) - lrpad) + leftpadding;
x += MIN(w, TEXTW(buffer) - lrpad) + leftpadding;
w -= MIN(w, TEXTW(buffer) - lrpad) + leftpadding;
// no highlighting if colored text
skiphighlight = 1;
leftpadding = 0;
char *character = item->text + rd + 1; // current character
char *character = item->text + rd + 1; // current character
// parse hex colors in scm, m is always the last character
while (*character != 'm') {
unsigned nextchar = strtoul(character + 1, &character, 10);
while (*character != 'm') {
unsigned nextchar = strtoul(character + 1, &character, 10);
if (ignore)
continue;
if (bgfg) {
if (bgfg < 4 && nextchar == 5) {
bgfg <<= 1;
continue;
}
if (bgfg == 4)
scm[0] = textclrs[fg = nextchar];
else if (bgfg == 6)
scm[1] = textclrs[bg = nextchar];
ignore = 1;
continue;
if (bgfg) {
if (bgfg < 4 && nextchar == 5) {
bgfg <<= 1;
continue;
}
if (bgfg == 4)
scm[0] = textclrs[fg = nextchar];
else if (bgfg == 6)
scm[1] = textclrs[bg = nextchar];
ignore = 1;
continue;
}
continue;
}
if (nextchar == 1) {
fg |= 8;
scm[0] = textclrs[fg];
} else if (nextchar == 22) {
fg &= ~8;
scm[0] = textclrs[fg];
if (nextchar == 1) {
fg |= 8;
scm[0] = textclrs[fg];
} else if (nextchar == 22) {
fg &= ~8;
scm[0] = textclrs[fg];
} else if (nextchar == 38) {
bgfg = 2;
} else if (nextchar >= 30 && nextchar <= 37) {
fg = nextchar % 10 | (fg & 8);
scm[0] = textclrs[fg];
} else if (nextchar >= 40 && nextchar <= 47) {
bg = nextchar % 10;
scm[1] = textclrs[bg];
} else if (nextchar == 48) {
bgfg = 2;
} else if (nextchar >= 30 && nextchar <= 37) {
fg = nextchar % 10 | (fg & 8);
scm[0] = textclrs[fg];
} else if (nextchar >= 40 && nextchar <= 47) {
bg = nextchar % 10;
scm[1] = textclrs[bg];
} else if (nextchar == 48) {
bgfg = 3;
} else if (nextchar == 0) {
if (item == sel) {
@ -160,25 +160,25 @@ drawitemtext(struct item *item, int x, int y, int w)
// don't color
if (!coloritems) memcpy(scm, scheme[SchemeItemNorm], sizeof(scm));
}
}
}
rd += alen + 2;
wr = 0;
rd += alen + 2;
wr = 0;
drw_setscheme(drw, scm); // set scheme
drw_setscheme(drw, scm); // set scheme
continue;
}
}
continue;
}
}
buffer[wr++] = item->text[rd];
}
buffer[wr++] = item->text[rd];
}
buffer[wr] = '\0';
buffer[wr] = '\0';
// now draw any non-colored text
apply_fribidi(buffer);
int r = drw_text(drw, x, y, w, bh, leftpadding, isrtl ? fribidi_text : buffer, 0, pango_item ? True : False);
int r = drw_text(drw, x, y, w, bh, leftpadding, isrtl ? fribidi_text : buffer, 0, pango_item ? True : False);
if (!hidehighlight && !skiphighlight) drawhighlights(item, x, y, w, leftpadding);
// copy current buffer to item->clntext instead of item->text, this way SGR sequences aren't drawn
@ -188,10 +188,10 @@ drawitemtext(struct item *item, int x, int y, int w)
return r;
}
int
int
drawitem(int x, int y, int w)
{
struct item *item;
struct item *item;
int numberWidth = 0;
int modeWidth = 0;
@ -210,22 +210,22 @@ drawitem(int x, int y, int w)
if (!strcmp(capstext, ""))
capsWidth = 0;
#if USEIMAGE
#if USEIMAGE
int ox = 0; // original x position
#endif
#endif
// draw items and image
if (lines > 0) {
int i = 0;
if (lines > 0) {
int i = 0;
int rx = 0;
// draw image first
#if USEIMAGE
#if USEIMAGE
if (!hideimage && longestedge != 0) {
rx = ox;
rx += MAX((imagegaps * 2) + imagewidth + menumarginh, indentitems ? x : 0);
} else
#endif
#endif
if (!indentitems) {
rx = 0;
} else {
@ -234,13 +234,13 @@ drawitem(int x, int y, int w)
int itemoverride = 1;
for (item = curr; item != next; item = item->right, i++) {
x = drawitemtext(
item,
rx + ((i / lines) * ((mw - rx) / columns)),
y + (((i % lines) + 1) * bh),
(mw - rx) / columns
);
for (item = curr; item != next; item = item->right, i++) {
x = drawitemtext(
item,
rx + ((i / lines) * ((mw - rx) / columns)),
y + (((i % lines) + 1) * bh),
(mw - rx) / columns
);
if (item == sel && itemoverride) {
itemnumber = i;
@ -248,9 +248,9 @@ drawitem(int x, int y, int w)
}
}
// horizontal list
} else if (matches) {
x += inputw;
// horizontal list
} else if (matches) {
x += inputw;
w = larrowWidth;
x = drawlarrow(x, y, w);
@ -258,7 +258,7 @@ drawitem(int x, int y, int w)
itemnumber = 0;
int itemoverride = 1;
for (item = curr; item != next; item = item->right) { // draw items
for (item = curr; item != next; item = item->right) { // draw items
x = drawitemtext(item, x, y, MIN(pango_item ? TEXTWM(item->text) : TEXTW(item->text),
mw - x -
rarrowWidth -
@ -268,7 +268,7 @@ drawitem(int x, int y, int w)
menumarginh -
2 * sp -
2 * borderwidth
));
));
if (itemoverride) {
itemnumber++;
@ -281,18 +281,18 @@ drawitem(int x, int y, int w)
w = rarrowWidth + numberWidth + modeWidth + capsWidth + menumarginh + 2 * sp + 2 * borderwidth;
x = drawrarrow(mw - w, y, w);
}
}
return x;
}
int
int
drawprompt(int x, int y, int w)
{
if (prompt && *prompt && !hideprompt) {
drw_setscheme(drw, scheme[SchemePrompt]);
if (prompt && *prompt && !hideprompt) {
drw_setscheme(drw, scheme[SchemePrompt]);
x = drw_text(drw, x, y, w, bh, lrpad / 2, prompt, 0, pango_prompt ? True : False);
x = drw_text(drw, x, y, w, bh, lrpad / 2, prompt, 0, pango_prompt ? True : False);
if (!hidepowerline && powerlineprompt) {
drw_settrans(drw, scheme[SchemePrompt], scheme[SchemeMenu]);
@ -300,77 +300,77 @@ drawprompt(int x, int y, int w)
x += plw;
}
}
}
return x;
}
int
int
drawinput(int x, int y, int w)
{
char *censort; // censor text (password)
unsigned int curpos = 0;
char *censort; // censor text (password)
unsigned int curpos = 0;
int fh = drw->font->h;
// draw input
drw_setscheme(drw, scheme[SchemeInput]);
drw_setscheme(drw, scheme[SchemeInput]);
if (passwd) {
censort = ecalloc(1, sizeof(text));
if (passwd) {
censort = ecalloc(1, sizeof(text));
for (int i = 0; i < strlen(text); i++)
memcpy(&censort[i], password, strlen(text));
apply_fribidi(censort);
drw_text(drw, x, y, w, bh, lrpad / 2, isrtl ? fribidi_text : censort, 0, pango_password ? True : False);
drw_text(drw, x, y, w, bh, lrpad / 2, isrtl ? fribidi_text : censort, 0, pango_password ? True : False);
curpos = TEXTW(censort) - TEXTW(&text[cursor]);
curpos = TEXTW(censort) - TEXTW(&text[cursor]);
free(censort);
} else if (!passwd) {
} else if (!passwd) {
apply_fribidi(text);
drw_text(drw, x, y, w, bh, lrpad / 2, isrtl ? fribidi_text : text, 0, pango_input ? True : False);
curpos = TEXTW(text) - TEXTW(&text[cursor]);
curpos = TEXTW(text) - TEXTW(&text[cursor]);
}
if ((curpos += lrpad / 2 - 1) < w && !hidecaret && cursorstate) {
drw_setscheme(drw, scheme[SchemeCaret]);
drw_rect(drw, x + curpos, 2 + (bh - fh) / 2 + y, 2, fh - 4, 1, 0);
}
if ((curpos += lrpad / 2 - 1) < w && !hidecaret && cursorstate) {
drw_setscheme(drw, scheme[SchemeCaret]);
drw_rect(drw, x + curpos, 2 + (bh - fh) / 2 + y, 2, fh - 4, 1, 0);
}
return x;
}
int
int
drawlarrow(int x, int y, int w)
{
if (hidelarrow) return x;
if (curr->left) { // draw left arrow
drw_setscheme(drw, scheme[SchemeLArrow]);
drw_text(drw, x, y, w, bh, lrpad / 2, leftarrow, 0, pango_leftarrow ? True : False);
x += w;
}
if (curr->left) { // draw left arrow
drw_setscheme(drw, scheme[SchemeLArrow]);
drw_text(drw, x, y, w, bh, lrpad / 2, leftarrow, 0, pango_leftarrow ? True : False);
x += w;
}
return x;
}
int
int
drawrarrow(int x, int y, int w)
{
if (hiderarrow) return x;
if (next) { // draw right arrow
drw_setscheme(drw, scheme[SchemeRArrow]);
if (next) { // draw right arrow
drw_setscheme(drw, scheme[SchemeRArrow]);
drw_text(drw, mw - w, y, w, bh, lrpad / 2, rightarrow, 0, pango_rightarrow ? True : False);
x += w;
}
}
return x;
}
int
int
drawnumber(int x, int y, int w)
{
if (hidematchcount) return x;
@ -395,7 +395,7 @@ drawnumber(int x, int y, int w)
return x;
}
int
int
drawmode(int x, int y, int w)
{
if (!hidemode) { // draw mode indicator
@ -417,10 +417,10 @@ drawmode(int x, int y, int w)
}
}
return x;
return x;
}
int
int
drawcaps(int x, int y, int w)
{
if (!w) return x; // not caps lock
@ -444,18 +444,18 @@ drawcaps(int x, int y, int w)
}
}
return x;
return x;
}
void
void
drawmenu(void)
{
int x = 0, y = 0, w = 0;
int x = 0, y = 0, w = 0;
plw = hidepowerline ? 0 : drw->font->h / 2 + 1; // powerline size
// draw menu first using menu scheme
drw_setscheme(drw, scheme[SchemeMenu]);
drw_rect(drw, 0, 0, mw, mh, 1, 1);
drw_setscheme(drw, scheme[SchemeMenu]);
drw_rect(drw, 0, 0, mw, mh, 1, 1);
int numberWidth = 0;
int modeWidth = 0;
@ -481,53 +481,53 @@ drawmenu(void)
// why have an empty line?
if ((hideprompt && hideinput && hidemode && hidematchcount && hidecaps
#if USEIMAGE
#if USEIMAGE
) && (!image || hideimage)) {
#else
#else
)) {
#endif
y -= bh;
mh = (lines + 1) * bh - bh + 2 * menumarginv;
#endif
y -= bh;
mh = (lines + 1) * bh - bh + 2 * menumarginv;
if (!win) return;
if (!win) return;
XResizeWindow(dpy, win, mw - 2 * sp - 2 * borderwidth, mh);
drw_resize(drw, mw - 2 * sp - 2 * borderwidth, mh);
XResizeWindow(dpy, win, mw - 2 * sp - 2 * borderwidth, mh);
drw_resize(drw, mw - 2 * sp - 2 * borderwidth, mh);
}
#if USEIMAGE
else if (hideprompt && hideinput && hidemode && hidematchcount) {
y -= bh;
}
#endif
if (!hideprompt) {
w = promptw;
x = drawprompt(x, y, w);
}
if (!hideinput) {
w = (lines > 0 || !matches) ? mw - x : inputw;
x = drawinput(x, y, w);
}
if (!hidemode) modeWidth = pango_mode ? TEXTWM(modetext) : TEXTW(modetext);
// draw the items, this function also calls drawrarrow() and drawlarrow()
if (!hideitem) drawitem(x, y, w);
if (!hidematchcount) {
w = numberWidth;
drawnumber(mw - numberWidth - modeWidth - capsWidth - 2 * sp - 2 * borderwidth - menumarginh, y, w);
}
if (!hidemode) {
w = modeWidth;
drawmode(mw - modeWidth - capsWidth - 2 * sp - 2 * borderwidth - menumarginh, y, w);
}
if (!hidecaps) {
w = capsWidth;
drawcaps(mw - capsWidth - 2 * sp - 2 * borderwidth - menumarginh, y, w);
}
drw_map(drw, win, 0, 0, mw, mh);
}
#if USEIMAGE
else if (hideprompt && hideinput && hidemode && hidematchcount) {
y -= bh;
}
#endif
if (!hideprompt) {
w = promptw;
x = drawprompt(x, y, w);
}
if (!hideinput) {
w = (lines > 0 || !matches) ? mw - x : inputw;
x = drawinput(x, y, w);
}
if (!hidemode) modeWidth = pango_mode ? TEXTWM(modetext) : TEXTW(modetext);
// draw the items, this function also calls drawrarrow() and drawlarrow()
if (!hideitem) drawitem(x, y, w);
if (!hidematchcount) {
w = numberWidth;
drawnumber(mw - numberWidth - modeWidth - capsWidth - 2 * sp - 2 * borderwidth - menumarginh, y, w);
}
if (!hidemode) {
w = modeWidth;
drawmode(mw - modeWidth - capsWidth - 2 * sp - 2 * borderwidth - menumarginh, y, w);
}
if (!hidecaps) {
w = capsWidth;
drawcaps(mw - capsWidth - 2 * sp - 2 * borderwidth - menumarginh, y, w);
}
drw_map(drw, win, 0, 0, mw, mh);
}

View file

@ -1,14 +1,14 @@
void eventloop(void) {
XEvent ev;
#if USEIMAGE
XEvent ev;
#if USEIMAGE
int noimg = 0;
#endif
#endif
while (!XNextEvent(dpy, &ev)) {
if (XFilterEvent(&ev, None))
continue;
while (!XNextEvent(dpy, &ev)) {
if (XFilterEvent(&ev, None))
continue;
switch(ev.type) {
switch(ev.type) {
case DestroyNotify:
if (ev.xdestroywindow.window != win)
break;
@ -16,9 +16,9 @@ void eventloop(void) {
exit(1);
case ButtonPress:
buttonpress(&ev);
#if USEIMAGE
#if USEIMAGE
noimg = 0;
#endif
#endif
break;
case MotionNotify: // currently does nothing
break;
@ -51,7 +51,7 @@ void eventloop(void) {
getcapsstate();
drawmenu();
break;
}
}
if (listfile) {
readfile();
@ -70,12 +70,12 @@ void eventloop(void) {
}
// redraw image on X11 event
#if USEIMAGE
#if USEIMAGE
if (!noimg) {
drawimage();
} else {
noimg = 0; // draw it next time
}
#endif
}
#endif
}
}

View file

@ -1,66 +1,66 @@
void loadhistory(void) {
FILE *fp = NULL;
static size_t cap = 0;
size_t llen;
char *line;
FILE *fp = NULL;
static size_t cap = 0;
size_t llen;
char *line;
// no history file, give up like i do with all things in life
if (!histfile) {
return;
}
if (!histfile) {
return;
}
// open history file, return if it failed
fp = fopen(histfile, "r");
if (!fp) {
fp = fopen(histfile, "r");
if (!fp) {
fprintf(stderr, "spmenu: failed to open history file\n");
return;
}
for (;;) {
line = NULL;
llen = 0;
for (;;) {
line = NULL;
llen = 0;
if (-1 == getline(&line, &llen, fp)) {
if (ferror(fp)) {
die("spmenu: failed to read history");
}
if (-1 == getline(&line, &llen, fp)) {
if (ferror(fp)) {
die("spmenu: failed to read history");
}
free(line);
break;
}
free(line);
break;
}
if (cap == histsz) {
cap += 64 * sizeof(char*);
history = realloc(history, cap);
if (!history) {
die("spmenu: failed to realloc memory");
}
}
strtok(line, "\n");
history[histsz] = line;
histsz++;
}
if (cap == histsz) {
cap += 64 * sizeof(char*);
history = realloc(history, cap);
if (!history) {
die("spmenu: failed to realloc memory");
}
}
strtok(line, "\n");
history[histsz] = line;
histsz++;
}
histpos = histsz;
histpos = histsz;
if (fclose(fp)) {
die("spmenu: failed to close file %s", histfile);
}
if (fclose(fp)) {
die("spmenu: failed to close file %s", histfile);
}
}
void navigatehistfile(int dir) {
static char def[BUFSIZ];
char *p = NULL;
size_t len = 0;
static char def[BUFSIZ];
char *p = NULL;
size_t len = 0;
if (!history || histpos + 1 == 0)
return;
if (!history || histpos + 1 == 0)
return;
if (histsz == histpos) {
strncpy(def, text, sizeof(def));
}
if (histsz == histpos) {
strncpy(def, text, sizeof(def));
}
switch (dir) {
switch (dir) {
case 1:
if (histpos < histsz - 1) {
p = history[++histpos];
@ -74,15 +74,15 @@ void navigatehistfile(int dir) {
p = history[--histpos];
}
break;
}
}
if (p == NULL) {
return;
}
if (p == NULL) {
return;
}
len = MIN(strlen(p), BUFSIZ - 1);
strcpy(text, p);
text[len] = '\0';
cursor = len;
match();
len = MIN(strlen(p), BUFSIZ - 1);
strcpy(text, p);
text[len] = '\0';
cursor = len;
match();
}

View file

@ -75,7 +75,7 @@ void drawimage(void) {
} else if ((!sel || !sel->image) && image) { // free image
cleanupimage();
} if (image && longestedge && width && height) { // render the image
// rotate and flip, will return if we don't need to
// rotate and flip, will return if we don't need to
rotateimage();
flipimage();
@ -94,9 +94,9 @@ void drawimage(void) {
xta += menumarginh;
wta += menumarginv;
if (mh != bh + height + imagegaps * 2 - wtr) { // menu height cannot be smaller than image height
resizetoimageheight(height);
}
if (mh != bh + height + imagegaps * 2 - wtr) { // menu height cannot be smaller than image height
resizetoimageheight(height);
}
// render image
if (!imageposition && image) { // top mode = 0
@ -124,106 +124,106 @@ void drawimage(void) {
void setimageopts(void) {
imlib_set_cache_size(8192 * 1024);
imlib_context_set_blend(1);
imlib_context_set_dither(1);
imlib_set_color_usage(128);
imlib_context_set_display(dpy);
imlib_context_set_visual(visual);
imlib_context_set_colormap(cmap);
imlib_context_set_drawable(win);
imlib_context_set_blend(1);
imlib_context_set_dither(1);
imlib_set_color_usage(128);
imlib_context_set_display(dpy);
imlib_context_set_visual(visual);
imlib_context_set_colormap(cmap);
imlib_context_set_drawable(win);
}
void createifnexist(const char *dir) {
// exists, so return
if (access(dir, F_OK) == 0)
if (access(dir, F_OK) == 0)
return;
// fatal: permission denied
if (errno == EACCES)
if (errno == EACCES)
fprintf(stderr, "spmenu: no access to create directory: %s\n", dir);
// mkdir() failure
if (mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1)
fprintf(stderr, "spmenu: failed to create directory: %s\n", dir);
if (mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1)
fprintf(stderr, "spmenu: failed to create directory: %s\n", dir);
}
void createifnexist_rec(const char *dir) {
char *buf, *s = (char*)dir, *bs;
char *buf, *s = (char*)dir, *bs;
if(!(buf = malloc(strlen(s)+1)))
return;
return;
memset(buf, 0, strlen(s)+1);
memset(buf, 0, strlen(s)+1);
for(bs = buf; *s; ++s, ++bs) {
if(*s == '/' && *buf)
for(bs = buf; *s; ++s, ++bs) {
if(*s == '/' && *buf)
createifnexist(buf);
*bs = *s;
}
*bs = *s;
}
free(buf);
free(buf);
}
void loadimage(const char *file, int *width, int *height) {
if (!file) return;
image = imlib_load_image(file);
image = imlib_load_image(file);
if (!image)
if (!image)
return;
imlib_context_set_image(image);
imlib_context_set_image(image);
*width = imlib_image_get_width();
*height = imlib_image_get_height();
*width = imlib_image_get_width();
*height = imlib_image_get_height();
}
void scaleimage(int *width, int *height) {
int new_width, new_height;
float aspect = 1.0f;
int new_width, new_height;
float aspect = 1.0f;
// depending on what size, we determine aspect ratio
if (imagewidth > *width)
aspect = (float)(*width)/imagewidth;
else
aspect = (float)imagewidth/(*width);
if (imagewidth > *width)
aspect = (float)(*width)/imagewidth;
else
aspect = (float)imagewidth/(*width);
new_width = *width * aspect;
new_height = *height * aspect;
new_width = *width * aspect;
new_height = *height * aspect;
if ((new_width == *width && new_height == *height) || (!image))
if ((new_width == *width && new_height == *height) || (!image))
return;
image = imlib_create_cropped_scaled_image(0,0,*width,*height,new_width,new_height);
image = imlib_create_cropped_scaled_image(0,0,*width,*height,new_width,new_height);
imlib_free_image();
imlib_free_image();
if(!image)
if(!image)
return;
imlib_context_set_image(image);
imlib_context_set_image(image);
*width = new_width;
*height = new_height;
*width = new_width;
*height = new_height;
return;
}
void loadimagecache(const char *file, int *width, int *height) {
int slen = 0, i;
unsigned char digest[MD5_DIGEST_LENGTH];
char md5[MD5_DIGEST_LENGTH*2+1];
char *xdg_cache, *home = NULL, *dsize, *buf = NULL;
struct passwd *pw = NULL;
int slen = 0, i;
unsigned char digest[MD5_DIGEST_LENGTH];
char md5[MD5_DIGEST_LENGTH*2+1];
char *xdg_cache, *home = NULL, *dsize, *buf = NULL;
struct passwd *pw = NULL;
// just load and don't store or try cache
if (longestedge > maxcache) {
loadimage(file, width, height);
// just load and don't store or try cache
if (longestedge > maxcache) {
loadimage(file, width, height);
if (image)
scaleimage(width, height);
return;
}
return;
}
if (generatecache) {
// try find image from cache first
@ -290,8 +290,8 @@ void loadimagecache(const char *file, int *width, int *height) {
}
// we din't find anything from cache, or it was just wrong
loadimage(file, width, height);
scaleimage(width, height);
loadimage(file, width, height);
scaleimage(width, height);
if (!generatecache) return;
@ -305,35 +305,35 @@ void loadimagecache(const char *file, int *width, int *height) {
}
void jumptoindex(unsigned int index) {
unsigned int i;
sel = curr = matches;
unsigned int i;
sel = curr = matches;
calcoffsets();
calcoffsets();
for (i = 1; i < index; ++i) {
if(sel && sel->right && (sel = sel->right) == next) {
curr = next;
calcoffsets();
}
}
for (i = 1; i < index; ++i) {
if(sel && sel->right && (sel = sel->right) == next) {
curr = next;
calcoffsets();
}
}
}
void resizetoimageheight(int imageheight) {
int omh = mh, olines = lines;
lines = reallines;
int omh = mh, olines = lines;
lines = reallines;
int wtr = 0;
int x, y;
#if USEXINERAMA
#if USEXINERAMA
int j, di, a, n, area = 0;
XineramaScreenInfo *info;
Window pw;
Window pw;
unsigned int du;
Window w, dw, *dws;
#endif
#endif
XWindowAttributes wa;
if (lines * bh < imageheight + imagegaps * 2) {
if (lines * bh < imageheight + imagegaps * 2) {
lines = (imageheight + imagegaps * 2) / bh;
}
@ -341,32 +341,32 @@ void resizetoimageheight(int imageheight) {
wtr = bh;
}
mh = MAX((lines + 1) * bh + 2 * menumarginv, ((lines + 1) * bh) - wtr + 2 * menumarginv);
mh = MAX((lines + 1) * bh + 2 * menumarginv, ((lines + 1) * bh) - wtr + 2 * menumarginv);
if (mh - bh < imageheight + imagegaps * 2) {
if (mh - bh < imageheight + imagegaps * 2) {
mh = (imageheight + imagegaps * 2 + bh) - wtr + 2 * menumarginv;
}
// init xinerama screens
#if USEXINERAMA
int i = 0;
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
XGetInputFocus(dpy, &w, &di);
if (mon >= 0 && mon < n) {
i = mon;
#if USEXINERAMA
int i = 0;
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
XGetInputFocus(dpy, &w, &di);
if (mon >= 0 && mon < n) {
i = mon;
} else if (w != root && w != PointerRoot && w != None) {
do {
if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
XFree(dws);
if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
XFree(dws);
} while (w != root && w != pw);
if (XGetWindowAttributes(dpy, pw, &wa)) {
for (j = 0; j < n; j++) {
if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
area = a;
i = j;
}
if (XGetWindowAttributes(dpy, pw, &wa)) {
for (j = 0; j < n; j++) {
if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
area = a;
i = j;
}
}
}
if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) {
for (i = 0; i < n; i++) {
@ -378,53 +378,53 @@ void resizetoimageheight(int imageheight) {
}
// calculate x/y position
if (menuposition == 2) { // centered
mw = MIN(MAX(max_textw() + promptw, minwidth), info[i].width);
x = info[i].x_org + ((info[i].width - mw) / 2);
y = info[i].y_org + ((info[i].height - mh) / 2);
} else { // top or bottom
x = info[i].x_org + xpos;
y = info[i].y_org + (menuposition ? 0 : info[i].height - mh - ypos);
mw = (menuwidth>0 ? menuwidth : info[i].width);
}
if (menuposition == 2) { // centered
mw = MIN(MAX(max_textw() + promptw, minwidth), info[i].width);
x = info[i].x_org + ((info[i].width - mw) / 2);
y = info[i].y_org + ((info[i].height - mh) / 2);
} else { // top or bottom
x = info[i].x_org + xpos;
y = info[i].y_org + (menuposition ? 0 : info[i].height - mh - ypos);
mw = (menuwidth>0 ? menuwidth : info[i].width);
}
XFree(info);
} else
#endif
{
XFree(info);
} else
#endif
{
if (!XGetWindowAttributes(dpy, parentwin, &wa))
die("spmenu: could not get embedding window attributes: 0x%lx",
parentwin); // die because unable to get attributes for the parent window
die("spmenu: could not get embedding window attributes: 0x%lx",
parentwin); // die because unable to get attributes for the parent window
if (menuposition == 2) { // centered
mw = MIN(MAX(max_textw() + promptw, minwidth), wa.width);
x = (wa.width - mw) / 2;
y = (wa.height - mh) / 2;
} else { // top or bottom
x = 0;
y = menuposition ? 0 : wa.height - mh - ypos;
mw = wa.width;
}
}
if (menuposition == 2) { // centered
mw = MIN(MAX(max_textw() + promptw, minwidth), wa.width);
x = (wa.width - mw) / 2;
y = (wa.height - mh) / 2;
} else { // top or bottom
x = 0;
y = menuposition ? 0 : wa.height - mh - ypos;
mw = wa.width;
}
}
if (!win || omh == mh) {
if (!win || omh == mh) {
return;
}
XMoveResizeWindow(dpy, win, x + sp, y + vp, mw - 2 * sp - borderwidth * 2, mh);
drw_resize(drw, mw - 2 * sp - borderwidth, mh);
drw_resize(drw, mw - 2 * sp - borderwidth, mh);
if (olines != lines) {
struct item *item;
unsigned int i = 1;
if (olines != lines) {
struct item *item;
unsigned int i = 1;
// walk through all matches
for (item = matches; item && item != sel; item = item->right)
for (item = matches; item && item != sel; item = item->right)
++i;
jumptoindex(i);
}
jumptoindex(i);
}
drawmenu();
drawmenu();
}
#endif

View file

@ -1,19 +1,19 @@
void updatenumlockmask(void) {
unsigned int i, j;
XModifierKeymap *modmap;
unsigned int i, j;
XModifierKeymap *modmap;
numlockmask = 0;
modmap = XGetModifierMapping(dpy);
for (i = 0; i < 8; i++)
for (j = 0; j < modmap->max_keypermod; j++)
if (modmap->modifiermap[i * modmap->max_keypermod + j]
== XKeysymToKeycode(dpy, XK_Num_Lock))
numlockmask = (1 << i);
XFreeModifiermap(modmap);
numlockmask = 0;
modmap = XGetModifierMapping(dpy);
for (i = 0; i < 8; i++)
for (j = 0; j < modmap->max_keypermod; j++)
if (modmap->modifiermap[i * modmap->max_keypermod + j]
== XKeysymToKeycode(dpy, XK_Num_Lock))
numlockmask = (1 << i);
XFreeModifiermap(modmap);
}
void keypress(XEvent *e) {
updatenumlockmask();
updatenumlockmask();
{
unsigned int i;
KeySym keysym;
@ -69,22 +69,22 @@ void keypress(XEvent *e) {
}
void grabkeyboard(void) {
struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
int i;
struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
int i;
// don't grab if embedded
if (embed || managed)
return;
// try to grab keyboard, we may have to wait for another process to ungrab
for (i = 0; i < 1000; i++) {
if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync,
GrabModeAsync, CurrentTime) == GrabSuccess) {
if (embed || managed)
return;
// try to grab keyboard, we may have to wait for another process to ungrab
for (i = 0; i < 1000; i++) {
if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync,
GrabModeAsync, CurrentTime) == GrabSuccess) {
getcapsstate();
return;
return;
}
nanosleep(&ts, NULL);
}
die("cannot grab keyboard");
nanosleep(&ts, NULL);
}
die("cannot grab keyboard");
}
void getcapsstate(void) {

View file

@ -1,9 +1,9 @@
typedef struct {
unsigned int mode;
unsigned int mod;
KeySym keysym;
void (*func)(Arg *);
Arg arg;
unsigned int mod;
KeySym keysym;
void (*func)(Arg *);
Arg arg;
} Key;
// user friendly names for all the modifiers we're using, but there are many more

View file

@ -29,542 +29,542 @@ static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000
static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
static long utf8decodebyte(const char c, size_t *i) {
for (*i = 0; *i < (UTF_SIZ + 1); ++(*i))
if (((unsigned char)c & utfmask[*i]) == utfbyte[*i])
return (unsigned char)c & ~utfmask[*i];
return 0;
for (*i = 0; *i < (UTF_SIZ + 1); ++(*i))
if (((unsigned char)c & utfmask[*i]) == utfbyte[*i])
return (unsigned char)c & ~utfmask[*i];
return 0;
}
static size_t utf8validate(long *u, size_t i) {
if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
*u = UTF_INVALID;
for (i = 1; *u > utfmax[i]; ++i)
;
return i;
if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
*u = UTF_INVALID;
for (i = 1; *u > utfmax[i]; ++i)
;
return i;
}
static size_t utf8decode(const char *c, long *u, size_t clen) {
size_t i, j, len, type;
long udecoded;
size_t i, j, len, type;
long udecoded;
*u = UTF_INVALID;
if (!clen)
return 0;
udecoded = utf8decodebyte(c[0], &len);
if (!BETWEEN(len, 1, UTF_SIZ))
return 1;
for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
if (type)
return j;
}
if (j < len)
return 0;
*u = udecoded;
utf8validate(u, len);
*u = UTF_INVALID;
if (!clen)
return 0;
udecoded = utf8decodebyte(c[0], &len);
if (!BETWEEN(len, 1, UTF_SIZ))
return 1;
for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
if (type)
return j;
}
if (j < len)
return 0;
*u = udecoded;
utf8validate(u, len);
return len;
return len;
}
#endif
Clr transcheme[3];
Drw * drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap) {
Drw *drw = ecalloc(1, sizeof(Drw));
Drw *drw = ecalloc(1, sizeof(Drw));
drw->dpy = dpy;
drw->screen = screen;
drw->root = root;
drw->w = w;
drw->h = h;
drw->visual = visual;
drw->depth = depth;
drw->cmap = cmap;
drw->drawable = XCreatePixmap(dpy, root, w, h, depth);
drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL);
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
drw->dpy = dpy;
drw->screen = screen;
drw->root = root;
drw->w = w;
drw->h = h;
drw->visual = visual;
drw->depth = depth;
drw->cmap = cmap;
drw->drawable = XCreatePixmap(dpy, root, w, h, depth);
drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL);
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
return drw;
return drw;
}
void drw_resize(Drw *drw, unsigned int w, unsigned int h) {
if (!drw)
return;
if (!drw)
return;
drw->w = w;
drw->h = h;
if (drw->drawable)
XFreePixmap(drw->dpy, drw->drawable);
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth);
drw->w = w;
drw->h = h;
if (drw->drawable)
XFreePixmap(drw->dpy, drw->drawable);
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth);
}
void drw_free(Drw *drw) {
XFreePixmap(drw->dpy, drw->drawable);
XFreeGC(drw->dpy, drw->gc);
drw_font_free(drw->font);
free(drw);
XFreePixmap(drw->dpy, drw->drawable);
XFreeGC(drw->dpy, drw->gc);
drw_font_free(drw->font);
free(drw);
}
#if USEPANGO
static Fnt * xfont_create(Drw *drw, const char *fontname) {
Fnt *font;
PangoFontMap *fontmap;
PangoContext *context;
PangoFontDescription *desc;
PangoFontMetrics *metrics;
Fnt *font;
PangoFontMap *fontmap;
PangoContext *context;
PangoFontDescription *desc;
PangoFontMetrics *metrics;
if (!fontname) {
die("spmenu: no font specified.");
}
if (!fontname) {
die("spmenu: no font specified.");
}
font = ecalloc(1, sizeof(Fnt));
font->dpy = drw->dpy;
font = ecalloc(1, sizeof(Fnt));
font->dpy = drw->dpy;
fontmap = pango_xft_get_font_map(drw->dpy, drw->screen);
context = pango_font_map_create_context(fontmap);
desc = pango_font_description_from_string(fontname);
font->layout = pango_layout_new(context);
pango_layout_set_font_description(font->layout, desc);
fontmap = pango_xft_get_font_map(drw->dpy, drw->screen);
context = pango_font_map_create_context(fontmap);
desc = pango_font_description_from_string(fontname);
font->layout = pango_layout_new(context);
pango_layout_set_font_description(font->layout, desc);
metrics = pango_context_get_metrics(context, desc, pango_language_from_string ("en-us"));
font->h = pango_font_metrics_get_height(metrics) / PANGO_SCALE;
metrics = pango_context_get_metrics(context, desc, pango_language_from_string ("en-us"));
font->h = pango_font_metrics_get_height(metrics) / PANGO_SCALE;
pango_font_metrics_unref(metrics);
g_object_unref(context);
pango_font_metrics_unref(metrics);
g_object_unref(context);
return font;
return font;
}
void xfont_free(Fnt *font) {
if (!font)
return;
if (font->layout)
g_object_unref(font->layout);
free(font);
if (!font)
return;
if (font->layout)
g_object_unref(font->layout);
free(font);
}
#else
static Fnt * xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) {
Fnt *font;
XftFont *xfont = NULL;
FcPattern *pattern = NULL;
Fnt *font;
XftFont *xfont = NULL;
FcPattern *pattern = NULL;
if (fontname) {
/* Using the pattern found at font->xfont->pattern does not yield the
* same substitution results as using the pattern returned by
* FcNameParse; using the latter results in the desired fallback
* behaviour whereas the former just results in missing-character
* rectangles being drawn, at least with some fonts. */
if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
return NULL;
}
if (fontname) {
/* Using the pattern found at font->xfont->pattern does not yield the
* same substitution results as using the pattern returned by
* FcNameParse; using the latter results in the desired fallback
* behaviour whereas the former just results in missing-character
* rectangles being drawn, at least with some fonts. */
if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
return NULL;
}
if (fontname[0] == '-')
pattern = XftXlfdParse(fontname, False, False);
else
pattern = FcNameParse((FcChar8 *) fontname);
if (!pattern) {
fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
XftFontClose(drw->dpy, xfont);
return NULL;
}
} else if (fontpattern) {
if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
fprintf(stderr, "spmenu: cannot load font from pattern.\n");
return NULL;
}
} else {
die("spmenu: no font specified.");
}
if (!pattern) {
fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
XftFontClose(drw->dpy, xfont);
return NULL;
}
} else if (fontpattern) {
if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
fprintf(stderr, "spmenu: cannot load font from pattern.\n");
return NULL;
}
} else {
die("spmenu: no font specified.");
}
font = ecalloc(1, sizeof(Fnt));
font->xfont = xfont;
font->pattern = pattern;
font->h = xfont->ascent + xfont->descent;
font->dpy = drw->dpy;
font = ecalloc(1, sizeof(Fnt));
font->xfont = xfont;
font->pattern = pattern;
font->h = xfont->ascent + xfont->descent;
font->dpy = drw->dpy;
return font;
return font;
}
void xfont_free(Fnt *font) {
if (!font)
return;
if (font->pattern)
FcPatternDestroy(font->pattern);
XftFontClose(font->dpy, font->xfont);
free(font);
if (!font)
return;
if (font->pattern)
FcPatternDestroy(font->pattern);
XftFontClose(font->dpy, font->xfont);
free(font);
}
#endif
Fnt* drw_font_create(Drw* drw, char *font[], size_t fontcount) {
if (!drw || !font)
return NULL;
if (!drw || !font)
return NULL;
#if USEPANGO
Fnt *fnt = NULL;
#if USEPANGO
Fnt *fnt = NULL;
fnt = xfont_create(drw, *font);
return (drw->font = fnt);
#else
fnt = xfont_create(drw, *font);
return (drw->font = fnt);
#else
Fnt *cur, *ret = NULL;
size_t i;
for (i = 1; i <= fontcount; i++) {
if ((cur = xfont_create(drw, font[fontcount - i], NULL))) {
cur->next = ret;
ret = cur;
}
}
return (drw->font = ret);
#endif
if ((cur = xfont_create(drw, font[fontcount - i], NULL))) {
cur->next = ret;
ret = cur;
}
}
return (drw->font = ret);
#endif
}
void drw_font_free(Fnt *font) {
if (font) {
#if !USEPANGO
if (font) {
#if !USEPANGO
drw_font_free(font->next);
#endif
xfont_free(font);
}
#endif
xfont_free(font);
}
}
void drw_clr_create(Drw *drw, Clr *dest, char *clrname, unsigned int alpha) {
if (!drw || !dest || !clrname)
return;
if (!drw || !dest || !clrname)
return;
if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap,
clrname, dest))
die("spmenu: cannot allocate color '%s'", clrname);
if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap,
clrname, dest))
die("spmenu: cannot allocate color '%s'", clrname);
dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24);
dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24);
}
/* Wrapper to create color schemes. The caller has to call free(3) on the
* returned color scheme when done using it. */
Clr * drw_scm_create(Drw *drw, char *clrnames[], unsigned int alphas[], size_t clrcount) {
size_t i;
Clr *ret;
size_t i;
Clr *ret;
/* need at least two colors for a scheme */
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
return NULL;
/* need at least two colors for a scheme */
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
return NULL;
for (i = 0; i < clrcount; i++)
drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]);
return ret;
for (i = 0; i < clrcount; i++)
drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]);
return ret;
}
void drw_setscheme(Drw *drw, Clr *scm) {
if (drw)
drw->scheme = scm;
if (drw)
drw->scheme = scm;
}
void drw_settrans(Drw *drw, Clr *psc, Clr *nsc) {
if (drw) {
transcheme[0] = psc[ColBg]; transcheme[1] = nsc[ColBg]; transcheme[2] = psc[ColPwl];
drw->scheme = transcheme;
}
if (drw) {
transcheme[0] = psc[ColBg]; transcheme[1] = nsc[ColBg]; transcheme[2] = psc[ColPwl];
drw->scheme = transcheme;
}
}
void drw_arrow(Drw *drw, int x, int y, unsigned int w, unsigned int h, int direction, int slash) {
if (!drw || !drw->scheme)
return;
if (!drw || !drw->scheme)
return;
x = direction ? x : x + w;
w = direction ? w : -w;
unsigned int hh = slash ? (direction ? 0 : h) : h/2;
x = direction ? x : x + w;
w = direction ? w : -w;
unsigned int hh = slash ? (direction ? 0 : h) : h/2;
XPoint points[] = {
{x , y },
{x + w, y + hh },
{x , y + h },
};
XPoint points[] = {
{x , y },
{x + w, y + hh },
{x , y + h },
};
XPoint bg[] = {
{x , y },
{x + w, y },
{x + w, y + h},
{x , y + h},
};
XPoint bg[] = {
{x , y },
{x + w, y },
{x + w, y + h},
{x , y + h},
};
XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel);
XFillPolygon(drw->dpy, drw->drawable, drw->gc, bg, 4, Convex, CoordModeOrigin);
XSetForeground(drw->dpy, drw->gc, drw->scheme[ColFg].pixel);
XFillPolygon(drw->dpy, drw->drawable, drw->gc, points, 3, Nonconvex, CoordModeOrigin);
XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel);
XFillPolygon(drw->dpy, drw->drawable, drw->gc, bg, 4, Convex, CoordModeOrigin);
XSetForeground(drw->dpy, drw->gc, drw->scheme[ColFg].pixel);
XFillPolygon(drw->dpy, drw->drawable, drw->gc, points, 3, Nonconvex, CoordModeOrigin);
}
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) {
if (!drw || !drw->scheme)
return;
XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
if (filled)
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
else
XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
if (!drw || !drw->scheme)
return;
XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
if (filled)
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
else
XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
}
int xerrordummy(Display *dpy, XErrorEvent *ee) {
return 0;
return 0;
}
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup) {
XSetErrorHandler(xerrordummy);
#if USEPANGO // pango
char buf[1024];
int ty;
unsigned int ew = 0;
XftDraw *d = NULL;
size_t i, len;
int render = x || y || w || h;
#if USEPANGO // pango
char buf[1024];
int ty;
unsigned int ew = 0;
XftDraw *d = NULL;
size_t i, len;
int render = x || y || w || h;
if (!drw || (render && !drw->scheme) || !text || !drw->font)
return 0;
if (!drw || (render && !drw->scheme) || !text || !drw->font)
return 0;
if (!render) {
w = ~w;
} else {
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap);
x += lpad;
w -= lpad;
}
if (!render) {
w = ~w;
} else {
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap);
x += lpad;
w -= lpad;
}
len = strlen(text);
len = strlen(text);
if (len) {
drw_font_getexts(drw->font, text, len, &ew, NULL, markup);
/* shorten text if necessary */
if (len) {
drw_font_getexts(drw->font, text, len, &ew, NULL, markup);
/* shorten text if necessary */
for (len = MIN(len, sizeof(buf) - 1); len && ew > w; drw_font_getexts(drw->font, text, len, &ew, NULL, markup))
len--;
if (len) {
memcpy(buf, text, len);
buf[len] = '\0';
if (len < strlen(text))
for (i = len; i && i > len - 3; buf[--i] = '.')
; /* NOP */
if (len) {
memcpy(buf, text, len);
buf[len] = '\0';
if (len < strlen(text))
for (i = len; i && i > len - 3; buf[--i] = '.')
; /* NOP */
if (render) {
ty = y + (h - drw->font->h) / 2;
if(markup)
pango_layout_set_markup(drw->font->layout, buf, len);
else
pango_layout_set_text(drw->font->layout, buf, len);
pango_xft_render_layout(d, &drw->scheme[invert ? ColBg : ColFg],
drw->font->layout, x * PANGO_SCALE, ty * PANGO_SCALE);
if(markup) /* clear markup attributes */
pango_layout_set_attributes(drw->font->layout, NULL);
}
if (render) {
ty = y + (h - drw->font->h) / 2;
if(markup)
pango_layout_set_markup(drw->font->layout, buf, len);
else
pango_layout_set_text(drw->font->layout, buf, len);
pango_xft_render_layout(d, &drw->scheme[invert ? ColBg : ColFg],
drw->font->layout, x * PANGO_SCALE, ty * PANGO_SCALE);
if(markup) /* clear markup attributes */
pango_layout_set_attributes(drw->font->layout, NULL);
}
x += ew;
w -= ew;
}
}
if (d)
XftDrawDestroy(d);
x += ew;
w -= ew;
}
}
if (d)
XftDrawDestroy(d);
return x + (render ? w : 0);
#else // xft
char buf[1024];
int ty;
unsigned int ew = 0;
XftDraw *d = NULL;
Fnt *usedfont, *curfont, *nextfont;
size_t i, len;
int utf8strlen, utf8charlen, render = x || y || w || h;
long utf8codepoint = 0;
const char *utf8str;
FcCharSet *fccharset;
FcPattern *fcpattern;
FcPattern *match;
XftResult result;
int charexists = 0;
return x + (render ? w : 0);
#else // xft
char buf[1024];
int ty;
unsigned int ew = 0;
XftDraw *d = NULL;
Fnt *usedfont, *curfont, *nextfont;
size_t i, len;
int utf8strlen, utf8charlen, render = x || y || w || h;
long utf8codepoint = 0;
const char *utf8str;
FcCharSet *fccharset;
FcPattern *fcpattern;
FcPattern *match;
XftResult result;
int charexists = 0;
if (!drw || (render && !drw->scheme) || !text || !drw->font)
return 0;
if (!drw || (render && !drw->scheme) || !text || !drw->font)
return 0;
if (!render) {
w = ~w;
} else {
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap);
x += lpad;
w -= lpad;
}
if (!render) {
w = ~w;
} else {
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap);
x += lpad;
w -= lpad;
}
usedfont = drw->font;
while (1) {
utf8strlen = 0;
utf8str = text;
nextfont = NULL;
while (*text) {
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
for (curfont = drw->font; curfont; curfont = curfont->next) {
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
if (charexists) {
if (curfont == usedfont) {
utf8strlen += utf8charlen;
text += utf8charlen;
} else {
nextfont = curfont;
}
break;
}
}
usedfont = drw->font;
while (1) {
utf8strlen = 0;
utf8str = text;
nextfont = NULL;
while (*text) {
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
for (curfont = drw->font; curfont; curfont = curfont->next) {
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
if (charexists) {
if (curfont == usedfont) {
utf8strlen += utf8charlen;
text += utf8charlen;
} else {
nextfont = curfont;
}
break;
}
}
if (!charexists || nextfont)
break;
else
charexists = 0;
}
if (!charexists || nextfont)
break;
else
charexists = 0;
}
if (utf8strlen) {
drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL, True);
/* shorten text if necessary */
for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; drw_font_getexts(usedfont, utf8str, len, &ew, NULL, True))
if (utf8strlen) {
drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL, True);
/* shorten text if necessary */
for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; drw_font_getexts(usedfont, utf8str, len, &ew, NULL, True))
len--;
if (len) {
memcpy(buf, utf8str, len);
buf[len] = '\0';
if (len < utf8strlen)
for (i = len; i && i > len - 3; buf[--i] = '.')
; /* NOP */
if (len) {
memcpy(buf, utf8str, len);
buf[len] = '\0';
if (len < utf8strlen)
for (i = len; i && i > len - 3; buf[--i] = '.')
; /* NOP */
if (render) {
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
usedfont->xfont, x, ty, (XftChar8 *)buf, len);
}
x += ew;
w -= ew;
}
}
if (render) {
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
usedfont->xfont, x, ty, (XftChar8 *)buf, len);
}
x += ew;
w -= ew;
}
}
if (!*text) {
break;
} else if (nextfont) {
charexists = 0;
usedfont = nextfont;
} else {
/* Regardless of whether or not a fallback font is found, the
* character must be drawn. */
charexists = 1;
if (!*text) {
break;
} else if (nextfont) {
charexists = 0;
usedfont = nextfont;
} else {
/* Regardless of whether or not a fallback font is found, the
* character must be drawn. */
charexists = 1;
fccharset = FcCharSetCreate();
FcCharSetAddChar(fccharset, utf8codepoint);
fccharset = FcCharSetCreate();
FcCharSetAddChar(fccharset, utf8codepoint);
if (!drw->font->pattern) {
/* Refer to the comment in xfont_create for more information. */
die("spmenu: the first font in the cache must be loaded from a font string.");
}
if (!drw->font->pattern) {
/* Refer to the comment in xfont_create for more information. */
die("spmenu: the first font in the cache must be loaded from a font string.");
}
fcpattern = FcPatternDuplicate(drw->font->pattern);
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
fcpattern = FcPatternDuplicate(drw->font->pattern);
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
FcDefaultSubstitute(fcpattern);
match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
FcDefaultSubstitute(fcpattern);
match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
FcCharSetDestroy(fccharset);
FcPatternDestroy(fcpattern);
FcCharSetDestroy(fccharset);
FcPatternDestroy(fcpattern);
if (match) {
usedfont = xfont_create(drw, NULL, match);
if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
for (curfont = drw->font; curfont->next; curfont = curfont->next)
; /* NOP */
curfont->next = usedfont;
} else {
xfont_free(usedfont);
usedfont = drw->font;
}
}
}
}
if (d)
XftDrawDestroy(d);
if (match) {
usedfont = xfont_create(drw, NULL, match);
if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
for (curfont = drw->font; curfont->next; curfont = curfont->next)
; /* NOP */
curfont->next = usedfont;
} else {
xfont_free(usedfont);
usedfont = drw->font;
}
}
}
}
if (d)
XftDrawDestroy(d);
XSync(drw->dpy, False);
return x + (render ? w : 0);
#endif
return x + (render ? w : 0);
#endif
XSync(drw->dpy, False);
}
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) {
if (!drw)
return;
if (!drw)
return;
XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
XSync(drw->dpy, False);
XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
XSync(drw->dpy, False);
}
unsigned int drw_font_getwidth(Drw *drw, const char *text, Bool markup) {
if (!drw || !drw->font || !text)
return 0;
return drw_text(drw, 0, 0, 0, 0, 0, text, 0, markup);
if (!drw || !drw->font || !text)
return 0;
return drw_text(drw, 0, 0, 0, 0, 0, text, 0, markup);
}
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup) {
#if !USEPANGO
#if !USEPANGO
XGlyphInfo ext;
#endif
#endif
if (!font || !text)
return;
if (!font || !text)
return;
#if USEPANGO
PangoRectangle r;
if(markup)
pango_layout_set_markup(font->layout, text, len);
else
pango_layout_set_text(font->layout, text, len);
pango_layout_get_extents(font->layout, 0, &r);
if(markup) // clear markup attributes
pango_layout_set_attributes(font->layout, NULL);
#else
#if USEPANGO
PangoRectangle r;
if(markup)
pango_layout_set_markup(font->layout, text, len);
else
pango_layout_set_text(font->layout, text, len);
pango_layout_get_extents(font->layout, 0, &r);
if(markup) // clear markup attributes
pango_layout_set_attributes(font->layout, NULL);
#else
XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
#endif
if (w)
#if USEPANGO
*w = r.width / PANGO_SCALE;
#else
*w = ext.xOff;
#endif
if (h)
*h = font->h;
#endif
if (w)
#if USEPANGO
*w = r.width / PANGO_SCALE;
#else
*w = ext.xOff;
#endif
if (h)
*h = font->h;
}
Cur * drw_cur_create(Drw *drw, int shape) {
Cur *cur;
Cur *cur;
if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
return NULL;
if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
return NULL;
cur->cursor = XCreateFontCursor(drw->dpy, shape);
cur->cursor = XCreateFontCursor(drw->dpy, shape);
return cur;
return cur;
}
void drw_cur_free(Drw *drw, Cur *cursor) {
if (!cursor)
return;
if (!cursor)
return;
XFreeCursor(drw->dpy, cursor->cursor);
free(cursor);
XFreeCursor(drw->dpy, cursor->cursor);
free(cursor);
}
unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n, Bool markup) {
unsigned int tmp = 0;
if (drw && drw->font && text && n)
tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n, markup);
return MIN(n, tmp);
unsigned int tmp = 0;
if (drw && drw->font && text && n)
tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n, markup);
return MIN(n, tmp);
}

View file

@ -7,36 +7,36 @@
#endif
typedef struct {
Cursor cursor;
Cursor cursor;
} Cur;
typedef struct Fnt {
Display *dpy;
unsigned int h;
#if USEPANGO
PangoLayout *layout;
#else
Display *dpy;
unsigned int h;
#if USEPANGO
PangoLayout *layout;
#else
XftFont *xfont;
FcPattern *pattern;
struct Fnt *next;
#endif
FcPattern *pattern;
struct Fnt *next;
#endif
} Fnt;
enum { ColFg, ColBg, ColPwl }; /* Clr scheme index */
typedef XftColor Clr;
typedef struct {
unsigned int w, h;
Display *dpy;
int screen;
Window root;
Visual *visual;
unsigned int depth;
Colormap cmap;
Drawable drawable;
GC gc;
Clr *scheme;
Fnt *font;
unsigned int w, h;
Display *dpy;
int screen;
Window root;
Visual *visual;
unsigned int depth;
Colormap cmap;
Drawable drawable;
GC gc;
Clr *scheme;
Fnt *font;
} Drw;
/* Drawable abstraction */

View file

@ -1,174 +1,175 @@
void fuzzymatch(void) {
struct item *it;
struct item **fuzzymatches = NULL;
struct item *it;
struct item **fuzzymatches = NULL;
struct item *lhpprefix, *hpprefixend;
lhpprefix = hpprefixend = NULL;
char c;
int number_of_matches = 0, i, pidx, sidx, eidx;
int text_len = strlen(text), itext_len;
lhpprefix = hpprefixend = NULL;
char c;
int number_of_matches = 0, i, pidx, sidx, eidx;
int text_len = strlen(text), itext_len;
matches = matchend = NULL;
matches = matchend = NULL;
// walk through all items
for (it = items; it && it->text; it++) {
if (text_len) {
itext_len = strlen(it->text);
pidx = 0; // pointer
sidx = eidx = -1; // start of match, end of match
// walk through item text
for (i = 0; i < itext_len && (c = it->text[i]); i++) {
// fuzzy match pattern
if (!fstrncmp(&text[pidx], &c, 1)) {
if(sidx == -1)
sidx = i;
pidx++;
if (pidx == text_len) {
eidx = i;
break;
}
}
}
// build list of matches
if (eidx != -1) {
// compute distance
// add penalty if match starts late (log(sidx+2))
//add penalty for long a match without many matching characters
it->distance = log(sidx + 2) + (double)(eidx - sidx - text_len);
// fprintf(stderr, "distance %s %f\n", it->text, it->distance);
appenditem(it, &matches, &matchend);
number_of_matches++;
}
} else {
appenditem(it, &matches, &matchend);
}
}
// walk through all items
for (it = items; it && it->text; it++) {
if (text_len) {
itext_len = strlen(it->text);
pidx = 0; // pointer
sidx = eidx = -1; // start of match, end of match
if (number_of_matches) {
// initialize array with matches
if (!(fuzzymatches = realloc(fuzzymatches, number_of_matches * sizeof(struct item*))))
die("spmenu: cannot realloc %u bytes:", number_of_matches * sizeof(struct item*));
for (i = 0, it = matches; it && i < number_of_matches; i++, it = it->right) {
fuzzymatches[i] = it;
}
// sort matches according to distance
// walk through item text
for (i = 0; i < itext_len && (c = it->text[i]); i++) {
// fuzzy match pattern
if (!fstrncmp(&text[pidx], &c, 1)) {
if(sidx == -1)
sidx = i;
pidx++;
if (pidx == text_len) {
eidx = i;
break;
}
}
}
// build list of matches
if (eidx != -1) {
// compute distance
// add penalty if match starts late (log(sidx+2))
//add penalty for long a match without many matching characters
it->distance = log(sidx + 2) + (double)(eidx - sidx - text_len);
// fprintf(stderr, "distance %s %f\n", it->text, it->distance);
appenditem(it, &matches, &matchend);
number_of_matches++;
}
} else {
appenditem(it, &matches, &matchend);
}
}
if (number_of_matches) {
// initialize array with matches
if (!(fuzzymatches = realloc(fuzzymatches, number_of_matches * sizeof(struct item*))))
die("spmenu: cannot realloc %u bytes:", number_of_matches * sizeof(struct item*));
for (i = 0, it = matches; it && i < number_of_matches; i++, it = it->right) {
fuzzymatches[i] = it;
}
// sort matches according to distance
if (sortmatches) qsort(fuzzymatches, number_of_matches, sizeof(struct item*), compare_distance);
// rebuild list of matches
matches = matchend = NULL;
for (i = 0, it = fuzzymatches[i]; i < number_of_matches && it && \
it->text; i++, it = fuzzymatches[i]) {
// rebuild list of matches
matches = matchend = NULL;
for (i = 0, it = fuzzymatches[i]; i < number_of_matches && it && \
it->text; i++, it = fuzzymatches[i]) {
if (sortmatches && it->hp)
appenditem(it, &lhpprefix, &hpprefixend);
appenditem(it, &matches, &matchend);
}
free(fuzzymatches);
}
}
free(fuzzymatches);
}
if (lhpprefix) {
hpprefixend->right = matches;
matches = lhpprefix;
}
hpprefixend->right = matches;
matches = lhpprefix;
}
curr = sel = matches;
curr = sel = matches;
for (i = 0; i < preselected; i++) {
if (sel && sel->right && (sel = sel->right) == next) {
curr = next;
calcoffsets();
}
}
if (sel && sel->right && (sel = sel->right) == next) {
curr = next;
calcoffsets();
}
}
}
void match(void) {
if (fuzzy) {
fuzzymatch();
return;
}
static char **tokv = NULL;
static int tokn = 0;
if (fuzzy) {
fuzzymatch();
return;
}
static char **tokv = NULL;
static int tokn = 0;
char buf[sizeof text], *s;
int i, tokc = 0;
size_t len, textsize;
char buf[sizeof text], *s;
int i, tokc = 0;
size_t len, textsize;
struct item *item, *lhpprefix, *lprefix, *lsubstr, *hpprefixend, *prefixend, *substrend;
strcpy(buf, text);
// separate input text into tokens to be matched individually
for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " "))
if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv)))
die("spmenu: cannot realloc %u bytes:", tokn * sizeof *tokv);
len = tokc ? strlen(tokv[0]) : 0;
strcpy(buf, text);
// separate input text into tokens to be matched individually
for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " "))
if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv)))
die("spmenu: cannot realloc %u bytes:", tokn * sizeof *tokv);
len = tokc ? strlen(tokv[0]) : 0;
matches = lhpprefix = lprefix = lsubstr = matchend = hpprefixend = prefixend = substrend = NULL;
textsize = strlen(text) + 1;
for (item = items; item && item->text; item++) {
for (i = 0; i < tokc; i++)
if (!fstrstr(item->text, tokv[i]))
break;
if (i != tokc) // not all tokens match
continue;
textsize = strlen(text) + 1;
for (item = items; item && item->text; item++) {
for (i = 0; i < tokc; i++)
if (!fstrstr(item->text, tokv[i]))
break;
if (i != tokc) // not all tokens match
continue;
if (!sortmatches)
appenditem(item, &matches, &matchend);
appenditem(item, &matches, &matchend);
else {
// exact matches go first, then prefixes with high priority, then prefixes, then substrings
if (item->hp && !fstrncmp(tokv[0], item->text, len))
appenditem(item, &lhpprefix, &hpprefixend);
appenditem(item, &lhpprefix, &hpprefixend);
else if (!tokc || !fstrncmp(text, item->text, textsize))
appenditem(item, &matches, &matchend);
else if (!fstrncmp(tokv[0], item->text, len))
appenditem(item, &lprefix, &prefixend);
else
appenditem(item, &lsubstr, &substrend);
}
}
appenditem(item, &matches, &matchend);
else if (!fstrncmp(tokv[0], item->text, len))
appenditem(item, &lprefix, &prefixend);
else
appenditem(item, &lsubstr, &substrend);
}
}
if (lhpprefix) {
if (matches) {
matchend->right = lhpprefix;
lhpprefix->left = matchend;
} else
matches = lhpprefix;
matchend = hpprefixend;
}
if (lprefix) {
if (matches) {
matchend->right = lprefix;
lprefix->left = matchend;
} else
matches = lprefix;
matchend = prefixend;
}
if (lsubstr) {
if (matches) {
matchend->right = lsubstr;
lsubstr->left = matchend;
} else
matches = lsubstr;
matchend = substrend;
}
curr = sel = matches;
if (matches) {
matchend->right = lhpprefix;
lhpprefix->left = matchend;
} else
matches = lhpprefix;
matchend = hpprefixend;
}
if (lprefix) {
if (matches) {
matchend->right = lprefix;
lprefix->left = matchend;
} else
matches = lprefix;
matchend = prefixend;
}
if (lsubstr) {
if (matches) {
matchend->right = lsubstr;
lsubstr->left = matchend;
} else
matches = lsubstr;
matchend = substrend;
}
curr = sel = matches;
for (i = 0; i < preselected; i++) {
if (sel && sel->right && (sel = sel->right) == next) {
curr = next;
calcoffsets();
}
}
if (sel && sel->right && (sel = sel->right) == next) {
curr = next;
calcoffsets();
}
}
calcoffsets();
calcoffsets();
}
int compare_distance(const void *a, const void *b) {
struct item *da = *(struct item **) a;
struct item *db = *(struct item **) b;
struct item *da = *(struct item **) a;
struct item *db = *(struct item **) b;
if (!db)
return 1;
if (!da)
return -1;
if (!db)
return 1;
if (!da)
return -1;
return da->distance == db->distance ? 0 : da->distance < db->distance ? -1 : 1;
return da->distance == db->distance ? 0 : da->distance < db->distance ? -1 : 1;
}

View file

@ -1,7 +1,7 @@
void buttonpress(XEvent *e) {
struct item *item;
XButtonPressedEvent *ev = &e->xbutton;
int x = 0, y = 0, h = bh, w, item_num = 0;
struct item *item;
XButtonPressedEvent *ev = &e->xbutton;
int x = 0, y = 0, h = bh, w, item_num = 0;
unsigned int i, click;
int xpad = 0;
@ -25,7 +25,7 @@ void buttonpress(XEvent *e) {
if (!hidecaps) capsWidth = pango_caps ? TEXTWM(capstext) : TEXTW(capstext);
if (!strcmp(capstext, "")) capsWidth = 0; // no caps lock width for no chars
if (ev->window != win) return; // if incorrect or wrong window, return
if (ev->window != win) return; // if incorrect or wrong window, return
click = ClickWindow; // clicking anywhere, we use this and override it if we clicked on something specific
@ -42,28 +42,28 @@ void buttonpress(XEvent *e) {
w = (lines > 0 || !matches) ? mw - x : inputw;
if ((lines <= 0 && ev->x >= 0 && ev->x <= x + w + promptw +
((!prev || !curr->left) ? larrowWidth : 0)) ||
(lines > 0 && ev->y >= y && ev->y <= y + h)) {
((!prev || !curr->left) ? larrowWidth : 0)) ||
(lines > 0 && ev->y >= y && ev->y <= y + h)) {
click = ClickInput;
}
}
// item click
if (lines > 0) {
// vertical list
w = mw - x;
for (item = curr; item != next; item = item->right) {
if (item_num++ == lines) {
item_num = 1;
x += w / columns;
y = 0;
}
if (lines > 0) {
// vertical list
w = mw - x;
for (item = curr; item != next; item = item->right) {
if (item_num++ == lines) {
item_num = 1;
x += w / columns;
y = 0;
}
y += h;
y += h;
// ClickSelItem, called function doesn't matter
if (ev->y >= y && ev->y <= (y + h) && ev->x >= x && ev->x <= (x + w / columns)) {
if (ev->y >= y && ev->y <= (y + h) && ev->x >= x && ev->x <= (x + w / columns)) {
for (i = 0; i < LENGTH(buttons); i++) {
if (ignoreglobalmouse) break;
if (buttons[i].click == ClickSelItem && buttons[i].button == ev->button && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) {
@ -82,23 +82,23 @@ void buttonpress(XEvent *e) {
click = ClickItem;
}
}
}
}
} else if (matches) { // a single line, meaning it could be arrows too, so we check that here
// left arrow
x += inputw;
w = larrowWidth;
if (prev && curr->left) {
if (ev->x >= x && ev->x <= x + w) {
}
}
} else if (matches) { // a single line, meaning it could be arrows too, so we check that here
// left arrow
x += inputw;
w = larrowWidth;
if (prev && curr->left) {
if (ev->x >= x && ev->x <= x + w) {
click = ClickLArrow;
}
}
}
}
// item click
// horizontal list
for (item = curr; item != next; item = item->right) {
x += w;
w = MIN(TEXTW(item->text), mw - x - rarrowWidth);
if (ev->x >= x && ev->x <= x + w) {
// horizontal list
for (item = curr; item != next; item = item->right) {
x += w;
w = MIN(TEXTW(item->text), mw - x - rarrowWidth);
if (ev->x >= x && ev->x <= x + w) {
for (i = 0; i < LENGTH(buttons); i++) {
if (ignoreglobalmouse) break;
if (buttons[i].click == ClickSelItem && buttons[i].button == ev->button && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) {
@ -118,21 +118,21 @@ void buttonpress(XEvent *e) {
}
}
}
}
// right arrow
w = rarrowWidth;
x = mw - w;
if (next && ev->x >= x && ev->x <= x + w) {
}
}
// right arrow
w = rarrowWidth;
x = mw - w;
if (next && ev->x >= x && ev->x <= x + w) {
click = ClickRArrow;
}
}
}
// go through mouse button array and run function
for (i = 0; i < LENGTH(buttons); i++) {
if (ignoreglobalmouse) break;
if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
&& CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
&& CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
buttons[i].func(&buttons[i].arg);
}
@ -140,7 +140,7 @@ void buttonpress(XEvent *e) {
for (i = 0; i < LENGTH(cbuttons); i++) {
if (ignoreconfmouse) break;
if (click == cbuttons[i].click && cbuttons[i].func && cbuttons[i].button == ev->button
&& CLEANMASK(cbuttons[i].mask) == CLEANMASK(ev->state))
&& CLEANMASK(cbuttons[i].mask) == CLEANMASK(ev->state))
cbuttons[i].func(&cbuttons[i].arg);
}
}

View file

@ -13,11 +13,11 @@ enum {
};
typedef struct {
unsigned int click;
unsigned int mask;
unsigned int button;
void (*func)(Arg *arg);
Arg arg;
unsigned int click;
unsigned int mask;
unsigned int button;
void (*func)(Arg *arg);
Arg arg;
} Mouse;
static Mouse cbuttons[256];

View file

@ -1,22 +1,22 @@
#if USERTL
void apply_fribidi(char *str) {
FriBidiStrIndex len = strlen(str);
FriBidiChar logical[BUFSIZ];
FriBidiChar visual[BUFSIZ];
FriBidiParType base = FRIBIDI_PAR_ON;
FriBidiCharSet charset;
fribidi_boolean result;
FriBidiStrIndex len = strlen(str);
FriBidiChar logical[BUFSIZ];
FriBidiChar visual[BUFSIZ];
FriBidiParType base = FRIBIDI_PAR_ON;
FriBidiCharSet charset;
fribidi_boolean result;
fribidi_text[0] = 0;
fribidi_text[0] = 0;
if (len > 0) {
charset = fribidi_parse_charset("UTF-8");
len = fribidi_charset_to_unicode(charset, str, len, logical);
result = fribidi_log2vis(logical, len, &base, visual, NULL, NULL, NULL);
len = fribidi_unicode_to_charset(charset, visual, len, fribidi_text);
}
if (len > 0) {
charset = fribidi_parse_charset("UTF-8");
len = fribidi_charset_to_unicode(charset, str, len, logical);
result = fribidi_log2vis(logical, len, &base, visual, NULL, NULL, NULL);
len = fribidi_unicode_to_charset(charset, visual, len, fribidi_text);
}
if (result||!result) return;
if (result||!result) return;
}
#else
void apply_fribidi(char *str) {

View file

@ -1,5 +1,5 @@
char sixd_to_8bit(int x) {
return x == 0 ? 0 : 0x37 + 0x28 * x;
return x == 0 ? 0 : 0x37 + 0x28 * x;
}
void init_appearance(void) {
@ -41,45 +41,45 @@ void init_appearance(void) {
// create color schemes from array
scheme = ecalloc(LENGTH(colors) + 1, sizeof(Clr *));
scheme[LENGTH(colors)] = drw_scm_create(drw, colors[0], alphas[i], 2);
scheme[LENGTH(colors)] = drw_scm_create(drw, colors[0], alphas[i], 2);
for (i = 0; i < LENGTH(colors) && i < LENGTH(alphas); i++)
scheme[i] = drw_scm_create(drw, colors[i], alphas[i], 2);
scheme[i] = drw_scm_create(drw, colors[i], alphas[i], 2);
for (i = 0; i < LENGTH(textcolors) && i < LENGTH(textclrs); i++)
drw_clr_create(drw, &textclrs[i], textcolors[i], 0);
if (i == 0)
drw_clr_create(drw, &textclrs[i++], "#000000", 0);
for (; i < 7; i++) {
snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
!!(i & 1) * 0x7f,
!!(i & 2) * 0x7f,
!!(i & 4) * 0x7f);
drw_clr_create(drw, &textclrs[i], cbuf, 0);
}
if (i == 7)
drw_clr_create(drw, &textclrs[i++], "#000000", 0);
if (i == 8)
drw_clr_create(drw, &textclrs[i++], "#333333", 0);
for (; i < 16; i++) {
snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
!!(i & 1) * 0xff,
!!(i & 2) * 0xff,
!!(i & 4) * 0xff);
drw_clr_create(drw, &textclrs[i], cbuf, 0);
}
for (; i < 6 * 6 * 6 + 16; i++) {
snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
sixd_to_8bit(((i - 16) / 36) % 6),
sixd_to_8bit(((i - 16) / 6) % 6),
sixd_to_8bit(((i - 16)) % 6));
drw_clr_create(drw, &textclrs[i], cbuf, 0);
}
for (; i < 256; i++) {
snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
0x08 + (i - 6 * 6 * 6 - 16) * 0x0a,
0x08 + (i - 6 * 6 * 6 - 16) * 0x0a,
0x08 + (i - 6 * 6 * 6 - 16) * 0x0a);
drw_clr_create(drw, &textclrs[i], cbuf, 0);
}
drw_clr_create(drw, &textclrs[i], textcolors[i], 0);
if (i == 0)
drw_clr_create(drw, &textclrs[i++], "#000000", 0);
for (; i < 7; i++) {
snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
!!(i & 1) * 0x7f,
!!(i & 2) * 0x7f,
!!(i & 4) * 0x7f);
drw_clr_create(drw, &textclrs[i], cbuf, 0);
}
if (i == 7)
drw_clr_create(drw, &textclrs[i++], "#000000", 0);
if (i == 8)
drw_clr_create(drw, &textclrs[i++], "#333333", 0);
for (; i < 16; i++) {
snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
!!(i & 1) * 0xff,
!!(i & 2) * 0xff,
!!(i & 4) * 0xff);
drw_clr_create(drw, &textclrs[i], cbuf, 0);
}
for (; i < 6 * 6 * 6 + 16; i++) {
snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
sixd_to_8bit(((i - 16) / 36) % 6),
sixd_to_8bit(((i - 16) / 6) % 6),
sixd_to_8bit(((i - 16)) % 6));
drw_clr_create(drw, &textclrs[i], cbuf, 0);
}
for (; i < 256; i++) {
snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
0x08 + (i - 6 * 6 * 6 - 16) * 0x0a,
0x08 + (i - 6 * 6 * 6 - 16) * 0x0a,
0x08 + (i - 6 * 6 * 6 - 16) * 0x0a);
drw_clr_create(drw, &textclrs[i], cbuf, 0);
}
}

View file

@ -2,19 +2,19 @@ static void init_appearance(void);
// Color schemes
enum { SchemeLArrow,
SchemeRArrow,
SchemeItemNorm,
SchemeItemSel,
SchemeItemNormPri,
SchemeItemSelPri,
SchemeMenu,
SchemeInput,
SchemePrompt,
SchemeNormHighlight,
SchemeSelHighlight,
SchemeCaret,
SchemeNumber,
SchemeMode,
SchemeBorder,
SchemeCaps,
SchemeRArrow,
SchemeItemNorm,
SchemeItemSel,
SchemeItemNormPri,
SchemeItemSelPri,
SchemeMenu,
SchemeInput,
SchemePrompt,
SchemeNormHighlight,
SchemeSelHighlight,
SchemeCaret,
SchemeNumber,
SchemeMode,
SchemeBorder,
SchemeCaps,
};

View file

@ -7,26 +7,26 @@
#include "main.h"
void * ecalloc(size_t nmemb, size_t size) {
void *p;
void *p;
if (!(p = calloc(nmemb, size)))
die("calloc:");
return p;
if (!(p = calloc(nmemb, size)))
die("calloc:");
return p;
}
void die(const char *fmt, ...) {
va_list ap;
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
fputc(' ', stderr);
perror(NULL);
} else {
fputc('\n', stderr);
}
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
fputc(' ', stderr);
perror(NULL);
} else {
fputc('\n', stderr);
}
exit(1);
exit(1);
}

View file

@ -1,31 +1,31 @@
char ** tokenize(char *source, const char *delim, int *llen) {
int listlength = 0, list_size = 0;
char **list = NULL, *token;
int listlength = 0, list_size = 0;
char **list = NULL, *token;
token = strtok(source, delim);
while (token) {
if (listlength + 1 >= list_size) {
if (!(list = realloc(list, (list_size += 8) * sizeof(*list))))
die("spmenu: unable to realloc %zu bytes\n", list_size * sizeof(*list));
}
if (!(list[listlength] = strdup(token)))
die("spmenu: unable to strdup %zu bytes\n", strlen(token) + 1);
token = strtok(NULL, delim);
listlength++;
}
token = strtok(source, delim);
while (token) {
if (listlength + 1 >= list_size) {
if (!(list = realloc(list, (list_size += 8) * sizeof(*list))))
die("spmenu: unable to realloc %zu bytes\n", list_size * sizeof(*list));
}
if (!(list[listlength] = strdup(token)))
die("spmenu: unable to strdup %zu bytes\n", strlen(token) + 1);
token = strtok(NULL, delim);
listlength++;
}
*llen = listlength;
return list;
*llen = listlength;
return list;
}
int arrayhas(char **list, int length, char *item) {
int i;
int i;
for (i = 0; i < length; i++) {
size_t len1 = strlen(list[i]);
size_t len2 = strlen(item);
if (!fstrncmp(list[i], item, len1 > len2 ? len2 : len1))
return 1;
}
return 0;
for (i = 0; i < length; i++) {
size_t len1 = strlen(list[i]);
size_t len2 = strlen(item);
if (!fstrncmp(list[i], item, len1 > len2 ? len2 : len1))
return 1;
}
return 0;
}

View file

@ -1,12 +1,12 @@
void readstdin(void) {
char buf[sizeof text], *p;
size_t i, imax = 0, itemsiz = 0;
unsigned int tmpmax = 0;
char buf[sizeof text], *p;
size_t i, imax = 0, itemsiz = 0;
unsigned int tmpmax = 0;
if (passwd) {
inputw = lines = 0;
return;
}
if (passwd) {
inputw = lines = 0;
return;
}
if (listfile) {
readfile();
@ -15,23 +15,23 @@ void readstdin(void) {
int o = 0;
// read each line from stdin and add it to the item list
for (i = 0; fgets(buf, sizeof buf, stdin); i++) {
if (i + 1 >= itemsiz) {
itemsiz += 256;
if (!(items = realloc(items, itemsiz * sizeof(*items))))
die("spmenu: cannot realloc %zu bytes:", itemsiz * sizeof(*items));
}
if ((p = strchr(buf, '\n')))
*p = '\0';
if (!(items[i].text = strdup(buf)))
die("spmenu: cannot strdup %u bytes:", strlen(buf) + 1);
// read each line from stdin and add it to the item list
for (i = 0; fgets(buf, sizeof buf, stdin); i++) {
if (i + 1 >= itemsiz) {
itemsiz += 256;
if (!(items = realloc(items, itemsiz * sizeof(*items))))
die("spmenu: cannot realloc %zu bytes:", itemsiz * sizeof(*items));
}
if ((p = strchr(buf, '\n')))
*p = '\0';
if (!(items[i].text = strdup(buf)))
die("spmenu: cannot strdup %u bytes:", strlen(buf) + 1);
items[i].hp = arrayhas(hpitems, hplength, items[i].text);
drw_font_getexts(drw->font, buf, strlen(buf), &tmpmax, NULL, True);
if (tmpmax > inputw) {
inputw = tmpmax;
imax = i;
}
drw_font_getexts(drw->font, buf, strlen(buf), &tmpmax, NULL, True);
if (tmpmax > inputw) {
inputw = tmpmax;
imax = i;
}
items[i].index = i;
@ -39,36 +39,36 @@ void readstdin(void) {
o = 1;
}
#if !USEIMAGE
#if !USEIMAGE
if (o) {
;
}
#endif
}
#if USEIMAGE
if (!o) longestedge = imagegaps = 0;
#endif
// clean
if (items) {
items[i].text = NULL;
#if USEIMAGE
items[i].image = NULL;
#endif
#endif
}
inputw = items ? TEXTWM(items[imax].text) : 0;
lines = MIN(lines, i);
#if USEIMAGE
if (!o) longestedge = imagegaps = 0;
#endif
// clean
if (items) {
items[i].text = NULL;
#if USEIMAGE
items[i].image = NULL;
#endif
}
inputw = items ? TEXTWM(items[imax].text) : 0;
lines = MIN(lines, i);
}
void readfile(void) {
if (passwd){
inputw = lines = 0;
return;
}
inputw = lines = 0;
return;
}
size_t len;
size_t len;
static size_t c = 0;
char *l;
@ -119,19 +119,19 @@ void readfile(void) {
o = 1;
}
#if !USEIMAGE
#if !USEIMAGE
if (o) {
;
}
#endif
#endif
}
inputw = items ? TEXTWM(items[i].text) : 0;
lines = columns == 1 ? i : MIN(i, lines); // i = number of items
lines = columns == 1 ? i : MIN(i, lines); // i = number of items
#if USEIMAGE
#if USEIMAGE
if (!o) longestedge = imagegaps = 0;
#endif
#endif
if (i == listcount) {
listchanged = 0;
@ -149,76 +149,76 @@ void readfile(void) {
}
int parsemarkup(int index) {
#if USEIMAGE
int w, h;
char *limg = NULL;
#endif
#if USEIMAGE
int w, h;
char *limg = NULL;
#endif
// parse image markup
#if USEIMAGE
if(!strncmp("IMG:", items[index].text, strlen("IMG:"))) {
if(!(items[index].image = malloc(strlen(items[index].text)+1)))
fprintf(stderr, "spmenu: cannot malloc %lu bytes\n", strlen(items[index].text));
if(sscanf(items[index].text, "IMG:%[^\t]", items[index].image)) {
items[index].text += strlen("IMG:")+strlen(items[index].image)+1;
} else {
free(items[index].image);
items[index].image = NULL;
}
// parse image markup
#if USEIMAGE
if(!strncmp("IMG:", items[index].text, strlen("IMG:"))) {
if(!(items[index].image = malloc(strlen(items[index].text)+1)))
fprintf(stderr, "spmenu: cannot malloc %lu bytes\n", strlen(items[index].text));
if(sscanf(items[index].text, "IMG:%[^\t]", items[index].image)) {
items[index].text += strlen("IMG:")+strlen(items[index].image)+1;
} else {
free(items[index].image);
items[index].image = NULL;
}
} else {
items[index].image = NULL;
}
// load image cache (or generate)
if (generatecache && longestedge <= maxcache && items[index].image && strcmp(items[index].image, limg ? limg : "")) {
loadimagecache(items[index].image, &w, &h);
// load image cache (or generate)
if (generatecache && longestedge <= maxcache && items[index].image && strcmp(items[index].image, limg ? limg : "")) {
loadimagecache(items[index].image, &w, &h);
}
if(items[index].image) {
limg = items[index].image;
}
#else // remove the data, just for convenience
char *data;
if(!strncmp("IMG:", items[index].text, strlen("IMG:"))) {
if(!(data = malloc(strlen(items[index].text)+1)))
fprintf(stderr, "spmenu: cannot malloc %lu bytes\n", strlen(items[index].text));
if(sscanf(items[index].text, "IMG:%[^\t]", data)) {
items[index].text += strlen("IMG:")+strlen(data)+1;
}
}
#endif
/* TODO: use this for something
* current usage is not very uslful, however it's here to be used later.
*/
if(!(items[index].ex = malloc(strlen(items[index].text)+1)))
fprintf(stderr, "spmenu: cannot malloc %lu bytes\n", strlen(items[index].text));
if (!strncmp("spmenu:", items[index].text, strlen("spmenu:"))) {
if (sscanf(items[index].text, "spmenu:%[^\t]", items[index].ex)) {
items[index].text += strlen("spmenu:")+strlen(items[index].ex)+1;
}
if(items[index].image) {
limg = items[index].image;
}
#else // remove the data, just for convenience
char *data;
if(!strncmp("IMG:", items[index].text, strlen("IMG:"))) {
if(!(data = malloc(strlen(items[index].text)+1)))
fprintf(stderr, "spmenu: cannot malloc %lu bytes\n", strlen(items[index].text));
if(sscanf(items[index].text, "IMG:%[^\t]", data)) {
items[index].text += strlen("IMG:")+strlen(data)+1;
}
}
#endif
/* TODO: use this for something
* current usage is not very uslful, however it's here to be used later.
*/
if(!(items[index].ex = malloc(strlen(items[index].text)+1)))
fprintf(stderr, "spmenu: cannot malloc %lu bytes\n", strlen(items[index].text));
if (!strncmp("spmenu:", items[index].text, strlen("spmenu:"))) {
if (sscanf(items[index].text, "spmenu:%[^\t]", items[index].ex)) {
items[index].text += strlen("spmenu:")+strlen(items[index].ex)+1;
}
// spmenu:version
if (!strncmp("version", items[index].ex, strlen("version"))) {
fprintf(stdout, "spmenu version %s\n", VERSION);
exit(0);
}
// spmenu:license
if (!strncmp("license", items[index].ex, strlen("license"))) {
fprintf(stdout, "spmenu is licensed under the MIT license. See the included LICENSE file for more information.\n");
exit(0);
}
// spmenu:version
if (!strncmp("version", items[index].ex, strlen("version"))) {
fprintf(stdout, "spmenu version %s\n", VERSION);
exit(0);
}
#if USEIMAGE
if (limg) {
return 1;
} else {
return 0;
// spmenu:license
if (!strncmp("license", items[index].ex, strlen("license"))) {
fprintf(stdout, "spmenu is licensed under the MIT license. See the included LICENSE file for more information.\n");
exit(0);
}
#else
}
#if USEIMAGE
if (limg) {
return 1;
} else {
return 0;
#endif
}
#else
return 0;
#endif
}

View file

@ -29,11 +29,11 @@ void theme_load(void) {
sprintf(theme, "%s/%s", xdg_conf, "spmenu/theme.conf");
}
} else { // custom config path
if (!(theme = malloc(snprintf(NULL, 0, "%s", argtheme) + 1))) {
die("spmenu: failed to malloc theme");
}
if (!(theme = malloc(snprintf(NULL, 0, "%s", argtheme) + 1))) {
die("spmenu: failed to malloc theme");
}
sprintf(theme, "%s", argtheme);
sprintf(theme, "%s", argtheme);
}
// don't bother trying to load if it doesn't exist.
@ -47,7 +47,7 @@ void theme_load(void) {
// attempt to read theme
if (!config_read_file(&cfg, theme)) {
fprintf(stdout, "spmenu: Invalid theme.\n"); // invalid configuration, but let's try to read it anyway
fprintf(stdout, "spmenu: Invalid theme.\n"); // invalid configuration, but let's try to read it anyway
}
// load options theme.window

View file

@ -1,20 +1,20 @@
#if USEXRESOURCES
void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst) {
char *sdst = NULL;
int *idst = NULL;
float *fdst = NULL;
sdst = dst;
idst = dst;
fdst = dst;
char fullname[256];
char *type;
XrmValue ret;
snprintf(fullname, sizeof(fullname), "%s.%s", "spmenu", name);
fullname[sizeof(fullname) - 1] = '\0';
XrmGetResource(db, fullname, "*", &type, &ret);
char *sdst = NULL;
int *idst = NULL;
float *fdst = NULL;
sdst = dst;
idst = dst;
fdst = dst;
char fullname[256];
char *type;
XrmValue ret;
snprintf(fullname, sizeof(fullname), "%s.%s", "spmenu", name);
fullname[sizeof(fullname) - 1] = '\0';
XrmGetResource(db, fullname, "*", &type, &ret);
if (!xresources) return;
if (!(ret.addr == NULL || strncmp("String", type, 64))) {
switch (rtype) { // type
if (!(ret.addr == NULL || strncmp("String", type, 64))) {
switch (rtype) { // type
case STRING:
strcpy(sdst, ret.addr);
break;
@ -25,22 +25,22 @@ void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *d
*fdst = strtof(ret.addr, NULL);
break;
}
}
}
}
void load_xresources(void) {
Display *display;
char *resm;
XrmDatabase db;
ResourcePref *p;
display = XOpenDisplay(NULL);
resm = XResourceManagerString(display);
if (!resm || !xresources)
return;
db = XrmGetStringDatabase(resm);
Display *display;
char *resm;
XrmDatabase db;
ResourcePref *p;
display = XOpenDisplay(NULL);
resm = XResourceManagerString(display);
if (!resm || !xresources)
return;
db = XrmGetStringDatabase(resm);
for (p = resources; p < resources + LENGTH(resources); p++)
resource_load(db, p->name, p->type, p->dst);
for (p = resources; p < resources + LENGTH(resources); p++)
resource_load(db, p->name, p->type, p->dst);
// recognize global colors
if (globalcolors) {
@ -48,6 +48,6 @@ void load_xresources(void) {
resource_load(db, p->name, p->type, p->dst);
}
XCloseDisplay(display);
XCloseDisplay(display);
}
#endif

View file

@ -1,14 +1,14 @@
#if USEXRESOURCES
enum resource_type {
STRING = 0,
INTEGER = 1,
FLOAT = 2
STRING = 0,
INTEGER = 1,
FLOAT = 2
};
typedef struct {
char *name;
enum resource_type type;
void *dst;
char *name;
enum resource_type type;
void *dst;
} ResourcePref;
// declare functions

View file

@ -1,7 +1,7 @@
// This .Xresources array is read and compared to the xrdb. Simply add to the array if you need to.
#if USEXRESOURCES
ResourcePref resources[] = {
{ "font", STRING, &font },
{ "font", STRING, &font },
{ "col_caretfg", STRING, &col_caretfg },
{ "col_caretbg", STRING, &col_caretbg },
{ "col_larrowfg", STRING, &col_larrowfg },
@ -19,14 +19,14 @@ ResourcePref resources[] = {
{ "col_inputbg", STRING, &col_inputbg },
{ "col_inputfg", STRING, &col_inputfg },
{ "col_menu", STRING, &col_menu },
{ "col_numfg", STRING, &col_numfg },
{ "col_numbg", STRING, &col_numbg },
{ "col_modefg", STRING, &col_modefg },
{ "col_modebg", STRING, &col_modebg },
{ "col_hlnormfg", STRING, &col_hlnormfg },
{ "col_hlnormbg", STRING, &col_hlnormbg },
{ "col_hlselfg", STRING, &col_hlselfg },
{ "col_hlselbg", STRING, &col_hlselbg },
{ "col_numfg", STRING, &col_numfg },
{ "col_numbg", STRING, &col_numbg },
{ "col_modefg", STRING, &col_modefg },
{ "col_modebg", STRING, &col_modebg },
{ "col_hlnormfg", STRING, &col_hlnormfg },
{ "col_hlnormbg", STRING, &col_hlnormbg },
{ "col_hlselfg", STRING, &col_hlselfg },
{ "col_hlselbg", STRING, &col_hlselbg },
{ "col_border", STRING, &col_border },
{ "col_promptfg", STRING, &col_promptfg },
{ "col_promptbg", STRING, &col_promptbg },
@ -66,22 +66,22 @@ ResourcePref resources[] = {
{ "alpha_capsbg", INTEGER, &alpha_capsbg },
// SGR sequence colors
{ "col_sgr0", STRING, &col_sgr0 },
{ "col_sgr1", STRING, &col_sgr1 },
{ "col_sgr2", STRING, &col_sgr2 },
{ "col_sgr3", STRING, &col_sgr3 },
{ "col_sgr4", STRING, &col_sgr4 },
{ "col_sgr5", STRING, &col_sgr5 },
{ "col_sgr6", STRING, &col_sgr6 },
{ "col_sgr7", STRING, &col_sgr7 },
{ "col_sgr8", STRING, &col_sgr8 },
{ "col_sgr9", STRING, &col_sgr9 },
{ "col_sgr10", STRING, &col_sgr10 },
{ "col_sgr11", STRING, &col_sgr11 },
{ "col_sgr12", STRING, &col_sgr12 },
{ "col_sgr13", STRING, &col_sgr13 },
{ "col_sgr14", STRING, &col_sgr14 },
{ "col_sgr15", STRING, &col_sgr15 },
{ "col_sgr0", STRING, &col_sgr0 },
{ "col_sgr1", STRING, &col_sgr1 },
{ "col_sgr2", STRING, &col_sgr2 },
{ "col_sgr3", STRING, &col_sgr3 },
{ "col_sgr4", STRING, &col_sgr4 },
{ "col_sgr5", STRING, &col_sgr5 },
{ "col_sgr6", STRING, &col_sgr6 },
{ "col_sgr7", STRING, &col_sgr7 },
{ "col_sgr8", STRING, &col_sgr8 },
{ "col_sgr9", STRING, &col_sgr9 },
{ "col_sgr10", STRING, &col_sgr10 },
{ "col_sgr11", STRING, &col_sgr11 },
{ "col_sgr12", STRING, &col_sgr12 },
{ "col_sgr13", STRING, &col_sgr13 },
{ "col_sgr14", STRING, &col_sgr14 },
{ "col_sgr15", STRING, &col_sgr15 },
// General options
{ "promptpwlstyle", INTEGER, &promptpwlstyle },
@ -96,12 +96,12 @@ ResourcePref resources[] = {
{ "globalcolors", INTEGER, &globalcolors },
{ "coloritems", INTEGER, &coloritems },
{ "sgr", INTEGER, &sgr },
{ "menuposition", INTEGER, &menuposition },
{ "menuposition", INTEGER, &menuposition },
{ "xpos", INTEGER, &xpos },
{ "ypos", INTEGER, &ypos },
{ "menuwidth", INTEGER, &menuwidth },
{ "menupaddingv", INTEGER, &menupaddingv },
{ "menupaddingh", INTEGER, &menupaddingh },
{ "menupaddingv", INTEGER, &menupaddingv },
{ "menupaddingh", INTEGER, &menupaddingh },
{ "menumarginv", INTEGER, &menumarginv },
{ "menumarginh", INTEGER, &menumarginh },
{ "textpadding", INTEGER, &textpadding },
@ -115,11 +115,11 @@ ResourcePref resources[] = {
{ "passwd", INTEGER, &passwd },
{ "minwidth", INTEGER, &minwidth },
{ "preselected", INTEGER, &preselected },
{ "borderwidth", INTEGER, &borderwidth },
{ "lines", INTEGER, &lines },
{ "borderwidth", INTEGER, &borderwidth },
{ "lines", INTEGER, &lines },
{ "lineheight", INTEGER, &lineheight },
{ "columns", INTEGER, &columns },
{ "maxhist", INTEGER, &maxhist },
{ "columns", INTEGER, &columns },
{ "maxhist", INTEGER, &maxhist },
{ "hideitem", INTEGER, &hideitem },
{ "hidematchcount", INTEGER, &hidematchcount },
{ "hidehighlight", INTEGER, &hidehighlight },
@ -133,7 +133,7 @@ ResourcePref resources[] = {
{ "hidecaret", INTEGER, &hidecaret },
{ "hidecursor", INTEGER, &hidecaret },
{ "hidecaps", INTEGER, &hidecaps },
{ "histdup", INTEGER, &histdup },
{ "histdup", INTEGER, &histdup },
{ "casesensitive", INTEGER, &casesensitive },
{ "imagewidth", INTEGER, &imagewidth },
{ "imageheight", INTEGER, &imageheight },
@ -163,51 +163,51 @@ ResourcePref resources[] = {
// global colors
ResourcePref cols[] = {
{ "color10", STRING, &col_caretfg },
{ "color10", STRING, &col_caretfg },
{ "color0", STRING, &col_caretbg },
{ "color4", STRING, &col_larrowfg },
{ "color4", STRING, &col_rarrowfg },
{ "color10", STRING, &col_itemnormfg },
{ "color10", STRING, &col_itemnormprifg },
{ "color10", STRING, &col_inputfg },
{ "color0", STRING, &col_itemnormbg },
{ "color0", STRING, &col_itemnormpribg },
{ "color0", STRING, &col_menu },
{ "color0", STRING, &col_larrowbg },
{ "color0", STRING, &col_rarrowbg },
{ "color0", STRING, &col_itemselfg },
{ "color0", STRING, &col_itemselprifg },
{ "color0", STRING, &col_inputbg },
{ "color12", STRING, &col_promptbg },
{ "color0", STRING, &col_promptfg },
{ "color7", STRING, &col_capsbg },
{ "color0", STRING, &col_capsfg },
{ "color6", STRING, &col_itemselbg },
{ "color6", STRING, &col_itemselpribg },
{ "color6", STRING, &col_border },
{ "color0", STRING, &col_numfg },
{ "color5", STRING, &col_numbg },
{ "color0", STRING, &col_modefg },
{ "color11", STRING, &col_modebg },
{ "color2", STRING, &col_hlnormbg },
{ "color3", STRING, &col_hlselbg },
{ "color0", STRING, &col_hlnormfg },
{ "color0", STRING, &col_hlselfg },
{ "color0", STRING, &col_sgr0 },
{ "color1", STRING, &col_sgr1 },
{ "color2", STRING, &col_sgr2 },
{ "color3", STRING, &col_sgr3 },
{ "color4", STRING, &col_sgr4 },
{ "color5", STRING, &col_sgr5 },
{ "color6", STRING, &col_sgr6 },
{ "color7", STRING, &col_sgr7 },
{ "color8", STRING, &col_sgr8 },
{ "color9", STRING, &col_sgr9 },
{ "color10", STRING, &col_sgr10 },
{ "color11", STRING, &col_sgr11 },
{ "color12", STRING, &col_sgr12 },
{ "color13", STRING, &col_sgr13 },
{ "color14", STRING, &col_sgr14 },
{ "color15", STRING, &col_sgr15 },
{ "color4", STRING, &col_larrowfg },
{ "color4", STRING, &col_rarrowfg },
{ "color10", STRING, &col_itemnormfg },
{ "color10", STRING, &col_itemnormprifg },
{ "color10", STRING, &col_inputfg },
{ "color0", STRING, &col_itemnormbg },
{ "color0", STRING, &col_itemnormpribg },
{ "color0", STRING, &col_menu },
{ "color0", STRING, &col_larrowbg },
{ "color0", STRING, &col_rarrowbg },
{ "color0", STRING, &col_itemselfg },
{ "color0", STRING, &col_itemselprifg },
{ "color0", STRING, &col_inputbg },
{ "color12", STRING, &col_promptbg },
{ "color0", STRING, &col_promptfg },
{ "color7", STRING, &col_capsbg },
{ "color0", STRING, &col_capsfg },
{ "color6", STRING, &col_itemselbg },
{ "color6", STRING, &col_itemselpribg },
{ "color6", STRING, &col_border },
{ "color0", STRING, &col_numfg },
{ "color5", STRING, &col_numbg },
{ "color0", STRING, &col_modefg },
{ "color11", STRING, &col_modebg },
{ "color2", STRING, &col_hlnormbg },
{ "color3", STRING, &col_hlselbg },
{ "color0", STRING, &col_hlnormfg },
{ "color0", STRING, &col_hlselfg },
{ "color0", STRING, &col_sgr0 },
{ "color1", STRING, &col_sgr1 },
{ "color2", STRING, &col_sgr2 },
{ "color3", STRING, &col_sgr3 },
{ "color4", STRING, &col_sgr4 },
{ "color5", STRING, &col_sgr5 },
{ "color6", STRING, &col_sgr6 },
{ "color7", STRING, &col_sgr7 },
{ "color8", STRING, &col_sgr8 },
{ "color9", STRING, &col_sgr9 },
{ "color10", STRING, &col_sgr10 },
{ "color11", STRING, &col_sgr11 },
{ "color12", STRING, &col_sgr12 },
{ "color13", STRING, &col_sgr13 },
{ "color14", STRING, &col_sgr14 },
{ "color15", STRING, &col_sgr15 },
};
#endif

View file

@ -70,8 +70,8 @@ declare -a icondir
# TODO: mac support
fail_mac() {
[ -f "/usr/local/share/spmenu/allowusageonmac" ] && return
cat << EOF
[ -f "/usr/local/share/spmenu/allowusageonmac" ] && return
cat << EOF
spmenu_run currently does not support macOS due to the outdated Bash version.
See https://spmenu.speedie.site/index.php/Using+spmenu+on+macOS for more information.
@ -114,14 +114,14 @@ path() {
xargs ls -lu --time-style=+%s 2>&1 | \
grep -vE "$HIDDEN_KEYWORDS" | \
grep -E "$KEYWORDS"
}
}
if [ "$SORT_BY_RECENT" != "false" ]; then
print | awk '/^(-|l)/ { print $6, $7 }' | sort "${sort_args[@]}" | cut -d' ' -f 2 2>&1
else
print | awk '/^(-|l)/ { print $7 }' | sort "${sort_args[@]}" | cut -d' ' -f 2 2>&1
fi
}
if [ "$SORT_BY_RECENT" != "false" ]; then
print | awk '/^(-|l)/ { print $6, $7 }' | sort "${sort_args[@]}" | cut -d' ' -f 2 2>&1
else
print | awk '/^(-|l)/ { print $7 }' | sort "${sort_args[@]}" | cut -d' ' -f 2 2>&1
fi
}
# uniq
if [ "$DISPLAY_DUPLICATES" != "false" ]; then
@ -134,12 +134,12 @@ path() {
}
print_help() {
if [ "$DMENU_COMPAT" != "true" ]; then
COL='\033[0;31m'
RUNLAUNCHER_EX_ARGS="--lines 20 --columns 1 --normal --sgr1 $HELP_COLOR --hide-cursor --no-allow-typing --no-color-items --hide-prompt --hide-powerline --hide-input --hide-right-arrow --hide-left-arrow --hide-mode --hide-match-count --hide-caps"
read -ra rl_ex <<< "$RUNLAUNCHER_EX_ARGS"
fi
cat << EOF | $RUNLAUNCHER "${rl_help[@]}" "${rl_ex[@]}" > /dev/null
if [ "$DMENU_COMPAT" != "true" ]; then
COL='\033[0;31m'
RUNLAUNCHER_EX_ARGS="--lines 20 --columns 1 --normal --sgr1 $HELP_COLOR --hide-cursor --no-allow-typing --no-color-items --hide-prompt --hide-powerline --hide-input --hide-right-arrow --hide-left-arrow --hide-mode --hide-match-count --hide-caps"
read -ra rl_ex <<< "$RUNLAUNCHER_EX_ARGS"
fi
cat << EOF | $RUNLAUNCHER "${rl_help[@]}" "${rl_ex[@]}" > /dev/null
Start typing in keywords to list out entries. Press Enter to select an entry. The selected entry will be run through a shell.
To set spmenu options, you pass arguments to 'spmenu_run' directly. See 'spmenu --help' for a list of valid arguments.
To configure spmenu, you may also copy ${DESTDIR}${PREFIX}/share/spmenu/example.Xresources to $CONFDIR/spmenu/spmenurc and edit that.
@ -155,7 +155,7 @@ EOF
}
print_cli_help() {
cat << EOF
cat << EOF
spmenu_run - Run launcher for spmenu
spmenu_run -x, --run List entries in \$PATH.
@ -174,9 +174,9 @@ EOF
}
print_config() {
[ -f "$CONFDIR/spmenu/run/config" ] && . "$CONFDIR/spmenu/run/config" && return
mkdir -p "$CONFDIR/spmenu/run"
cat << EOF > "$CONFDIR/spmenu/run/config"
[ -f "$CONFDIR/spmenu/run/config" ] && . "$CONFDIR/spmenu/run/config" && return
mkdir -p "$CONFDIR/spmenu/run"
cat << EOF > "$CONFDIR/spmenu/run/config"
# spmenu_run default configuration file
#
# This is the configuration file for the run launcher spmenu comes with.
@ -319,15 +319,15 @@ exec_cmd() {
"web") $BROWSER "$(printf "%s" "$sout" | sed "s/www //g")" & ;;
"torrent") $TORRENT "$(printf "%s" "$sout" | sed "s/magnet //g")" & ;;
"man") exec="$(printf "%s" "$sout" | sed "s/?//g")"
[ -x "$(command -v "$exec")" ] || return
if [ "$(command -v read_man)" ]; then
read_man "$exec"
return
else
read_nman "$exec"
return
fi
;;
[ -x "$(command -v "$exec")" ] || return
if [ "$(command -v read_man)" ]; then
read_man "$exec"
return
else
read_nman "$exec"
return
fi
;;
esac
}
@ -351,39 +351,39 @@ read_args() {
-o|-stdout|--stdout) remove_arg "$arg" && STDOUT=true ;;
-no|-no-stdout) remove_arg "$arg" && STDOUT=false ;;
-f|-fm|--fm) remove_arg "$arg"
[ -d "$narg" ] && dir="$narg" && remove_arg "$narg"
function=fm
;;
[ -d "$narg" ] && dir="$narg" && remove_arg "$narg"
function=fm
;;
-c|-cc|--clear-cache) remove_arg "$arg"
clearcache="true"
;;
clearcache="true"
;;
-d|-desktop|--desktop) remove_arg "$arg"
function=desktop
;;
function=desktop
;;
-p|-full-path|--full-path) remove_arg "$arg"
USE_FULL_PATH="true"
;;
USE_FULL_PATH="true"
;;
-np|-no-full-path|--no-full-path) remove_arg "$arg"
USE_FULL_PATH="false"
;;
USE_FULL_PATH="false"
;;
-dm|-dmenu|--dmenu) remove_arg "$arg"
DMENU_COMPAT="true"
;;
DMENU_COMPAT="true"
;;
-ndm|-no-dmenu|--no-dmenu) remove_arg "$arg"
DMENU_COMPAT="false"
;;
DMENU_COMPAT="false"
;;
-a|-args|--args) remove_arg "$arg"
[ -z "$narg" ] && printf "You must specify a list of arguments to pass to %s.\n" "$RUNLAUNCHER" && exit 1
[ -z "$narg" ] && printf "You must specify a list of arguments to pass to %s.\n" "$RUNLAUNCHER" && exit 1
remove_arg "$narg"
MARGS="$narg"
;;
remove_arg "$narg"
MARGS="$narg"
;;
-h|--help) remove_arg "$arg" && function=help
;;
;;
"") :
;;
*) printf "spmenu_run: Invalid argument: '%s'. If you meant to pass this to spmenu, use the '%s' option.\n" "$arg" "-a"
;;
;;
esac
[ "$argc" = "$i" ] && break
@ -410,7 +410,7 @@ exec_file() {
else
$GENERIC "$1"
fi
;;
;;
esac
}
@ -448,17 +448,17 @@ prepare_dirnav() {
else
return 1
fi
;;
;;
esac
}
print_desktop_help() {
if [ "$DMENU_COMPAT" != "true" ]; then
COL='\033[0;31m'
RUNLAUNCHER_EX_ARGS="--lines 20 --columns 1 --normal --sgr1 $HELP_COLOR --hide-cursor --hide-caps --no-allow-typing --no-color-items --hide-prompt --hide-powerline --hide-input --hide-right-arrow --hide-left-arrow --hide-mode --hide-match-count"
read -ra rl_ex <<< "${RUNLAUNCHER_EX_ARGS}"
fi
cat << EOF | $RUNLAUNCHER "${rl_help[@]}" "${rl_ex[@]}" > /dev/null
if [ "$DMENU_COMPAT" != "true" ]; then
COL='\033[0;31m'
RUNLAUNCHER_EX_ARGS="--lines 20 --columns 1 --normal --sgr1 $HELP_COLOR --hide-cursor --hide-caps --no-allow-typing --no-color-items --hide-prompt --hide-powerline --hide-input --hide-right-arrow --hide-left-arrow --hide-mode --hide-match-count"
read -ra rl_ex <<< "${RUNLAUNCHER_EX_ARGS}"
fi
cat << EOF | $RUNLAUNCHER "${rl_help[@]}" "${rl_ex[@]}" > /dev/null
Start typing in keywords to list out entries. Press Enter to select an entry. The selected entry will be run through a shell.
To set spmenu options, you modify \$RUNLAUNCHER_ARGS in the config. See 'spmenu --help' for a list of valid arguments to add to the variable.
To configure spmenu itself, you may copy ${DESTDIR}${PREFIX}/share/spmenu.conf to ~/.config/spmenu/spmenu.conf.
@ -608,7 +608,7 @@ print_desktop_menu() {
[ "$menusel" = "?" ] && print_desktop_help && print_desktop_menu
command -v desktop_post_func > /dev/null && desktop_post_func "$menusel"
[ -z "$menusel" ] && return 1 \
|| printf "User input: %s\n" "$menusel" >> "$LOGFILE"
|| printf "User input: %s\n" "$menusel" >> "$LOGFILE"
# this must now be the title only
menusel="$(printf "%s" "$menusel" | sed "s/ -.*//")"
@ -729,20 +729,20 @@ main() {
"run")
parse "$args"
exec_cmd "$args"
;;
;;
"fm") prepare_dirnav "$args"
;;
;;
"desktop")
print_desktop_menu "$args"
;;
;;
"help")
print_cli_help
exit 0
;;
;;
*)
printf "Undefined function: '%s'\n" "$function"
exit 1
;;
;;
esac
}

View file

@ -46,39 +46,39 @@ command -v maim > /dev/null && maim -uB > /tmp/image.png
IMAGE="/tmp/image.png"
main() {
[ -e "$IMAGE" ] && IMAGEARG="--image-size 500 --no-generate-cache" && IMAGEPREFIX="IMG:" || IMAGE=""
[ -e "$IMAGE" ] && IMAGEARG="--image-size 500 --no-generate-cache" && IMAGEPREFIX="IMG:" || IMAGE=""
printf "$IMAGEPREFIX$IMAGE\t${v2}s${v3}p${v4}m${v5}e${v6}n${v7}u${v8} $([ -f "${DESTDIR}${PREFIX}/share/spmenu/version" ] && cat "${DESTDIR}${PREFIX}/share/spmenu/version")\n\
$IMAGEPREFIX$IMAGE\t${b1}\n\
$IMAGEPREFIX$IMAGE\t${b2}\n\
$IMAGEPREFIX$IMAGE\t${b3}\n\
$IMAGEPREFIX$IMAGE\t${b4}\n\
$IMAGEPREFIX$IMAGE\t${b5}\n\
$IMAGEPREFIX$IMAGE\t${b6}\n\
$IMAGEPREFIX$IMAGE\t${b7}\n\
$IMAGEPREFIX$IMAGE\t${b8}\n\
$IMAGEPREFIX$IMAGE\t${b9}\n\
$IMAGEPREFIX$IMAGE\t${b10}\n\
$IMAGEPREFIX$IMAGE\t${b11}\n\
$IMAGEPREFIX$IMAGE\t${b12}\n\
$IMAGEPREFIX$IMAGE\t${b13}\n\
$IMAGEPREFIX$IMAGE\t${b14}\n\
$IMAGEPREFIX$IMAGE\t${b15}\n\
$IMAGEPREFIX$IMAGE\t${b16}\n\
$IMAGEPREFIX$IMAGE\t${v1}q${v2}w${v3}e${v4}r${v5}t${v6}y${v7}u${v8}i${v9}o${v10}p${v11}[${v12}]${v13}a${v14}s${v15}d${v16}f\n\
$IMAGEPREFIX$IMAGE\t<b>qwertyuiop[]asdf</b> - b\n\
$IMAGEPREFIX$IMAGE\t<i>qwertyuiop[]asdf</i> - i\n\
$IMAGEPREFIX$IMAGE\t<s>qwertyuiop[]asdf</s> - s\n\
$IMAGEPREFIX$IMAGE\t<u>qwertyuiop[]asdf</u> - u\n\
$IMAGEPREFIX$IMAGE\t<sub>qwertyuiop[]asdf - sub</sub>\n\
$IMAGEPREFIX$IMAGE\t<sup>qwertyuiop[]asdf - sup</sup>\n\
$IMAGEPREFIX$IMAGE\t<tt>qwertyuiop[]asdf</tt> - tt\n\
$IMAGEPREFIX$IMAGE\t<small>qwertyuiop[]asdf</small> - small\n\
$IMAGEPREFIX$IMAGE\t<big>qwertyuiop[]asdf</big> - big\n\
$IMAGEPREFIX$IMAGE\t\n\
$IMAGEPREFIX$IMAGE\tArguments will be passed to spmenu.\n\
$IMAGEPREFIX$IMAGE\tReport any issues at the Codeberg repo.\n\
" | spmenu --no-alpha --lines 40 $IMAGEARG "$@" --columns 1 --prompt "<big>spmenu <i>test</i> <small>script</small></big>"
}
printf "$IMAGEPREFIX$IMAGE\t${v2}s${v3}p${v4}m${v5}e${v6}n${v7}u${v8} $([ -f "${DESTDIR}${PREFIX}/share/spmenu/version" ] && cat "${DESTDIR}${PREFIX}/share/spmenu/version")\n\
$IMAGEPREFIX$IMAGE\t${b1}\n\
$IMAGEPREFIX$IMAGE\t${b2}\n\
$IMAGEPREFIX$IMAGE\t${b3}\n\
$IMAGEPREFIX$IMAGE\t${b4}\n\
$IMAGEPREFIX$IMAGE\t${b5}\n\
$IMAGEPREFIX$IMAGE\t${b6}\n\
$IMAGEPREFIX$IMAGE\t${b7}\n\
$IMAGEPREFIX$IMAGE\t${b8}\n\
$IMAGEPREFIX$IMAGE\t${b9}\n\
$IMAGEPREFIX$IMAGE\t${b10}\n\
$IMAGEPREFIX$IMAGE\t${b11}\n\
$IMAGEPREFIX$IMAGE\t${b12}\n\
$IMAGEPREFIX$IMAGE\t${b13}\n\
$IMAGEPREFIX$IMAGE\t${b14}\n\
$IMAGEPREFIX$IMAGE\t${b15}\n\
$IMAGEPREFIX$IMAGE\t${b16}\n\
$IMAGEPREFIX$IMAGE\t${v1}q${v2}w${v3}e${v4}r${v5}t${v6}y${v7}u${v8}i${v9}o${v10}p${v11}[${v12}]${v13}a${v14}s${v15}d${v16}f\n\
$IMAGEPREFIX$IMAGE\t<b>qwertyuiop[]asdf</b> - b\n\
$IMAGEPREFIX$IMAGE\t<i>qwertyuiop[]asdf</i> - i\n\
$IMAGEPREFIX$IMAGE\t<s>qwertyuiop[]asdf</s> - s\n\
$IMAGEPREFIX$IMAGE\t<u>qwertyuiop[]asdf</u> - u\n\
$IMAGEPREFIX$IMAGE\t<sub>qwertyuiop[]asdf - sub</sub>\n\
$IMAGEPREFIX$IMAGE\t<sup>qwertyuiop[]asdf - sup</sup>\n\
$IMAGEPREFIX$IMAGE\t<tt>qwertyuiop[]asdf</tt> - tt\n\
$IMAGEPREFIX$IMAGE\t<small>qwertyuiop[]asdf</small> - small\n\
$IMAGEPREFIX$IMAGE\t<big>qwertyuiop[]asdf</big> - big\n\
$IMAGEPREFIX$IMAGE\t\n\
$IMAGEPREFIX$IMAGE\tArguments will be passed to spmenu.\n\
$IMAGEPREFIX$IMAGE\tReport any issues at the Codeberg repo.\n\
" | spmenu --no-alpha --lines 40 $IMAGEARG "$@" --columns 1 --prompt "<big>spmenu <i>test</i> <small>script</small></big>"
}
main "$@"
main "$@"

498
spmenu.c
View file

@ -161,16 +161,16 @@ static int screen;
// item struct
struct item {
char *text;
char *text;
char *clntext;
#if USEIMAGE
#if USEIMAGE
char *image;
#endif
#endif
char *ex;
struct item *left, *right;
struct item *left, *right;
int hp;
int index;
double distance;
double distance;
};
// image globals
@ -285,40 +285,40 @@ static char *(*fstrstr)(const char *, const char *) = cistrstr;
#include "libs/event.c"
void appenditem(struct item *item, struct item **list, struct item **last) {
if (*last)
(*last)->right = item;
else
*list = item;
if (*last)
(*last)->right = item;
else
*list = item;
item->left = *last;
item->right = NULL;
*last = item;
item->left = *last;
item->right = NULL;
*last = item;
}
void recalculatenumbers(void) {
unsigned int numer = 0, denom = 0;
struct item *item;
if (matchend) {
numer++;
unsigned int numer = 0, denom = 0;
struct item *item;
if (matchend) {
numer++;
// walk through items that match and add to numer
for (item = matchend; item && item->left; item = item->left)
numer++;
}
for (item = matchend; item && item->left; item = item->left)
numer++;
}
// walk through all items, matching or not and add to denom
for (item = items; item && item->text; item++)
denom++;
for (item = items; item && item->text; item++)
denom++;
snprintf(numbers, NUMBERSBUFSIZE, "%d/%d", numer, denom);
snprintf(numbers, NUMBERSBUFSIZE, "%d/%d", numer, denom);
}
void calcoffsets(void) {
int i, n;
int i, n;
if (lines > 0)
n = lines * columns * bh;
else { // no lines, therefore the size of items must be decreased to fit the menu elements
if (lines > 0)
n = lines * columns * bh;
else { // no lines, therefore the size of items must be decreased to fit the menu elements
int numberWidth = 0;
int modeWidth = 0;
int larrowWidth = 0;
@ -334,85 +334,85 @@ void calcoffsets(void) {
if (!strcmp(capstext, ""))
capsWidth = 0;
n = mw - (promptw + inputw + larrowWidth + rarrowWidth + modeWidth + numberWidth + capsWidth + menumarginv);
n = mw - (promptw + inputw + larrowWidth + rarrowWidth + modeWidth + numberWidth + capsWidth + menumarginv);
}
// calculate which items will begin the next page
for (i = 0, next = curr; next; next = next->right)
if ((i += (lines > 0) ? bh : MIN(TEXTWM(next->text), n)) > n)
break;
// calculate which items will begin the next page
for (i = 0, next = curr; next; next = next->right)
if ((i += (lines > 0) ? bh : MIN(TEXTWM(next->text), n)) > n)
break;
// calculate which items will begin the previous page
for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
if ((i += (lines > 0) ? bh : MIN(TEXTWM(prev->left->text), n)) > n)
break;
// calculate which items will begin the previous page
for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
if ((i += (lines > 0) ? bh : MIN(TEXTWM(prev->left->text), n)) > n)
break;
}
int max_textw(void) {
int len = 0;
int len = 0;
for (struct item *item = items; item && item->text; item++)
len = MAX(TEXTW(item->text), len);
for (struct item *item = items; item && item->text; item++)
len = MAX(TEXTW(item->text), len);
return len;
return len;
}
void cleanup(void) {
size_t i;
size_t i;
#if USEIMAGE
#if USEIMAGE
cleanupimage(); // function frees images
#endif
#endif
XUngrabKey(dpy, AnyKey, AnyModifier, root); // ungrab keys
XUngrabKey(dpy, AnyKey, AnyModifier, root); // ungrab keys
// free color scheme
for (i = 0; i < LENGTH(colors) + 1; i++)
free(scheme[i]);
for (i = 0; i < LENGTH(colors) + 1; i++)
free(scheme[i]);
// free high priority items
for (i = 0; i < hplength; ++i)
free(hpitems[i]);
free(hpitems[i]);
// free drawing and close the display
drw_free(drw);
XSync(dpy, False);
XCloseDisplay(dpy);
drw_free(drw);
XSync(dpy, False);
XCloseDisplay(dpy);
}
char * cistrstr(const char *h, const char *n) {
size_t i;
size_t i;
if (!n[0])
return (char *)h;
if (!n[0])
return (char *)h;
for (; *h; ++h) {
for (i = 0; n[i] && tolower((unsigned char)n[i]) ==
tolower((unsigned char)h[i]); ++i);
for (; *h; ++h) {
for (i = 0; n[i] && tolower((unsigned char)n[i]) ==
tolower((unsigned char)h[i]); ++i);
if (n[i] == '\0')
return (char *)h;
}
if (n[i] == '\0')
return (char *)h;
}
return NULL;
return NULL;
}
void grabfocus(void) {
struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
Window focuswin;
int i, revertwin;
struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
Window focuswin;
int i, revertwin;
XWindowAttributes wa;
XSync(dpy, False);
XGetWindowAttributes(dpy, win, &wa);
XGetWindowAttributes(dpy, win, &wa);
for (i = 0; i < 100; ++i) {
XGetInputFocus(dpy, &focuswin, &revertwin);
if (focuswin == win)
return;
for (i = 0; i < 100; ++i) {
XGetInputFocus(dpy, &focuswin, &revertwin);
if (focuswin == win)
return;
// if it's a client, we can't just steal all the input for ourselves
if (managed) {
if (managed) {
if (wa.map_state == IsViewable) {
XTextProperty prop;
char *windowtitle = prompt != NULL ? prompt : "spmenu";
@ -426,130 +426,130 @@ void grabfocus(void) {
XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
}
nanosleep(&ts, NULL);
}
nanosleep(&ts, NULL);
}
die("spmenu: cannot grab focus"); // not possible to grab focus, abort immediately
die("spmenu: cannot grab focus"); // not possible to grab focus, abort immediately
}
void insert(const char *str, ssize_t n) {
if (strlen(text) + n > sizeof text - 1)
return;
if (strlen(text) + n > sizeof text - 1)
return;
// move existing text out of the way, insert new text, and update cursor
memmove(&text[cursor + n], &text[cursor], sizeof text - cursor - MAX(n, 0));
// move existing text out of the way, insert new text, and update cursor
memmove(&text[cursor + n], &text[cursor], sizeof text - cursor - MAX(n, 0));
// update cursor
if (n > 0 && str && n)
memcpy(&text[cursor], str, n);
if (n > 0 && str && n)
memcpy(&text[cursor], str, n);
// add to cursor position and continue matching
cursor += n;
match();
cursor += n;
match();
}
size_t nextrune(int inc) {
ssize_t n;
ssize_t n;
// return location of next utf8 rune in the given direction (+1 or -1)
for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc)
// return location of next utf8 rune in the given direction (+1 or -1)
for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc)
;
return n;
return n;
}
void pastesel(void) {
char *p, *q;
int di;
unsigned long dl;
Atom da;
char *p, *q;
int di;
unsigned long dl;
Atom da;
// we have been given the current selection, now insert it into input
if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False,
utf8, &da, &di, &dl, &dl, (unsigned char **)&p)
== Success && p) {
insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p)); // insert selection
XFree(p);
}
// we have been given the current selection, now insert it into input
if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False,
utf8, &da, &di, &dl, &dl, (unsigned char **)&p)
== Success && p) {
insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p)); // insert selection
XFree(p);
}
// draw the menu
drawmenu();
drawmenu();
}
void xinitvisual(void) {
XVisualInfo *infos;
XRenderPictFormat *fmt;
int nitems;
int i;
XVisualInfo *infos;
XRenderPictFormat *fmt;
int nitems;
int i;
// visual properties
XVisualInfo tpl = {
.screen = screen,
.depth = 32,
.class = TrueColor
};
XVisualInfo tpl = {
.screen = screen,
.depth = 32,
.class = TrueColor
};
long masks = VisualScreenMask | VisualDepthMask | VisualClassMask;
long masks = VisualScreenMask | VisualDepthMask | VisualClassMask;
infos = XGetVisualInfo(dpy, masks, &tpl, &nitems);
visual = NULL;
infos = XGetVisualInfo(dpy, masks, &tpl, &nitems);
visual = NULL;
// create colormap
for(i = 0; i < nitems; i ++) {
fmt = XRenderFindVisualFormat(dpy, infos[i].visual);
if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) {
visual = infos[i].visual;
depth = infos[i].depth;
cmap = XCreateColormap(dpy, root, visual, AllocNone);
useargb = 1;
break;
}
}
for(i = 0; i < nitems; i ++) {
fmt = XRenderFindVisualFormat(dpy, infos[i].visual);
if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) {
visual = infos[i].visual;
depth = infos[i].depth;
cmap = XCreateColormap(dpy, root, visual, AllocNone);
useargb = 1;
break;
}
}
XFree(infos);
XFree(infos);
// no alpha, reset to default
if (!visual || !alpha) {
visual = DefaultVisual(dpy, screen);
depth = DefaultDepth(dpy, screen);
cmap = DefaultColormap(dpy, screen);
}
if (!visual || !alpha) {
visual = DefaultVisual(dpy, screen);
depth = DefaultDepth(dpy, screen);
cmap = DefaultColormap(dpy, screen);
}
}
void setupdisplay(void) {
int x, y, i;
#if USEXINERAMA
int x, y, i;
#if USEXINERAMA
int j, di;
#endif
unsigned int du;
#endif
unsigned int du;
unsigned int tmp, minstrlen = 0, curstrlen = 0;
int numwidthchecks = 100;
struct item *item;
XIM xim;
Window w, dw, *dws;
XIM xim;
Window w, dw, *dws;
XWindowAttributes wa;
#if USEXINERAMA
XineramaScreenInfo *info;
Window pw;
int a, n, area = 0;
#endif
#if USEXINERAMA
XineramaScreenInfo *info;
Window pw;
int a, n, area = 0;
#endif
init_appearance(); // init colorschemes by reading arrays
// set properties indicating what spmenu handles
clip = XInternAtom(dpy, "CLIPBOARD", False);
utf8 = XInternAtom(dpy, "UTF8_STRING", False);
types = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
dock = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
clip = XInternAtom(dpy, "CLIPBOARD", False);
utf8 = XInternAtom(dpy, "UTF8_STRING", False);
types = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
dock = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
// resize client
bh = MAX(drw->font->h, drw->font->h + 2 + lineheight);
lines = MAX(lines, 0);
lines = MAX(lines, 0);
reallines = lines;
// resize client to image height if deemed necessary
#if USEIMAGE
#if USEIMAGE
if (image) resizetoimageheight(imageheight);
#endif
#endif
mh = (lines + 1) * bh + 2 * menumarginv; // lines + 1 * bh is the menu height
@ -574,122 +574,122 @@ void setupdisplay(void) {
}
// init xinerama screens
#if USEXINERAMA
i = 0;
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
XGetInputFocus(dpy, &w, &di);
if (mon >= 0 && mon < n)
i = mon;
else if (w != root && w != PointerRoot && w != None) {
// find top-level window containing current input focus
do {
if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
XFree(dws);
} while (w != root && w != pw);
// find xinerama screen with which the window intersects most
if (XGetWindowAttributes(dpy, pw, &wa))
for (j = 0; j < n; j++)
if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
area = a;
i = j;
}
}
// no focused window is on screen, so use pointer location instead
if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
for (i = 0; i < n; i++)
if (INTERSECT(x, y, 1, 1, info[i]))
break;
#if USEXINERAMA
i = 0;
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
XGetInputFocus(dpy, &w, &di);
if (mon >= 0 && mon < n)
i = mon;
else if (w != root && w != PointerRoot && w != None) {
// find top-level window containing current input focus
do {
if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
XFree(dws);
} while (w != root && w != pw);
// find xinerama screen with which the window intersects most
if (XGetWindowAttributes(dpy, pw, &wa))
for (j = 0; j < n; j++)
if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
area = a;
i = j;
}
}
// no focused window is on screen, so use pointer location instead
if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
for (i = 0; i < n; i++)
if (INTERSECT(x, y, 1, 1, info[i]))
break;
// calculate x/y position
if (menuposition == 2) { // centered
mw = MIN(MAX(max_textw() + promptw, minwidth), info[i].width);
x = info[i].x_org + ((info[i].width - mw) / 2);
y = info[i].y_org + ((info[i].height - mh) / 2);
} else { // top or bottom
x = info[i].x_org + xpos;
y = info[i].y_org + (menuposition ? 0 : info[i].height - mh - ypos);
mw = (menuwidth>0 ? menuwidth : info[i].width);
}
if (menuposition == 2) { // centered
mw = MIN(MAX(max_textw() + promptw, minwidth), info[i].width);
x = info[i].x_org + ((info[i].width - mw) / 2);
y = info[i].y_org + ((info[i].height - mh) / 2);
} else { // top or bottom
x = info[i].x_org + xpos;
y = info[i].y_org + (menuposition ? 0 : info[i].height - mh - ypos);
mw = (menuwidth>0 ? menuwidth : info[i].width);
}
XFree(info);
} else
#endif
{
if (!XGetWindowAttributes(dpy, parentwin, &wa))
die("spmenu: could not get embedding window attributes: 0x%lx",
parentwin); // die because unable to get attributes for the parent window
XFree(info);
} else
#endif
{
if (!XGetWindowAttributes(dpy, parentwin, &wa))
die("spmenu: could not get embedding window attributes: 0x%lx",
parentwin); // die because unable to get attributes for the parent window
if (menuposition == 2) { // centered
mw = MIN(MAX(max_textw() + promptw, minwidth), wa.width);
x = (wa.width - mw) / 2;
y = (wa.height - mh) / 2;
} else { // top or bottom
x = 0;
y = menuposition ? 0 : wa.width - mh - ypos;
mw = wa.width;
}
}
if (menuposition == 2) { // centered
mw = MIN(MAX(max_textw() + promptw, minwidth), wa.width);
x = (wa.width - mw) / 2;
y = (wa.height - mh) / 2;
} else { // top or bottom
x = 0;
y = menuposition ? 0 : wa.width - mh - ypos;
mw = wa.width;
}
}
// might be faster in some instances, most of the time unnecessary
// might be faster in some instances, most of the time unnecessary
if (!accuratewidth) inputw = MIN(inputw, mw/3);
match(); // match entries
match(); // match entries
// create menu window and set properties for it
// create menu window and set properties for it
create_window(x + sp, y + vp - (menuposition == 1 ? 0 : menuposition == 2 ? borderwidth : borderwidth * 2), mw - 2 * sp - borderwidth * 2, mh);
set_window();
set_prop();
#if USEIMAGE
#if USEIMAGE
setimageopts();
#endif
#endif
// input methods
// input methods
if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) {
XSetLocaleModifiers("@im=local");
if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) {
XSetLocaleModifiers("@im=");
if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL)
die("XOpenIM failed: could not open input device");
}
}
XSetLocaleModifiers("@im=local");
if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) {
XSetLocaleModifiers("@im=");
if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL)
die("XOpenIM failed: could not open input device");
}
}
xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
XNClientWindow, win, XNFocusWindow, win, NULL);
xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
XNClientWindow, win, XNFocusWindow, win, NULL);
XMapRaised(dpy, win);
XMapRaised(dpy, win);
XSync(dpy, False);
XGetWindowAttributes(dpy, win, &wa);
XGetWindowAttributes(dpy, win, &wa);
if (wa.map_state == IsViewable) // must be viewable, otherwise we get a BadMatch error
XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
// embed spmenu inside parent window
if (embed) {
if (embed) {
XReparentWindow(dpy, win, parentwin, x, y);
XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask);
if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
for (i = 0; i < du && dws[i] != win; ++i)
XSelectInput(dpy, dws[i], FocusChangeMask);
XFree(dws);
}
grabfocus();
}
XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask);
if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
for (i = 0; i < du && dws[i] != win; ++i)
XSelectInput(dpy, dws[i], FocusChangeMask);
XFree(dws);
}
grabfocus();
}
// resize and draw
drw_resize(drw, mw - 2 * sp - borderwidth * 2, mh);
drawmenu();
drw_resize(drw, mw - 2 * sp - borderwidth * 2, mh);
drawmenu();
}
int main(int argc, char *argv[]) {
XWindowAttributes wa;
XWindowAttributes wa;
readargs(argc, argv); // start by reading arguments
#if USEIMAGE
#if USEIMAGE
longestedge = MAX(imagewidth, imageheight);
#endif
#endif
if (!type) {
mode = 0;
@ -708,65 +708,65 @@ int main(int argc, char *argv[]) {
strcpy(modetext, normtext);
}
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
fputs("warning: no locale support\n", stderr); // invalid locale, so notify the user about it
if (!XSetLocaleModifiers(""))
fputs("warning: no locale modifiers support\n", stderr);
fputs("warning: no locale modifiers support\n", stderr);
if (!(dpy = XOpenDisplay(NULL)))
die("spmenu: cannot open display"); // failed to open display
// set screen and root window
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
root = RootWindow(dpy, screen);
// parent window is the root window (ie. window manager) because we're not embedding
if (!embed || !(parentwin = strtol(embed, NULL, 0)))
parentwin = root;
parentwin = root;
if (!XGetWindowAttributes(dpy, parentwin, &wa))
die("spmenu: could not get embedding window attributes: 0x%lx", parentwin);
die("spmenu: could not get embedding window attributes: 0x%lx", parentwin);
xinitvisual(); // init visual and create drawable after
drw = drw_create(dpy, screen, root, wa.width, wa.height, visual, depth, cmap); // wrapper function creating a drawable
xinitvisual(); // init visual and create drawable after
drw = drw_create(dpy, screen, root, wa.width, wa.height, visual, depth, cmap); // wrapper function creating a drawable
// load fonts
if (!drw_font_create(drw, fonts, LENGTH(fonts)))
die("no fonts could be loaded.");
if (!drw_font_create(drw, fonts, LENGTH(fonts)))
die("no fonts could be loaded.");
// resize window
lrpad = drw->font->h + textpadding;
prepare_window_size(); // this function sets padding size
// pledge limits what programs can do, so here we specify what spmenu should be allowed to do
#ifdef __OpenBSD__
if (pledge("stdio rpath wpath cpath", NULL) == -1)
die("pledge");
#endif
#ifdef __OpenBSD__
if (pledge("stdio rpath wpath cpath", NULL) == -1)
die("pledge");
#endif
loadhistory(); // read history entries
loadhistory(); // read history entries
// fast (-f) means we grab keyboard before reading standard input
if (fast && !isatty(0)) {
grabkeyboard();
readstdin();
} else {
readstdin();
grabkeyboard();
}
if (fast && !isatty(0)) {
grabkeyboard();
readstdin();
} else {
readstdin();
grabkeyboard();
}
// set default values
#if USEIMAGE
#if USEIMAGE
if (!imagew || !imageh || !imageg) {
imagew = imagewidth;
imageh = imageheight;
imagegaps = imagegaps;
}
#endif
#endif
setupdisplay(); // set up display and create window
eventloop(); // function is a loop which checks X11 events and calls other functions accordingly
setupdisplay(); // set up display and create window
eventloop(); // function is a loop which checks X11 events and calls other functions accordingly
return 1; // should be unreachable
return 1; // should be unreachable
}