forked from speedie/spmenu
indent lots of code using vim gg=G
This commit is contained in:
parent
fc8d12cd0a
commit
5efe236380
38
keybinds.h
38
keybinds.h
|
@ -22,9 +22,9 @@ static Key keys[] = {
|
||||||
{ -1, 0, XK_Right, movecursor, {.i = +1 } },
|
{ -1, 0, XK_Right, movecursor, {.i = +1 } },
|
||||||
{ -1, Ctrl|Shift, XK_p, setprofile, {0} },
|
{ -1, Ctrl|Shift, XK_p, setprofile, {0} },
|
||||||
|
|
||||||
/* normal mode */
|
/* normal mode */
|
||||||
{ 0, 0, XK_i, switchmode, {0} },
|
{ 0, 0, XK_i, switchmode, {0} },
|
||||||
{ 0, 0, XK_slash, switchmode, {0} },
|
{ 0, 0, XK_slash, switchmode, {0} },
|
||||||
{ 0, Ctrl, XK_equal, setimgsize, {.i = +1 } },
|
{ 0, Ctrl, XK_equal, setimgsize, {.i = +1 } },
|
||||||
{ 0, Ctrl, XK_minus, setimgsize, {.i = -1 } },
|
{ 0, Ctrl, XK_minus, setimgsize, {.i = -1 } },
|
||||||
{ 0, 0, XK_equal, setimgsize, {.i = +10 } },
|
{ 0, 0, XK_equal, setimgsize, {.i = +10 } },
|
||||||
|
@ -43,20 +43,20 @@ static Key keys[] = {
|
||||||
{ 0, 0, XK_t, toggleimg, {0} },
|
{ 0, 0, XK_t, toggleimg, {0} },
|
||||||
{ 0, 0, XK_h, flipimg, {.i = 1 } },
|
{ 0, 0, XK_h, flipimg, {.i = 1 } },
|
||||||
{ 0, 0, XK_v, flipimg, {.i = 0 } },
|
{ 0, 0, XK_v, flipimg, {.i = 0 } },
|
||||||
{ 0, 0, XK_k, moveup, {0} },
|
{ 0, 0, XK_k, moveup, {0} },
|
||||||
{ 0, 0, XK_j, movedown, {0} },
|
{ 0, 0, XK_j, movedown, {0} },
|
||||||
{ 0, 0, XK_h, moveleft, {0} },
|
{ 0, 0, XK_h, moveleft, {0} },
|
||||||
{ 0, 0, XK_l, moveright, {0} },
|
{ 0, 0, XK_l, moveright, {0} },
|
||||||
{ 0, Ctrl, XK_u, moveup, {.i = 5 } },
|
{ 0, Ctrl, XK_u, moveup, {.i = 5 } },
|
||||||
{ 0, Ctrl, XK_d, movedown, {.i = 5 } },
|
{ 0, Ctrl, XK_d, movedown, {.i = 5 } },
|
||||||
{ 0, Ctrl, XK_k, setlines, {.i = +1 } },
|
{ 0, Ctrl, XK_k, setlines, {.i = +1 } },
|
||||||
{ 0, Ctrl, XK_j, setlines, {.i = -1 } },
|
{ 0, Ctrl, XK_j, setlines, {.i = -1 } },
|
||||||
{ 0, Ctrl|Alt|Shift, XK_k, setlines, {.i = +5 } },
|
{ 0, Ctrl|Alt|Shift, XK_k, setlines, {.i = +5 } },
|
||||||
{ 0, Ctrl|Alt|Shift, XK_j, setlines, {.i = -5 } },
|
{ 0, Ctrl|Alt|Shift, XK_j, setlines, {.i = -5 } },
|
||||||
{ 0, Ctrl, XK_h, setcolumns, {.i = +1 } },
|
{ 0, Ctrl, XK_h, setcolumns, {.i = +1 } },
|
||||||
{ 0, Ctrl, XK_l, setcolumns, {.i = -1 } },
|
{ 0, Ctrl, XK_l, setcolumns, {.i = -1 } },
|
||||||
{ 0, Ctrl|Alt|Shift, XK_h, setcolumns, {.i = +5 } },
|
{ 0, Ctrl|Alt|Shift, XK_h, setcolumns, {.i = +5 } },
|
||||||
{ 0, Ctrl|Alt|Shift, XK_l, setcolumns, {.i = -5 } },
|
{ 0, Ctrl|Alt|Shift, XK_l, setcolumns, {.i = -5 } },
|
||||||
{ 0, 0, XK_u, togglehighlight, {0} },
|
{ 0, 0, XK_u, togglehighlight, {0} },
|
||||||
{ 0, Ctrl|Shift, XK_h, viewhist, {0} },
|
{ 0, Ctrl|Shift, XK_h, viewhist, {0} },
|
||||||
{ 0, 0, XK_d, clear, {0} },
|
{ 0, 0, XK_d, clear, {0} },
|
||||||
|
@ -71,6 +71,6 @@ static Key keys[] = {
|
||||||
{ 0, Alt, XK_p, navhistory, {.i = -1 } },
|
{ 0, Alt, XK_p, navhistory, {.i = -1 } },
|
||||||
{ 0, Alt, XK_n, navhistory, {.i = +1 } },
|
{ 0, Alt, XK_n, navhistory, {.i = +1 } },
|
||||||
|
|
||||||
/* insert mode */
|
/* insert mode */
|
||||||
{ 1, 0, XK_Escape, switchmode, {0} },
|
{ 1, 0, XK_Escape, switchmode, {0} },
|
||||||
};
|
};
|
||||||
|
|
310
libs/arg.c
310
libs/arg.c
|
@ -4,34 +4,34 @@ void moveleft(Arg *arg) {
|
||||||
int argu = arg->i ? arg->i : 1;
|
int argu = arg->i ? arg->i : 1;
|
||||||
|
|
||||||
if (columns > 1) {
|
if (columns > 1) {
|
||||||
if (!sel)
|
if (!sel)
|
||||||
return;
|
return;
|
||||||
tmpsel = sel;
|
tmpsel = sel;
|
||||||
for (i = 0; i < lines; i++) {
|
for (i = 0; i < lines; i++) {
|
||||||
if (!tmpsel->left || tmpsel->left->right != tmpsel) {
|
if (!tmpsel->left || tmpsel->left->right != tmpsel) {
|
||||||
if (offscreen)
|
if (offscreen)
|
||||||
drawmenu();
|
drawmenu();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tmpsel == curr)
|
if (tmpsel == curr)
|
||||||
offscreen = 1;
|
offscreen = 1;
|
||||||
tmpsel = tmpsel->left;
|
tmpsel = tmpsel->left;
|
||||||
}
|
}
|
||||||
sel = tmpsel;
|
sel = tmpsel;
|
||||||
if (offscreen) {
|
if (offscreen) {
|
||||||
for (int j = 0; j < argu; j++) {
|
for (int j = 0; j < argu; j++) {
|
||||||
curr = prev;
|
curr = prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drawmenu();
|
drawmenu();
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cursor > 0 && (!sel || !sel->left || lines > 0)) {
|
if (cursor > 0 && (!sel || !sel->left || lines > 0)) {
|
||||||
cursor = nextrune(-1);
|
cursor = nextrune(-1);
|
||||||
drawmenu();
|
drawmenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void moveright(Arg *arg) {
|
void moveright(Arg *arg) {
|
||||||
|
@ -40,46 +40,46 @@ void moveright(Arg *arg) {
|
||||||
int argu = arg->i ? arg->i : 1;
|
int argu = arg->i ? arg->i : 1;
|
||||||
|
|
||||||
if (columns > 1) {
|
if (columns > 1) {
|
||||||
if (!sel)
|
if (!sel)
|
||||||
return;
|
return;
|
||||||
tmpsel = sel;
|
tmpsel = sel;
|
||||||
for (i = 0; i < lines; i++) {
|
for (i = 0; i < lines; i++) {
|
||||||
if (!tmpsel->right || tmpsel->right->left != tmpsel) {
|
if (!tmpsel->right || tmpsel->right->left != tmpsel) {
|
||||||
if (offscreen)
|
if (offscreen)
|
||||||
drawmenu();
|
drawmenu();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tmpsel = tmpsel->right;
|
tmpsel = tmpsel->right;
|
||||||
if (tmpsel == next)
|
if (tmpsel == next)
|
||||||
offscreen = 1;
|
offscreen = 1;
|
||||||
}
|
}
|
||||||
sel = tmpsel;
|
sel = tmpsel;
|
||||||
if (offscreen) {
|
if (offscreen) {
|
||||||
for (int j = 0; j < argu; j++)
|
for (int j = 0; j < argu; j++)
|
||||||
curr = next;
|
curr = next;
|
||||||
}
|
}
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
}
|
}
|
||||||
|
|
||||||
drawmenu();
|
drawmenu();
|
||||||
|
|
||||||
if (text[cursor] != '\0') {
|
if (text[cursor] != '\0') {
|
||||||
cursor = nextrune(+1);
|
cursor = nextrune(+1);
|
||||||
drawmenu();
|
drawmenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void movedown(Arg *arg) {
|
void movedown(Arg *arg) {
|
||||||
int argu = arg->i ? arg->i : 1;
|
int argu = arg->i ? arg->i : 1;
|
||||||
|
|
||||||
for (int j = 0; j < argu; j++) {
|
for (int j = 0; j < argu; j++) {
|
||||||
if (sel && sel->right && (sel = sel->right) == next) {
|
if (sel && sel->right && (sel = sel->right) == next) {
|
||||||
curr = next;
|
curr = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
drawmenu();
|
drawmenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void moveup(Arg *arg) {
|
void moveup(Arg *arg) {
|
||||||
|
@ -87,31 +87,31 @@ void moveup(Arg *arg) {
|
||||||
|
|
||||||
for (int j = 0; j < argu; j++) {
|
for (int j = 0; j < argu; j++) {
|
||||||
if (sel && sel->left && (sel = sel->left)->right == curr) {
|
if (sel && sel->left && (sel = sel->left)->right == curr) {
|
||||||
curr = prev;
|
curr = prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
drawmenu();
|
drawmenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void complete(Arg *arg) {
|
void complete(Arg *arg) {
|
||||||
if (hideitem) return;
|
if (hideitem) return;
|
||||||
|
|
||||||
strncpy(text, sel->clntext, sizeof text - 1);
|
strncpy(text, sel->clntext, sizeof text - 1);
|
||||||
text[sizeof text - 1] = '\0';
|
text[sizeof text - 1] = '\0';
|
||||||
cursor = strlen(text);
|
cursor = strlen(text);
|
||||||
|
|
||||||
match();
|
match();
|
||||||
drawmenu();
|
drawmenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void movenext(Arg *arg) {
|
void movenext(Arg *arg) {
|
||||||
if (!next)
|
if (!next)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sel = curr = next;
|
sel = curr = next;
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
drawmenu();
|
drawmenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,35 +125,35 @@ void moveprev(Arg *arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void movestart(Arg *arg) {
|
void movestart(Arg *arg) {
|
||||||
if (sel == matches) {
|
if (sel == matches) {
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
drawmenu();
|
drawmenu();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sel = curr = matches;
|
sel = curr = matches;
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
drawmenu();
|
drawmenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void moveend(Arg *arg) {
|
void moveend(Arg *arg) {
|
||||||
if (text[cursor] != '\0') {
|
if (text[cursor] != '\0') {
|
||||||
cursor = strlen(text);
|
cursor = strlen(text);
|
||||||
drawmenu();
|
drawmenu();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next) {
|
if (next) {
|
||||||
curr = matchend;
|
curr = matchend;
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
curr = prev;
|
curr = prev;
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
|
|
||||||
while (next && (curr = curr->right))
|
while (next && (curr = curr->right))
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
}
|
}
|
||||||
|
|
||||||
sel = matchend;
|
sel = matchend;
|
||||||
drawmenu();
|
drawmenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,8 +166,8 @@ void paste(Arg *arg) {
|
||||||
clipboard = clip;
|
clipboard = clip;
|
||||||
}
|
}
|
||||||
|
|
||||||
XConvertSelection(dpy, clipboard, utf8, utf8, win, CurrentTime);
|
XConvertSelection(dpy, clipboard, utf8, utf8, win, CurrentTime);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,32 +175,32 @@ void viewhist(Arg *arg) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (histfile) {
|
if (histfile) {
|
||||||
if (!backup_items) {
|
if (!backup_items) {
|
||||||
backup_items = items;
|
backup_items = items;
|
||||||
items = calloc(histsz + 1, sizeof(struct item));
|
items = calloc(histsz + 1, sizeof(struct item));
|
||||||
|
|
||||||
if (!items) {
|
if (!items) {
|
||||||
die("spmenu: cannot allocate memory");
|
die("spmenu: cannot allocate memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < histsz; i++) {
|
for (i = 0; i < histsz; i++) {
|
||||||
items[i].text = history[i];
|
items[i].text = history[i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
free(items);
|
free(items);
|
||||||
items = backup_items;
|
items = backup_items;
|
||||||
backup_items = NULL;
|
backup_items = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match();
|
match();
|
||||||
drawmenu();
|
drawmenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void deleteword(Arg *arg) {
|
void deleteword(Arg *arg) {
|
||||||
if (cursor == 0) return;
|
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);
|
insert(NULL, nextrune(-1) - cursor);
|
||||||
} while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) {
|
} while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) {
|
||||||
insert(NULL, nextrune(-1) - cursor);
|
insert(NULL, nextrune(-1) - cursor);
|
||||||
|
@ -211,32 +211,32 @@ void deleteword(Arg *arg) {
|
||||||
|
|
||||||
void moveword(Arg *arg) {
|
void moveword(Arg *arg) {
|
||||||
if (arg->i < 0) { // move cursor to the start of the word
|
if (arg->i < 0) { // move cursor to the start of the word
|
||||||
while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) {
|
while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) {
|
||||||
cursor = nextrune(-1);
|
cursor = nextrune(-1);
|
||||||
} while (cursor > 0 && !strchr(worddelimiters, text[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
|
} else { // move cursor to the end of the word
|
||||||
while (text[cursor] && strchr(worddelimiters, text[cursor])) {
|
while (text[cursor] && strchr(worddelimiters, text[cursor])) {
|
||||||
cursor = nextrune(+1);
|
cursor = nextrune(+1);
|
||||||
} while (text[cursor] && !strchr(worddelimiters, text[cursor])) {
|
} while (text[cursor] && !strchr(worddelimiters, text[cursor])) {
|
||||||
cursor = nextrune(+1);
|
cursor = nextrune(+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drawmenu();
|
drawmenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void movecursor(Arg *arg) {
|
void movecursor(Arg *arg) {
|
||||||
if (arg->i < 0) {
|
if (arg->i < 0) {
|
||||||
if (cursor > 0) {
|
if (cursor > 0) {
|
||||||
cursor = nextrune(-1);
|
cursor = nextrune(-1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (text[cursor]) {
|
if (text[cursor]) {
|
||||||
cursor = nextrune(+1);
|
cursor = nextrune(+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drawmenu();
|
drawmenu();
|
||||||
}
|
}
|
||||||
|
@ -272,8 +272,8 @@ void selectitem(Arg *arg) {
|
||||||
puts(selection);
|
puts(selection);
|
||||||
savehistory(selection);
|
savehistory(selection);
|
||||||
|
|
||||||
cleanup();
|
cleanup();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void navhistory(Arg *arg) {
|
void navhistory(Arg *arg) {
|
||||||
|
@ -304,53 +304,53 @@ void clearins(Arg *arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void quit(Arg *arg) {
|
void quit(Arg *arg) {
|
||||||
cleanup();
|
cleanup();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void savehistory(char *input) {
|
void savehistory(char *input) {
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
if (!histfile ||
|
if (!histfile ||
|
||||||
0 == maxhist ||
|
0 == maxhist ||
|
||||||
0 == strlen(input)) {
|
0 == strlen(input)) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
fp = fopen(histfile, "w");
|
fp = fopen(histfile, "w");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
die("spmenu: failed to open %s", histfile);
|
die("spmenu: failed to open %s", histfile);
|
||||||
}
|
}
|
||||||
for (i = histsz < maxhist ? 0 : histsz - maxhist; i < histsz; i++) {
|
for (i = histsz < maxhist ? 0 : histsz - maxhist; i < histsz; i++) {
|
||||||
if (0 >= fprintf(fp, "%s\n", history[i])) {
|
if (0 >= fprintf(fp, "%s\n", history[i])) {
|
||||||
die("spmenu: failed to write to %s", histfile);
|
die("spmenu: failed to write to %s", histfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (histsz == 0 || histdup || (histsz > 0 && strcmp(input, history[histsz-1]) != 0)) {
|
if (histsz == 0 || histdup || (histsz > 0 && strcmp(input, history[histsz-1]) != 0)) {
|
||||||
if (0 >= fputs(input, fp)) {
|
if (0 >= fputs(input, fp)) {
|
||||||
die("spmenu: failed to write to %s", histfile);
|
die("spmenu: failed to write to %s", histfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fclose(fp)) {
|
if (fclose(fp)) {
|
||||||
die("spmenu: failed to close file %s", histfile);
|
die("spmenu: failed to close file %s", histfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
for (i = 0; i < histsz; i++) {
|
for (i = 0; i < histsz; i++) {
|
||||||
free(history[i]);
|
free(history[i]);
|
||||||
}
|
}
|
||||||
free(history);
|
free(history);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setimgsize(Arg *arg) {
|
void setimgsize(Arg *arg) {
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
setimagesize(imagewidth + arg->i, imageheight + arg->i);
|
setimagesize(imagewidth + arg->i, imageheight + arg->i);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void flipimg(Arg *arg) {
|
void flipimg(Arg *arg) {
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
|
|
||||||
if (!image) return;
|
if (!image) return;
|
||||||
|
|
||||||
|
@ -358,11 +358,11 @@ void flipimg(Arg *arg) {
|
||||||
|
|
||||||
drawmenu();
|
drawmenu();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void setimgpos(Arg *arg) {
|
void setimgpos(Arg *arg) {
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
if (!image || hideimage) return;
|
if (!image || hideimage) return;
|
||||||
|
|
||||||
if (imageposition < 3) {
|
if (imageposition < 3) {
|
||||||
|
@ -372,11 +372,11 @@ void setimgpos(Arg *arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
drawmenu();
|
drawmenu();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void setimggaps(Arg *arg) {
|
void setimggaps(Arg *arg) {
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
imagegaps += arg->i;
|
imagegaps += arg->i;
|
||||||
|
|
||||||
if (!image || hideimage) return;
|
if (!image || hideimage) return;
|
||||||
|
@ -389,32 +389,32 @@ void setimggaps(Arg *arg) {
|
||||||
imagegaps -= arg->i;
|
imagegaps -= arg->i;
|
||||||
|
|
||||||
drawmenu();
|
drawmenu();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void rotateimg(Arg *arg) {
|
void rotateimg(Arg *arg) {
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
|
|
||||||
if (!image || hideimage) return;
|
if (!image || hideimage) return;
|
||||||
|
|
||||||
rotation += arg->i ? arg->i : 1;
|
rotation += arg->i ? arg->i : 1;
|
||||||
|
|
||||||
drawmenu();
|
drawmenu();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void toggleimg(Arg *arg) {
|
void toggleimg(Arg *arg) {
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
|
|
||||||
hideimage = !hideimage;
|
hideimage = !hideimage;
|
||||||
|
|
||||||
drawmenu();
|
drawmenu();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void defaultimg(Arg *arg) {
|
void defaultimg(Arg *arg) {
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
|
|
||||||
if (hideimage || !image) return;
|
if (hideimage || !image) return;
|
||||||
|
|
||||||
|
@ -425,7 +425,7 @@ void defaultimg(Arg *arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
drawmenu();
|
drawmenu();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void setlines(Arg *arg) {
|
void setlines(Arg *arg) {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
typedef union {
|
typedef union {
|
||||||
int i; // integer
|
int i; // integer
|
||||||
unsigned int ui; // unsigned int
|
unsigned int ui; // unsigned int
|
||||||
float f; // float
|
float f; // float
|
||||||
const void *v; // void
|
const void *v; // void
|
||||||
const char *c; // char
|
const char *c; // char
|
||||||
} Arg;
|
} Arg;
|
||||||
|
|
||||||
|
|
890
libs/argv.c
890
libs/argv.c
File diff suppressed because it is too large
Load diff
104
libs/client.c
104
libs/client.c
|
@ -1,7 +1,7 @@
|
||||||
void prepare_window_size(void) {
|
void prepare_window_size(void) {
|
||||||
// set horizontal and vertical padding
|
// set horizontal and vertical padding
|
||||||
sp = menupaddingh;
|
sp = menupaddingh;
|
||||||
vp = (menuposition == 1) ? menupaddingv : - menupaddingv;
|
vp = (menuposition == 1) ? menupaddingv : - menupaddingv;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,9 @@ void create_window(int x, int y, int w, int h) {
|
||||||
XSetWindowAttributes swa;
|
XSetWindowAttributes swa;
|
||||||
|
|
||||||
swa.override_redirect = managed ? False : True;
|
swa.override_redirect = managed ? False : True;
|
||||||
swa.background_pixel = 0;
|
swa.background_pixel = 0;
|
||||||
swa.colormap = cmap;
|
swa.colormap = cmap;
|
||||||
swa.event_mask =
|
swa.event_mask =
|
||||||
ExposureMask | // mapping the drawing
|
ExposureMask | // mapping the drawing
|
||||||
KeyPressMask | // keypresses
|
KeyPressMask | // keypresses
|
||||||
VisibilityChangeMask | // whether or not client is visible
|
VisibilityChangeMask | // whether or not client is visible
|
||||||
|
@ -21,8 +21,8 @@ void create_window(int x, int y, int w, int h) {
|
||||||
|
|
||||||
// create client
|
// create client
|
||||||
win = XCreateWindow(dpy, root, x, y, w, h, borderwidth,
|
win = XCreateWindow(dpy, root, x, y, w, h, borderwidth,
|
||||||
depth, InputOutput, visual,
|
depth, InputOutput, visual,
|
||||||
CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &swa);
|
CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &swa);
|
||||||
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -33,7 +33,7 @@ void set_window(void) {
|
||||||
|
|
||||||
// set border and class
|
// set border and class
|
||||||
XSetWindowBorder(dpy, win, scheme[SchemeBorder][ColBg].pixel);
|
XSetWindowBorder(dpy, win, scheme[SchemeBorder][ColBg].pixel);
|
||||||
XSetClassHint(dpy, win, &ch);
|
XSetClassHint(dpy, win, &ch);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -46,13 +46,13 @@ void set_prop(void) {
|
||||||
void resizeclient(void) {
|
void resizeclient(void) {
|
||||||
int omh = mh;
|
int omh = mh;
|
||||||
int x, y;
|
int x, y;
|
||||||
#if USEXINERAMA
|
#if USEXINERAMA
|
||||||
int j, di, a, n, area = 0;
|
int j, di, a, n, area = 0;
|
||||||
XineramaScreenInfo *info;
|
XineramaScreenInfo *info;
|
||||||
Window pw;
|
Window pw;
|
||||||
unsigned int du;
|
unsigned int du;
|
||||||
Window w, dw, *dws;
|
Window w, dw, *dws;
|
||||||
#endif
|
#endif
|
||||||
XWindowAttributes wa;
|
XWindowAttributes wa;
|
||||||
struct item *item;
|
struct item *item;
|
||||||
int itemCount = 0;
|
int itemCount = 0;
|
||||||
|
@ -62,36 +62,36 @@ void resizeclient(void) {
|
||||||
itemCount++;
|
itemCount++;
|
||||||
|
|
||||||
bh = MAX(drw->font->h, drw->font->h + 2 + lineheight);
|
bh = MAX(drw->font->h, drw->font->h + 2 + lineheight);
|
||||||
lines = MIN(itemCount, MAX(lines, 0));
|
lines = MIN(itemCount, MAX(lines, 0));
|
||||||
reallines = lines;
|
reallines = lines;
|
||||||
|
|
||||||
// resize client to image height
|
// resize client to image height
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
if (image) resizetoimageheight(imageheight);
|
if (image) resizetoimageheight(imageheight);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mh = (lines + 1) * bh + 2 * menumarginv;
|
mh = (lines + 1) * bh + 2 * menumarginv;
|
||||||
|
|
||||||
// init xinerama screens
|
// init xinerama screens
|
||||||
#if USEXINERAMA
|
#if USEXINERAMA
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
|
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
|
||||||
XGetInputFocus(dpy, &w, &di);
|
XGetInputFocus(dpy, &w, &di);
|
||||||
if (mon >= 0 && mon < n) {
|
if (mon >= 0 && mon < n) {
|
||||||
i = mon;
|
i = mon;
|
||||||
} else if (w != root && w != PointerRoot && w != None) {
|
} else if (w != root && w != PointerRoot && w != None) {
|
||||||
do {
|
do {
|
||||||
if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
|
if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
|
||||||
XFree(dws);
|
XFree(dws);
|
||||||
} while (w != root && w != pw);
|
} while (w != root && w != pw);
|
||||||
if (XGetWindowAttributes(dpy, pw, &wa)) {
|
if (XGetWindowAttributes(dpy, pw, &wa)) {
|
||||||
for (j = 0; j < n; j++) {
|
for (j = 0; j < n; j++) {
|
||||||
if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
|
if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
|
||||||
area = a;
|
area = a;
|
||||||
i = j;
|
i = j;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) {
|
if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) {
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
|
@ -103,33 +103,33 @@ void resizeclient(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate x/y position
|
// calculate x/y position
|
||||||
if (menuposition == 2) { // centered
|
if (menuposition == 2) { // centered
|
||||||
mw = MIN(MAX(max_textw() + promptw, minwidth), info[i].width);
|
mw = MIN(MAX(max_textw() + promptw, minwidth), info[i].width);
|
||||||
x = info[i].x_org + ((info[i].width - mw) / 2);
|
x = info[i].x_org + ((info[i].width - mw) / 2);
|
||||||
y = info[i].y_org + ((info[i].height - mh) / 2);
|
y = info[i].y_org + ((info[i].height - mh) / 2);
|
||||||
} else { // top or bottom
|
} else { // top or bottom
|
||||||
x = info[i].x_org + xpos;
|
x = info[i].x_org + xpos;
|
||||||
y = info[i].y_org + (menuposition ? 0 : info[i].height - mh - ypos);
|
y = info[i].y_org + (menuposition ? 0 : info[i].height - mh - ypos);
|
||||||
mw = (menuwidth>0 ? menuwidth : info[i].width);
|
mw = (menuwidth>0 ? menuwidth : info[i].width);
|
||||||
}
|
}
|
||||||
|
|
||||||
XFree(info);
|
XFree(info);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (!XGetWindowAttributes(dpy, parentwin, &wa))
|
if (!XGetWindowAttributes(dpy, parentwin, &wa))
|
||||||
die("spmenu: could not get embedding window attributes: 0x%lx",
|
die("spmenu: could not get embedding window attributes: 0x%lx",
|
||||||
parentwin); // die because unable to get attributes for the parent window
|
parentwin); // die because unable to get attributes for the parent window
|
||||||
if (menuposition == 2) { // centered
|
if (menuposition == 2) { // centered
|
||||||
mw = MIN(MAX(max_textw() + promptw, minwidth), wa.width);
|
mw = MIN(MAX(max_textw() + promptw, minwidth), wa.width);
|
||||||
x = (wa.width - mw) / 2;
|
x = (wa.width - mw) / 2;
|
||||||
y = (wa.height - mh) / 2;
|
y = (wa.height - mh) / 2;
|
||||||
} else { // top or bottom
|
} else { // top or bottom
|
||||||
x = 0;
|
x = 0;
|
||||||
y = menuposition ? 0 : wa.height - mh - ypos;
|
y = menuposition ? 0 : wa.height - mh - ypos;
|
||||||
mw = wa.width;
|
mw = wa.width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// why have an empty line? when there's nothing to draw there anyway?
|
// why have an empty line? when there's nothing to draw there anyway?
|
||||||
if (hideprompt && hideinput && hidemode && hidematchcount)
|
if (hideprompt && hideinput && hidemode && hidematchcount)
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
// alpha array
|
// alpha array
|
||||||
static unsigned int alphas[][2] = {
|
static unsigned int alphas[][2] = {
|
||||||
// fg bg
|
// fg bg
|
||||||
[SchemeLArrow] = { 255, 200 },
|
[SchemeLArrow] = { 255, 200 },
|
||||||
[SchemeRArrow] = { 255, 200 },
|
[SchemeRArrow] = { 255, 200 },
|
||||||
[SchemeItemNorm] = { 255, 200 },
|
[SchemeItemNorm] = { 255, 200 },
|
||||||
[SchemeItemSel] = { 255, 200 },
|
[SchemeItemSel] = { 255, 200 },
|
||||||
[SchemeItemNormPri] = { 255, 200 },
|
[SchemeItemNormPri] = { 255, 200 },
|
||||||
[SchemeItemSelPri] = { 255, 200 },
|
[SchemeItemSelPri] = { 255, 200 },
|
||||||
[SchemeMenu] = { 255, 200 },
|
[SchemeMenu] = { 255, 200 },
|
||||||
[SchemeInput] = { 255, 200 },
|
[SchemeInput] = { 255, 200 },
|
||||||
[SchemePrompt] = { 255, 200 },
|
[SchemePrompt] = { 255, 200 },
|
||||||
[SchemeNormHighlight] = { 255, 200 },
|
[SchemeNormHighlight] = { 255, 200 },
|
||||||
[SchemeSelHighlight] = { 255, 200 },
|
[SchemeSelHighlight] = { 255, 200 },
|
||||||
[SchemeMode] = { 255, 200 },
|
[SchemeMode] = { 255, 200 },
|
||||||
[SchemeCaret] = { 255, 200 },
|
[SchemeCaret] = { 255, 200 },
|
||||||
[SchemeNumber] = { 255, 200 },
|
[SchemeNumber] = { 255, 200 },
|
||||||
|
@ -21,17 +21,17 @@ static unsigned int alphas[][2] = {
|
||||||
|
|
||||||
// colorscheme array
|
// colorscheme array
|
||||||
static char *colors[][2] = {
|
static char *colors[][2] = {
|
||||||
// fg bg
|
// fg bg
|
||||||
[SchemeLArrow] = { col_larrowfg, col_larrowbg },
|
[SchemeLArrow] = { col_larrowfg, col_larrowbg },
|
||||||
[SchemeRArrow] = { col_rarrowfg, col_rarrowbg },
|
[SchemeRArrow] = { col_rarrowfg, col_rarrowbg },
|
||||||
[SchemeItemNorm] = { col_itemnormfg, col_itemnormbg },
|
[SchemeItemNorm] = { col_itemnormfg, col_itemnormbg },
|
||||||
[SchemeItemSel] = { col_itemselfg, col_itemselbg },
|
[SchemeItemSel] = { col_itemselfg, col_itemselbg },
|
||||||
[SchemeItemNormPri] = { col_itemnormprifg, col_itemnormpribg },
|
[SchemeItemNormPri] = { col_itemnormprifg, col_itemnormpribg },
|
||||||
[SchemeItemSelPri] = { col_itemselprifg, col_itemselpribg },
|
[SchemeItemSelPri] = { col_itemselprifg, col_itemselpribg },
|
||||||
[SchemeInput] = { col_inputfg, col_inputbg, },
|
[SchemeInput] = { col_inputfg, col_inputbg, },
|
||||||
[SchemeMenu] = { NULL, col_menu },
|
[SchemeMenu] = { NULL, col_menu },
|
||||||
[SchemeCaps] = { col_capsfg, col_capsbg },
|
[SchemeCaps] = { col_capsfg, col_capsbg },
|
||||||
[SchemePrompt] = { col_promptfg, col_promptbg },
|
[SchemePrompt] = { col_promptfg, col_promptbg },
|
||||||
[SchemeNormHighlight] = { col_hlnormfg, col_hlnormbg },
|
[SchemeNormHighlight] = { col_hlnormfg, col_hlnormbg },
|
||||||
[SchemeSelHighlight] = { col_hlselfg, col_hlselbg },
|
[SchemeSelHighlight] = { col_hlselfg, col_hlselbg },
|
||||||
[SchemeCaret] = { col_caretfg, col_caretbg },
|
[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
|
// sgr color array, first 16 colors are defined in the config, the rest are 256 colors
|
||||||
static char *textcolors[] = {
|
static char *textcolors[] = {
|
||||||
col_sgr0,
|
col_sgr0,
|
||||||
col_sgr1,
|
col_sgr1,
|
||||||
col_sgr2,
|
col_sgr2,
|
||||||
col_sgr3,
|
col_sgr3,
|
||||||
col_sgr4,
|
col_sgr4,
|
||||||
col_sgr5,
|
col_sgr5,
|
||||||
col_sgr6,
|
col_sgr6,
|
||||||
col_sgr7,
|
col_sgr7,
|
||||||
col_sgr8,
|
col_sgr8,
|
||||||
col_sgr9,
|
col_sgr9,
|
||||||
col_sgr10,
|
col_sgr10,
|
||||||
col_sgr11,
|
col_sgr11,
|
||||||
col_sgr12,
|
col_sgr12,
|
||||||
col_sgr13,
|
col_sgr13,
|
||||||
col_sgr14,
|
col_sgr14,
|
||||||
col_sgr15,
|
col_sgr15,
|
||||||
"#00005f",
|
"#00005f",
|
||||||
"#000087",
|
"#000087",
|
||||||
"#0000af",
|
"#0000af",
|
||||||
|
|
|
@ -32,11 +32,11 @@ void conf_init(void) {
|
||||||
sprintf(cfgfile, "%s/%s", xdg_conf, "spmenu/spmenu.conf");
|
sprintf(cfgfile, "%s/%s", xdg_conf, "spmenu/spmenu.conf");
|
||||||
}
|
}
|
||||||
} else { // custom config path
|
} else { // custom config path
|
||||||
if (!(cfgfile = malloc(snprintf(NULL, 0, "%s", argconf) + 1))) {
|
if (!(cfgfile = malloc(snprintf(NULL, 0, "%s", argconf) + 1))) {
|
||||||
die("spmenu: failed to malloc cfgfile");
|
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.
|
// 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
|
// attempt to read config file to cfg
|
||||||
if (!config_read_file(&cfg, cfgfile)) {
|
if (!config_read_file(&cfg, cfgfile)) {
|
||||||
// invalid configuration, but let's try to read it anyway
|
// invalid configuration, but let's try to read it anyway
|
||||||
fprintf(stdout, "spmenu: Invalid configuration.\n");
|
fprintf(stdout, "spmenu: Invalid configuration.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// load options spmenu.window
|
// load options spmenu.window
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
|
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
|
||||||
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
|
#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)) \
|
#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 LENGTH(X) (sizeof X / sizeof X[0])
|
||||||
#define TEXTW(X) (drw_font_getwidth(drw, (X), False) + lrpad)
|
#define TEXTW(X) (drw_font_getwidth(drw, (X), False) + lrpad)
|
||||||
#define TEXTWM(X) (drw_font_getwidth(drw, (X), True) + lrpad)
|
#define TEXTWM(X) (drw_font_getwidth(drw, (X), True) + lrpad)
|
||||||
|
|
364
libs/draw.c
364
libs/draw.c
|
@ -1,52 +1,52 @@
|
||||||
void
|
void
|
||||||
drawhighlights(struct item *item, int x, int y, int w, int p)
|
drawhighlights(struct item *item, int x, int y, int w, int p)
|
||||||
{
|
{
|
||||||
int i, indent;
|
int i, indent;
|
||||||
char *highlight;
|
char *highlight;
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
// limitation in order to prevent highlighting from drawing when the text isn't visible
|
// limitation in order to prevent highlighting from drawing when the text isn't visible
|
||||||
if (columns > 5 && lines > 1) return;
|
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
|
drw_setscheme(drw, scheme[item == sel
|
||||||
? SchemeSelHighlight
|
? SchemeSelHighlight
|
||||||
: SchemeNormHighlight]);
|
: SchemeNormHighlight]);
|
||||||
for (i = 0, highlight = itemtext; *highlight && text[i];) {
|
for (i = 0, highlight = itemtext; *highlight && text[i];) {
|
||||||
if (((fuzzy && !fstrncmp(&(*highlight), &text[i], 1)) || (!fuzzy && *highlight == text[i]))) {
|
if (((fuzzy && !fstrncmp(&(*highlight), &text[i], 1)) || (!fuzzy && *highlight == text[i]))) {
|
||||||
c = *highlight;
|
c = *highlight;
|
||||||
*highlight = '\0';
|
*highlight = '\0';
|
||||||
indent = TEXTW(itemtext) - lrpad;
|
indent = TEXTW(itemtext) - lrpad;
|
||||||
*highlight = c;
|
*highlight = c;
|
||||||
|
|
||||||
// highlight character
|
// highlight character
|
||||||
c = highlight[1];
|
c = highlight[1];
|
||||||
highlight[1] = '\0';
|
highlight[1] = '\0';
|
||||||
drw_text(
|
drw_text(
|
||||||
drw,
|
drw,
|
||||||
x + indent + (p),
|
x + indent + (p),
|
||||||
y,
|
y,
|
||||||
MIN(w - indent - lrpad, TEXTW(highlight) - lrpad),
|
MIN(w - indent - lrpad, TEXTW(highlight) - lrpad),
|
||||||
bh, 0, highlight, 0, pango_highlight ? True : False);
|
bh, 0, highlight, 0, pango_highlight ? True : False);
|
||||||
highlight[1] = c;
|
highlight[1] = c;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
highlight++;
|
highlight++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drawitemtext(struct item *item, int x, int y, int w)
|
drawitemtext(struct item *item, int x, int y, int w)
|
||||||
{
|
{
|
||||||
char buffer[MAXITEMLENGTH]; // buffer containing item text
|
char buffer[MAXITEMLENGTH]; // buffer containing item text
|
||||||
Clr scm[2]; // color scheme
|
Clr scm[2]; // color scheme
|
||||||
int leftpadding = lrpad / 2; // padding
|
int leftpadding = lrpad / 2; // padding
|
||||||
int wr, rd; // character
|
int wr, rd; // character
|
||||||
int fg = 7; // foreground
|
int fg = 7; // foreground
|
||||||
int bg = 0; // background
|
int bg = 0; // background
|
||||||
int bgfg = 0; // both
|
int bgfg = 0; // both
|
||||||
int ignore = 0; // ignore colors
|
int ignore = 0; // ignore colors
|
||||||
int skiphighlight = 0; // skip highlighting
|
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
|
drw_setscheme(drw, scm); // set scheme
|
||||||
|
|
||||||
// parse item text
|
// parse item text
|
||||||
for (wr = 0, rd = 0; item->text[rd]; rd++) {
|
for (wr = 0, rd = 0; item->text[rd]; rd++) {
|
||||||
if (item->text[rd] == '' && item->text[rd + 1] == '[') {
|
if (item->text[rd] == '' && item->text[rd + 1] == '[') {
|
||||||
size_t alen = strspn(item->text + rd + 2, "0123456789;");
|
size_t alen = strspn(item->text + rd + 2, "0123456789;");
|
||||||
if (item->text[rd + alen + 2] == 'm' && sgr) { // last character in sequence is always 'm'
|
if (item->text[rd + alen + 2] == 'm' && sgr) { // last character in sequence is always 'm'
|
||||||
buffer[wr] = '\0';
|
buffer[wr] = '\0';
|
||||||
|
|
||||||
if (!lines) {
|
if (!lines) {
|
||||||
w -= item->text[rd + alen];
|
w -= item->text[rd + alen];
|
||||||
}
|
}
|
||||||
|
|
||||||
apply_fribidi(buffer);
|
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
|
// position and width
|
||||||
x += MIN(w, TEXTW(buffer) - lrpad) + leftpadding;
|
x += MIN(w, TEXTW(buffer) - lrpad) + leftpadding;
|
||||||
w -= MIN(w, TEXTW(buffer) - lrpad) + leftpadding;
|
w -= MIN(w, TEXTW(buffer) - lrpad) + leftpadding;
|
||||||
|
|
||||||
// no highlighting if colored text
|
// no highlighting if colored text
|
||||||
skiphighlight = 1;
|
skiphighlight = 1;
|
||||||
leftpadding = 0;
|
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
|
// parse hex colors in scm, m is always the last character
|
||||||
while (*character != 'm') {
|
while (*character != 'm') {
|
||||||
unsigned nextchar = strtoul(character + 1, &character, 10);
|
unsigned nextchar = strtoul(character + 1, &character, 10);
|
||||||
if (ignore)
|
if (ignore)
|
||||||
continue;
|
continue;
|
||||||
if (bgfg) {
|
if (bgfg) {
|
||||||
if (bgfg < 4 && nextchar == 5) {
|
if (bgfg < 4 && nextchar == 5) {
|
||||||
bgfg <<= 1;
|
bgfg <<= 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (bgfg == 4)
|
if (bgfg == 4)
|
||||||
scm[0] = textclrs[fg = nextchar];
|
scm[0] = textclrs[fg = nextchar];
|
||||||
else if (bgfg == 6)
|
else if (bgfg == 6)
|
||||||
scm[1] = textclrs[bg = nextchar];
|
scm[1] = textclrs[bg = nextchar];
|
||||||
ignore = 1;
|
ignore = 1;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextchar == 1) {
|
if (nextchar == 1) {
|
||||||
fg |= 8;
|
fg |= 8;
|
||||||
scm[0] = textclrs[fg];
|
scm[0] = textclrs[fg];
|
||||||
} else if (nextchar == 22) {
|
} else if (nextchar == 22) {
|
||||||
fg &= ~8;
|
fg &= ~8;
|
||||||
scm[0] = textclrs[fg];
|
scm[0] = textclrs[fg];
|
||||||
} else if (nextchar == 38) {
|
} else if (nextchar == 38) {
|
||||||
bgfg = 2;
|
bgfg = 2;
|
||||||
} else if (nextchar >= 30 && nextchar <= 37) {
|
} else if (nextchar >= 30 && nextchar <= 37) {
|
||||||
fg = nextchar % 10 | (fg & 8);
|
fg = nextchar % 10 | (fg & 8);
|
||||||
scm[0] = textclrs[fg];
|
scm[0] = textclrs[fg];
|
||||||
} else if (nextchar >= 40 && nextchar <= 47) {
|
} else if (nextchar >= 40 && nextchar <= 47) {
|
||||||
bg = nextchar % 10;
|
bg = nextchar % 10;
|
||||||
scm[1] = textclrs[bg];
|
scm[1] = textclrs[bg];
|
||||||
} else if (nextchar == 48) {
|
} else if (nextchar == 48) {
|
||||||
bgfg = 3;
|
bgfg = 3;
|
||||||
} else if (nextchar == 0) {
|
} else if (nextchar == 0) {
|
||||||
if (item == sel) {
|
if (item == sel) {
|
||||||
|
@ -160,25 +160,25 @@ drawitemtext(struct item *item, int x, int y, int w)
|
||||||
// don't color
|
// don't color
|
||||||
if (!coloritems) memcpy(scm, scheme[SchemeItemNorm], sizeof(scm));
|
if (!coloritems) memcpy(scm, scheme[SchemeItemNorm], sizeof(scm));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rd += alen + 2;
|
rd += alen + 2;
|
||||||
wr = 0;
|
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
|
// now draw any non-colored text
|
||||||
apply_fribidi(buffer);
|
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);
|
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
|
// 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;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drawitem(int x, int y, int w)
|
drawitem(int x, int y, int w)
|
||||||
{
|
{
|
||||||
struct item *item;
|
struct item *item;
|
||||||
|
|
||||||
int numberWidth = 0;
|
int numberWidth = 0;
|
||||||
int modeWidth = 0;
|
int modeWidth = 0;
|
||||||
|
@ -210,22 +210,22 @@ drawitem(int x, int y, int w)
|
||||||
if (!strcmp(capstext, ""))
|
if (!strcmp(capstext, ""))
|
||||||
capsWidth = 0;
|
capsWidth = 0;
|
||||||
|
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
int ox = 0; // original x position
|
int ox = 0; // original x position
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// draw items and image
|
// draw items and image
|
||||||
if (lines > 0) {
|
if (lines > 0) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int rx = 0;
|
int rx = 0;
|
||||||
|
|
||||||
// draw image first
|
// draw image first
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
if (!hideimage && longestedge != 0) {
|
if (!hideimage && longestedge != 0) {
|
||||||
rx = ox;
|
rx = ox;
|
||||||
rx += MAX((imagegaps * 2) + imagewidth + menumarginh, indentitems ? x : 0);
|
rx += MAX((imagegaps * 2) + imagewidth + menumarginh, indentitems ? x : 0);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (!indentitems) {
|
if (!indentitems) {
|
||||||
rx = 0;
|
rx = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -234,13 +234,13 @@ drawitem(int x, int y, int w)
|
||||||
|
|
||||||
int itemoverride = 1;
|
int itemoverride = 1;
|
||||||
|
|
||||||
for (item = curr; item != next; item = item->right, i++) {
|
for (item = curr; item != next; item = item->right, i++) {
|
||||||
x = drawitemtext(
|
x = drawitemtext(
|
||||||
item,
|
item,
|
||||||
rx + ((i / lines) * ((mw - rx) / columns)),
|
rx + ((i / lines) * ((mw - rx) / columns)),
|
||||||
y + (((i % lines) + 1) * bh),
|
y + (((i % lines) + 1) * bh),
|
||||||
(mw - rx) / columns
|
(mw - rx) / columns
|
||||||
);
|
);
|
||||||
|
|
||||||
if (item == sel && itemoverride) {
|
if (item == sel && itemoverride) {
|
||||||
itemnumber = i;
|
itemnumber = i;
|
||||||
|
@ -248,9 +248,9 @@ drawitem(int x, int y, int w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// horizontal list
|
// horizontal list
|
||||||
} else if (matches) {
|
} else if (matches) {
|
||||||
x += inputw;
|
x += inputw;
|
||||||
|
|
||||||
w = larrowWidth;
|
w = larrowWidth;
|
||||||
x = drawlarrow(x, y, w);
|
x = drawlarrow(x, y, w);
|
||||||
|
@ -258,7 +258,7 @@ drawitem(int x, int y, int w)
|
||||||
itemnumber = 0;
|
itemnumber = 0;
|
||||||
int itemoverride = 1;
|
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),
|
x = drawitemtext(item, x, y, MIN(pango_item ? TEXTWM(item->text) : TEXTW(item->text),
|
||||||
mw - x -
|
mw - x -
|
||||||
rarrowWidth -
|
rarrowWidth -
|
||||||
|
@ -268,7 +268,7 @@ drawitem(int x, int y, int w)
|
||||||
menumarginh -
|
menumarginh -
|
||||||
2 * sp -
|
2 * sp -
|
||||||
2 * borderwidth
|
2 * borderwidth
|
||||||
));
|
));
|
||||||
|
|
||||||
if (itemoverride) {
|
if (itemoverride) {
|
||||||
itemnumber++;
|
itemnumber++;
|
||||||
|
@ -281,18 +281,18 @@ drawitem(int x, int y, int w)
|
||||||
|
|
||||||
w = rarrowWidth + numberWidth + modeWidth + capsWidth + menumarginh + 2 * sp + 2 * borderwidth;
|
w = rarrowWidth + numberWidth + modeWidth + capsWidth + menumarginh + 2 * sp + 2 * borderwidth;
|
||||||
x = drawrarrow(mw - w, y, w);
|
x = drawrarrow(mw - w, y, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drawprompt(int x, int y, int w)
|
drawprompt(int x, int y, int w)
|
||||||
{
|
{
|
||||||
if (prompt && *prompt && !hideprompt) {
|
if (prompt && *prompt && !hideprompt) {
|
||||||
drw_setscheme(drw, scheme[SchemePrompt]);
|
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) {
|
if (!hidepowerline && powerlineprompt) {
|
||||||
drw_settrans(drw, scheme[SchemePrompt], scheme[SchemeMenu]);
|
drw_settrans(drw, scheme[SchemePrompt], scheme[SchemeMenu]);
|
||||||
|
@ -300,77 +300,77 @@ drawprompt(int x, int y, int w)
|
||||||
|
|
||||||
x += plw;
|
x += plw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drawinput(int x, int y, int w)
|
drawinput(int x, int y, int w)
|
||||||
{
|
{
|
||||||
char *censort; // censor text (password)
|
char *censort; // censor text (password)
|
||||||
unsigned int curpos = 0;
|
unsigned int curpos = 0;
|
||||||
int fh = drw->font->h;
|
int fh = drw->font->h;
|
||||||
|
|
||||||
// draw input
|
// draw input
|
||||||
drw_setscheme(drw, scheme[SchemeInput]);
|
drw_setscheme(drw, scheme[SchemeInput]);
|
||||||
|
|
||||||
if (passwd) {
|
if (passwd) {
|
||||||
censort = ecalloc(1, sizeof(text));
|
censort = ecalloc(1, sizeof(text));
|
||||||
|
|
||||||
for (int i = 0; i < strlen(text); i++)
|
for (int i = 0; i < strlen(text); i++)
|
||||||
memcpy(&censort[i], password, strlen(text));
|
memcpy(&censort[i], password, strlen(text));
|
||||||
|
|
||||||
apply_fribidi(censort);
|
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);
|
free(censort);
|
||||||
} else if (!passwd) {
|
} else if (!passwd) {
|
||||||
apply_fribidi(text);
|
apply_fribidi(text);
|
||||||
drw_text(drw, x, y, w, bh, lrpad / 2, isrtl ? fribidi_text : text, 0, pango_input ? True : False);
|
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) {
|
if ((curpos += lrpad / 2 - 1) < w && !hidecaret && cursorstate) {
|
||||||
drw_setscheme(drw, scheme[SchemeCaret]);
|
drw_setscheme(drw, scheme[SchemeCaret]);
|
||||||
drw_rect(drw, x + curpos, 2 + (bh - fh) / 2 + y, 2, fh - 4, 1, 0);
|
drw_rect(drw, x + curpos, 2 + (bh - fh) / 2 + y, 2, fh - 4, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drawlarrow(int x, int y, int w)
|
drawlarrow(int x, int y, int w)
|
||||||
{
|
{
|
||||||
if (hidelarrow) return x;
|
if (hidelarrow) return x;
|
||||||
|
|
||||||
if (curr->left) { // draw left arrow
|
if (curr->left) { // draw left arrow
|
||||||
drw_setscheme(drw, scheme[SchemeLArrow]);
|
drw_setscheme(drw, scheme[SchemeLArrow]);
|
||||||
drw_text(drw, x, y, w, bh, lrpad / 2, leftarrow, 0, pango_leftarrow ? True : False);
|
drw_text(drw, x, y, w, bh, lrpad / 2, leftarrow, 0, pango_leftarrow ? True : False);
|
||||||
x += w;
|
x += w;
|
||||||
}
|
}
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drawrarrow(int x, int y, int w)
|
drawrarrow(int x, int y, int w)
|
||||||
{
|
{
|
||||||
if (hiderarrow) return x;
|
if (hiderarrow) return x;
|
||||||
|
|
||||||
if (next) { // draw right arrow
|
if (next) { // draw right arrow
|
||||||
drw_setscheme(drw, scheme[SchemeRArrow]);
|
drw_setscheme(drw, scheme[SchemeRArrow]);
|
||||||
drw_text(drw, mw - w, y, w, bh, lrpad / 2, rightarrow, 0, pango_rightarrow ? True : False);
|
drw_text(drw, mw - w, y, w, bh, lrpad / 2, rightarrow, 0, pango_rightarrow ? True : False);
|
||||||
x += w;
|
x += w;
|
||||||
}
|
}
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drawnumber(int x, int y, int w)
|
drawnumber(int x, int y, int w)
|
||||||
{
|
{
|
||||||
if (hidematchcount) return x;
|
if (hidematchcount) return x;
|
||||||
|
@ -395,7 +395,7 @@ drawnumber(int x, int y, int w)
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drawmode(int x, int y, int w)
|
drawmode(int x, int y, int w)
|
||||||
{
|
{
|
||||||
if (!hidemode) { // draw mode indicator
|
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)
|
drawcaps(int x, int y, int w)
|
||||||
{
|
{
|
||||||
if (!w) return x; // not caps lock
|
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)
|
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
|
plw = hidepowerline ? 0 : drw->font->h / 2 + 1; // powerline size
|
||||||
|
|
||||||
// draw menu first using menu scheme
|
// draw menu first using menu scheme
|
||||||
drw_setscheme(drw, scheme[SchemeMenu]);
|
drw_setscheme(drw, scheme[SchemeMenu]);
|
||||||
drw_rect(drw, 0, 0, mw, mh, 1, 1);
|
drw_rect(drw, 0, 0, mw, mh, 1, 1);
|
||||||
|
|
||||||
int numberWidth = 0;
|
int numberWidth = 0;
|
||||||
int modeWidth = 0;
|
int modeWidth = 0;
|
||||||
|
@ -481,53 +481,53 @@ drawmenu(void)
|
||||||
|
|
||||||
// why have an empty line?
|
// why have an empty line?
|
||||||
if ((hideprompt && hideinput && hidemode && hidematchcount && hidecaps
|
if ((hideprompt && hideinput && hidemode && hidematchcount && hidecaps
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
) && (!image || hideimage)) {
|
) && (!image || hideimage)) {
|
||||||
#else
|
#else
|
||||||
)) {
|
)) {
|
||||||
#endif
|
#endif
|
||||||
y -= bh;
|
y -= bh;
|
||||||
mh = (lines + 1) * bh - bh + 2 * menumarginv;
|
mh = (lines + 1) * bh - bh + 2 * menumarginv;
|
||||||
|
|
||||||
if (!win) return;
|
if (!win) return;
|
||||||
|
|
||||||
XResizeWindow(dpy, win, mw - 2 * sp - 2 * borderwidth, mh);
|
XResizeWindow(dpy, win, mw - 2 * sp - 2 * borderwidth, mh);
|
||||||
drw_resize(drw, 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);
|
|
||||||
}
|
|
||||||
|
|
26
libs/event.c
26
libs/event.c
|
@ -1,14 +1,14 @@
|
||||||
void eventloop(void) {
|
void eventloop(void) {
|
||||||
XEvent ev;
|
XEvent ev;
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
int noimg = 0;
|
int noimg = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (!XNextEvent(dpy, &ev)) {
|
while (!XNextEvent(dpy, &ev)) {
|
||||||
if (XFilterEvent(&ev, None))
|
if (XFilterEvent(&ev, None))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch(ev.type) {
|
switch(ev.type) {
|
||||||
case DestroyNotify:
|
case DestroyNotify:
|
||||||
if (ev.xdestroywindow.window != win)
|
if (ev.xdestroywindow.window != win)
|
||||||
break;
|
break;
|
||||||
|
@ -16,9 +16,9 @@ void eventloop(void) {
|
||||||
exit(1);
|
exit(1);
|
||||||
case ButtonPress:
|
case ButtonPress:
|
||||||
buttonpress(&ev);
|
buttonpress(&ev);
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
noimg = 0;
|
noimg = 0;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case MotionNotify: // currently does nothing
|
case MotionNotify: // currently does nothing
|
||||||
break;
|
break;
|
||||||
|
@ -51,7 +51,7 @@ void eventloop(void) {
|
||||||
getcapsstate();
|
getcapsstate();
|
||||||
drawmenu();
|
drawmenu();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listfile) {
|
if (listfile) {
|
||||||
readfile();
|
readfile();
|
||||||
|
@ -70,12 +70,12 @@ void eventloop(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// redraw image on X11 event
|
// redraw image on X11 event
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
if (!noimg) {
|
if (!noimg) {
|
||||||
drawimage();
|
drawimage();
|
||||||
} else {
|
} else {
|
||||||
noimg = 0; // draw it next time
|
noimg = 0; // draw it next time
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
104
libs/history.c
104
libs/history.c
|
@ -1,66 +1,66 @@
|
||||||
void loadhistory(void) {
|
void loadhistory(void) {
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
static size_t cap = 0;
|
static size_t cap = 0;
|
||||||
size_t llen;
|
size_t llen;
|
||||||
char *line;
|
char *line;
|
||||||
|
|
||||||
// no history file, give up like i do with all things in life
|
// no history file, give up like i do with all things in life
|
||||||
if (!histfile) {
|
if (!histfile) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// open history file, return if it failed
|
// open history file, return if it failed
|
||||||
fp = fopen(histfile, "r");
|
fp = fopen(histfile, "r");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
fprintf(stderr, "spmenu: failed to open history file\n");
|
fprintf(stderr, "spmenu: failed to open history file\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
line = NULL;
|
line = NULL;
|
||||||
llen = 0;
|
llen = 0;
|
||||||
|
|
||||||
if (-1 == getline(&line, &llen, fp)) {
|
if (-1 == getline(&line, &llen, fp)) {
|
||||||
if (ferror(fp)) {
|
if (ferror(fp)) {
|
||||||
die("spmenu: failed to read history");
|
die("spmenu: failed to read history");
|
||||||
}
|
}
|
||||||
|
|
||||||
free(line);
|
free(line);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cap == histsz) {
|
if (cap == histsz) {
|
||||||
cap += 64 * sizeof(char*);
|
cap += 64 * sizeof(char*);
|
||||||
history = realloc(history, cap);
|
history = realloc(history, cap);
|
||||||
if (!history) {
|
if (!history) {
|
||||||
die("spmenu: failed to realloc memory");
|
die("spmenu: failed to realloc memory");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strtok(line, "\n");
|
strtok(line, "\n");
|
||||||
history[histsz] = line;
|
history[histsz] = line;
|
||||||
histsz++;
|
histsz++;
|
||||||
}
|
}
|
||||||
|
|
||||||
histpos = histsz;
|
histpos = histsz;
|
||||||
|
|
||||||
if (fclose(fp)) {
|
if (fclose(fp)) {
|
||||||
die("spmenu: failed to close file %s", histfile);
|
die("spmenu: failed to close file %s", histfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void navigatehistfile(int dir) {
|
void navigatehistfile(int dir) {
|
||||||
static char def[BUFSIZ];
|
static char def[BUFSIZ];
|
||||||
char *p = NULL;
|
char *p = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
if (!history || histpos + 1 == 0)
|
if (!history || histpos + 1 == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (histsz == histpos) {
|
if (histsz == histpos) {
|
||||||
strncpy(def, text, sizeof(def));
|
strncpy(def, text, sizeof(def));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case 1:
|
case 1:
|
||||||
if (histpos < histsz - 1) {
|
if (histpos < histsz - 1) {
|
||||||
p = history[++histpos];
|
p = history[++histpos];
|
||||||
|
@ -74,15 +74,15 @@ void navigatehistfile(int dir) {
|
||||||
p = history[--histpos];
|
p = history[--histpos];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = MIN(strlen(p), BUFSIZ - 1);
|
len = MIN(strlen(p), BUFSIZ - 1);
|
||||||
strcpy(text, p);
|
strcpy(text, p);
|
||||||
text[len] = '\0';
|
text[len] = '\0';
|
||||||
cursor = len;
|
cursor = len;
|
||||||
match();
|
match();
|
||||||
}
|
}
|
||||||
|
|
240
libs/img.c
240
libs/img.c
|
@ -75,7 +75,7 @@ void drawimage(void) {
|
||||||
} else if ((!sel || !sel->image) && image) { // free image
|
} else if ((!sel || !sel->image) && image) { // free image
|
||||||
cleanupimage();
|
cleanupimage();
|
||||||
} if (image && longestedge && width && height) { // render the image
|
} 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();
|
rotateimage();
|
||||||
flipimage();
|
flipimage();
|
||||||
|
|
||||||
|
@ -94,9 +94,9 @@ void drawimage(void) {
|
||||||
xta += menumarginh;
|
xta += menumarginh;
|
||||||
wta += menumarginv;
|
wta += menumarginv;
|
||||||
|
|
||||||
if (mh != bh + height + imagegaps * 2 - wtr) { // menu height cannot be smaller than image height
|
if (mh != bh + height + imagegaps * 2 - wtr) { // menu height cannot be smaller than image height
|
||||||
resizetoimageheight(height);
|
resizetoimageheight(height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// render image
|
// render image
|
||||||
if (!imageposition && image) { // top mode = 0
|
if (!imageposition && image) { // top mode = 0
|
||||||
|
@ -124,106 +124,106 @@ void drawimage(void) {
|
||||||
|
|
||||||
void setimageopts(void) {
|
void setimageopts(void) {
|
||||||
imlib_set_cache_size(8192 * 1024);
|
imlib_set_cache_size(8192 * 1024);
|
||||||
imlib_context_set_blend(1);
|
imlib_context_set_blend(1);
|
||||||
imlib_context_set_dither(1);
|
imlib_context_set_dither(1);
|
||||||
imlib_set_color_usage(128);
|
imlib_set_color_usage(128);
|
||||||
imlib_context_set_display(dpy);
|
imlib_context_set_display(dpy);
|
||||||
imlib_context_set_visual(visual);
|
imlib_context_set_visual(visual);
|
||||||
imlib_context_set_colormap(cmap);
|
imlib_context_set_colormap(cmap);
|
||||||
imlib_context_set_drawable(win);
|
imlib_context_set_drawable(win);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createifnexist(const char *dir) {
|
void createifnexist(const char *dir) {
|
||||||
// exists, so return
|
// exists, so return
|
||||||
if (access(dir, F_OK) == 0)
|
if (access(dir, F_OK) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// fatal: permission denied
|
// fatal: permission denied
|
||||||
if (errno == EACCES)
|
if (errno == EACCES)
|
||||||
fprintf(stderr, "spmenu: no access to create directory: %s\n", dir);
|
fprintf(stderr, "spmenu: no access to create directory: %s\n", dir);
|
||||||
|
|
||||||
// mkdir() failure
|
// mkdir() failure
|
||||||
if (mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1)
|
if (mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1)
|
||||||
fprintf(stderr, "spmenu: failed to create directory: %s\n", dir);
|
fprintf(stderr, "spmenu: failed to create directory: %s\n", dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createifnexist_rec(const char *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)))
|
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) {
|
for(bs = buf; *s; ++s, ++bs) {
|
||||||
if(*s == '/' && *buf)
|
if(*s == '/' && *buf)
|
||||||
createifnexist(buf);
|
createifnexist(buf);
|
||||||
|
|
||||||
*bs = *s;
|
*bs = *s;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadimage(const char *file, int *width, int *height) {
|
void loadimage(const char *file, int *width, int *height) {
|
||||||
if (!file) return;
|
if (!file) return;
|
||||||
|
|
||||||
image = imlib_load_image(file);
|
image = imlib_load_image(file);
|
||||||
|
|
||||||
if (!image)
|
if (!image)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
imlib_context_set_image(image);
|
imlib_context_set_image(image);
|
||||||
|
|
||||||
*width = imlib_image_get_width();
|
*width = imlib_image_get_width();
|
||||||
*height = imlib_image_get_height();
|
*height = imlib_image_get_height();
|
||||||
}
|
}
|
||||||
|
|
||||||
void scaleimage(int *width, int *height) {
|
void scaleimage(int *width, int *height) {
|
||||||
int new_width, new_height;
|
int new_width, new_height;
|
||||||
float aspect = 1.0f;
|
float aspect = 1.0f;
|
||||||
|
|
||||||
// depending on what size, we determine aspect ratio
|
// depending on what size, we determine aspect ratio
|
||||||
if (imagewidth > *width)
|
if (imagewidth > *width)
|
||||||
aspect = (float)(*width)/imagewidth;
|
aspect = (float)(*width)/imagewidth;
|
||||||
else
|
else
|
||||||
aspect = (float)imagewidth/(*width);
|
aspect = (float)imagewidth/(*width);
|
||||||
|
|
||||||
new_width = *width * aspect;
|
new_width = *width * aspect;
|
||||||
new_height = *height * aspect;
|
new_height = *height * aspect;
|
||||||
|
|
||||||
if ((new_width == *width && new_height == *height) || (!image))
|
if ((new_width == *width && new_height == *height) || (!image))
|
||||||
return;
|
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;
|
return;
|
||||||
|
|
||||||
imlib_context_set_image(image);
|
imlib_context_set_image(image);
|
||||||
|
|
||||||
*width = new_width;
|
*width = new_width;
|
||||||
*height = new_height;
|
*height = new_height;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadimagecache(const char *file, int *width, int *height) {
|
void loadimagecache(const char *file, int *width, int *height) {
|
||||||
int slen = 0, i;
|
int slen = 0, i;
|
||||||
unsigned char digest[MD5_DIGEST_LENGTH];
|
unsigned char digest[MD5_DIGEST_LENGTH];
|
||||||
char md5[MD5_DIGEST_LENGTH*2+1];
|
char md5[MD5_DIGEST_LENGTH*2+1];
|
||||||
char *xdg_cache, *home = NULL, *dsize, *buf = NULL;
|
char *xdg_cache, *home = NULL, *dsize, *buf = NULL;
|
||||||
struct passwd *pw = NULL;
|
struct passwd *pw = NULL;
|
||||||
|
|
||||||
// just load and don't store or try cache
|
// just load and don't store or try cache
|
||||||
if (longestedge > maxcache) {
|
if (longestedge > maxcache) {
|
||||||
loadimage(file, width, height);
|
loadimage(file, width, height);
|
||||||
if (image)
|
if (image)
|
||||||
scaleimage(width, height);
|
scaleimage(width, height);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (generatecache) {
|
if (generatecache) {
|
||||||
// try find image from cache first
|
// 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
|
// we din't find anything from cache, or it was just wrong
|
||||||
loadimage(file, width, height);
|
loadimage(file, width, height);
|
||||||
scaleimage(width, height);
|
scaleimage(width, height);
|
||||||
|
|
||||||
if (!generatecache) return;
|
if (!generatecache) return;
|
||||||
|
|
||||||
|
@ -305,35 +305,35 @@ void loadimagecache(const char *file, int *width, int *height) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void jumptoindex(unsigned int index) {
|
void jumptoindex(unsigned int index) {
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
sel = curr = matches;
|
sel = curr = matches;
|
||||||
|
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
|
|
||||||
for (i = 1; i < index; ++i) {
|
for (i = 1; i < index; ++i) {
|
||||||
if(sel && sel->right && (sel = sel->right) == next) {
|
if(sel && sel->right && (sel = sel->right) == next) {
|
||||||
curr = next;
|
curr = next;
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void resizetoimageheight(int imageheight) {
|
void resizetoimageheight(int imageheight) {
|
||||||
int omh = mh, olines = lines;
|
int omh = mh, olines = lines;
|
||||||
lines = reallines;
|
lines = reallines;
|
||||||
int wtr = 0;
|
int wtr = 0;
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
#if USEXINERAMA
|
#if USEXINERAMA
|
||||||
int j, di, a, n, area = 0;
|
int j, di, a, n, area = 0;
|
||||||
XineramaScreenInfo *info;
|
XineramaScreenInfo *info;
|
||||||
Window pw;
|
Window pw;
|
||||||
unsigned int du;
|
unsigned int du;
|
||||||
Window w, dw, *dws;
|
Window w, dw, *dws;
|
||||||
#endif
|
#endif
|
||||||
XWindowAttributes wa;
|
XWindowAttributes wa;
|
||||||
|
|
||||||
if (lines * bh < imageheight + imagegaps * 2) {
|
if (lines * bh < imageheight + imagegaps * 2) {
|
||||||
lines = (imageheight + imagegaps * 2) / bh;
|
lines = (imageheight + imagegaps * 2) / bh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,32 +341,32 @@ void resizetoimageheight(int imageheight) {
|
||||||
wtr = bh;
|
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;
|
mh = (imageheight + imagegaps * 2 + bh) - wtr + 2 * menumarginv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// init xinerama screens
|
// init xinerama screens
|
||||||
#if USEXINERAMA
|
#if USEXINERAMA
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
|
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
|
||||||
XGetInputFocus(dpy, &w, &di);
|
XGetInputFocus(dpy, &w, &di);
|
||||||
if (mon >= 0 && mon < n) {
|
if (mon >= 0 && mon < n) {
|
||||||
i = mon;
|
i = mon;
|
||||||
} else if (w != root && w != PointerRoot && w != None) {
|
} else if (w != root && w != PointerRoot && w != None) {
|
||||||
do {
|
do {
|
||||||
if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
|
if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
|
||||||
XFree(dws);
|
XFree(dws);
|
||||||
} while (w != root && w != pw);
|
} while (w != root && w != pw);
|
||||||
if (XGetWindowAttributes(dpy, pw, &wa)) {
|
if (XGetWindowAttributes(dpy, pw, &wa)) {
|
||||||
for (j = 0; j < n; j++) {
|
for (j = 0; j < n; j++) {
|
||||||
if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
|
if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
|
||||||
area = a;
|
area = a;
|
||||||
i = j;
|
i = j;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) {
|
if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) {
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
|
@ -378,53 +378,53 @@ void resizetoimageheight(int imageheight) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate x/y position
|
// calculate x/y position
|
||||||
if (menuposition == 2) { // centered
|
if (menuposition == 2) { // centered
|
||||||
mw = MIN(MAX(max_textw() + promptw, minwidth), info[i].width);
|
mw = MIN(MAX(max_textw() + promptw, minwidth), info[i].width);
|
||||||
x = info[i].x_org + ((info[i].width - mw) / 2);
|
x = info[i].x_org + ((info[i].width - mw) / 2);
|
||||||
y = info[i].y_org + ((info[i].height - mh) / 2);
|
y = info[i].y_org + ((info[i].height - mh) / 2);
|
||||||
} else { // top or bottom
|
} else { // top or bottom
|
||||||
x = info[i].x_org + xpos;
|
x = info[i].x_org + xpos;
|
||||||
y = info[i].y_org + (menuposition ? 0 : info[i].height - mh - ypos);
|
y = info[i].y_org + (menuposition ? 0 : info[i].height - mh - ypos);
|
||||||
mw = (menuwidth>0 ? menuwidth : info[i].width);
|
mw = (menuwidth>0 ? menuwidth : info[i].width);
|
||||||
}
|
}
|
||||||
|
|
||||||
XFree(info);
|
XFree(info);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (!XGetWindowAttributes(dpy, parentwin, &wa))
|
if (!XGetWindowAttributes(dpy, parentwin, &wa))
|
||||||
die("spmenu: could not get embedding window attributes: 0x%lx",
|
die("spmenu: could not get embedding window attributes: 0x%lx",
|
||||||
parentwin); // die because unable to get attributes for the parent window
|
parentwin); // die because unable to get attributes for the parent window
|
||||||
|
|
||||||
if (menuposition == 2) { // centered
|
if (menuposition == 2) { // centered
|
||||||
mw = MIN(MAX(max_textw() + promptw, minwidth), wa.width);
|
mw = MIN(MAX(max_textw() + promptw, minwidth), wa.width);
|
||||||
x = (wa.width - mw) / 2;
|
x = (wa.width - mw) / 2;
|
||||||
y = (wa.height - mh) / 2;
|
y = (wa.height - mh) / 2;
|
||||||
} else { // top or bottom
|
} else { // top or bottom
|
||||||
x = 0;
|
x = 0;
|
||||||
y = menuposition ? 0 : wa.height - mh - ypos;
|
y = menuposition ? 0 : wa.height - mh - ypos;
|
||||||
mw = wa.width;
|
mw = wa.width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!win || omh == mh) {
|
if (!win || omh == mh) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
XMoveResizeWindow(dpy, win, x + sp, y + vp, mw - 2 * sp - borderwidth * 2, mh);
|
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) {
|
if (olines != lines) {
|
||||||
struct item *item;
|
struct item *item;
|
||||||
unsigned int i = 1;
|
unsigned int i = 1;
|
||||||
|
|
||||||
// walk through all matches
|
// walk through all matches
|
||||||
for (item = matches; item && item != sel; item = item->right)
|
for (item = matches; item && item != sel; item = item->right)
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
jumptoindex(i);
|
jumptoindex(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
drawmenu();
|
drawmenu();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
46
libs/key.c
46
libs/key.c
|
@ -1,19 +1,19 @@
|
||||||
void updatenumlockmask(void) {
|
void updatenumlockmask(void) {
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
XModifierKeymap *modmap;
|
XModifierKeymap *modmap;
|
||||||
|
|
||||||
numlockmask = 0;
|
numlockmask = 0;
|
||||||
modmap = XGetModifierMapping(dpy);
|
modmap = XGetModifierMapping(dpy);
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
for (j = 0; j < modmap->max_keypermod; j++)
|
for (j = 0; j < modmap->max_keypermod; j++)
|
||||||
if (modmap->modifiermap[i * modmap->max_keypermod + j]
|
if (modmap->modifiermap[i * modmap->max_keypermod + j]
|
||||||
== XKeysymToKeycode(dpy, XK_Num_Lock))
|
== XKeysymToKeycode(dpy, XK_Num_Lock))
|
||||||
numlockmask = (1 << i);
|
numlockmask = (1 << i);
|
||||||
XFreeModifiermap(modmap);
|
XFreeModifiermap(modmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void keypress(XEvent *e) {
|
void keypress(XEvent *e) {
|
||||||
updatenumlockmask();
|
updatenumlockmask();
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
KeySym keysym;
|
KeySym keysym;
|
||||||
|
@ -69,22 +69,22 @@ void keypress(XEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void grabkeyboard(void) {
|
void grabkeyboard(void) {
|
||||||
struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
|
struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// don't grab if embedded
|
// don't grab if embedded
|
||||||
if (embed || managed)
|
if (embed || managed)
|
||||||
return;
|
return;
|
||||||
// try to grab keyboard, we may have to wait for another process to ungrab
|
// try to grab keyboard, we may have to wait for another process to ungrab
|
||||||
for (i = 0; i < 1000; i++) {
|
for (i = 0; i < 1000; i++) {
|
||||||
if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync,
|
if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync,
|
||||||
GrabModeAsync, CurrentTime) == GrabSuccess) {
|
GrabModeAsync, CurrentTime) == GrabSuccess) {
|
||||||
getcapsstate();
|
getcapsstate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nanosleep(&ts, NULL);
|
nanosleep(&ts, NULL);
|
||||||
}
|
}
|
||||||
die("cannot grab keyboard");
|
die("cannot grab keyboard");
|
||||||
}
|
}
|
||||||
|
|
||||||
void getcapsstate(void) {
|
void getcapsstate(void) {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int mode;
|
unsigned int mode;
|
||||||
unsigned int mod;
|
unsigned int mod;
|
||||||
KeySym keysym;
|
KeySym keysym;
|
||||||
void (*func)(Arg *);
|
void (*func)(Arg *);
|
||||||
Arg arg;
|
Arg arg;
|
||||||
} Key;
|
} Key;
|
||||||
|
|
||||||
// user friendly names for all the modifiers we're using, but there are many more
|
// user friendly names for all the modifiers we're using, but there are many more
|
||||||
|
|
|
@ -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 const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
|
||||||
|
|
||||||
static long utf8decodebyte(const char c, size_t *i) {
|
static long utf8decodebyte(const char c, size_t *i) {
|
||||||
for (*i = 0; *i < (UTF_SIZ + 1); ++(*i))
|
for (*i = 0; *i < (UTF_SIZ + 1); ++(*i))
|
||||||
if (((unsigned char)c & utfmask[*i]) == utfbyte[*i])
|
if (((unsigned char)c & utfmask[*i]) == utfbyte[*i])
|
||||||
return (unsigned char)c & ~utfmask[*i];
|
return (unsigned char)c & ~utfmask[*i];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t utf8validate(long *u, size_t i) {
|
static size_t utf8validate(long *u, size_t i) {
|
||||||
if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
|
if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
|
||||||
*u = UTF_INVALID;
|
*u = UTF_INVALID;
|
||||||
for (i = 1; *u > utfmax[i]; ++i)
|
for (i = 1; *u > utfmax[i]; ++i)
|
||||||
;
|
;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t utf8decode(const char *c, long *u, size_t clen) {
|
static size_t utf8decode(const char *c, long *u, size_t clen) {
|
||||||
size_t i, j, len, type;
|
size_t i, j, len, type;
|
||||||
long udecoded;
|
long udecoded;
|
||||||
|
|
||||||
*u = UTF_INVALID;
|
*u = UTF_INVALID;
|
||||||
if (!clen)
|
if (!clen)
|
||||||
return 0;
|
return 0;
|
||||||
udecoded = utf8decodebyte(c[0], &len);
|
udecoded = utf8decodebyte(c[0], &len);
|
||||||
if (!BETWEEN(len, 1, UTF_SIZ))
|
if (!BETWEEN(len, 1, UTF_SIZ))
|
||||||
return 1;
|
return 1;
|
||||||
for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
|
for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
|
||||||
udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
|
udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
|
||||||
if (type)
|
if (type)
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
if (j < len)
|
if (j < len)
|
||||||
return 0;
|
return 0;
|
||||||
*u = udecoded;
|
*u = udecoded;
|
||||||
utf8validate(u, len);
|
utf8validate(u, len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Clr transcheme[3];
|
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_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->dpy = dpy;
|
||||||
drw->screen = screen;
|
drw->screen = screen;
|
||||||
drw->root = root;
|
drw->root = root;
|
||||||
drw->w = w;
|
drw->w = w;
|
||||||
drw->h = h;
|
drw->h = h;
|
||||||
drw->visual = visual;
|
drw->visual = visual;
|
||||||
drw->depth = depth;
|
drw->depth = depth;
|
||||||
drw->cmap = cmap;
|
drw->cmap = cmap;
|
||||||
drw->drawable = XCreatePixmap(dpy, root, w, h, depth);
|
drw->drawable = XCreatePixmap(dpy, root, w, h, depth);
|
||||||
drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL);
|
drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL);
|
||||||
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
|
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
|
||||||
|
|
||||||
return drw;
|
return drw;
|
||||||
}
|
}
|
||||||
|
|
||||||
void drw_resize(Drw *drw, unsigned int w, unsigned int h) {
|
void drw_resize(Drw *drw, unsigned int w, unsigned int h) {
|
||||||
if (!drw)
|
if (!drw)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
drw->w = w;
|
drw->w = w;
|
||||||
drw->h = h;
|
drw->h = h;
|
||||||
if (drw->drawable)
|
if (drw->drawable)
|
||||||
XFreePixmap(drw->dpy, drw->drawable);
|
XFreePixmap(drw->dpy, drw->drawable);
|
||||||
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth);
|
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drw_free(Drw *drw) {
|
void drw_free(Drw *drw) {
|
||||||
XFreePixmap(drw->dpy, drw->drawable);
|
XFreePixmap(drw->dpy, drw->drawable);
|
||||||
XFreeGC(drw->dpy, drw->gc);
|
XFreeGC(drw->dpy, drw->gc);
|
||||||
drw_font_free(drw->font);
|
drw_font_free(drw->font);
|
||||||
free(drw);
|
free(drw);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USEPANGO
|
#if USEPANGO
|
||||||
static Fnt * xfont_create(Drw *drw, const char *fontname) {
|
static Fnt * xfont_create(Drw *drw, const char *fontname) {
|
||||||
Fnt *font;
|
Fnt *font;
|
||||||
PangoFontMap *fontmap;
|
PangoFontMap *fontmap;
|
||||||
PangoContext *context;
|
PangoContext *context;
|
||||||
PangoFontDescription *desc;
|
PangoFontDescription *desc;
|
||||||
PangoFontMetrics *metrics;
|
PangoFontMetrics *metrics;
|
||||||
|
|
||||||
if (!fontname) {
|
if (!fontname) {
|
||||||
die("spmenu: no font specified.");
|
die("spmenu: no font specified.");
|
||||||
}
|
}
|
||||||
|
|
||||||
font = ecalloc(1, sizeof(Fnt));
|
font = ecalloc(1, sizeof(Fnt));
|
||||||
font->dpy = drw->dpy;
|
font->dpy = drw->dpy;
|
||||||
|
|
||||||
fontmap = pango_xft_get_font_map(drw->dpy, drw->screen);
|
fontmap = pango_xft_get_font_map(drw->dpy, drw->screen);
|
||||||
context = pango_font_map_create_context(fontmap);
|
context = pango_font_map_create_context(fontmap);
|
||||||
desc = pango_font_description_from_string(fontname);
|
desc = pango_font_description_from_string(fontname);
|
||||||
font->layout = pango_layout_new(context);
|
font->layout = pango_layout_new(context);
|
||||||
pango_layout_set_font_description(font->layout, desc);
|
pango_layout_set_font_description(font->layout, desc);
|
||||||
|
|
||||||
metrics = pango_context_get_metrics(context, desc, pango_language_from_string ("en-us"));
|
metrics = pango_context_get_metrics(context, desc, pango_language_from_string ("en-us"));
|
||||||
font->h = pango_font_metrics_get_height(metrics) / PANGO_SCALE;
|
font->h = pango_font_metrics_get_height(metrics) / PANGO_SCALE;
|
||||||
|
|
||||||
pango_font_metrics_unref(metrics);
|
pango_font_metrics_unref(metrics);
|
||||||
g_object_unref(context);
|
g_object_unref(context);
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xfont_free(Fnt *font) {
|
void xfont_free(Fnt *font) {
|
||||||
if (!font)
|
if (!font)
|
||||||
return;
|
return;
|
||||||
if (font->layout)
|
if (font->layout)
|
||||||
g_object_unref(font->layout);
|
g_object_unref(font->layout);
|
||||||
free(font);
|
free(font);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static Fnt * xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) {
|
static Fnt * xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) {
|
||||||
Fnt *font;
|
Fnt *font;
|
||||||
XftFont *xfont = NULL;
|
XftFont *xfont = NULL;
|
||||||
FcPattern *pattern = NULL;
|
FcPattern *pattern = NULL;
|
||||||
|
|
||||||
if (fontname) {
|
if (fontname) {
|
||||||
/* Using the pattern found at font->xfont->pattern does not yield the
|
/* Using the pattern found at font->xfont->pattern does not yield the
|
||||||
* same substitution results as using the pattern returned by
|
* same substitution results as using the pattern returned by
|
||||||
* FcNameParse; using the latter results in the desired fallback
|
* FcNameParse; using the latter results in the desired fallback
|
||||||
* behaviour whereas the former just results in missing-character
|
* behaviour whereas the former just results in missing-character
|
||||||
* rectangles being drawn, at least with some fonts. */
|
* rectangles being drawn, at least with some fonts. */
|
||||||
if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
|
if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
|
||||||
fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
|
fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fontname[0] == '-')
|
if (fontname[0] == '-')
|
||||||
pattern = XftXlfdParse(fontname, False, False);
|
pattern = XftXlfdParse(fontname, False, False);
|
||||||
else
|
else
|
||||||
pattern = FcNameParse((FcChar8 *) fontname);
|
pattern = FcNameParse((FcChar8 *) fontname);
|
||||||
|
|
||||||
if (!pattern) {
|
if (!pattern) {
|
||||||
fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
|
fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
|
||||||
XftFontClose(drw->dpy, xfont);
|
XftFontClose(drw->dpy, xfont);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else if (fontpattern) {
|
} else if (fontpattern) {
|
||||||
if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
|
if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
|
||||||
fprintf(stderr, "spmenu: cannot load font from pattern.\n");
|
fprintf(stderr, "spmenu: cannot load font from pattern.\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
die("spmenu: no font specified.");
|
die("spmenu: no font specified.");
|
||||||
}
|
}
|
||||||
|
|
||||||
font = ecalloc(1, sizeof(Fnt));
|
font = ecalloc(1, sizeof(Fnt));
|
||||||
font->xfont = xfont;
|
font->xfont = xfont;
|
||||||
font->pattern = pattern;
|
font->pattern = pattern;
|
||||||
font->h = xfont->ascent + xfont->descent;
|
font->h = xfont->ascent + xfont->descent;
|
||||||
font->dpy = drw->dpy;
|
font->dpy = drw->dpy;
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xfont_free(Fnt *font) {
|
void xfont_free(Fnt *font) {
|
||||||
if (!font)
|
if (!font)
|
||||||
return;
|
return;
|
||||||
if (font->pattern)
|
if (font->pattern)
|
||||||
FcPatternDestroy(font->pattern);
|
FcPatternDestroy(font->pattern);
|
||||||
XftFontClose(font->dpy, font->xfont);
|
XftFontClose(font->dpy, font->xfont);
|
||||||
free(font);
|
free(font);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Fnt* drw_font_create(Drw* drw, char *font[], size_t fontcount) {
|
Fnt* drw_font_create(Drw* drw, char *font[], size_t fontcount) {
|
||||||
if (!drw || !font)
|
if (!drw || !font)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
#if USEPANGO
|
#if USEPANGO
|
||||||
Fnt *fnt = NULL;
|
Fnt *fnt = NULL;
|
||||||
|
|
||||||
fnt = xfont_create(drw, *font);
|
fnt = xfont_create(drw, *font);
|
||||||
return (drw->font = fnt);
|
return (drw->font = fnt);
|
||||||
#else
|
#else
|
||||||
Fnt *cur, *ret = NULL;
|
Fnt *cur, *ret = NULL;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 1; i <= fontcount; i++) {
|
for (i = 1; i <= fontcount; i++) {
|
||||||
if ((cur = xfont_create(drw, font[fontcount - i], NULL))) {
|
if ((cur = xfont_create(drw, font[fontcount - i], NULL))) {
|
||||||
cur->next = ret;
|
cur->next = ret;
|
||||||
ret = cur;
|
ret = cur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (drw->font = ret);
|
return (drw->font = ret);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void drw_font_free(Fnt *font) {
|
void drw_font_free(Fnt *font) {
|
||||||
if (font) {
|
if (font) {
|
||||||
#if !USEPANGO
|
#if !USEPANGO
|
||||||
drw_font_free(font->next);
|
drw_font_free(font->next);
|
||||||
#endif
|
#endif
|
||||||
xfont_free(font);
|
xfont_free(font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void drw_clr_create(Drw *drw, Clr *dest, char *clrname, unsigned int alpha) {
|
void drw_clr_create(Drw *drw, Clr *dest, char *clrname, unsigned int alpha) {
|
||||||
if (!drw || !dest || !clrname)
|
if (!drw || !dest || !clrname)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap,
|
if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap,
|
||||||
clrname, dest))
|
clrname, dest))
|
||||||
die("spmenu: cannot allocate color '%s'", clrname);
|
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
|
/* Wrapper to create color schemes. The caller has to call free(3) on the
|
||||||
* returned color scheme when done using it. */
|
* returned color scheme when done using it. */
|
||||||
Clr * drw_scm_create(Drw *drw, char *clrnames[], unsigned int alphas[], size_t clrcount) {
|
Clr * drw_scm_create(Drw *drw, char *clrnames[], unsigned int alphas[], size_t clrcount) {
|
||||||
size_t i;
|
size_t i;
|
||||||
Clr *ret;
|
Clr *ret;
|
||||||
|
|
||||||
/* need at least two colors for a scheme */
|
/* need at least two colors for a scheme */
|
||||||
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
|
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (i = 0; i < clrcount; i++)
|
for (i = 0; i < clrcount; i++)
|
||||||
drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]);
|
drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void drw_setscheme(Drw *drw, Clr *scm) {
|
void drw_setscheme(Drw *drw, Clr *scm) {
|
||||||
if (drw)
|
if (drw)
|
||||||
drw->scheme = scm;
|
drw->scheme = scm;
|
||||||
}
|
}
|
||||||
|
|
||||||
void drw_settrans(Drw *drw, Clr *psc, Clr *nsc) {
|
void drw_settrans(Drw *drw, Clr *psc, Clr *nsc) {
|
||||||
if (drw) {
|
if (drw) {
|
||||||
transcheme[0] = psc[ColBg]; transcheme[1] = nsc[ColBg]; transcheme[2] = psc[ColPwl];
|
transcheme[0] = psc[ColBg]; transcheme[1] = nsc[ColBg]; transcheme[2] = psc[ColPwl];
|
||||||
drw->scheme = transcheme;
|
drw->scheme = transcheme;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void drw_arrow(Drw *drw, int x, int y, unsigned int w, unsigned int h, int direction, int slash) {
|
void drw_arrow(Drw *drw, int x, int y, unsigned int w, unsigned int h, int direction, int slash) {
|
||||||
if (!drw || !drw->scheme)
|
if (!drw || !drw->scheme)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
x = direction ? x : x + w;
|
x = direction ? x : x + w;
|
||||||
w = direction ? w : -w;
|
w = direction ? w : -w;
|
||||||
unsigned int hh = slash ? (direction ? 0 : h) : h/2;
|
unsigned int hh = slash ? (direction ? 0 : h) : h/2;
|
||||||
|
|
||||||
XPoint points[] = {
|
XPoint points[] = {
|
||||||
{x , y },
|
{x , y },
|
||||||
{x + w, y + hh },
|
{x + w, y + hh },
|
||||||
{x , y + h },
|
{x , y + h },
|
||||||
};
|
};
|
||||||
|
|
||||||
XPoint bg[] = {
|
XPoint bg[] = {
|
||||||
{x , y },
|
{x , y },
|
||||||
{x + w, y },
|
{x + w, y },
|
||||||
{x + w, y + h},
|
{x + w, y + h},
|
||||||
{x , y + h},
|
{x , y + h},
|
||||||
};
|
};
|
||||||
|
|
||||||
XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel);
|
XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel);
|
||||||
XFillPolygon(drw->dpy, drw->drawable, drw->gc, bg, 4, Convex, CoordModeOrigin);
|
XFillPolygon(drw->dpy, drw->drawable, drw->gc, bg, 4, Convex, CoordModeOrigin);
|
||||||
XSetForeground(drw->dpy, drw->gc, drw->scheme[ColFg].pixel);
|
XSetForeground(drw->dpy, drw->gc, drw->scheme[ColFg].pixel);
|
||||||
XFillPolygon(drw->dpy, drw->drawable, drw->gc, points, 3, Nonconvex, CoordModeOrigin);
|
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) {
|
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) {
|
||||||
if (!drw || !drw->scheme)
|
if (!drw || !drw->scheme)
|
||||||
return;
|
return;
|
||||||
XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
|
XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
|
||||||
if (filled)
|
if (filled)
|
||||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
||||||
else
|
else
|
||||||
XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
|
XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int xerrordummy(Display *dpy, XErrorEvent *ee) {
|
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) {
|
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);
|
XSetErrorHandler(xerrordummy);
|
||||||
|
|
||||||
#if USEPANGO // pango
|
#if USEPANGO // pango
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int ty;
|
int ty;
|
||||||
unsigned int ew = 0;
|
unsigned int ew = 0;
|
||||||
XftDraw *d = NULL;
|
XftDraw *d = NULL;
|
||||||
size_t i, len;
|
size_t i, len;
|
||||||
int render = x || y || w || h;
|
int render = x || y || w || h;
|
||||||
|
|
||||||
if (!drw || (render && !drw->scheme) || !text || !drw->font)
|
if (!drw || (render && !drw->scheme) || !text || !drw->font)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!render) {
|
if (!render) {
|
||||||
w = ~w;
|
w = ~w;
|
||||||
} else {
|
} else {
|
||||||
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
||||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
||||||
d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap);
|
d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap);
|
||||||
x += lpad;
|
x += lpad;
|
||||||
w -= lpad;
|
w -= lpad;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen(text);
|
len = strlen(text);
|
||||||
|
|
||||||
if (len) {
|
if (len) {
|
||||||
drw_font_getexts(drw->font, text, len, &ew, NULL, markup);
|
drw_font_getexts(drw->font, text, len, &ew, NULL, markup);
|
||||||
/* shorten text if necessary */
|
/* shorten text if necessary */
|
||||||
for (len = MIN(len, sizeof(buf) - 1); len && ew > w; drw_font_getexts(drw->font, text, len, &ew, NULL, markup))
|
for (len = MIN(len, sizeof(buf) - 1); len && ew > w; drw_font_getexts(drw->font, text, len, &ew, NULL, markup))
|
||||||
len--;
|
len--;
|
||||||
|
|
||||||
|
|
||||||
if (len) {
|
if (len) {
|
||||||
memcpy(buf, text, len);
|
memcpy(buf, text, len);
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
if (len < strlen(text))
|
if (len < strlen(text))
|
||||||
for (i = len; i && i > len - 3; buf[--i] = '.')
|
for (i = len; i && i > len - 3; buf[--i] = '.')
|
||||||
; /* NOP */
|
; /* NOP */
|
||||||
|
|
||||||
if (render) {
|
if (render) {
|
||||||
ty = y + (h - drw->font->h) / 2;
|
ty = y + (h - drw->font->h) / 2;
|
||||||
if(markup)
|
if(markup)
|
||||||
pango_layout_set_markup(drw->font->layout, buf, len);
|
pango_layout_set_markup(drw->font->layout, buf, len);
|
||||||
else
|
else
|
||||||
pango_layout_set_text(drw->font->layout, buf, len);
|
pango_layout_set_text(drw->font->layout, buf, len);
|
||||||
pango_xft_render_layout(d, &drw->scheme[invert ? ColBg : ColFg],
|
pango_xft_render_layout(d, &drw->scheme[invert ? ColBg : ColFg],
|
||||||
drw->font->layout, x * PANGO_SCALE, ty * PANGO_SCALE);
|
drw->font->layout, x * PANGO_SCALE, ty * PANGO_SCALE);
|
||||||
if(markup) /* clear markup attributes */
|
if(markup) /* clear markup attributes */
|
||||||
pango_layout_set_attributes(drw->font->layout, NULL);
|
pango_layout_set_attributes(drw->font->layout, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
x += ew;
|
x += ew;
|
||||||
w -= ew;
|
w -= ew;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (d)
|
if (d)
|
||||||
XftDrawDestroy(d);
|
XftDrawDestroy(d);
|
||||||
|
|
||||||
return x + (render ? w : 0);
|
return x + (render ? w : 0);
|
||||||
#else // xft
|
#else // xft
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int ty;
|
int ty;
|
||||||
unsigned int ew = 0;
|
unsigned int ew = 0;
|
||||||
XftDraw *d = NULL;
|
XftDraw *d = NULL;
|
||||||
Fnt *usedfont, *curfont, *nextfont;
|
Fnt *usedfont, *curfont, *nextfont;
|
||||||
size_t i, len;
|
size_t i, len;
|
||||||
int utf8strlen, utf8charlen, render = x || y || w || h;
|
int utf8strlen, utf8charlen, render = x || y || w || h;
|
||||||
long utf8codepoint = 0;
|
long utf8codepoint = 0;
|
||||||
const char *utf8str;
|
const char *utf8str;
|
||||||
FcCharSet *fccharset;
|
FcCharSet *fccharset;
|
||||||
FcPattern *fcpattern;
|
FcPattern *fcpattern;
|
||||||
FcPattern *match;
|
FcPattern *match;
|
||||||
XftResult result;
|
XftResult result;
|
||||||
int charexists = 0;
|
int charexists = 0;
|
||||||
|
|
||||||
if (!drw || (render && !drw->scheme) || !text || !drw->font)
|
if (!drw || (render && !drw->scheme) || !text || !drw->font)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!render) {
|
if (!render) {
|
||||||
w = ~w;
|
w = ~w;
|
||||||
} else {
|
} else {
|
||||||
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
||||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
||||||
d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap);
|
d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap);
|
||||||
x += lpad;
|
x += lpad;
|
||||||
w -= lpad;
|
w -= lpad;
|
||||||
}
|
}
|
||||||
|
|
||||||
usedfont = drw->font;
|
usedfont = drw->font;
|
||||||
while (1) {
|
while (1) {
|
||||||
utf8strlen = 0;
|
utf8strlen = 0;
|
||||||
utf8str = text;
|
utf8str = text;
|
||||||
nextfont = NULL;
|
nextfont = NULL;
|
||||||
while (*text) {
|
while (*text) {
|
||||||
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
|
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
|
||||||
for (curfont = drw->font; curfont; curfont = curfont->next) {
|
for (curfont = drw->font; curfont; curfont = curfont->next) {
|
||||||
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
||||||
if (charexists) {
|
if (charexists) {
|
||||||
if (curfont == usedfont) {
|
if (curfont == usedfont) {
|
||||||
utf8strlen += utf8charlen;
|
utf8strlen += utf8charlen;
|
||||||
text += utf8charlen;
|
text += utf8charlen;
|
||||||
} else {
|
} else {
|
||||||
nextfont = curfont;
|
nextfont = curfont;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!charexists || nextfont)
|
if (!charexists || nextfont)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
charexists = 0;
|
charexists = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (utf8strlen) {
|
if (utf8strlen) {
|
||||||
drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL, True);
|
drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL, True);
|
||||||
/* shorten text if necessary */
|
/* shorten text if necessary */
|
||||||
for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; drw_font_getexts(usedfont, utf8str, len, &ew, NULL, True))
|
for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; drw_font_getexts(usedfont, utf8str, len, &ew, NULL, True))
|
||||||
len--;
|
len--;
|
||||||
|
|
||||||
if (len) {
|
if (len) {
|
||||||
memcpy(buf, utf8str, len);
|
memcpy(buf, utf8str, len);
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
if (len < utf8strlen)
|
if (len < utf8strlen)
|
||||||
for (i = len; i && i > len - 3; buf[--i] = '.')
|
for (i = len; i && i > len - 3; buf[--i] = '.')
|
||||||
; /* NOP */
|
; /* NOP */
|
||||||
|
|
||||||
if (render) {
|
if (render) {
|
||||||
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
|
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
|
||||||
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
|
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
|
||||||
usedfont->xfont, x, ty, (XftChar8 *)buf, len);
|
usedfont->xfont, x, ty, (XftChar8 *)buf, len);
|
||||||
}
|
}
|
||||||
x += ew;
|
x += ew;
|
||||||
w -= ew;
|
w -= ew;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*text) {
|
if (!*text) {
|
||||||
break;
|
break;
|
||||||
} else if (nextfont) {
|
} else if (nextfont) {
|
||||||
charexists = 0;
|
charexists = 0;
|
||||||
usedfont = nextfont;
|
usedfont = nextfont;
|
||||||
} else {
|
} else {
|
||||||
/* Regardless of whether or not a fallback font is found, the
|
/* Regardless of whether or not a fallback font is found, the
|
||||||
* character must be drawn. */
|
* character must be drawn. */
|
||||||
charexists = 1;
|
charexists = 1;
|
||||||
|
|
||||||
fccharset = FcCharSetCreate();
|
fccharset = FcCharSetCreate();
|
||||||
FcCharSetAddChar(fccharset, utf8codepoint);
|
FcCharSetAddChar(fccharset, utf8codepoint);
|
||||||
|
|
||||||
if (!drw->font->pattern) {
|
if (!drw->font->pattern) {
|
||||||
/* Refer to the comment in xfont_create for more information. */
|
/* 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.");
|
die("spmenu: the first font in the cache must be loaded from a font string.");
|
||||||
}
|
}
|
||||||
|
|
||||||
fcpattern = FcPatternDuplicate(drw->font->pattern);
|
fcpattern = FcPatternDuplicate(drw->font->pattern);
|
||||||
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
|
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
|
||||||
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
|
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
|
||||||
|
|
||||||
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
|
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
|
||||||
FcDefaultSubstitute(fcpattern);
|
FcDefaultSubstitute(fcpattern);
|
||||||
match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
|
match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
|
||||||
|
|
||||||
FcCharSetDestroy(fccharset);
|
FcCharSetDestroy(fccharset);
|
||||||
FcPatternDestroy(fcpattern);
|
FcPatternDestroy(fcpattern);
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
usedfont = xfont_create(drw, NULL, match);
|
usedfont = xfont_create(drw, NULL, match);
|
||||||
if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
|
if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
|
||||||
for (curfont = drw->font; curfont->next; curfont = curfont->next)
|
for (curfont = drw->font; curfont->next; curfont = curfont->next)
|
||||||
; /* NOP */
|
; /* NOP */
|
||||||
curfont->next = usedfont;
|
curfont->next = usedfont;
|
||||||
} else {
|
} else {
|
||||||
xfont_free(usedfont);
|
xfont_free(usedfont);
|
||||||
usedfont = drw->font;
|
usedfont = drw->font;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (d)
|
if (d)
|
||||||
XftDrawDestroy(d);
|
XftDrawDestroy(d);
|
||||||
|
|
||||||
XSync(drw->dpy, False);
|
XSync(drw->dpy, False);
|
||||||
|
|
||||||
return x + (render ? w : 0);
|
return x + (render ? w : 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
XSync(drw->dpy, False);
|
XSync(drw->dpy, False);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) {
|
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) {
|
||||||
if (!drw)
|
if (!drw)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
|
XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
|
||||||
XSync(drw->dpy, False);
|
XSync(drw->dpy, False);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int drw_font_getwidth(Drw *drw, const char *text, Bool markup) {
|
unsigned int drw_font_getwidth(Drw *drw, const char *text, Bool markup) {
|
||||||
if (!drw || !drw->font || !text)
|
if (!drw || !drw->font || !text)
|
||||||
return 0;
|
return 0;
|
||||||
return drw_text(drw, 0, 0, 0, 0, 0, text, 0, markup);
|
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) {
|
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;
|
XGlyphInfo ext;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!font || !text)
|
if (!font || !text)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if USEPANGO
|
#if USEPANGO
|
||||||
PangoRectangle r;
|
PangoRectangle r;
|
||||||
if(markup)
|
if(markup)
|
||||||
pango_layout_set_markup(font->layout, text, len);
|
pango_layout_set_markup(font->layout, text, len);
|
||||||
else
|
else
|
||||||
pango_layout_set_text(font->layout, text, len);
|
pango_layout_set_text(font->layout, text, len);
|
||||||
pango_layout_get_extents(font->layout, 0, &r);
|
pango_layout_get_extents(font->layout, 0, &r);
|
||||||
if(markup) // clear markup attributes
|
if(markup) // clear markup attributes
|
||||||
pango_layout_set_attributes(font->layout, NULL);
|
pango_layout_set_attributes(font->layout, NULL);
|
||||||
#else
|
#else
|
||||||
XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
|
XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
|
||||||
#endif
|
#endif
|
||||||
if (w)
|
if (w)
|
||||||
#if USEPANGO
|
#if USEPANGO
|
||||||
*w = r.width / PANGO_SCALE;
|
*w = r.width / PANGO_SCALE;
|
||||||
#else
|
#else
|
||||||
*w = ext.xOff;
|
*w = ext.xOff;
|
||||||
#endif
|
#endif
|
||||||
if (h)
|
if (h)
|
||||||
*h = font->h;
|
*h = font->h;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cur * drw_cur_create(Drw *drw, int shape) {
|
Cur * drw_cur_create(Drw *drw, int shape) {
|
||||||
Cur *cur;
|
Cur *cur;
|
||||||
|
|
||||||
if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
|
if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
|
||||||
return NULL;
|
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) {
|
void drw_cur_free(Drw *drw, Cur *cursor) {
|
||||||
if (!cursor)
|
if (!cursor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
XFreeCursor(drw->dpy, cursor->cursor);
|
XFreeCursor(drw->dpy, cursor->cursor);
|
||||||
free(cursor);
|
free(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n, Bool markup) {
|
unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n, Bool markup) {
|
||||||
unsigned int tmp = 0;
|
unsigned int tmp = 0;
|
||||||
if (drw && drw->font && text && n)
|
if (drw && drw->font && text && n)
|
||||||
tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n, markup);
|
tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n, markup);
|
||||||
return MIN(n, tmp);
|
return MIN(n, tmp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,36 +7,36 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Cursor cursor;
|
Cursor cursor;
|
||||||
} Cur;
|
} Cur;
|
||||||
|
|
||||||
typedef struct Fnt {
|
typedef struct Fnt {
|
||||||
Display *dpy;
|
Display *dpy;
|
||||||
unsigned int h;
|
unsigned int h;
|
||||||
#if USEPANGO
|
#if USEPANGO
|
||||||
PangoLayout *layout;
|
PangoLayout *layout;
|
||||||
#else
|
#else
|
||||||
XftFont *xfont;
|
XftFont *xfont;
|
||||||
FcPattern *pattern;
|
FcPattern *pattern;
|
||||||
struct Fnt *next;
|
struct Fnt *next;
|
||||||
#endif
|
#endif
|
||||||
} Fnt;
|
} Fnt;
|
||||||
|
|
||||||
enum { ColFg, ColBg, ColPwl }; /* Clr scheme index */
|
enum { ColFg, ColBg, ColPwl }; /* Clr scheme index */
|
||||||
typedef XftColor Clr;
|
typedef XftColor Clr;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int w, h;
|
unsigned int w, h;
|
||||||
Display *dpy;
|
Display *dpy;
|
||||||
int screen;
|
int screen;
|
||||||
Window root;
|
Window root;
|
||||||
Visual *visual;
|
Visual *visual;
|
||||||
unsigned int depth;
|
unsigned int depth;
|
||||||
Colormap cmap;
|
Colormap cmap;
|
||||||
Drawable drawable;
|
Drawable drawable;
|
||||||
GC gc;
|
GC gc;
|
||||||
Clr *scheme;
|
Clr *scheme;
|
||||||
Fnt *font;
|
Fnt *font;
|
||||||
} Drw;
|
} Drw;
|
||||||
|
|
||||||
/* Drawable abstraction */
|
/* Drawable abstraction */
|
||||||
|
|
265
libs/match.c
265
libs/match.c
|
@ -1,174 +1,175 @@
|
||||||
void fuzzymatch(void) {
|
void fuzzymatch(void) {
|
||||||
struct item *it;
|
struct item *it;
|
||||||
struct item **fuzzymatches = NULL;
|
struct item **fuzzymatches = NULL;
|
||||||
struct item *lhpprefix, *hpprefixend;
|
struct item *lhpprefix, *hpprefixend;
|
||||||
lhpprefix = hpprefixend = NULL;
|
lhpprefix = hpprefixend = NULL;
|
||||||
char c;
|
char c;
|
||||||
int number_of_matches = 0, i, pidx, sidx, eidx;
|
int number_of_matches = 0, i, pidx, sidx, eidx;
|
||||||
int text_len = strlen(text), itext_len;
|
int text_len = strlen(text), itext_len;
|
||||||
|
|
||||||
matches = matchend = NULL;
|
matches = matchend = NULL;
|
||||||
|
|
||||||
// walk through all items
|
// walk through all items
|
||||||
for (it = items; it && it->text; it++) {
|
for (it = items; it && it->text; it++) {
|
||||||
if (text_len) {
|
if (text_len) {
|
||||||
itext_len = strlen(it->text);
|
itext_len = strlen(it->text);
|
||||||
pidx = 0; // pointer
|
pidx = 0; // pointer
|
||||||
sidx = eidx = -1; // start of match, end of match
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (number_of_matches) {
|
// walk through item text
|
||||||
// initialize array with matches
|
for (i = 0; i < itext_len && (c = it->text[i]); i++) {
|
||||||
if (!(fuzzymatches = realloc(fuzzymatches, number_of_matches * sizeof(struct item*))))
|
// fuzzy match pattern
|
||||||
die("spmenu: cannot realloc %u bytes:", number_of_matches * sizeof(struct item*));
|
if (!fstrncmp(&text[pidx], &c, 1)) {
|
||||||
for (i = 0, it = matches; it && i < number_of_matches; i++, it = it->right) {
|
if(sidx == -1)
|
||||||
fuzzymatches[i] = it;
|
sidx = i;
|
||||||
}
|
pidx++;
|
||||||
// sort matches according to distance
|
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);
|
if (sortmatches) qsort(fuzzymatches, number_of_matches, sizeof(struct item*), compare_distance);
|
||||||
|
|
||||||
// rebuild list of matches
|
// rebuild list of matches
|
||||||
matches = matchend = NULL;
|
matches = matchend = NULL;
|
||||||
for (i = 0, it = fuzzymatches[i]; i < number_of_matches && it && \
|
for (i = 0, it = fuzzymatches[i]; i < number_of_matches && it && \
|
||||||
it->text; i++, it = fuzzymatches[i]) {
|
it->text; i++, it = fuzzymatches[i]) {
|
||||||
|
|
||||||
if (sortmatches && it->hp)
|
if (sortmatches && it->hp)
|
||||||
appenditem(it, &lhpprefix, &hpprefixend);
|
appenditem(it, &lhpprefix, &hpprefixend);
|
||||||
|
|
||||||
appenditem(it, &matches, &matchend);
|
appenditem(it, &matches, &matchend);
|
||||||
}
|
}
|
||||||
free(fuzzymatches);
|
free(fuzzymatches);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lhpprefix) {
|
if (lhpprefix) {
|
||||||
hpprefixend->right = matches;
|
hpprefixend->right = matches;
|
||||||
matches = lhpprefix;
|
matches = lhpprefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
curr = sel = matches;
|
curr = sel = matches;
|
||||||
|
|
||||||
for (i = 0; i < preselected; i++) {
|
for (i = 0; i < preselected; i++) {
|
||||||
if (sel && sel->right && (sel = sel->right) == next) {
|
if (sel && sel->right && (sel = sel->right) == next) {
|
||||||
curr = next;
|
curr = next;
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void match(void) {
|
void match(void) {
|
||||||
if (fuzzy) {
|
if (fuzzy) {
|
||||||
fuzzymatch();
|
fuzzymatch();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
static char **tokv = NULL;
|
static char **tokv = NULL;
|
||||||
static int tokn = 0;
|
static int tokn = 0;
|
||||||
|
|
||||||
char buf[sizeof text], *s;
|
char buf[sizeof text], *s;
|
||||||
int i, tokc = 0;
|
int i, tokc = 0;
|
||||||
size_t len, textsize;
|
size_t len, textsize;
|
||||||
struct item *item, *lhpprefix, *lprefix, *lsubstr, *hpprefixend, *prefixend, *substrend;
|
struct item *item, *lhpprefix, *lprefix, *lsubstr, *hpprefixend, *prefixend, *substrend;
|
||||||
|
|
||||||
|
|
||||||
strcpy(buf, text);
|
strcpy(buf, text);
|
||||||
// separate input text into tokens to be matched individually
|
// separate input text into tokens to be matched individually
|
||||||
for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " "))
|
for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " "))
|
||||||
if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv)))
|
if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv)))
|
||||||
die("spmenu: cannot realloc %u bytes:", tokn * sizeof *tokv);
|
die("spmenu: cannot realloc %u bytes:", tokn * sizeof *tokv);
|
||||||
len = tokc ? strlen(tokv[0]) : 0;
|
len = tokc ? strlen(tokv[0]) : 0;
|
||||||
|
|
||||||
matches = lhpprefix = lprefix = lsubstr = matchend = hpprefixend = prefixend = substrend = NULL;
|
matches = lhpprefix = lprefix = lsubstr = matchend = hpprefixend = prefixend = substrend = NULL;
|
||||||
textsize = strlen(text) + 1;
|
textsize = strlen(text) + 1;
|
||||||
for (item = items; item && item->text; item++) {
|
for (item = items; item && item->text; item++) {
|
||||||
for (i = 0; i < tokc; i++)
|
for (i = 0; i < tokc; i++)
|
||||||
if (!fstrstr(item->text, tokv[i]))
|
if (!fstrstr(item->text, tokv[i]))
|
||||||
break;
|
break;
|
||||||
if (i != tokc) // not all tokens match
|
if (i != tokc) // not all tokens match
|
||||||
continue;
|
continue;
|
||||||
if (!sortmatches)
|
if (!sortmatches)
|
||||||
appenditem(item, &matches, &matchend);
|
appenditem(item, &matches, &matchend);
|
||||||
else {
|
else {
|
||||||
// exact matches go first, then prefixes with high priority, then prefixes, then substrings
|
// exact matches go first, then prefixes with high priority, then prefixes, then substrings
|
||||||
if (item->hp && !fstrncmp(tokv[0], item->text, len))
|
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))
|
else if (!tokc || !fstrncmp(text, item->text, textsize))
|
||||||
appenditem(item, &matches, &matchend);
|
appenditem(item, &matches, &matchend);
|
||||||
else if (!fstrncmp(tokv[0], item->text, len))
|
else if (!fstrncmp(tokv[0], item->text, len))
|
||||||
appenditem(item, &lprefix, &prefixend);
|
appenditem(item, &lprefix, &prefixend);
|
||||||
else
|
else
|
||||||
appenditem(item, &lsubstr, &substrend);
|
appenditem(item, &lsubstr, &substrend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lhpprefix) {
|
if (lhpprefix) {
|
||||||
if (matches) {
|
if (matches) {
|
||||||
matchend->right = lhpprefix;
|
matchend->right = lhpprefix;
|
||||||
lhpprefix->left = matchend;
|
lhpprefix->left = matchend;
|
||||||
} else
|
} else
|
||||||
matches = lhpprefix;
|
matches = lhpprefix;
|
||||||
matchend = hpprefixend;
|
matchend = hpprefixend;
|
||||||
}
|
}
|
||||||
if (lprefix) {
|
if (lprefix) {
|
||||||
if (matches) {
|
if (matches) {
|
||||||
matchend->right = lprefix;
|
matchend->right = lprefix;
|
||||||
lprefix->left = matchend;
|
lprefix->left = matchend;
|
||||||
} else
|
} else
|
||||||
matches = lprefix;
|
matches = lprefix;
|
||||||
matchend = prefixend;
|
matchend = prefixend;
|
||||||
}
|
}
|
||||||
if (lsubstr) {
|
if (lsubstr) {
|
||||||
if (matches) {
|
if (matches) {
|
||||||
matchend->right = lsubstr;
|
matchend->right = lsubstr;
|
||||||
lsubstr->left = matchend;
|
lsubstr->left = matchend;
|
||||||
} else
|
} else
|
||||||
matches = lsubstr;
|
matches = lsubstr;
|
||||||
matchend = substrend;
|
matchend = substrend;
|
||||||
}
|
}
|
||||||
curr = sel = matches;
|
curr = sel = matches;
|
||||||
|
|
||||||
for (i = 0; i < preselected; i++) {
|
for (i = 0; i < preselected; i++) {
|
||||||
if (sel && sel->right && (sel = sel->right) == next) {
|
if (sel && sel->right && (sel = sel->right) == next) {
|
||||||
curr = next;
|
curr = next;
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
}
|
}
|
||||||
|
|
||||||
int compare_distance(const void *a, const void *b) {
|
int compare_distance(const void *a, const void *b) {
|
||||||
struct item *da = *(struct item **) a;
|
struct item *da = *(struct item **) a;
|
||||||
struct item *db = *(struct item **) b;
|
struct item *db = *(struct item **) b;
|
||||||
|
|
||||||
if (!db)
|
if (!db)
|
||||||
return 1;
|
return 1;
|
||||||
if (!da)
|
if (!da)
|
||||||
return -1;
|
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;
|
||||||
}
|
}
|
||||||
|
|
82
libs/mouse.c
82
libs/mouse.c
|
@ -1,7 +1,7 @@
|
||||||
void buttonpress(XEvent *e) {
|
void buttonpress(XEvent *e) {
|
||||||
struct item *item;
|
struct item *item;
|
||||||
XButtonPressedEvent *ev = &e->xbutton;
|
XButtonPressedEvent *ev = &e->xbutton;
|
||||||
int x = 0, y = 0, h = bh, w, item_num = 0;
|
int x = 0, y = 0, h = bh, w, item_num = 0;
|
||||||
unsigned int i, click;
|
unsigned int i, click;
|
||||||
int xpad = 0;
|
int xpad = 0;
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ void buttonpress(XEvent *e) {
|
||||||
if (!hidecaps) capsWidth = pango_caps ? TEXTWM(capstext) : TEXTW(capstext);
|
if (!hidecaps) capsWidth = pango_caps ? TEXTWM(capstext) : TEXTW(capstext);
|
||||||
|
|
||||||
if (!strcmp(capstext, "")) capsWidth = 0; // no caps lock width for no chars
|
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
|
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;
|
w = (lines > 0 || !matches) ? mw - x : inputw;
|
||||||
|
|
||||||
if ((lines <= 0 && ev->x >= 0 && ev->x <= x + w + promptw +
|
if ((lines <= 0 && ev->x >= 0 && ev->x <= x + w + promptw +
|
||||||
((!prev || !curr->left) ? larrowWidth : 0)) ||
|
((!prev || !curr->left) ? larrowWidth : 0)) ||
|
||||||
(lines > 0 && ev->y >= y && ev->y <= y + h)) {
|
(lines > 0 && ev->y >= y && ev->y <= y + h)) {
|
||||||
|
|
||||||
click = ClickInput;
|
click = ClickInput;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// item click
|
// item click
|
||||||
if (lines > 0) {
|
if (lines > 0) {
|
||||||
// vertical list
|
// vertical list
|
||||||
w = mw - x;
|
w = mw - x;
|
||||||
for (item = curr; item != next; item = item->right) {
|
for (item = curr; item != next; item = item->right) {
|
||||||
if (item_num++ == lines) {
|
if (item_num++ == lines) {
|
||||||
item_num = 1;
|
item_num = 1;
|
||||||
x += w / columns;
|
x += w / columns;
|
||||||
y = 0;
|
y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
y += h;
|
y += h;
|
||||||
|
|
||||||
// ClickSelItem, called function doesn't matter
|
// 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++) {
|
for (i = 0; i < LENGTH(buttons); i++) {
|
||||||
if (ignoreglobalmouse) break;
|
if (ignoreglobalmouse) break;
|
||||||
if (buttons[i].click == ClickSelItem && buttons[i].button == ev->button && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) {
|
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;
|
click = ClickItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (matches) { // a single line, meaning it could be arrows too, so we check that here
|
} else if (matches) { // a single line, meaning it could be arrows too, so we check that here
|
||||||
// left arrow
|
// left arrow
|
||||||
x += inputw;
|
x += inputw;
|
||||||
w = larrowWidth;
|
w = larrowWidth;
|
||||||
if (prev && curr->left) {
|
if (prev && curr->left) {
|
||||||
if (ev->x >= x && ev->x <= x + w) {
|
if (ev->x >= x && ev->x <= x + w) {
|
||||||
click = ClickLArrow;
|
click = ClickLArrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// item click
|
// item click
|
||||||
// horizontal list
|
// horizontal list
|
||||||
for (item = curr; item != next; item = item->right) {
|
for (item = curr; item != next; item = item->right) {
|
||||||
x += w;
|
x += w;
|
||||||
w = MIN(TEXTW(item->text), mw - x - rarrowWidth);
|
w = MIN(TEXTW(item->text), mw - x - rarrowWidth);
|
||||||
if (ev->x >= x && ev->x <= x + w) {
|
if (ev->x >= x && ev->x <= x + w) {
|
||||||
for (i = 0; i < LENGTH(buttons); i++) {
|
for (i = 0; i < LENGTH(buttons); i++) {
|
||||||
if (ignoreglobalmouse) break;
|
if (ignoreglobalmouse) break;
|
||||||
if (buttons[i].click == ClickSelItem && buttons[i].button == ev->button && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) {
|
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
|
// right arrow
|
||||||
w = rarrowWidth;
|
w = rarrowWidth;
|
||||||
x = mw - w;
|
x = mw - w;
|
||||||
if (next && ev->x >= x && ev->x <= x + w) {
|
if (next && ev->x >= x && ev->x <= x + w) {
|
||||||
click = ClickRArrow;
|
click = ClickRArrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// go through mouse button array and run function
|
// go through mouse button array and run function
|
||||||
for (i = 0; i < LENGTH(buttons); i++) {
|
for (i = 0; i < LENGTH(buttons); i++) {
|
||||||
if (ignoreglobalmouse) break;
|
if (ignoreglobalmouse) break;
|
||||||
if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
|
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);
|
buttons[i].func(&buttons[i].arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ void buttonpress(XEvent *e) {
|
||||||
for (i = 0; i < LENGTH(cbuttons); i++) {
|
for (i = 0; i < LENGTH(cbuttons); i++) {
|
||||||
if (ignoreconfmouse) break;
|
if (ignoreconfmouse) break;
|
||||||
if (click == cbuttons[i].click && cbuttons[i].func && cbuttons[i].button == ev->button
|
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);
|
cbuttons[i].func(&cbuttons[i].arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
libs/mouse.h
10
libs/mouse.h
|
@ -13,11 +13,11 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int click;
|
unsigned int click;
|
||||||
unsigned int mask;
|
unsigned int mask;
|
||||||
unsigned int button;
|
unsigned int button;
|
||||||
void (*func)(Arg *arg);
|
void (*func)(Arg *arg);
|
||||||
Arg arg;
|
Arg arg;
|
||||||
} Mouse;
|
} Mouse;
|
||||||
|
|
||||||
static Mouse cbuttons[256];
|
static Mouse cbuttons[256];
|
||||||
|
|
28
libs/rtl.c
28
libs/rtl.c
|
@ -1,22 +1,22 @@
|
||||||
#if USERTL
|
#if USERTL
|
||||||
void apply_fribidi(char *str) {
|
void apply_fribidi(char *str) {
|
||||||
FriBidiStrIndex len = strlen(str);
|
FriBidiStrIndex len = strlen(str);
|
||||||
FriBidiChar logical[BUFSIZ];
|
FriBidiChar logical[BUFSIZ];
|
||||||
FriBidiChar visual[BUFSIZ];
|
FriBidiChar visual[BUFSIZ];
|
||||||
FriBidiParType base = FRIBIDI_PAR_ON;
|
FriBidiParType base = FRIBIDI_PAR_ON;
|
||||||
FriBidiCharSet charset;
|
FriBidiCharSet charset;
|
||||||
fribidi_boolean result;
|
fribidi_boolean result;
|
||||||
|
|
||||||
fribidi_text[0] = 0;
|
fribidi_text[0] = 0;
|
||||||
|
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
charset = fribidi_parse_charset("UTF-8");
|
charset = fribidi_parse_charset("UTF-8");
|
||||||
len = fribidi_charset_to_unicode(charset, str, len, logical);
|
len = fribidi_charset_to_unicode(charset, str, len, logical);
|
||||||
result = fribidi_log2vis(logical, len, &base, visual, NULL, NULL, NULL);
|
result = fribidi_log2vis(logical, len, &base, visual, NULL, NULL, NULL);
|
||||||
len = fribidi_unicode_to_charset(charset, visual, len, fribidi_text);
|
len = fribidi_unicode_to_charset(charset, visual, len, fribidi_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result||!result) return;
|
if (result||!result) return;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void apply_fribidi(char *str) {
|
void apply_fribidi(char *str) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
char sixd_to_8bit(int x) {
|
char sixd_to_8bit(int x) {
|
||||||
return x == 0 ? 0 : 0x37 + 0x28 * x;
|
return x == 0 ? 0 : 0x37 + 0x28 * x;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_appearance(void) {
|
void init_appearance(void) {
|
||||||
|
@ -41,45 +41,45 @@ void init_appearance(void) {
|
||||||
|
|
||||||
// create color schemes from array
|
// create color schemes from array
|
||||||
scheme = ecalloc(LENGTH(colors) + 1, sizeof(Clr *));
|
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++)
|
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++)
|
for (i = 0; i < LENGTH(textcolors) && i < LENGTH(textclrs); i++)
|
||||||
drw_clr_create(drw, &textclrs[i], textcolors[i], 0);
|
drw_clr_create(drw, &textclrs[i], textcolors[i], 0);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
drw_clr_create(drw, &textclrs[i++], "#000000", 0);
|
drw_clr_create(drw, &textclrs[i++], "#000000", 0);
|
||||||
for (; i < 7; i++) {
|
for (; i < 7; i++) {
|
||||||
snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
|
snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
|
||||||
!!(i & 1) * 0x7f,
|
!!(i & 1) * 0x7f,
|
||||||
!!(i & 2) * 0x7f,
|
!!(i & 2) * 0x7f,
|
||||||
!!(i & 4) * 0x7f);
|
!!(i & 4) * 0x7f);
|
||||||
drw_clr_create(drw, &textclrs[i], cbuf, 0);
|
drw_clr_create(drw, &textclrs[i], cbuf, 0);
|
||||||
}
|
}
|
||||||
if (i == 7)
|
if (i == 7)
|
||||||
drw_clr_create(drw, &textclrs[i++], "#000000", 0);
|
drw_clr_create(drw, &textclrs[i++], "#000000", 0);
|
||||||
if (i == 8)
|
if (i == 8)
|
||||||
drw_clr_create(drw, &textclrs[i++], "#333333", 0);
|
drw_clr_create(drw, &textclrs[i++], "#333333", 0);
|
||||||
for (; i < 16; i++) {
|
for (; i < 16; i++) {
|
||||||
snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
|
snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
|
||||||
!!(i & 1) * 0xff,
|
!!(i & 1) * 0xff,
|
||||||
!!(i & 2) * 0xff,
|
!!(i & 2) * 0xff,
|
||||||
!!(i & 4) * 0xff);
|
!!(i & 4) * 0xff);
|
||||||
drw_clr_create(drw, &textclrs[i], cbuf, 0);
|
drw_clr_create(drw, &textclrs[i], cbuf, 0);
|
||||||
}
|
}
|
||||||
for (; i < 6 * 6 * 6 + 16; i++) {
|
for (; i < 6 * 6 * 6 + 16; i++) {
|
||||||
snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
|
snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
|
||||||
sixd_to_8bit(((i - 16) / 36) % 6),
|
sixd_to_8bit(((i - 16) / 36) % 6),
|
||||||
sixd_to_8bit(((i - 16) / 6) % 6),
|
sixd_to_8bit(((i - 16) / 6) % 6),
|
||||||
sixd_to_8bit(((i - 16)) % 6));
|
sixd_to_8bit(((i - 16)) % 6));
|
||||||
drw_clr_create(drw, &textclrs[i], cbuf, 0);
|
drw_clr_create(drw, &textclrs[i], cbuf, 0);
|
||||||
}
|
}
|
||||||
for (; i < 256; i++) {
|
for (; i < 256; i++) {
|
||||||
snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x",
|
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,
|
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], cbuf, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,19 @@ static void init_appearance(void);
|
||||||
|
|
||||||
// Color schemes
|
// Color schemes
|
||||||
enum { SchemeLArrow,
|
enum { SchemeLArrow,
|
||||||
SchemeRArrow,
|
SchemeRArrow,
|
||||||
SchemeItemNorm,
|
SchemeItemNorm,
|
||||||
SchemeItemSel,
|
SchemeItemSel,
|
||||||
SchemeItemNormPri,
|
SchemeItemNormPri,
|
||||||
SchemeItemSelPri,
|
SchemeItemSelPri,
|
||||||
SchemeMenu,
|
SchemeMenu,
|
||||||
SchemeInput,
|
SchemeInput,
|
||||||
SchemePrompt,
|
SchemePrompt,
|
||||||
SchemeNormHighlight,
|
SchemeNormHighlight,
|
||||||
SchemeSelHighlight,
|
SchemeSelHighlight,
|
||||||
SchemeCaret,
|
SchemeCaret,
|
||||||
SchemeNumber,
|
SchemeNumber,
|
||||||
SchemeMode,
|
SchemeMode,
|
||||||
SchemeBorder,
|
SchemeBorder,
|
||||||
SchemeCaps,
|
SchemeCaps,
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,26 +7,26 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
void * ecalloc(size_t nmemb, size_t size) {
|
void * ecalloc(size_t nmemb, size_t size) {
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
if (!(p = calloc(nmemb, size)))
|
if (!(p = calloc(nmemb, size)))
|
||||||
die("calloc:");
|
die("calloc:");
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void die(const char *fmt, ...) {
|
void die(const char *fmt, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vfprintf(stderr, fmt, ap);
|
vfprintf(stderr, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
|
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
|
||||||
fputc(' ', stderr);
|
fputc(' ', stderr);
|
||||||
perror(NULL);
|
perror(NULL);
|
||||||
} else {
|
} else {
|
||||||
fputc('\n', stderr);
|
fputc('\n', stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
46
libs/sort.c
46
libs/sort.c
|
@ -1,31 +1,31 @@
|
||||||
char ** tokenize(char *source, const char *delim, int *llen) {
|
char ** tokenize(char *source, const char *delim, int *llen) {
|
||||||
int listlength = 0, list_size = 0;
|
int listlength = 0, list_size = 0;
|
||||||
char **list = NULL, *token;
|
char **list = NULL, *token;
|
||||||
|
|
||||||
token = strtok(source, delim);
|
token = strtok(source, delim);
|
||||||
while (token) {
|
while (token) {
|
||||||
if (listlength + 1 >= list_size) {
|
if (listlength + 1 >= list_size) {
|
||||||
if (!(list = realloc(list, (list_size += 8) * sizeof(*list))))
|
if (!(list = realloc(list, (list_size += 8) * sizeof(*list))))
|
||||||
die("spmenu: unable to realloc %zu bytes\n", list_size * sizeof(*list));
|
die("spmenu: unable to realloc %zu bytes\n", list_size * sizeof(*list));
|
||||||
}
|
}
|
||||||
if (!(list[listlength] = strdup(token)))
|
if (!(list[listlength] = strdup(token)))
|
||||||
die("spmenu: unable to strdup %zu bytes\n", strlen(token) + 1);
|
die("spmenu: unable to strdup %zu bytes\n", strlen(token) + 1);
|
||||||
token = strtok(NULL, delim);
|
token = strtok(NULL, delim);
|
||||||
listlength++;
|
listlength++;
|
||||||
}
|
}
|
||||||
|
|
||||||
*llen = listlength;
|
*llen = listlength;
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arrayhas(char **list, int length, char *item) {
|
int arrayhas(char **list, int length, char *item) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
size_t len1 = strlen(list[i]);
|
size_t len1 = strlen(list[i]);
|
||||||
size_t len2 = strlen(item);
|
size_t len2 = strlen(item);
|
||||||
if (!fstrncmp(list[i], item, len1 > len2 ? len2 : len1))
|
if (!fstrncmp(list[i], item, len1 > len2 ? len2 : len1))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
218
libs/stream.c
218
libs/stream.c
|
@ -1,12 +1,12 @@
|
||||||
void readstdin(void) {
|
void readstdin(void) {
|
||||||
char buf[sizeof text], *p;
|
char buf[sizeof text], *p;
|
||||||
size_t i, imax = 0, itemsiz = 0;
|
size_t i, imax = 0, itemsiz = 0;
|
||||||
unsigned int tmpmax = 0;
|
unsigned int tmpmax = 0;
|
||||||
|
|
||||||
if (passwd) {
|
if (passwd) {
|
||||||
inputw = lines = 0;
|
inputw = lines = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listfile) {
|
if (listfile) {
|
||||||
readfile();
|
readfile();
|
||||||
|
@ -15,23 +15,23 @@ void readstdin(void) {
|
||||||
|
|
||||||
int o = 0;
|
int o = 0;
|
||||||
|
|
||||||
// read each line from stdin and add it to the item list
|
// read each line from stdin and add it to the item list
|
||||||
for (i = 0; fgets(buf, sizeof buf, stdin); i++) {
|
for (i = 0; fgets(buf, sizeof buf, stdin); i++) {
|
||||||
if (i + 1 >= itemsiz) {
|
if (i + 1 >= itemsiz) {
|
||||||
itemsiz += 256;
|
itemsiz += 256;
|
||||||
if (!(items = realloc(items, itemsiz * sizeof(*items))))
|
if (!(items = realloc(items, itemsiz * sizeof(*items))))
|
||||||
die("spmenu: cannot realloc %zu bytes:", itemsiz * sizeof(*items));
|
die("spmenu: cannot realloc %zu bytes:", itemsiz * sizeof(*items));
|
||||||
}
|
}
|
||||||
if ((p = strchr(buf, '\n')))
|
if ((p = strchr(buf, '\n')))
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
if (!(items[i].text = strdup(buf)))
|
if (!(items[i].text = strdup(buf)))
|
||||||
die("spmenu: cannot strdup %u bytes:", strlen(buf) + 1);
|
die("spmenu: cannot strdup %u bytes:", strlen(buf) + 1);
|
||||||
items[i].hp = arrayhas(hpitems, hplength, items[i].text);
|
items[i].hp = arrayhas(hpitems, hplength, items[i].text);
|
||||||
drw_font_getexts(drw->font, buf, strlen(buf), &tmpmax, NULL, True);
|
drw_font_getexts(drw->font, buf, strlen(buf), &tmpmax, NULL, True);
|
||||||
if (tmpmax > inputw) {
|
if (tmpmax > inputw) {
|
||||||
inputw = tmpmax;
|
inputw = tmpmax;
|
||||||
imax = i;
|
imax = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
items[i].index = i;
|
items[i].index = i;
|
||||||
|
|
||||||
|
@ -39,36 +39,36 @@ void readstdin(void) {
|
||||||
o = 1;
|
o = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !USEIMAGE
|
#if !USEIMAGE
|
||||||
if (o) {
|
if (o) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
#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;
|
#if USEIMAGE
|
||||||
lines = MIN(lines, i);
|
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) {
|
void readfile(void) {
|
||||||
if (passwd){
|
if (passwd){
|
||||||
inputw = lines = 0;
|
inputw = lines = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t len;
|
size_t len;
|
||||||
static size_t c = 0;
|
static size_t c = 0;
|
||||||
char *l;
|
char *l;
|
||||||
|
|
||||||
|
@ -119,19 +119,19 @@ void readfile(void) {
|
||||||
o = 1;
|
o = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !USEIMAGE
|
#if !USEIMAGE
|
||||||
if (o) {
|
if (o) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inputw = items ? TEXTWM(items[i].text) : 0;
|
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;
|
if (!o) longestedge = imagegaps = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (i == listcount) {
|
if (i == listcount) {
|
||||||
listchanged = 0;
|
listchanged = 0;
|
||||||
|
@ -149,76 +149,76 @@ void readfile(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int parsemarkup(int index) {
|
int parsemarkup(int index) {
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
int w, h;
|
int w, h;
|
||||||
char *limg = NULL;
|
char *limg = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// parse image markup
|
// parse image markup
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
if(!strncmp("IMG:", items[index].text, strlen("IMG:"))) {
|
if(!strncmp("IMG:", items[index].text, strlen("IMG:"))) {
|
||||||
if(!(items[index].image = malloc(strlen(items[index].text)+1)))
|
if(!(items[index].image = malloc(strlen(items[index].text)+1)))
|
||||||
fprintf(stderr, "spmenu: cannot malloc %lu bytes\n", strlen(items[index].text));
|
fprintf(stderr, "spmenu: cannot malloc %lu bytes\n", strlen(items[index].text));
|
||||||
if(sscanf(items[index].text, "IMG:%[^\t]", items[index].image)) {
|
if(sscanf(items[index].text, "IMG:%[^\t]", items[index].image)) {
|
||||||
items[index].text += strlen("IMG:")+strlen(items[index].image)+1;
|
items[index].text += strlen("IMG:")+strlen(items[index].image)+1;
|
||||||
} else {
|
|
||||||
free(items[index].image);
|
|
||||||
items[index].image = NULL;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
free(items[index].image);
|
||||||
items[index].image = NULL;
|
items[index].image = NULL;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
items[index].image = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// load image cache (or generate)
|
// load image cache (or generate)
|
||||||
if (generatecache && longestedge <= maxcache && items[index].image && strcmp(items[index].image, limg ? limg : "")) {
|
if (generatecache && longestedge <= maxcache && items[index].image && strcmp(items[index].image, limg ? limg : "")) {
|
||||||
loadimagecache(items[index].image, &w, &h);
|
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) {
|
// spmenu:version
|
||||||
limg = items[index].image;
|
if (!strncmp("version", items[index].ex, strlen("version"))) {
|
||||||
}
|
fprintf(stdout, "spmenu version %s\n", VERSION);
|
||||||
#else // remove the data, just for convenience
|
exit(0);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USEIMAGE
|
// spmenu:license
|
||||||
if (limg) {
|
if (!strncmp("license", items[index].ex, strlen("license"))) {
|
||||||
return 1;
|
fprintf(stdout, "spmenu is licensed under the MIT license. See the included LICENSE file for more information.\n");
|
||||||
} else {
|
exit(0);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#else
|
}
|
||||||
|
|
||||||
|
#if USEIMAGE
|
||||||
|
if (limg) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
}
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,11 +29,11 @@ void theme_load(void) {
|
||||||
sprintf(theme, "%s/%s", xdg_conf, "spmenu/theme.conf");
|
sprintf(theme, "%s/%s", xdg_conf, "spmenu/theme.conf");
|
||||||
}
|
}
|
||||||
} else { // custom config path
|
} else { // custom config path
|
||||||
if (!(theme = malloc(snprintf(NULL, 0, "%s", argtheme) + 1))) {
|
if (!(theme = malloc(snprintf(NULL, 0, "%s", argtheme) + 1))) {
|
||||||
die("spmenu: failed to malloc theme");
|
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.
|
// don't bother trying to load if it doesn't exist.
|
||||||
|
@ -47,7 +47,7 @@ void theme_load(void) {
|
||||||
|
|
||||||
// attempt to read theme
|
// attempt to read theme
|
||||||
if (!config_read_file(&cfg, 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
|
// load options theme.window
|
||||||
|
|
54
libs/xrdb.c
54
libs/xrdb.c
|
@ -1,20 +1,20 @@
|
||||||
#if USEXRESOURCES
|
#if USEXRESOURCES
|
||||||
void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst) {
|
void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst) {
|
||||||
char *sdst = NULL;
|
char *sdst = NULL;
|
||||||
int *idst = NULL;
|
int *idst = NULL;
|
||||||
float *fdst = NULL;
|
float *fdst = NULL;
|
||||||
sdst = dst;
|
sdst = dst;
|
||||||
idst = dst;
|
idst = dst;
|
||||||
fdst = dst;
|
fdst = dst;
|
||||||
char fullname[256];
|
char fullname[256];
|
||||||
char *type;
|
char *type;
|
||||||
XrmValue ret;
|
XrmValue ret;
|
||||||
snprintf(fullname, sizeof(fullname), "%s.%s", "spmenu", name);
|
snprintf(fullname, sizeof(fullname), "%s.%s", "spmenu", name);
|
||||||
fullname[sizeof(fullname) - 1] = '\0';
|
fullname[sizeof(fullname) - 1] = '\0';
|
||||||
XrmGetResource(db, fullname, "*", &type, &ret);
|
XrmGetResource(db, fullname, "*", &type, &ret);
|
||||||
if (!xresources) return;
|
if (!xresources) return;
|
||||||
if (!(ret.addr == NULL || strncmp("String", type, 64))) {
|
if (!(ret.addr == NULL || strncmp("String", type, 64))) {
|
||||||
switch (rtype) { // type
|
switch (rtype) { // type
|
||||||
case STRING:
|
case STRING:
|
||||||
strcpy(sdst, ret.addr);
|
strcpy(sdst, ret.addr);
|
||||||
break;
|
break;
|
||||||
|
@ -25,22 +25,22 @@ void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *d
|
||||||
*fdst = strtof(ret.addr, NULL);
|
*fdst = strtof(ret.addr, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_xresources(void) {
|
void load_xresources(void) {
|
||||||
Display *display;
|
Display *display;
|
||||||
char *resm;
|
char *resm;
|
||||||
XrmDatabase db;
|
XrmDatabase db;
|
||||||
ResourcePref *p;
|
ResourcePref *p;
|
||||||
display = XOpenDisplay(NULL);
|
display = XOpenDisplay(NULL);
|
||||||
resm = XResourceManagerString(display);
|
resm = XResourceManagerString(display);
|
||||||
if (!resm || !xresources)
|
if (!resm || !xresources)
|
||||||
return;
|
return;
|
||||||
db = XrmGetStringDatabase(resm);
|
db = XrmGetStringDatabase(resm);
|
||||||
|
|
||||||
for (p = resources; p < resources + LENGTH(resources); p++)
|
for (p = resources; p < resources + LENGTH(resources); p++)
|
||||||
resource_load(db, p->name, p->type, p->dst);
|
resource_load(db, p->name, p->type, p->dst);
|
||||||
|
|
||||||
// recognize global colors
|
// recognize global colors
|
||||||
if (globalcolors) {
|
if (globalcolors) {
|
||||||
|
@ -48,6 +48,6 @@ void load_xresources(void) {
|
||||||
resource_load(db, p->name, p->type, p->dst);
|
resource_load(db, p->name, p->type, p->dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
XCloseDisplay(display);
|
XCloseDisplay(display);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
12
libs/xrdb.h
12
libs/xrdb.h
|
@ -1,14 +1,14 @@
|
||||||
#if USEXRESOURCES
|
#if USEXRESOURCES
|
||||||
enum resource_type {
|
enum resource_type {
|
||||||
STRING = 0,
|
STRING = 0,
|
||||||
INTEGER = 1,
|
INTEGER = 1,
|
||||||
FLOAT = 2
|
FLOAT = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *name;
|
char *name;
|
||||||
enum resource_type type;
|
enum resource_type type;
|
||||||
void *dst;
|
void *dst;
|
||||||
} ResourcePref;
|
} ResourcePref;
|
||||||
|
|
||||||
// declare functions
|
// declare functions
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// This .Xresources array is read and compared to the xrdb. Simply add to the array if you need to.
|
// This .Xresources array is read and compared to the xrdb. Simply add to the array if you need to.
|
||||||
#if USEXRESOURCES
|
#if USEXRESOURCES
|
||||||
ResourcePref resources[] = {
|
ResourcePref resources[] = {
|
||||||
{ "font", STRING, &font },
|
{ "font", STRING, &font },
|
||||||
{ "col_caretfg", STRING, &col_caretfg },
|
{ "col_caretfg", STRING, &col_caretfg },
|
||||||
{ "col_caretbg", STRING, &col_caretbg },
|
{ "col_caretbg", STRING, &col_caretbg },
|
||||||
{ "col_larrowfg", STRING, &col_larrowfg },
|
{ "col_larrowfg", STRING, &col_larrowfg },
|
||||||
|
@ -19,14 +19,14 @@ ResourcePref resources[] = {
|
||||||
{ "col_inputbg", STRING, &col_inputbg },
|
{ "col_inputbg", STRING, &col_inputbg },
|
||||||
{ "col_inputfg", STRING, &col_inputfg },
|
{ "col_inputfg", STRING, &col_inputfg },
|
||||||
{ "col_menu", STRING, &col_menu },
|
{ "col_menu", STRING, &col_menu },
|
||||||
{ "col_numfg", STRING, &col_numfg },
|
{ "col_numfg", STRING, &col_numfg },
|
||||||
{ "col_numbg", STRING, &col_numbg },
|
{ "col_numbg", STRING, &col_numbg },
|
||||||
{ "col_modefg", STRING, &col_modefg },
|
{ "col_modefg", STRING, &col_modefg },
|
||||||
{ "col_modebg", STRING, &col_modebg },
|
{ "col_modebg", STRING, &col_modebg },
|
||||||
{ "col_hlnormfg", STRING, &col_hlnormfg },
|
{ "col_hlnormfg", STRING, &col_hlnormfg },
|
||||||
{ "col_hlnormbg", STRING, &col_hlnormbg },
|
{ "col_hlnormbg", STRING, &col_hlnormbg },
|
||||||
{ "col_hlselfg", STRING, &col_hlselfg },
|
{ "col_hlselfg", STRING, &col_hlselfg },
|
||||||
{ "col_hlselbg", STRING, &col_hlselbg },
|
{ "col_hlselbg", STRING, &col_hlselbg },
|
||||||
{ "col_border", STRING, &col_border },
|
{ "col_border", STRING, &col_border },
|
||||||
{ "col_promptfg", STRING, &col_promptfg },
|
{ "col_promptfg", STRING, &col_promptfg },
|
||||||
{ "col_promptbg", STRING, &col_promptbg },
|
{ "col_promptbg", STRING, &col_promptbg },
|
||||||
|
@ -66,22 +66,22 @@ ResourcePref resources[] = {
|
||||||
{ "alpha_capsbg", INTEGER, &alpha_capsbg },
|
{ "alpha_capsbg", INTEGER, &alpha_capsbg },
|
||||||
|
|
||||||
// SGR sequence colors
|
// SGR sequence colors
|
||||||
{ "col_sgr0", STRING, &col_sgr0 },
|
{ "col_sgr0", STRING, &col_sgr0 },
|
||||||
{ "col_sgr1", STRING, &col_sgr1 },
|
{ "col_sgr1", STRING, &col_sgr1 },
|
||||||
{ "col_sgr2", STRING, &col_sgr2 },
|
{ "col_sgr2", STRING, &col_sgr2 },
|
||||||
{ "col_sgr3", STRING, &col_sgr3 },
|
{ "col_sgr3", STRING, &col_sgr3 },
|
||||||
{ "col_sgr4", STRING, &col_sgr4 },
|
{ "col_sgr4", STRING, &col_sgr4 },
|
||||||
{ "col_sgr5", STRING, &col_sgr5 },
|
{ "col_sgr5", STRING, &col_sgr5 },
|
||||||
{ "col_sgr6", STRING, &col_sgr6 },
|
{ "col_sgr6", STRING, &col_sgr6 },
|
||||||
{ "col_sgr7", STRING, &col_sgr7 },
|
{ "col_sgr7", STRING, &col_sgr7 },
|
||||||
{ "col_sgr8", STRING, &col_sgr8 },
|
{ "col_sgr8", STRING, &col_sgr8 },
|
||||||
{ "col_sgr9", STRING, &col_sgr9 },
|
{ "col_sgr9", STRING, &col_sgr9 },
|
||||||
{ "col_sgr10", STRING, &col_sgr10 },
|
{ "col_sgr10", STRING, &col_sgr10 },
|
||||||
{ "col_sgr11", STRING, &col_sgr11 },
|
{ "col_sgr11", STRING, &col_sgr11 },
|
||||||
{ "col_sgr12", STRING, &col_sgr12 },
|
{ "col_sgr12", STRING, &col_sgr12 },
|
||||||
{ "col_sgr13", STRING, &col_sgr13 },
|
{ "col_sgr13", STRING, &col_sgr13 },
|
||||||
{ "col_sgr14", STRING, &col_sgr14 },
|
{ "col_sgr14", STRING, &col_sgr14 },
|
||||||
{ "col_sgr15", STRING, &col_sgr15 },
|
{ "col_sgr15", STRING, &col_sgr15 },
|
||||||
|
|
||||||
// General options
|
// General options
|
||||||
{ "promptpwlstyle", INTEGER, &promptpwlstyle },
|
{ "promptpwlstyle", INTEGER, &promptpwlstyle },
|
||||||
|
@ -96,12 +96,12 @@ ResourcePref resources[] = {
|
||||||
{ "globalcolors", INTEGER, &globalcolors },
|
{ "globalcolors", INTEGER, &globalcolors },
|
||||||
{ "coloritems", INTEGER, &coloritems },
|
{ "coloritems", INTEGER, &coloritems },
|
||||||
{ "sgr", INTEGER, &sgr },
|
{ "sgr", INTEGER, &sgr },
|
||||||
{ "menuposition", INTEGER, &menuposition },
|
{ "menuposition", INTEGER, &menuposition },
|
||||||
{ "xpos", INTEGER, &xpos },
|
{ "xpos", INTEGER, &xpos },
|
||||||
{ "ypos", INTEGER, &ypos },
|
{ "ypos", INTEGER, &ypos },
|
||||||
{ "menuwidth", INTEGER, &menuwidth },
|
{ "menuwidth", INTEGER, &menuwidth },
|
||||||
{ "menupaddingv", INTEGER, &menupaddingv },
|
{ "menupaddingv", INTEGER, &menupaddingv },
|
||||||
{ "menupaddingh", INTEGER, &menupaddingh },
|
{ "menupaddingh", INTEGER, &menupaddingh },
|
||||||
{ "menumarginv", INTEGER, &menumarginv },
|
{ "menumarginv", INTEGER, &menumarginv },
|
||||||
{ "menumarginh", INTEGER, &menumarginh },
|
{ "menumarginh", INTEGER, &menumarginh },
|
||||||
{ "textpadding", INTEGER, &textpadding },
|
{ "textpadding", INTEGER, &textpadding },
|
||||||
|
@ -115,11 +115,11 @@ ResourcePref resources[] = {
|
||||||
{ "passwd", INTEGER, &passwd },
|
{ "passwd", INTEGER, &passwd },
|
||||||
{ "minwidth", INTEGER, &minwidth },
|
{ "minwidth", INTEGER, &minwidth },
|
||||||
{ "preselected", INTEGER, &preselected },
|
{ "preselected", INTEGER, &preselected },
|
||||||
{ "borderwidth", INTEGER, &borderwidth },
|
{ "borderwidth", INTEGER, &borderwidth },
|
||||||
{ "lines", INTEGER, &lines },
|
{ "lines", INTEGER, &lines },
|
||||||
{ "lineheight", INTEGER, &lineheight },
|
{ "lineheight", INTEGER, &lineheight },
|
||||||
{ "columns", INTEGER, &columns },
|
{ "columns", INTEGER, &columns },
|
||||||
{ "maxhist", INTEGER, &maxhist },
|
{ "maxhist", INTEGER, &maxhist },
|
||||||
{ "hideitem", INTEGER, &hideitem },
|
{ "hideitem", INTEGER, &hideitem },
|
||||||
{ "hidematchcount", INTEGER, &hidematchcount },
|
{ "hidematchcount", INTEGER, &hidematchcount },
|
||||||
{ "hidehighlight", INTEGER, &hidehighlight },
|
{ "hidehighlight", INTEGER, &hidehighlight },
|
||||||
|
@ -133,7 +133,7 @@ ResourcePref resources[] = {
|
||||||
{ "hidecaret", INTEGER, &hidecaret },
|
{ "hidecaret", INTEGER, &hidecaret },
|
||||||
{ "hidecursor", INTEGER, &hidecaret },
|
{ "hidecursor", INTEGER, &hidecaret },
|
||||||
{ "hidecaps", INTEGER, &hidecaps },
|
{ "hidecaps", INTEGER, &hidecaps },
|
||||||
{ "histdup", INTEGER, &histdup },
|
{ "histdup", INTEGER, &histdup },
|
||||||
{ "casesensitive", INTEGER, &casesensitive },
|
{ "casesensitive", INTEGER, &casesensitive },
|
||||||
{ "imagewidth", INTEGER, &imagewidth },
|
{ "imagewidth", INTEGER, &imagewidth },
|
||||||
{ "imageheight", INTEGER, &imageheight },
|
{ "imageheight", INTEGER, &imageheight },
|
||||||
|
@ -163,51 +163,51 @@ ResourcePref resources[] = {
|
||||||
|
|
||||||
// global colors
|
// global colors
|
||||||
ResourcePref cols[] = {
|
ResourcePref cols[] = {
|
||||||
{ "color10", STRING, &col_caretfg },
|
{ "color10", STRING, &col_caretfg },
|
||||||
{ "color0", STRING, &col_caretbg },
|
{ "color0", STRING, &col_caretbg },
|
||||||
{ "color4", STRING, &col_larrowfg },
|
{ "color4", STRING, &col_larrowfg },
|
||||||
{ "color4", STRING, &col_rarrowfg },
|
{ "color4", STRING, &col_rarrowfg },
|
||||||
{ "color10", STRING, &col_itemnormfg },
|
{ "color10", STRING, &col_itemnormfg },
|
||||||
{ "color10", STRING, &col_itemnormprifg },
|
{ "color10", STRING, &col_itemnormprifg },
|
||||||
{ "color10", STRING, &col_inputfg },
|
{ "color10", STRING, &col_inputfg },
|
||||||
{ "color0", STRING, &col_itemnormbg },
|
{ "color0", STRING, &col_itemnormbg },
|
||||||
{ "color0", STRING, &col_itemnormpribg },
|
{ "color0", STRING, &col_itemnormpribg },
|
||||||
{ "color0", STRING, &col_menu },
|
{ "color0", STRING, &col_menu },
|
||||||
{ "color0", STRING, &col_larrowbg },
|
{ "color0", STRING, &col_larrowbg },
|
||||||
{ "color0", STRING, &col_rarrowbg },
|
{ "color0", STRING, &col_rarrowbg },
|
||||||
{ "color0", STRING, &col_itemselfg },
|
{ "color0", STRING, &col_itemselfg },
|
||||||
{ "color0", STRING, &col_itemselprifg },
|
{ "color0", STRING, &col_itemselprifg },
|
||||||
{ "color0", STRING, &col_inputbg },
|
{ "color0", STRING, &col_inputbg },
|
||||||
{ "color12", STRING, &col_promptbg },
|
{ "color12", STRING, &col_promptbg },
|
||||||
{ "color0", STRING, &col_promptfg },
|
{ "color0", STRING, &col_promptfg },
|
||||||
{ "color7", STRING, &col_capsbg },
|
{ "color7", STRING, &col_capsbg },
|
||||||
{ "color0", STRING, &col_capsfg },
|
{ "color0", STRING, &col_capsfg },
|
||||||
{ "color6", STRING, &col_itemselbg },
|
{ "color6", STRING, &col_itemselbg },
|
||||||
{ "color6", STRING, &col_itemselpribg },
|
{ "color6", STRING, &col_itemselpribg },
|
||||||
{ "color6", STRING, &col_border },
|
{ "color6", STRING, &col_border },
|
||||||
{ "color0", STRING, &col_numfg },
|
{ "color0", STRING, &col_numfg },
|
||||||
{ "color5", STRING, &col_numbg },
|
{ "color5", STRING, &col_numbg },
|
||||||
{ "color0", STRING, &col_modefg },
|
{ "color0", STRING, &col_modefg },
|
||||||
{ "color11", STRING, &col_modebg },
|
{ "color11", STRING, &col_modebg },
|
||||||
{ "color2", STRING, &col_hlnormbg },
|
{ "color2", STRING, &col_hlnormbg },
|
||||||
{ "color3", STRING, &col_hlselbg },
|
{ "color3", STRING, &col_hlselbg },
|
||||||
{ "color0", STRING, &col_hlnormfg },
|
{ "color0", STRING, &col_hlnormfg },
|
||||||
{ "color0", STRING, &col_hlselfg },
|
{ "color0", STRING, &col_hlselfg },
|
||||||
{ "color0", STRING, &col_sgr0 },
|
{ "color0", STRING, &col_sgr0 },
|
||||||
{ "color1", STRING, &col_sgr1 },
|
{ "color1", STRING, &col_sgr1 },
|
||||||
{ "color2", STRING, &col_sgr2 },
|
{ "color2", STRING, &col_sgr2 },
|
||||||
{ "color3", STRING, &col_sgr3 },
|
{ "color3", STRING, &col_sgr3 },
|
||||||
{ "color4", STRING, &col_sgr4 },
|
{ "color4", STRING, &col_sgr4 },
|
||||||
{ "color5", STRING, &col_sgr5 },
|
{ "color5", STRING, &col_sgr5 },
|
||||||
{ "color6", STRING, &col_sgr6 },
|
{ "color6", STRING, &col_sgr6 },
|
||||||
{ "color7", STRING, &col_sgr7 },
|
{ "color7", STRING, &col_sgr7 },
|
||||||
{ "color8", STRING, &col_sgr8 },
|
{ "color8", STRING, &col_sgr8 },
|
||||||
{ "color9", STRING, &col_sgr9 },
|
{ "color9", STRING, &col_sgr9 },
|
||||||
{ "color10", STRING, &col_sgr10 },
|
{ "color10", STRING, &col_sgr10 },
|
||||||
{ "color11", STRING, &col_sgr11 },
|
{ "color11", STRING, &col_sgr11 },
|
||||||
{ "color12", STRING, &col_sgr12 },
|
{ "color12", STRING, &col_sgr12 },
|
||||||
{ "color13", STRING, &col_sgr13 },
|
{ "color13", STRING, &col_sgr13 },
|
||||||
{ "color14", STRING, &col_sgr14 },
|
{ "color14", STRING, &col_sgr14 },
|
||||||
{ "color15", STRING, &col_sgr15 },
|
{ "color15", STRING, &col_sgr15 },
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -70,8 +70,8 @@ declare -a icondir
|
||||||
|
|
||||||
# TODO: mac support
|
# TODO: mac support
|
||||||
fail_mac() {
|
fail_mac() {
|
||||||
[ -f "/usr/local/share/spmenu/allowusageonmac" ] && return
|
[ -f "/usr/local/share/spmenu/allowusageonmac" ] && return
|
||||||
cat << EOF
|
cat << EOF
|
||||||
spmenu_run currently does not support macOS due to the outdated Bash version.
|
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.
|
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 | \
|
xargs ls -lu --time-style=+%s 2>&1 | \
|
||||||
grep -vE "$HIDDEN_KEYWORDS" | \
|
grep -vE "$HIDDEN_KEYWORDS" | \
|
||||||
grep -E "$KEYWORDS"
|
grep -E "$KEYWORDS"
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "$SORT_BY_RECENT" != "false" ]; then
|
if [ "$SORT_BY_RECENT" != "false" ]; then
|
||||||
print | awk '/^(-|l)/ { print $6, $7 }' | sort "${sort_args[@]}" | cut -d' ' -f 2 2>&1
|
print | awk '/^(-|l)/ { print $6, $7 }' | sort "${sort_args[@]}" | cut -d' ' -f 2 2>&1
|
||||||
else
|
else
|
||||||
print | awk '/^(-|l)/ { print $7 }' | sort "${sort_args[@]}" | cut -d' ' -f 2 2>&1
|
print | awk '/^(-|l)/ { print $7 }' | sort "${sort_args[@]}" | cut -d' ' -f 2 2>&1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# uniq
|
# uniq
|
||||||
if [ "$DISPLAY_DUPLICATES" != "false" ]; then
|
if [ "$DISPLAY_DUPLICATES" != "false" ]; then
|
||||||
|
@ -134,12 +134,12 @@ path() {
|
||||||
}
|
}
|
||||||
|
|
||||||
print_help() {
|
print_help() {
|
||||||
if [ "$DMENU_COMPAT" != "true" ]; then
|
if [ "$DMENU_COMPAT" != "true" ]; then
|
||||||
COL='\033[0;31m'
|
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"
|
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"
|
read -ra rl_ex <<< "$RUNLAUNCHER_EX_ARGS"
|
||||||
fi
|
fi
|
||||||
cat << EOF | $RUNLAUNCHER "${rl_help[@]}" "${rl_ex[@]}" > /dev/null
|
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.
|
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 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.
|
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() {
|
print_cli_help() {
|
||||||
cat << EOF
|
cat << EOF
|
||||||
spmenu_run - Run launcher for spmenu
|
spmenu_run - Run launcher for spmenu
|
||||||
|
|
||||||
spmenu_run -x, --run List entries in \$PATH.
|
spmenu_run -x, --run List entries in \$PATH.
|
||||||
|
@ -174,9 +174,9 @@ EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
print_config() {
|
print_config() {
|
||||||
[ -f "$CONFDIR/spmenu/run/config" ] && . "$CONFDIR/spmenu/run/config" && return
|
[ -f "$CONFDIR/spmenu/run/config" ] && . "$CONFDIR/spmenu/run/config" && return
|
||||||
mkdir -p "$CONFDIR/spmenu/run"
|
mkdir -p "$CONFDIR/spmenu/run"
|
||||||
cat << EOF > "$CONFDIR/spmenu/run/config"
|
cat << EOF > "$CONFDIR/spmenu/run/config"
|
||||||
# spmenu_run default configuration file
|
# spmenu_run default configuration file
|
||||||
#
|
#
|
||||||
# This is the configuration file for the run launcher spmenu comes with.
|
# 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")" & ;;
|
"web") $BROWSER "$(printf "%s" "$sout" | sed "s/www //g")" & ;;
|
||||||
"torrent") $TORRENT "$(printf "%s" "$sout" | sed "s/magnet //g")" & ;;
|
"torrent") $TORRENT "$(printf "%s" "$sout" | sed "s/magnet //g")" & ;;
|
||||||
"man") exec="$(printf "%s" "$sout" | sed "s/?//g")"
|
"man") exec="$(printf "%s" "$sout" | sed "s/?//g")"
|
||||||
[ -x "$(command -v "$exec")" ] || return
|
[ -x "$(command -v "$exec")" ] || return
|
||||||
if [ "$(command -v read_man)" ]; then
|
if [ "$(command -v read_man)" ]; then
|
||||||
read_man "$exec"
|
read_man "$exec"
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
read_nman "$exec"
|
read_nman "$exec"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,39 +351,39 @@ read_args() {
|
||||||
-o|-stdout|--stdout) remove_arg "$arg" && STDOUT=true ;;
|
-o|-stdout|--stdout) remove_arg "$arg" && STDOUT=true ;;
|
||||||
-no|-no-stdout) remove_arg "$arg" && STDOUT=false ;;
|
-no|-no-stdout) remove_arg "$arg" && STDOUT=false ;;
|
||||||
-f|-fm|--fm) remove_arg "$arg"
|
-f|-fm|--fm) remove_arg "$arg"
|
||||||
[ -d "$narg" ] && dir="$narg" && remove_arg "$narg"
|
[ -d "$narg" ] && dir="$narg" && remove_arg "$narg"
|
||||||
function=fm
|
function=fm
|
||||||
;;
|
;;
|
||||||
-c|-cc|--clear-cache) remove_arg "$arg"
|
-c|-cc|--clear-cache) remove_arg "$arg"
|
||||||
clearcache="true"
|
clearcache="true"
|
||||||
;;
|
;;
|
||||||
-d|-desktop|--desktop) remove_arg "$arg"
|
-d|-desktop|--desktop) remove_arg "$arg"
|
||||||
function=desktop
|
function=desktop
|
||||||
;;
|
;;
|
||||||
-p|-full-path|--full-path) remove_arg "$arg"
|
-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"
|
-np|-no-full-path|--no-full-path) remove_arg "$arg"
|
||||||
USE_FULL_PATH="false"
|
USE_FULL_PATH="false"
|
||||||
;;
|
;;
|
||||||
-dm|-dmenu|--dmenu) remove_arg "$arg"
|
-dm|-dmenu|--dmenu) remove_arg "$arg"
|
||||||
DMENU_COMPAT="true"
|
DMENU_COMPAT="true"
|
||||||
;;
|
;;
|
||||||
-ndm|-no-dmenu|--no-dmenu) remove_arg "$arg"
|
-ndm|-no-dmenu|--no-dmenu) remove_arg "$arg"
|
||||||
DMENU_COMPAT="false"
|
DMENU_COMPAT="false"
|
||||||
;;
|
;;
|
||||||
-a|-args|--args) remove_arg "$arg"
|
-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"
|
remove_arg "$narg"
|
||||||
MARGS="$narg"
|
MARGS="$narg"
|
||||||
;;
|
;;
|
||||||
-h|--help) remove_arg "$arg" && function=help
|
-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"
|
*) printf "spmenu_run: Invalid argument: '%s'. If you meant to pass this to spmenu, use the '%s' option.\n" "$arg" "-a"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
[ "$argc" = "$i" ] && break
|
[ "$argc" = "$i" ] && break
|
||||||
|
@ -410,7 +410,7 @@ exec_file() {
|
||||||
else
|
else
|
||||||
$GENERIC "$1"
|
$GENERIC "$1"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,17 +448,17 @@ prepare_dirnav() {
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
print_desktop_help() {
|
print_desktop_help() {
|
||||||
if [ "$DMENU_COMPAT" != "true" ]; then
|
if [ "$DMENU_COMPAT" != "true" ]; then
|
||||||
COL='\033[0;31m'
|
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"
|
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}"
|
read -ra rl_ex <<< "${RUNLAUNCHER_EX_ARGS}"
|
||||||
fi
|
fi
|
||||||
cat << EOF | $RUNLAUNCHER "${rl_help[@]}" "${rl_ex[@]}" > /dev/null
|
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.
|
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 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.
|
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
|
[ "$menusel" = "?" ] && print_desktop_help && print_desktop_menu
|
||||||
command -v desktop_post_func > /dev/null && desktop_post_func "$menusel"
|
command -v desktop_post_func > /dev/null && desktop_post_func "$menusel"
|
||||||
[ -z "$menusel" ] && return 1 \
|
[ -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
|
# this must now be the title only
|
||||||
menusel="$(printf "%s" "$menusel" | sed "s/ -.*//")"
|
menusel="$(printf "%s" "$menusel" | sed "s/ -.*//")"
|
||||||
|
@ -729,20 +729,20 @@ main() {
|
||||||
"run")
|
"run")
|
||||||
parse "$args"
|
parse "$args"
|
||||||
exec_cmd "$args"
|
exec_cmd "$args"
|
||||||
;;
|
;;
|
||||||
"fm") prepare_dirnav "$args"
|
"fm") prepare_dirnav "$args"
|
||||||
;;
|
;;
|
||||||
"desktop")
|
"desktop")
|
||||||
print_desktop_menu "$args"
|
print_desktop_menu "$args"
|
||||||
;;
|
;;
|
||||||
"help")
|
"help")
|
||||||
print_cli_help
|
print_cli_help
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
printf "Undefined function: '%s'\n" "$function"
|
printf "Undefined function: '%s'\n" "$function"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,39 +46,39 @@ command -v maim > /dev/null && maim -uB > /tmp/image.png
|
||||||
IMAGE="/tmp/image.png"
|
IMAGE="/tmp/image.png"
|
||||||
|
|
||||||
main() {
|
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\
|
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${b1}\n\
|
||||||
$IMAGEPREFIX$IMAGE\t${b2}\n\
|
$IMAGEPREFIX$IMAGE\t${b2}\n\
|
||||||
$IMAGEPREFIX$IMAGE\t${b3}\n\
|
$IMAGEPREFIX$IMAGE\t${b3}\n\
|
||||||
$IMAGEPREFIX$IMAGE\t${b4}\n\
|
$IMAGEPREFIX$IMAGE\t${b4}\n\
|
||||||
$IMAGEPREFIX$IMAGE\t${b5}\n\
|
$IMAGEPREFIX$IMAGE\t${b5}\n\
|
||||||
$IMAGEPREFIX$IMAGE\t${b6}\n\
|
$IMAGEPREFIX$IMAGE\t${b6}\n\
|
||||||
$IMAGEPREFIX$IMAGE\t${b7}\n\
|
$IMAGEPREFIX$IMAGE\t${b7}\n\
|
||||||
$IMAGEPREFIX$IMAGE\t${b8}\n\
|
$IMAGEPREFIX$IMAGE\t${b8}\n\
|
||||||
$IMAGEPREFIX$IMAGE\t${b9}\n\
|
$IMAGEPREFIX$IMAGE\t${b9}\n\
|
||||||
$IMAGEPREFIX$IMAGE\t${b10}\n\
|
$IMAGEPREFIX$IMAGE\t${b10}\n\
|
||||||
$IMAGEPREFIX$IMAGE\t${b11}\n\
|
$IMAGEPREFIX$IMAGE\t${b11}\n\
|
||||||
$IMAGEPREFIX$IMAGE\t${b12}\n\
|
$IMAGEPREFIX$IMAGE\t${b12}\n\
|
||||||
$IMAGEPREFIX$IMAGE\t${b13}\n\
|
$IMAGEPREFIX$IMAGE\t${b13}\n\
|
||||||
$IMAGEPREFIX$IMAGE\t${b14}\n\
|
$IMAGEPREFIX$IMAGE\t${b14}\n\
|
||||||
$IMAGEPREFIX$IMAGE\t${b15}\n\
|
$IMAGEPREFIX$IMAGE\t${b15}\n\
|
||||||
$IMAGEPREFIX$IMAGE\t${b16}\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${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<b>qwertyuiop[]asdf</b> - b\n\
|
||||||
$IMAGEPREFIX$IMAGE\t<i>qwertyuiop[]asdf</i> - i\n\
|
$IMAGEPREFIX$IMAGE\t<i>qwertyuiop[]asdf</i> - i\n\
|
||||||
$IMAGEPREFIX$IMAGE\t<s>qwertyuiop[]asdf</s> - s\n\
|
$IMAGEPREFIX$IMAGE\t<s>qwertyuiop[]asdf</s> - s\n\
|
||||||
$IMAGEPREFIX$IMAGE\t<u>qwertyuiop[]asdf</u> - u\n\
|
$IMAGEPREFIX$IMAGE\t<u>qwertyuiop[]asdf</u> - u\n\
|
||||||
$IMAGEPREFIX$IMAGE\t<sub>qwertyuiop[]asdf - sub</sub>\n\
|
$IMAGEPREFIX$IMAGE\t<sub>qwertyuiop[]asdf - sub</sub>\n\
|
||||||
$IMAGEPREFIX$IMAGE\t<sup>qwertyuiop[]asdf - sup</sup>\n\
|
$IMAGEPREFIX$IMAGE\t<sup>qwertyuiop[]asdf - sup</sup>\n\
|
||||||
$IMAGEPREFIX$IMAGE\t<tt>qwertyuiop[]asdf</tt> - tt\n\
|
$IMAGEPREFIX$IMAGE\t<tt>qwertyuiop[]asdf</tt> - tt\n\
|
||||||
$IMAGEPREFIX$IMAGE\t<small>qwertyuiop[]asdf</small> - small\n\
|
$IMAGEPREFIX$IMAGE\t<small>qwertyuiop[]asdf</small> - small\n\
|
||||||
$IMAGEPREFIX$IMAGE\t<big>qwertyuiop[]asdf</big> - big\n\
|
$IMAGEPREFIX$IMAGE\t<big>qwertyuiop[]asdf</big> - big\n\
|
||||||
$IMAGEPREFIX$IMAGE\t\n\
|
$IMAGEPREFIX$IMAGE\t\n\
|
||||||
$IMAGEPREFIX$IMAGE\tArguments will be passed to spmenu.\n\
|
$IMAGEPREFIX$IMAGE\tArguments will be passed to spmenu.\n\
|
||||||
$IMAGEPREFIX$IMAGE\tReport any issues at the Codeberg repo.\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>"
|
" | spmenu --no-alpha --lines 40 $IMAGEARG "$@" --columns 1 --prompt "<big>spmenu <i>test</i> <small>script</small></big>"
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|
498
spmenu.c
498
spmenu.c
|
@ -161,16 +161,16 @@ static int screen;
|
||||||
|
|
||||||
// item struct
|
// item struct
|
||||||
struct item {
|
struct item {
|
||||||
char *text;
|
char *text;
|
||||||
char *clntext;
|
char *clntext;
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
char *image;
|
char *image;
|
||||||
#endif
|
#endif
|
||||||
char *ex;
|
char *ex;
|
||||||
struct item *left, *right;
|
struct item *left, *right;
|
||||||
int hp;
|
int hp;
|
||||||
int index;
|
int index;
|
||||||
double distance;
|
double distance;
|
||||||
};
|
};
|
||||||
|
|
||||||
// image globals
|
// image globals
|
||||||
|
@ -285,40 +285,40 @@ static char *(*fstrstr)(const char *, const char *) = cistrstr;
|
||||||
#include "libs/event.c"
|
#include "libs/event.c"
|
||||||
|
|
||||||
void appenditem(struct item *item, struct item **list, struct item **last) {
|
void appenditem(struct item *item, struct item **list, struct item **last) {
|
||||||
if (*last)
|
if (*last)
|
||||||
(*last)->right = item;
|
(*last)->right = item;
|
||||||
else
|
else
|
||||||
*list = item;
|
*list = item;
|
||||||
|
|
||||||
item->left = *last;
|
item->left = *last;
|
||||||
item->right = NULL;
|
item->right = NULL;
|
||||||
*last = item;
|
*last = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
void recalculatenumbers(void) {
|
void recalculatenumbers(void) {
|
||||||
unsigned int numer = 0, denom = 0;
|
unsigned int numer = 0, denom = 0;
|
||||||
struct item *item;
|
struct item *item;
|
||||||
if (matchend) {
|
if (matchend) {
|
||||||
numer++;
|
numer++;
|
||||||
|
|
||||||
// walk through items that match and add to numer
|
// walk through items that match and add to numer
|
||||||
for (item = matchend; item && item->left; item = item->left)
|
for (item = matchend; item && item->left; item = item->left)
|
||||||
numer++;
|
numer++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// walk through all items, matching or not and add to denom
|
// walk through all items, matching or not and add to denom
|
||||||
for (item = items; item && item->text; item++)
|
for (item = items; item && item->text; item++)
|
||||||
denom++;
|
denom++;
|
||||||
|
|
||||||
snprintf(numbers, NUMBERSBUFSIZE, "%d/%d", numer, denom);
|
snprintf(numbers, NUMBERSBUFSIZE, "%d/%d", numer, denom);
|
||||||
}
|
}
|
||||||
|
|
||||||
void calcoffsets(void) {
|
void calcoffsets(void) {
|
||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
if (lines > 0)
|
if (lines > 0)
|
||||||
n = lines * columns * bh;
|
n = lines * columns * bh;
|
||||||
else { // no lines, therefore the size of items must be decreased to fit the menu elements
|
else { // no lines, therefore the size of items must be decreased to fit the menu elements
|
||||||
int numberWidth = 0;
|
int numberWidth = 0;
|
||||||
int modeWidth = 0;
|
int modeWidth = 0;
|
||||||
int larrowWidth = 0;
|
int larrowWidth = 0;
|
||||||
|
@ -334,85 +334,85 @@ void calcoffsets(void) {
|
||||||
if (!strcmp(capstext, ""))
|
if (!strcmp(capstext, ""))
|
||||||
capsWidth = 0;
|
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
|
// calculate which items will begin the next page
|
||||||
for (i = 0, next = curr; next; next = next->right)
|
for (i = 0, next = curr; next; next = next->right)
|
||||||
if ((i += (lines > 0) ? bh : MIN(TEXTWM(next->text), n)) > n)
|
if ((i += (lines > 0) ? bh : MIN(TEXTWM(next->text), n)) > n)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// calculate which items will begin the previous page
|
// calculate which items will begin the previous page
|
||||||
for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
|
for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
|
||||||
if ((i += (lines > 0) ? bh : MIN(TEXTWM(prev->left->text), n)) > n)
|
if ((i += (lines > 0) ? bh : MIN(TEXTWM(prev->left->text), n)) > n)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int max_textw(void) {
|
int max_textw(void) {
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
for (struct item *item = items; item && item->text; item++)
|
for (struct item *item = items; item && item->text; item++)
|
||||||
len = MAX(TEXTW(item->text), len);
|
len = MAX(TEXTW(item->text), len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup(void) {
|
void cleanup(void) {
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
cleanupimage(); // function frees images
|
cleanupimage(); // function frees images
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
XUngrabKey(dpy, AnyKey, AnyModifier, root); // ungrab keys
|
XUngrabKey(dpy, AnyKey, AnyModifier, root); // ungrab keys
|
||||||
|
|
||||||
// free color scheme
|
// free color scheme
|
||||||
for (i = 0; i < LENGTH(colors) + 1; i++)
|
for (i = 0; i < LENGTH(colors) + 1; i++)
|
||||||
free(scheme[i]);
|
free(scheme[i]);
|
||||||
|
|
||||||
// free high priority items
|
// free high priority items
|
||||||
for (i = 0; i < hplength; ++i)
|
for (i = 0; i < hplength; ++i)
|
||||||
free(hpitems[i]);
|
free(hpitems[i]);
|
||||||
|
|
||||||
// free drawing and close the display
|
// free drawing and close the display
|
||||||
drw_free(drw);
|
drw_free(drw);
|
||||||
XSync(dpy, False);
|
XSync(dpy, False);
|
||||||
XCloseDisplay(dpy);
|
XCloseDisplay(dpy);
|
||||||
}
|
}
|
||||||
|
|
||||||
char * cistrstr(const char *h, const char *n) {
|
char * cistrstr(const char *h, const char *n) {
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if (!n[0])
|
if (!n[0])
|
||||||
return (char *)h;
|
return (char *)h;
|
||||||
|
|
||||||
for (; *h; ++h) {
|
for (; *h; ++h) {
|
||||||
for (i = 0; n[i] && tolower((unsigned char)n[i]) ==
|
for (i = 0; n[i] && tolower((unsigned char)n[i]) ==
|
||||||
tolower((unsigned char)h[i]); ++i);
|
tolower((unsigned char)h[i]); ++i);
|
||||||
|
|
||||||
if (n[i] == '\0')
|
if (n[i] == '\0')
|
||||||
return (char *)h;
|
return (char *)h;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void grabfocus(void) {
|
void grabfocus(void) {
|
||||||
struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
|
struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
|
||||||
Window focuswin;
|
Window focuswin;
|
||||||
int i, revertwin;
|
int i, revertwin;
|
||||||
XWindowAttributes wa;
|
XWindowAttributes wa;
|
||||||
|
|
||||||
XSync(dpy, False);
|
XSync(dpy, False);
|
||||||
XGetWindowAttributes(dpy, win, &wa);
|
XGetWindowAttributes(dpy, win, &wa);
|
||||||
|
|
||||||
for (i = 0; i < 100; ++i) {
|
for (i = 0; i < 100; ++i) {
|
||||||
XGetInputFocus(dpy, &focuswin, &revertwin);
|
XGetInputFocus(dpy, &focuswin, &revertwin);
|
||||||
if (focuswin == win)
|
if (focuswin == win)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// if it's a client, we can't just steal all the input for ourselves
|
// if it's a client, we can't just steal all the input for ourselves
|
||||||
if (managed) {
|
if (managed) {
|
||||||
if (wa.map_state == IsViewable) {
|
if (wa.map_state == IsViewable) {
|
||||||
XTextProperty prop;
|
XTextProperty prop;
|
||||||
char *windowtitle = prompt != NULL ? prompt : "spmenu";
|
char *windowtitle = prompt != NULL ? prompt : "spmenu";
|
||||||
|
@ -426,130 +426,130 @@ void grabfocus(void) {
|
||||||
XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
|
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) {
|
void insert(const char *str, ssize_t n) {
|
||||||
if (strlen(text) + n > sizeof text - 1)
|
if (strlen(text) + n > sizeof text - 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// move existing text out of the way, insert new text, and update cursor
|
// 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));
|
memmove(&text[cursor + n], &text[cursor], sizeof text - cursor - MAX(n, 0));
|
||||||
|
|
||||||
// update cursor
|
// update cursor
|
||||||
if (n > 0 && str && n)
|
if (n > 0 && str && n)
|
||||||
memcpy(&text[cursor], str, n);
|
memcpy(&text[cursor], str, n);
|
||||||
|
|
||||||
// add to cursor position and continue matching
|
// add to cursor position and continue matching
|
||||||
cursor += n;
|
cursor += n;
|
||||||
match();
|
match();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nextrune(int inc) {
|
size_t nextrune(int inc) {
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
// return location of next utf8 rune in the given direction (+1 or -1)
|
// 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)
|
for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc)
|
||||||
;
|
;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pastesel(void) {
|
void pastesel(void) {
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
int di;
|
int di;
|
||||||
unsigned long dl;
|
unsigned long dl;
|
||||||
Atom da;
|
Atom da;
|
||||||
|
|
||||||
// we have been given the current selection, now insert it into input
|
// we have been given the current selection, now insert it into input
|
||||||
if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False,
|
if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False,
|
||||||
utf8, &da, &di, &dl, &dl, (unsigned char **)&p)
|
utf8, &da, &di, &dl, &dl, (unsigned char **)&p)
|
||||||
== Success && p) {
|
== Success && p) {
|
||||||
insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p)); // insert selection
|
insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p)); // insert selection
|
||||||
XFree(p);
|
XFree(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw the menu
|
// draw the menu
|
||||||
drawmenu();
|
drawmenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void xinitvisual(void) {
|
void xinitvisual(void) {
|
||||||
XVisualInfo *infos;
|
XVisualInfo *infos;
|
||||||
XRenderPictFormat *fmt;
|
XRenderPictFormat *fmt;
|
||||||
int nitems;
|
int nitems;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// visual properties
|
// visual properties
|
||||||
XVisualInfo tpl = {
|
XVisualInfo tpl = {
|
||||||
.screen = screen,
|
.screen = screen,
|
||||||
.depth = 32,
|
.depth = 32,
|
||||||
.class = TrueColor
|
.class = TrueColor
|
||||||
};
|
};
|
||||||
|
|
||||||
long masks = VisualScreenMask | VisualDepthMask | VisualClassMask;
|
long masks = VisualScreenMask | VisualDepthMask | VisualClassMask;
|
||||||
|
|
||||||
infos = XGetVisualInfo(dpy, masks, &tpl, &nitems);
|
infos = XGetVisualInfo(dpy, masks, &tpl, &nitems);
|
||||||
visual = NULL;
|
visual = NULL;
|
||||||
|
|
||||||
// create colormap
|
// create colormap
|
||||||
for(i = 0; i < nitems; i ++) {
|
for(i = 0; i < nitems; i ++) {
|
||||||
fmt = XRenderFindVisualFormat(dpy, infos[i].visual);
|
fmt = XRenderFindVisualFormat(dpy, infos[i].visual);
|
||||||
if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) {
|
if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) {
|
||||||
visual = infos[i].visual;
|
visual = infos[i].visual;
|
||||||
depth = infos[i].depth;
|
depth = infos[i].depth;
|
||||||
cmap = XCreateColormap(dpy, root, visual, AllocNone);
|
cmap = XCreateColormap(dpy, root, visual, AllocNone);
|
||||||
useargb = 1;
|
useargb = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XFree(infos);
|
XFree(infos);
|
||||||
|
|
||||||
// no alpha, reset to default
|
// no alpha, reset to default
|
||||||
if (!visual || !alpha) {
|
if (!visual || !alpha) {
|
||||||
visual = DefaultVisual(dpy, screen);
|
visual = DefaultVisual(dpy, screen);
|
||||||
depth = DefaultDepth(dpy, screen);
|
depth = DefaultDepth(dpy, screen);
|
||||||
cmap = DefaultColormap(dpy, screen);
|
cmap = DefaultColormap(dpy, screen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupdisplay(void) {
|
void setupdisplay(void) {
|
||||||
int x, y, i;
|
int x, y, i;
|
||||||
#if USEXINERAMA
|
#if USEXINERAMA
|
||||||
int j, di;
|
int j, di;
|
||||||
#endif
|
#endif
|
||||||
unsigned int du;
|
unsigned int du;
|
||||||
unsigned int tmp, minstrlen = 0, curstrlen = 0;
|
unsigned int tmp, minstrlen = 0, curstrlen = 0;
|
||||||
int numwidthchecks = 100;
|
int numwidthchecks = 100;
|
||||||
struct item *item;
|
struct item *item;
|
||||||
XIM xim;
|
XIM xim;
|
||||||
Window w, dw, *dws;
|
Window w, dw, *dws;
|
||||||
XWindowAttributes wa;
|
XWindowAttributes wa;
|
||||||
#if USEXINERAMA
|
#if USEXINERAMA
|
||||||
XineramaScreenInfo *info;
|
XineramaScreenInfo *info;
|
||||||
Window pw;
|
Window pw;
|
||||||
int a, n, area = 0;
|
int a, n, area = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
init_appearance(); // init colorschemes by reading arrays
|
init_appearance(); // init colorschemes by reading arrays
|
||||||
|
|
||||||
// set properties indicating what spmenu handles
|
// set properties indicating what spmenu handles
|
||||||
clip = XInternAtom(dpy, "CLIPBOARD", False);
|
clip = XInternAtom(dpy, "CLIPBOARD", False);
|
||||||
utf8 = XInternAtom(dpy, "UTF8_STRING", False);
|
utf8 = XInternAtom(dpy, "UTF8_STRING", False);
|
||||||
types = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
|
types = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
|
||||||
dock = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
|
dock = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
|
||||||
|
|
||||||
// resize client
|
// resize client
|
||||||
bh = MAX(drw->font->h, drw->font->h + 2 + lineheight);
|
bh = MAX(drw->font->h, drw->font->h + 2 + lineheight);
|
||||||
lines = MAX(lines, 0);
|
lines = MAX(lines, 0);
|
||||||
reallines = lines;
|
reallines = lines;
|
||||||
|
|
||||||
// resize client to image height if deemed necessary
|
// resize client to image height if deemed necessary
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
if (image) resizetoimageheight(imageheight);
|
if (image) resizetoimageheight(imageheight);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mh = (lines + 1) * bh + 2 * menumarginv; // lines + 1 * bh is the menu height
|
mh = (lines + 1) * bh + 2 * menumarginv; // lines + 1 * bh is the menu height
|
||||||
|
|
||||||
|
@ -574,122 +574,122 @@ void setupdisplay(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// init xinerama screens
|
// init xinerama screens
|
||||||
#if USEXINERAMA
|
#if USEXINERAMA
|
||||||
i = 0;
|
i = 0;
|
||||||
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
|
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
|
||||||
XGetInputFocus(dpy, &w, &di);
|
XGetInputFocus(dpy, &w, &di);
|
||||||
if (mon >= 0 && mon < n)
|
if (mon >= 0 && mon < n)
|
||||||
i = mon;
|
i = mon;
|
||||||
else if (w != root && w != PointerRoot && w != None) {
|
else if (w != root && w != PointerRoot && w != None) {
|
||||||
// find top-level window containing current input focus
|
// find top-level window containing current input focus
|
||||||
do {
|
do {
|
||||||
if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
|
if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
|
||||||
XFree(dws);
|
XFree(dws);
|
||||||
} while (w != root && w != pw);
|
} while (w != root && w != pw);
|
||||||
// find xinerama screen with which the window intersects most
|
// find xinerama screen with which the window intersects most
|
||||||
if (XGetWindowAttributes(dpy, pw, &wa))
|
if (XGetWindowAttributes(dpy, pw, &wa))
|
||||||
for (j = 0; j < n; j++)
|
for (j = 0; j < n; j++)
|
||||||
if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
|
if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
|
||||||
area = a;
|
area = a;
|
||||||
i = j;
|
i = j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// no focused window is on screen, so use pointer location instead
|
// 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))
|
if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
if (INTERSECT(x, y, 1, 1, info[i]))
|
if (INTERSECT(x, y, 1, 1, info[i]))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// calculate x/y position
|
// calculate x/y position
|
||||||
if (menuposition == 2) { // centered
|
if (menuposition == 2) { // centered
|
||||||
mw = MIN(MAX(max_textw() + promptw, minwidth), info[i].width);
|
mw = MIN(MAX(max_textw() + promptw, minwidth), info[i].width);
|
||||||
x = info[i].x_org + ((info[i].width - mw) / 2);
|
x = info[i].x_org + ((info[i].width - mw) / 2);
|
||||||
y = info[i].y_org + ((info[i].height - mh) / 2);
|
y = info[i].y_org + ((info[i].height - mh) / 2);
|
||||||
} else { // top or bottom
|
} else { // top or bottom
|
||||||
x = info[i].x_org + xpos;
|
x = info[i].x_org + xpos;
|
||||||
y = info[i].y_org + (menuposition ? 0 : info[i].height - mh - ypos);
|
y = info[i].y_org + (menuposition ? 0 : info[i].height - mh - ypos);
|
||||||
mw = (menuwidth>0 ? menuwidth : info[i].width);
|
mw = (menuwidth>0 ? menuwidth : info[i].width);
|
||||||
}
|
}
|
||||||
|
|
||||||
XFree(info);
|
XFree(info);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (!XGetWindowAttributes(dpy, parentwin, &wa))
|
if (!XGetWindowAttributes(dpy, parentwin, &wa))
|
||||||
die("spmenu: could not get embedding window attributes: 0x%lx",
|
die("spmenu: could not get embedding window attributes: 0x%lx",
|
||||||
parentwin); // die because unable to get attributes for the parent window
|
parentwin); // die because unable to get attributes for the parent window
|
||||||
|
|
||||||
if (menuposition == 2) { // centered
|
if (menuposition == 2) { // centered
|
||||||
mw = MIN(MAX(max_textw() + promptw, minwidth), wa.width);
|
mw = MIN(MAX(max_textw() + promptw, minwidth), wa.width);
|
||||||
x = (wa.width - mw) / 2;
|
x = (wa.width - mw) / 2;
|
||||||
y = (wa.height - mh) / 2;
|
y = (wa.height - mh) / 2;
|
||||||
} else { // top or bottom
|
} else { // top or bottom
|
||||||
x = 0;
|
x = 0;
|
||||||
y = menuposition ? 0 : wa.width - mh - ypos;
|
y = menuposition ? 0 : wa.width - mh - ypos;
|
||||||
mw = wa.width;
|
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);
|
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);
|
create_window(x + sp, y + vp - (menuposition == 1 ? 0 : menuposition == 2 ? borderwidth : borderwidth * 2), mw - 2 * sp - borderwidth * 2, mh);
|
||||||
set_window();
|
set_window();
|
||||||
set_prop();
|
set_prop();
|
||||||
|
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
setimageopts();
|
setimageopts();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// input methods
|
// input methods
|
||||||
if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) {
|
if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) {
|
||||||
XSetLocaleModifiers("@im=local");
|
XSetLocaleModifiers("@im=local");
|
||||||
if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) {
|
if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) {
|
||||||
XSetLocaleModifiers("@im=");
|
XSetLocaleModifiers("@im=");
|
||||||
if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL)
|
if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL)
|
||||||
die("XOpenIM failed: could not open input device");
|
die("XOpenIM failed: could not open input device");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
|
xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
|
||||||
XNClientWindow, win, XNFocusWindow, win, NULL);
|
XNClientWindow, win, XNFocusWindow, win, NULL);
|
||||||
|
|
||||||
XMapRaised(dpy, win);
|
XMapRaised(dpy, win);
|
||||||
|
|
||||||
XSync(dpy, False);
|
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
|
if (wa.map_state == IsViewable) // must be viewable, otherwise we get a BadMatch error
|
||||||
XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
|
XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
|
||||||
|
|
||||||
// embed spmenu inside parent window
|
// embed spmenu inside parent window
|
||||||
if (embed) {
|
if (embed) {
|
||||||
XReparentWindow(dpy, win, parentwin, x, y);
|
XReparentWindow(dpy, win, parentwin, x, y);
|
||||||
XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask);
|
XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask);
|
||||||
if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
|
if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
|
||||||
for (i = 0; i < du && dws[i] != win; ++i)
|
for (i = 0; i < du && dws[i] != win; ++i)
|
||||||
XSelectInput(dpy, dws[i], FocusChangeMask);
|
XSelectInput(dpy, dws[i], FocusChangeMask);
|
||||||
XFree(dws);
|
XFree(dws);
|
||||||
}
|
}
|
||||||
grabfocus();
|
grabfocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// resize and draw
|
// resize and draw
|
||||||
drw_resize(drw, mw - 2 * sp - borderwidth * 2, mh);
|
drw_resize(drw, mw - 2 * sp - borderwidth * 2, mh);
|
||||||
drawmenu();
|
drawmenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
XWindowAttributes wa;
|
XWindowAttributes wa;
|
||||||
|
|
||||||
readargs(argc, argv); // start by reading arguments
|
readargs(argc, argv); // start by reading arguments
|
||||||
|
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
longestedge = MAX(imagewidth, imageheight);
|
longestedge = MAX(imagewidth, imageheight);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!type) {
|
if (!type) {
|
||||||
mode = 0;
|
mode = 0;
|
||||||
|
@ -708,65 +708,65 @@ int main(int argc, char *argv[]) {
|
||||||
strcpy(modetext, normtext);
|
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
|
fputs("warning: no locale support\n", stderr); // invalid locale, so notify the user about it
|
||||||
|
|
||||||
if (!XSetLocaleModifiers(""))
|
if (!XSetLocaleModifiers(""))
|
||||||
fputs("warning: no locale modifiers support\n", stderr);
|
fputs("warning: no locale modifiers support\n", stderr);
|
||||||
|
|
||||||
if (!(dpy = XOpenDisplay(NULL)))
|
if (!(dpy = XOpenDisplay(NULL)))
|
||||||
die("spmenu: cannot open display"); // failed to open display
|
die("spmenu: cannot open display"); // failed to open display
|
||||||
|
|
||||||
// set screen and root window
|
// set screen and root window
|
||||||
screen = DefaultScreen(dpy);
|
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
|
// parent window is the root window (ie. window manager) because we're not embedding
|
||||||
if (!embed || !(parentwin = strtol(embed, NULL, 0)))
|
if (!embed || !(parentwin = strtol(embed, NULL, 0)))
|
||||||
parentwin = root;
|
parentwin = root;
|
||||||
|
|
||||||
if (!XGetWindowAttributes(dpy, parentwin, &wa))
|
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
|
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
|
drw = drw_create(dpy, screen, root, wa.width, wa.height, visual, depth, cmap); // wrapper function creating a drawable
|
||||||
|
|
||||||
// load fonts
|
// load fonts
|
||||||
if (!drw_font_create(drw, fonts, LENGTH(fonts)))
|
if (!drw_font_create(drw, fonts, LENGTH(fonts)))
|
||||||
die("no fonts could be loaded.");
|
die("no fonts could be loaded.");
|
||||||
|
|
||||||
// resize window
|
// resize window
|
||||||
lrpad = drw->font->h + textpadding;
|
lrpad = drw->font->h + textpadding;
|
||||||
prepare_window_size(); // this function sets padding size
|
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
|
// pledge limits what programs can do, so here we specify what spmenu should be allowed to do
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
if (pledge("stdio rpath wpath cpath", NULL) == -1)
|
if (pledge("stdio rpath wpath cpath", NULL) == -1)
|
||||||
die("pledge");
|
die("pledge");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
loadhistory(); // read history entries
|
loadhistory(); // read history entries
|
||||||
|
|
||||||
// fast (-f) means we grab keyboard before reading standard input
|
// fast (-f) means we grab keyboard before reading standard input
|
||||||
if (fast && !isatty(0)) {
|
if (fast && !isatty(0)) {
|
||||||
grabkeyboard();
|
grabkeyboard();
|
||||||
readstdin();
|
readstdin();
|
||||||
} else {
|
} else {
|
||||||
readstdin();
|
readstdin();
|
||||||
grabkeyboard();
|
grabkeyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
// set default values
|
// set default values
|
||||||
#if USEIMAGE
|
#if USEIMAGE
|
||||||
if (!imagew || !imageh || !imageg) {
|
if (!imagew || !imageh || !imageg) {
|
||||||
imagew = imagewidth;
|
imagew = imagewidth;
|
||||||
imageh = imageheight;
|
imageh = imageheight;
|
||||||
imagegaps = imagegaps;
|
imagegaps = imagegaps;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setupdisplay(); // set up display and create window
|
setupdisplay(); // set up display and create window
|
||||||
eventloop(); // function is a loop which checks X11 events and calls other functions accordingly
|
eventloop(); // function is a loop which checks X11 events and calls other functions accordingly
|
||||||
|
|
||||||
return 1; // should be unreachable
|
return 1; // should be unreachable
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue