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