spmenu/libs/arg.c

529 lines
10 KiB
C
Raw Normal View History

2023-05-14 00:21:16 +02:00
/* See LICENSE file for copyright and license details. */
void moveleft(Arg *arg) {
struct item *tmpsel;
int i, offscreen = 0;
int argu = arg->i ? arg->i : 1;
if (columns > 1) {
2023-05-08 23:00:45 +02:00
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;
}
2023-05-08 23:00:45 +02:00
}
2023-05-08 23:00:45 +02:00
drawmenu();
calcoffsets();
2023-05-08 23:00:45 +02:00
}
}
void moveright(Arg *arg) {
struct item *tmpsel;
int i, offscreen = 0;
int argu = arg->i ? arg->i : 1;
if (columns > 1) {
2023-05-08 23:00:45 +02:00
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;
2023-05-08 23:00:45 +02:00
}
calcoffsets();
}
2023-05-08 23:00:45 +02:00
drawmenu();
}
void movedown(Arg *arg) {
int argu = arg->i ? arg->i : 1;
for (int j = 0; j < argu; j++) {
2023-05-08 23:00:45 +02:00
if (sel && sel->right && (sel = sel->right) == next) {
curr = next;
}
}
calcoffsets();
2023-05-08 23:00:45 +02:00
drawmenu();
}
void moveup(Arg *arg) {
int argu = arg->i ? arg->i : 1;
for (int j = 0; j < argu; j++) {
if (sel && sel->left && (sel = sel->left)->right == curr) {
2023-05-08 23:00:45 +02:00
curr = prev;
}
}
2023-05-08 23:00:45 +02:00
calcoffsets();
drawmenu();
}
void complete(Arg *arg) {
if (hideitem) return;
2023-06-23 03:38:21 +02:00
strncpy(tx.text, sel->clntext, sizeof tx.text - 1);
tx.text[sizeof tx.text - 1] = '\0';
sp.cursor = strlen(tx.text);
2023-05-08 23:00:45 +02:00
match();
drawmenu();
}
void movenext(Arg *arg) {
2023-05-08 23:00:45 +02:00
if (!next)
return;
2023-05-08 23:00:45 +02:00
sel = curr = next;
drawmenu();
}
void moveprev(Arg *arg) {
if (!prev)
return;
sel = curr = prev;
calcoffsets();
drawmenu();
}
2023-05-22 16:35:57 +02:00
void moveitem(Arg *arg) {
for (int i = 0; i < arg->i; i++) {
if (sel && sel->right && (sel = sel->right) == next) {
curr = next;
calcoffsets();
}
}
drawmenu();
}
void movestart(Arg *arg) {
2023-05-08 23:00:45 +02:00
if (sel == matches) {
2023-06-23 03:38:21 +02:00
sp.cursor = 0;
drawmenu();
return;
2023-05-08 23:00:45 +02:00
}
2023-05-08 23:00:45 +02:00
sel = curr = matches;
calcoffsets();
drawmenu();
}
void moveend(Arg *arg) {
2023-06-23 03:38:21 +02:00
if (tx.text[sp.cursor] != '\0') {
sp.cursor = strlen(tx.text);
drawmenu();
return;
2023-05-08 23:00:45 +02:00
}
2023-05-08 23:00:45 +02:00
if (next) {
curr = matchend;
calcoffsets();
curr = prev;
calcoffsets();
2023-05-08 23:00:45 +02:00
while (next && (curr = curr->right))
calcoffsets();
}
2023-05-08 23:00:45 +02:00
sel = matchend;
drawmenu();
}
void paste(Arg *arg) {
#if USEX
if (!protocol) {
paste_x11(arg->i);
}
#endif
}
void viewhist(Arg *arg) {
int i;
if (histfile) {
2023-05-08 23:00:45 +02:00
if (!backup_items) {
backup_items = items;
items = calloc(histsz + 1, sizeof(struct item));
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;
}
}
match();
drawmenu();
}
void deleteword(Arg *arg) {
2023-06-23 03:38:21 +02:00
if (sp.cursor == 0) return;
2023-06-23 03:38:21 +02:00
while (sp.cursor > 0 && strchr(worddelimiters, tx.text[nextrune(-1)])) {
insert(NULL, nextrune(-1) - sp.cursor);
} while (sp.cursor > 0 && !strchr(worddelimiters, tx.text[nextrune(-1)])) {
insert(NULL, nextrune(-1) - sp.cursor);
}
drawmenu();
}
void moveword(Arg *arg) {
2023-06-23 03:38:21 +02:00
if (arg->i < 0) { // move sp.cursor to the start of the word
while (sp.cursor > 0 && strchr(worddelimiters, tx.text[nextrune(-1)])) {
sp.cursor = nextrune(-1);
} while (sp.cursor > 0 && !strchr(worddelimiters, tx.text[nextrune(-1)])) {
sp.cursor = nextrune(-1);
}
2023-06-23 03:38:21 +02:00
} else { // move sp.cursor to the end of the word
while (tx.text[sp.cursor] && strchr(worddelimiters, tx.text[sp.cursor])) {
sp.cursor = nextrune(+1);
} while (tx.text[sp.cursor] && !strchr(worddelimiters, tx.text[sp.cursor])) {
sp.cursor = nextrune(+1);
}
2023-05-08 23:00:45 +02:00
}
drawmenu();
}
void movecursor(Arg *arg) {
2023-03-24 14:38:28 +01:00
if (arg->i < 0) {
2023-06-23 03:38:21 +02:00
if (sp.cursor > 0) {
sp.cursor = nextrune(-1);
2023-03-24 14:38:28 +01:00
}
2023-05-08 23:00:45 +02:00
} else {
2023-06-23 03:38:21 +02:00
if (tx.text[sp.cursor]) {
sp.cursor = nextrune(+1);
2023-03-24 14:38:28 +01:00
}
2023-05-08 23:00:45 +02:00
}
2023-03-24 14:38:28 +01:00
drawmenu();
}
void backspace(Arg *arg) {
2023-06-23 03:38:21 +02:00
if (sp.cursor == 0)
return;
2023-06-23 03:38:21 +02:00
insert(NULL, nextrune(-1) - sp.cursor);
drawmenu();
}
void markitem(Arg *arg) {
if (!mark) return;
if (sel && is_selected(sel->index)) {
for (int i = 0; i < sel_size; i++) {
if (sel_index[i] == sel->index) {
sel_index[i] = -1;
}
}
} else {
for (int i = 0; i < sel_size; i++) {
if (sel_index[i] == -1) {
sel_index[i] = sel->index;
return;
}
}
sel_size++;
sel_index = realloc(sel_index, (sel_size + 1) * sizeof(int));
sel_index[sel_size - 1] = sel->index;
}
}
void selectitem(Arg *arg) {
char *selection;
// print index
if (printindex && sel && arg->i) {
fprintf(stdout, "%d\n", sel->index);
cleanup();
exit(0);
}
// selected item or input?
if (sel && arg->i && !hideitem) {
selection = sel->text;
} else {
2023-06-23 03:38:21 +02:00
selection = tx.text;
}
for (int i = 0; i < sel_size; i++) {
if (sel_index[i] != -1 && (!sel || sel->index != sel_index[i])) {
puts(items[sel_index[i]].text);
}
}
if (!selection)
return;
puts(selection);
savehistory(selection);
2023-05-08 23:00:45 +02:00
cleanup();
exit(0);
}
void navhistory(Arg *arg) {
navigatehistfile(arg->i);
drawmenu();
}
void restoresel(Arg *arg) {
2023-06-23 03:38:21 +02:00
tx.text[sp.cursor] = '\0';
match();
drawmenu();
}
void clear(Arg *arg) {
2023-06-23 03:38:21 +02:00
insert(NULL, 0 - sp.cursor);
drawmenu();
}
void clearins(Arg *arg) {
2023-06-23 03:38:21 +02:00
insert(NULL, 0 - sp.cursor);
2023-06-23 03:38:21 +02:00
sp.mode = 1;
sp.allowkeys = 0;
strncpy(tx.modetext, instext, 15);
2023-04-21 09:49:38 +02:00
calcoffsets();
drawmenu();
}
void quit(Arg *arg) {
2023-05-08 23:00:45 +02:00
cleanup();
exit(0);
}
void savehistory(char *input) {
2023-05-08 23:00:45 +02:00
unsigned int i;
FILE *fp;
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);
}
out:
2023-05-08 23:00:45 +02:00
for (i = 0; i < histsz; i++) {
free(history[i]);
}
free(history);
}
void setimgsize(Arg *arg) {
2023-05-08 23:00:45 +02:00
#if USEIMAGE
setimagesize(imagewidth + arg->i, imageheight + arg->i);
drawmenu();
2023-05-08 23:00:45 +02:00
#endif
}
void flipimg(Arg *arg) {
2023-05-08 23:00:45 +02:00
#if USEIMAGE
if (!image) return;
2023-06-23 03:38:21 +02:00
img.flip = img.flip ? 0 : arg->i ? 1 : 2;
drawmenu();
2023-05-08 23:00:45 +02:00
#endif
}
void setimgpos(Arg *arg) {
2023-05-08 23:00:45 +02:00
#if USEIMAGE
if (!image || hideimage) return;
2023-03-08 20:13:39 +01:00
if (imageposition < 3) {
imageposition += arg->i;
} else {
2023-03-08 20:13:39 +01:00
imageposition = 0;
}
drawmenu();
2023-05-08 23:00:45 +02:00
#endif
}
void setimggaps(Arg *arg) {
2023-05-08 23:00:45 +02:00
#if USEIMAGE
2023-03-08 20:13:39 +01:00
imagegaps += arg->i;
if (!image || hideimage) return;
2023-03-08 20:13:39 +01:00
if (imagegaps < 0)
imagegaps = 0;
// limitation to make sure we have a reasonable gap size
2023-03-08 20:13:39 +01:00
if (imagegaps > imagewidth / 2)
imagegaps -= arg->i;
drawmenu();
2023-05-08 23:00:45 +02:00
#endif
2023-03-08 20:13:39 +01:00
}
void toggleimg(Arg *arg) {
2023-05-08 23:00:45 +02:00
#if USEIMAGE
hideimage = !hideimage;
drawmenu();
2023-05-08 23:00:45 +02:00
#endif
}
void togglefullimg(Arg *arg) {
#if USEIMAGE
fullscreen = image ? !fullscreen : 0;
if (fullscreen) {
2023-06-23 03:38:21 +02:00
img.ow = imagewidth;
img.oh = imageheight;
2023-06-23 03:38:21 +02:00
imagewidth = sp.mw;
imageheight = sp.mh;
} else {
2023-06-23 03:38:21 +02:00
imagewidth = img.ow;
imageheight = img.oh;
}
drawmenu();
#endif
}
void defaultimg(Arg *arg) {
2023-05-08 23:00:45 +02:00
#if USEIMAGE
if (hideimage || !image) return;
2023-06-23 03:38:21 +02:00
if (img.imagew) {
imagewidth = img.imagew;
imageheight = img.imageh;
imagegaps = img.imageg;
}
drawmenu();
2023-05-08 23:00:45 +02:00
#endif
}
2023-03-13 22:45:04 +01:00
void setlines(Arg *arg) {
if (fullscreen || !overridelines) return;
2023-03-13 22:45:04 +01:00
lines += arg->i;
if (lines < 0) {
lines = 0;
}
if (lines == 0) {
match();
}
2023-03-13 22:45:04 +01:00
resizeclient();
calcoffsets();
2023-03-13 22:45:04 +01:00
drawmenu();
}
void setcolumns(Arg *arg) {
if (fullscreen || !overridecolumns) return;
2023-03-13 22:45:04 +01:00
columns += arg->i;
if (columns < 1) {
columns = 1;
}
if (lines == 0) {
match();
}
2023-03-13 22:45:04 +01:00
resizeclient();
calcoffsets();
2023-03-13 22:45:04 +01:00
drawmenu();
}
2023-03-29 23:45:54 +02:00
void spawn(Arg *arg) {
if (!system(arg->c))
die("spmenu: failed to execute command '%s'", arg->c);
else
exit(0);
2023-04-21 09:49:38 +02:00
}
void togglehighlight(Arg *arg) {
hidehighlight = !hidehighlight;
drawmenu();
}
void setprofile(Arg *arg) {
if (!system("command -v spmenu_profile > /dev/null && spmenu_profile --spmenu-set-profile")) {
die("spmenu: failed to run profile menu\n");
} else {
exit(0);
}
}
void switchmode(Arg *arg) {
2023-06-23 03:38:21 +02:00
sp.mode = !sp.mode;
2023-06-23 03:38:21 +02:00
if (!type) sp.mode = 0; // only normal mode allowed
2023-06-23 03:38:21 +02:00
sp.allowkeys = !sp.mode;
2023-06-23 03:38:21 +02:00
strncpy(tx.modetext, sp.mode ? instext : normtext, 15);
drawmenu();
}