forked from speedie/spmenu
Add some more comments
This commit is contained in:
parent
8e33d4c667
commit
7b7c1a56f4
11
libs/arg.c
11
libs/arg.c
|
@ -4,14 +4,17 @@ void moveleft(Arg *arg) {
|
||||||
int i, offscreen = 0;
|
int i, offscreen = 0;
|
||||||
int argu = arg->i ? arg->i : 1;
|
int argu = arg->i ? arg->i : 1;
|
||||||
|
|
||||||
|
// If we cannot move left because !lines, moving left should move to the next item. Calling moveup() does this.
|
||||||
if (!lines) {
|
if (!lines) {
|
||||||
moveup(arg);
|
moveup(arg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (columns > 1) {
|
if (columns > 1) {
|
||||||
if (!sel)
|
if (!sel) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
tmpsel = sel;
|
tmpsel = sel;
|
||||||
for (i = 0; i < lines; i++) {
|
for (i = 0; i < lines; i++) {
|
||||||
if (!tmpsel->left || tmpsel->left->right != tmpsel) {
|
if (!tmpsel->left || tmpsel->left->right != tmpsel) {
|
||||||
|
@ -40,7 +43,7 @@ void moveright(Arg *arg) {
|
||||||
int i, offscreen = 0;
|
int i, offscreen = 0;
|
||||||
int argu = arg->i ? arg->i : 1;
|
int argu = arg->i ? arg->i : 1;
|
||||||
|
|
||||||
if (!lines) {
|
if (!lines) { // If we cannot move right because !lines, moving right should move to the previous item. Calling down() does this.
|
||||||
movedown(arg);
|
movedown(arg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +78,7 @@ void movedown(Arg *arg) {
|
||||||
|
|
||||||
for (int j = 0; j < argu; j++) {
|
for (int j = 0; j < argu; j++) {
|
||||||
if (sel && sel->right && (sel = sel->right) == next) {
|
if (sel && sel->right && (sel = sel->right) == next) {
|
||||||
curr = next;
|
curr = next; // Current item is now the next item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +91,7 @@ void moveup(Arg *arg) {
|
||||||
|
|
||||||
for (int j = 0; j < argu; j++) {
|
for (int j = 0; j < argu; j++) {
|
||||||
if (sel && sel->left && (sel = sel->left)->right == curr) {
|
if (sel && sel->left && (sel = sel->left)->right == curr) {
|
||||||
curr = prev;
|
curr = prev; // Current item is now the previous item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
45
libs/icon.c
45
libs/icon.c
|
@ -9,8 +9,8 @@ int draw_icon(struct item *item, int x, int y, int w, int h) {
|
||||||
int slen = 0, i;
|
int slen = 0, i;
|
||||||
unsigned int digest_len = EVP_MD_size(EVP_md5());
|
unsigned int digest_len = EVP_MD_size(EVP_md5());
|
||||||
unsigned char *digest = (unsigned char *)OPENSSL_malloc(digest_len);
|
unsigned char *digest = (unsigned char *)OPENSSL_malloc(digest_len);
|
||||||
char *xdg_cache, *home = NULL, *dsize, *buf = NULL;
|
char *xdg_cache, *home = NULL, *cachesize, *buf = NULL;
|
||||||
struct passwd *pw = NULL;
|
struct passwd *user_id = NULL;
|
||||||
|
|
||||||
if (hideimage) {
|
if (hideimage) {
|
||||||
return x;
|
return x;
|
||||||
|
@ -19,15 +19,17 @@ int draw_icon(struct item *item, int x, int y, int w, int h) {
|
||||||
if (item->image) {
|
if (item->image) {
|
||||||
if (generatecache) {
|
if (generatecache) {
|
||||||
if(!(xdg_cache = getenv("XDG_CACHE_HOME"))) {
|
if(!(xdg_cache = getenv("XDG_CACHE_HOME"))) {
|
||||||
if(!(home = getenv("HOME")) && (pw = getpwuid(getuid())))
|
if(!(home = getenv("HOME")) && (user_id = getpwuid(getuid()))) {
|
||||||
home = pw->pw_dir;
|
home = user_id->pw_dir;
|
||||||
if(!home) {
|
}
|
||||||
|
|
||||||
|
if(!home) { // no home directory.. somehow
|
||||||
fprintf(stderr, "spmenu: could not find home directory");
|
fprintf(stderr, "spmenu: could not find home directory");
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dsize = "icon";
|
cachesize = "icon";
|
||||||
|
|
||||||
slen = snprintf(NULL, 0, "file://%s", item->image)+1;
|
slen = snprintf(NULL, 0, "file://%s", item->image)+1;
|
||||||
|
|
||||||
|
@ -46,34 +48,34 @@ int draw_icon(struct item *item, int x, int y, int w, int h) {
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
char md5[digest_len*2+1];
|
char md5sum[digest_len*2+1];
|
||||||
|
|
||||||
for (i = 0; i < digest_len; ++i)
|
for (i = 0; i < digest_len; ++i)
|
||||||
sprintf(&md5[i*2], "%02x", (unsigned int)digest[i]);
|
sprintf(&md5sum[i*2], "%02x", (unsigned int)digest[i]);
|
||||||
|
|
||||||
if (!cachedir || !strcmp(cachedir, "default")) {
|
if (!cachedir || !strcmp(cachedir, "default")) { // "default" here is from the config file
|
||||||
if (xdg_cache || !strcmp(cachedir, "xdg"))
|
if (xdg_cache || !strcmp(cachedir, "xdg"))
|
||||||
slen = snprintf(NULL, 0, "%s/thumbnails/%s/%s.png", xdg_cache, dsize, md5)+1;
|
slen = snprintf(NULL, 0, "%s/thumbnails/%s/%s.png", xdg_cache, cachesize, md5sum)+1;
|
||||||
else
|
else
|
||||||
slen = snprintf(NULL, 0, "%s/.cache/thumbnails/%s/%s.png", home, dsize, md5)+1;
|
slen = snprintf(NULL, 0, "%s/.cache/thumbnails/%s/%s.png", home, cachesize, md5sum)+1;
|
||||||
} else {
|
} else {
|
||||||
slen = snprintf(NULL, 0, "%s/%s/%s.png", cachedir, dsize, md5)+1;
|
slen = snprintf(NULL, 0, "%s/%s/%s.png", cachedir, cachesize, md5sum)+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(buf = malloc(slen))) {
|
if(!(buf = malloc(slen))) {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cachedir || !strcmp(cachedir, "default")) {
|
if (!cachedir || !strcmp(cachedir, "default")) { // "default" here is from the config file
|
||||||
if (xdg_cache)
|
if (xdg_cache)
|
||||||
sprintf(buf, "%s/thumbnails/%s/%s.png", xdg_cache, dsize, md5);
|
sprintf(buf, "%s/thumbnails/%s/%s.png", xdg_cache, cachesize, md5sum);
|
||||||
else
|
else
|
||||||
sprintf(buf, "%s/.cache/thumbnails/%s/%s.png", home, dsize, md5);
|
sprintf(buf, "%s/.cache/thumbnails/%s/%s.png", home, cachesize, md5sum);
|
||||||
} else {
|
} else {
|
||||||
sprintf(buf, "%s/%s/%s.png", cachedir, dsize, md5);
|
sprintf(buf, "%s/%s/%s.png", cachedir, cachesize, md5sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
image = imlib_load_image(buf);
|
image = imlib_load_image(buf); // attempt to load image from path
|
||||||
|
|
||||||
if (image) {
|
if (image) {
|
||||||
imlib_context_set_image(image);
|
imlib_context_set_image(image);
|
||||||
|
@ -83,10 +85,15 @@ int draw_icon(struct item *item, int x, int y, int w, int h) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If passed w or h has changed, cache is invalid and has to be regenerated. This prevents flickering.
|
||||||
|
* It could change if sp.bh has changed in some way, such as font size being changed after cache has
|
||||||
|
* been generated.
|
||||||
|
*/
|
||||||
if (ich != h || icw != w) {
|
if (ich != h || icw != w) {
|
||||||
image = NULL;
|
image = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load regular image, because an image was not loaded from cache
|
||||||
if (!image || !generatecache) {
|
if (!image || !generatecache) {
|
||||||
image = imlib_load_image(item->image);
|
image = imlib_load_image(item->image);
|
||||||
|
|
||||||
|
@ -107,19 +114,21 @@ int draw_icon(struct item *item, int x, int y, int w, int h) {
|
||||||
imlib_free_image();
|
imlib_free_image();
|
||||||
imlib_context_set_image(image);
|
imlib_context_set_image(image);
|
||||||
|
|
||||||
|
// get new width/height
|
||||||
icw = imlib_image_get_width();
|
icw = imlib_image_get_width();
|
||||||
ich = imlib_image_get_height();
|
ich = imlib_image_get_height();
|
||||||
}
|
}
|
||||||
|
|
||||||
imlib_image_set_format("png");
|
imlib_image_set_format("png");
|
||||||
|
|
||||||
|
// create directory and write cache file
|
||||||
if (buf && generatecache && image) {
|
if (buf && generatecache && image) {
|
||||||
createifnexist_rec(buf);
|
createifnexist_rec(buf);
|
||||||
imlib_save_image(buf);
|
imlib_save_image(buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the image
|
// draw the image
|
||||||
draw_set_img(draw, imlib_image_get_data(), w, h);
|
draw_set_img(draw, imlib_image_get_data(), w, h);
|
||||||
draw_img(draw, x, y);
|
draw_img(draw, x, y);
|
||||||
|
|
||||||
|
|
30
libs/img.c
30
libs/img.c
|
@ -190,8 +190,8 @@ void loadimagecache(const char *file, int *width, int *height) {
|
||||||
int slen = 0, i;
|
int slen = 0, i;
|
||||||
unsigned int digest_len = EVP_MD_size(EVP_md5());
|
unsigned int digest_len = EVP_MD_size(EVP_md5());
|
||||||
unsigned char *digest = (unsigned char *)OPENSSL_malloc(digest_len);
|
unsigned char *digest = (unsigned char *)OPENSSL_malloc(digest_len);
|
||||||
char *xdg_cache, *home = NULL, *dsize, *buf = NULL;
|
char *xdg_cache, *home = NULL, *cachesize, *buf = NULL;
|
||||||
struct passwd *pw = NULL;
|
struct passwd *user_id = NULL;
|
||||||
|
|
||||||
// just load and don't store or try cache
|
// just load and don't store or try cache
|
||||||
if (img.longestedge > maxcache) {
|
if (img.longestedge > maxcache) {
|
||||||
|
@ -204,18 +204,20 @@ void loadimagecache(const char *file, int *width, int *height) {
|
||||||
if (generatecache) {
|
if (generatecache) {
|
||||||
// try find image from cache first
|
// try find image from cache first
|
||||||
if(!(xdg_cache = getenv("XDG_CACHE_HOME"))) {
|
if(!(xdg_cache = getenv("XDG_CACHE_HOME"))) {
|
||||||
if(!(home = getenv("HOME")) && (pw = getpwuid(getuid())))
|
if(!(home = getenv("HOME")) && (user_id = getpwuid(getuid()))) {
|
||||||
home = pw->pw_dir;
|
home = user_id->pw_dir;
|
||||||
if(!home) {
|
}
|
||||||
|
|
||||||
|
if(!home) { // no home directory could be grabbed.. somehow
|
||||||
fprintf(stderr, "spmenu: could not find home directory");
|
fprintf(stderr, "spmenu: could not find home directory");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// which cache do we try?
|
// which cache do we try?
|
||||||
dsize = "normal";
|
cachesize = "normal";
|
||||||
if (img.longestedge > 128)
|
if (img.longestedge > 128)
|
||||||
dsize = "large";
|
cachesize = "large";
|
||||||
|
|
||||||
slen = snprintf(NULL, 0, "file://%s", file)+1;
|
slen = snprintf(NULL, 0, "file://%s", file)+1;
|
||||||
|
|
||||||
|
@ -243,11 +245,11 @@ void loadimagecache(const char *file, int *width, int *height) {
|
||||||
// path for cached thumbnail
|
// path for cached thumbnail
|
||||||
if (!cachedir || !strcmp(cachedir, "default")) {
|
if (!cachedir || !strcmp(cachedir, "default")) {
|
||||||
if (xdg_cache || !strcmp(cachedir, "xdg"))
|
if (xdg_cache || !strcmp(cachedir, "xdg"))
|
||||||
slen = snprintf(NULL, 0, "%s/thumbnails/%s/%s.png", xdg_cache, dsize, md5)+1;
|
slen = snprintf(NULL, 0, "%s/thumbnails/%s/%s.png", xdg_cache, cachesize, md5)+1;
|
||||||
else
|
else
|
||||||
slen = snprintf(NULL, 0, "%s/.cache/thumbnails/%s/%s.png", home, dsize, md5)+1;
|
slen = snprintf(NULL, 0, "%s/.cache/thumbnails/%s/%s.png", home, cachesize, md5)+1;
|
||||||
} else {
|
} else {
|
||||||
slen = snprintf(NULL, 0, "%s/%s/%s.png", cachedir, dsize, md5)+1;
|
slen = snprintf(NULL, 0, "%s/%s/%s.png", cachedir, cachesize, md5)+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(buf = malloc(slen))) {
|
if(!(buf = malloc(slen))) {
|
||||||
|
@ -256,11 +258,11 @@ void loadimagecache(const char *file, int *width, int *height) {
|
||||||
|
|
||||||
if (!cachedir || !strcmp(cachedir, "default")) {
|
if (!cachedir || !strcmp(cachedir, "default")) {
|
||||||
if (xdg_cache)
|
if (xdg_cache)
|
||||||
sprintf(buf, "%s/thumbnails/%s/%s.png", xdg_cache, dsize, md5);
|
sprintf(buf, "%s/thumbnails/%s/%s.png", xdg_cache, cachesize, md5);
|
||||||
else
|
else
|
||||||
sprintf(buf, "%s/.cache/thumbnails/%s/%s.png", home, dsize, md5);
|
sprintf(buf, "%s/.cache/thumbnails/%s/%s.png", home, cachesize, md5);
|
||||||
} else {
|
} else {
|
||||||
sprintf(buf, "%s/%s/%s.png", cachedir, dsize, md5);
|
sprintf(buf, "%s/%s/%s.png", cachedir, cachesize, md5);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadimage(buf, width, height);
|
loadimage(buf, width, height);
|
||||||
|
@ -298,7 +300,7 @@ void jumptoindex(unsigned int index) {
|
||||||
|
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
|
|
||||||
for (i = 1; i < index; ++i) {
|
for (i = 1; i < index; ++i) { // move to item index
|
||||||
if(sel && sel->right && (sel = sel->right) == next) {
|
if(sel && sel->right && (sel = sel->right) == next) {
|
||||||
curr = next;
|
curr = next;
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
|
|
83
spmenu.c
83
spmenu.c
|
@ -95,7 +95,7 @@
|
||||||
// include macros and other defines
|
// include macros and other defines
|
||||||
#include "libs/define.c"
|
#include "libs/define.c"
|
||||||
|
|
||||||
enum {
|
enum { // click enum
|
||||||
ClickWindow,
|
ClickWindow,
|
||||||
ClickPrompt,
|
ClickPrompt,
|
||||||
ClickInput,
|
ClickInput,
|
||||||
|
@ -159,7 +159,7 @@ struct mo {
|
||||||
struct img {
|
struct img {
|
||||||
int setlines; // actual lines
|
int setlines; // actual lines
|
||||||
int flip; // %=
|
int flip; // %=
|
||||||
int longestedge; // MAX(imagewidth, imagheight)
|
int longestedge; // MAX(imagewidth, imageheight)
|
||||||
int imagewidth; // current image width
|
int imagewidth; // current image width
|
||||||
int imageheight; // current image height
|
int imageheight; // current image height
|
||||||
int imagegaps; // current image gaps
|
int imagegaps; // current image gaps
|
||||||
|
@ -206,12 +206,12 @@ static struct item *prev, *curr, *next, *sel;
|
||||||
#include "libs/stream.h"
|
#include "libs/stream.h"
|
||||||
#include "libs/schemes.h"
|
#include "libs/schemes.h"
|
||||||
#include "libs/arg.h"
|
#include "libs/arg.h"
|
||||||
#include "libs/x11/inc.h" // include x11
|
#include "libs/x11/inc.h"
|
||||||
#include "libs/wl/inc.h" // include wayland
|
#include "libs/wl/inc.h"
|
||||||
#include "libs/sort.h"
|
#include "libs/sort.h"
|
||||||
#include "libs/history.h"
|
#include "libs/history.h"
|
||||||
|
|
||||||
static Draw_t *draw;
|
static Draw_t *draw; // Draw_t type, see libs/draw/draw.c
|
||||||
|
|
||||||
// high priority
|
// high priority
|
||||||
static int hplength = 0;
|
static int hplength = 0;
|
||||||
|
@ -243,13 +243,15 @@ static void handle(void);
|
||||||
static void appenditem(struct item *item, struct item **list, struct item **last);
|
static void appenditem(struct item *item, struct item **list, struct item **last);
|
||||||
static int max_textw(void);
|
static int max_textw(void);
|
||||||
static size_t nextrune(int inc);
|
static size_t nextrune(int inc);
|
||||||
|
|
||||||
|
// matching
|
||||||
static char * cistrstr(const char *s, const char *sub);
|
static char * cistrstr(const char *s, const char *sub);
|
||||||
static int (*fstrncmp)(const char *, const char *, size_t) = strncasecmp;
|
static int (*fstrncmp)(const char *, const char *, size_t) = strncasecmp;
|
||||||
static char *(*fstrstr)(const char *, const char *) = cistrstr;
|
static char *(*fstrstr)(const char *, const char *) = cistrstr;
|
||||||
|
|
||||||
#if USEX
|
#if USEX
|
||||||
static void pastesel(void);
|
static void pastesel(void); // TODO: wayland clipboard
|
||||||
static void grabfocus(void);
|
static void grabfocus(void); // focus doesn't need to be grabbed on wayland
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static char **list;
|
static char **list;
|
||||||
|
@ -298,7 +300,7 @@ static char *fonts[] = { font };
|
||||||
int is_selected(size_t index) {
|
int is_selected(size_t index) {
|
||||||
for (int i = 0; i < sel_size; i++) {
|
for (int i = 0; i < sel_size; i++) {
|
||||||
if (sel_index[i] == index) {
|
if (sel_index[i] == index) {
|
||||||
return 1;
|
return 1; // selected item index is size_t index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,6 +321,7 @@ void appenditem(struct item *item, struct item **list, struct item **last) {
|
||||||
void recalculatenumbers(void) {
|
void recalculatenumbers(void) {
|
||||||
unsigned int numer = 0, denom = 0, selected = 0;
|
unsigned int numer = 0, denom = 0, selected = 0;
|
||||||
struct item *item;
|
struct item *item;
|
||||||
|
|
||||||
if (matchend) {
|
if (matchend) {
|
||||||
numer++;
|
numer++;
|
||||||
|
|
||||||
|
@ -328,8 +331,9 @@ void recalculatenumbers(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// walk through all items, matching or not and add to denom
|
// walk through all items, matching or not and add to denom
|
||||||
for (item = items; item && item->text; item++)
|
for (item = items; item && item->text; item++) {
|
||||||
denom++;
|
denom++;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < sel_size; i++) {
|
for (int i = 0; i < sel_size; i++) {
|
||||||
if (sel_index[i] == -1) {
|
if (sel_index[i] == -1) {
|
||||||
|
@ -347,37 +351,38 @@ void recalculatenumbers(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void calcoffsets(void) {
|
void calcoffsets(void) {
|
||||||
int i, n;
|
int i, offset;
|
||||||
|
|
||||||
if (lines > 0)
|
if (lines > 0) {
|
||||||
n = lines * columns * sp.bh;
|
offset = lines * columns * sp.bh;
|
||||||
else { // no lines, therefore the size of items must be decreased to fit the menu elements
|
} else { // no lines, therefore the size of items must be decreased to fit the menu elements
|
||||||
int numberw = 0;
|
int numberw = 0;
|
||||||
int modeWidth = 0;
|
int modew = 0;
|
||||||
int larroww = 0;
|
int larroww = 0;
|
||||||
int rarrowWidth = 0;
|
int rarroww = 0;
|
||||||
int capsw = 0;
|
int capsw = 0;
|
||||||
|
|
||||||
if (!hidematchcount) numberw = pango_numbers ? TEXTWM(tx.numbers) : TEXTW(tx.numbers);
|
if (!hidematchcount) numberw = pango_numbers ? TEXTWM(tx.numbers) : TEXTW(tx.numbers);
|
||||||
if (!hidemode) modeWidth = pango_mode ? TEXTWM(tx.modetext) : TEXTW(tx.modetext);
|
if (!hidemode) modew = pango_mode ? TEXTWM(tx.modetext) : TEXTW(tx.modetext);
|
||||||
if (!hidelarrow) larroww = pango_leftarrow ? TEXTWM(leftarrow) : TEXTW(leftarrow);
|
if (!hidelarrow) larroww = pango_leftarrow ? TEXTWM(leftarrow) : TEXTW(leftarrow);
|
||||||
if (!hiderarrow) rarrowWidth = pango_rightarrow ? TEXTWM(rightarrow) : TEXTW(rightarrow);
|
if (!hiderarrow) rarroww = pango_rightarrow ? TEXTWM(rightarrow) : TEXTW(rightarrow);
|
||||||
if (!hidecaps) capsw = pango_caps ? TEXTWM(tx.capstext) : TEXTW(tx.capstext);
|
if (!hidecaps) capsw = pango_caps ? TEXTWM(tx.capstext) : TEXTW(tx.capstext);
|
||||||
|
|
||||||
if (!strcmp(tx.capstext, ""))
|
if (!strcmp(tx.capstext, "")) {
|
||||||
capsw = 0;
|
capsw = 0;
|
||||||
|
}
|
||||||
|
|
||||||
n = sp.mw - (sp.promptw + sp.inputw + larroww + rarrowWidth + modeWidth + numberw + capsw + menumarginh);
|
offset = sp.mw - (sp.promptw + sp.inputw + larroww + rarroww + modew + numberw + capsw + menumarginh);
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate which items will begin the next page
|
// calculate which items will begin the next page
|
||||||
for (i = 0, next = curr; next; next = next->right)
|
for (i = 0, next = curr; next; next = next->right)
|
||||||
if ((i += (lines > 0) ? sp.bh : MIN(TEXTWM(next->text) + (powerlineitems ? !lines ? 2 * sp.plw : 0 : 0), n)) > n)
|
if ((i += (lines > 0) ? sp.bh : MIN(TEXTWM(next->text) + (powerlineitems ? !lines ? 2 * sp.plw : 0 : 0), offset)) > offset)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// calculate which items will begin the previous page
|
// calculate which items will begin the previous page
|
||||||
for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
|
for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
|
||||||
if ((i += (lines > 0) ? sp.bh : MIN(TEXTWM(prev->left->text) + (powerlineitems ? !lines ? 2 * sp.plw : 0 : 0), n)) > n)
|
if ((i += (lines > 0) ? sp.bh : MIN(TEXTWM(prev->left->text) + (powerlineitems ? !lines ? 2 * sp.plw : 0 : 0), offset)) > offset)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,6 +418,7 @@ void cleanup(void) {
|
||||||
free(sel_index);
|
free(sel_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function handles case insensitive matching
|
||||||
char * cistrstr(const char *h, const char *n) {
|
char * cistrstr(const char *h, const char *n) {
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
@ -438,17 +444,25 @@ void grabfocus(void) {
|
||||||
|
|
||||||
void insert(const char *str, ssize_t n) {
|
void insert(const char *str, ssize_t n) {
|
||||||
if (strlen(tx.text) + n > sizeof tx.text - 1)
|
if (strlen(tx.text) + n > sizeof tx.text - 1)
|
||||||
return;
|
return; // length of text should not exceed size
|
||||||
|
|
||||||
static char l[BUFSIZ] = "";
|
static char l[BUFSIZ] = "";
|
||||||
if (requirematch) memcpy(l, tx.text, BUFSIZ);
|
|
||||||
|
if (requirematch) {
|
||||||
|
memcpy(l, tx.text, BUFSIZ);
|
||||||
|
}
|
||||||
|
|
||||||
// move existing text out of the way, insert new text, and update cursor
|
// move existing text out of the way, insert new text, and update cursor
|
||||||
memmove(&tx.text[sp.cursor + n], &tx.text[sp.cursor], sizeof tx.text - sp.cursor - MAX(n, 0));
|
memmove(
|
||||||
|
&tx.text[sp.cursor + n],
|
||||||
|
&tx.text[sp.cursor],
|
||||||
|
sizeof tx.text - sp.cursor - MAX(n, 0)
|
||||||
|
);
|
||||||
|
|
||||||
// update cursor
|
// update cursor
|
||||||
if (n > 0 && str && n)
|
if (n > 0 && str && n) {
|
||||||
memcpy(&tx.text[sp.cursor], str, n);
|
memcpy(&tx.text[sp.cursor], str, n);
|
||||||
|
}
|
||||||
|
|
||||||
// add to cursor position and continue matching
|
// add to cursor position and continue matching
|
||||||
sp.cursor += n;
|
sp.cursor += n;
|
||||||
|
@ -460,6 +474,7 @@ void insert(const char *str, ssize_t n) {
|
||||||
match();
|
match();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// output on insertion
|
||||||
if (incremental) {
|
if (incremental) {
|
||||||
puts(tx.text);
|
puts(tx.text);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
@ -467,12 +482,13 @@ void insert(const char *str, ssize_t n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nextrune(int inc) {
|
size_t nextrune(int inc) {
|
||||||
ssize_t n;
|
ssize_t rune;
|
||||||
|
|
||||||
// return location of next utf8 rune in the given direction (+1 or -1)
|
// return location of next utf8 rune in the given direction (+1 or -1)
|
||||||
for (n = sp.cursor + inc; n + inc >= 0 && (tx.text[n] & 0xc0) == 0x80; n += inc)
|
for (rune = sp.cursor + inc; rune + inc >= 0 && (tx.text[rune] & 0xc0) == 0x80; rune += inc)
|
||||||
;
|
;
|
||||||
return n;
|
|
||||||
|
return rune;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USEX
|
#if USEX
|
||||||
|
@ -497,6 +513,10 @@ void resizeclient(void) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Width reserved for input when !lines is a fixed size of the menu width / 3
|
||||||
|
* This is reasonable, but in rare cases may cause input text to overlap
|
||||||
|
* items.
|
||||||
|
*/
|
||||||
void get_width(void) {
|
void get_width(void) {
|
||||||
sp.inputw = sp.mw / 3;
|
sp.inputw = sp.mw / 3;
|
||||||
}
|
}
|
||||||
|
@ -507,12 +527,14 @@ void get_mh(void) {
|
||||||
sp.mh = (lines + 1) * sp.bh;
|
sp.mh = (lines + 1) * sp.bh;
|
||||||
sp.mh += 2 * menumarginv;
|
sp.mh += 2 * menumarginv;
|
||||||
|
|
||||||
|
// subtract 1 line if there's nothing to draw on the top line
|
||||||
if ((hideprompt && hideinput && hidemode && hidematchcount && hidecaps) && lines) {
|
if ((hideprompt && hideinput && hidemode && hidematchcount && hidecaps) && lines) {
|
||||||
sp.mh -= sp.bh;
|
sp.mh -= sp.bh;
|
||||||
}
|
}
|
||||||
|
|
||||||
epad = 2 * menupaddingv;
|
epad = 2 * menupaddingv;
|
||||||
|
|
||||||
|
// the spmenu window should not exceed the screen resolution height
|
||||||
if (mo.output_height && !xpos && !ypos) {
|
if (mo.output_height && !xpos && !ypos) {
|
||||||
sp.mh = MIN(sp.mh, mo.output_height - epad);
|
sp.mh = MIN(sp.mh, mo.output_height - epad);
|
||||||
|
|
||||||
|
@ -540,6 +562,7 @@ void set_mode(void) {
|
||||||
sp_strncpy(tx.modetext, normtext, sizeof(tx.modetext));
|
sp_strncpy(tx.modetext, normtext, sizeof(tx.modetext));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// normal mode disabled
|
||||||
if (sp.forceinsertmode) {
|
if (sp.forceinsertmode) {
|
||||||
sp.mode = 1;
|
sp.mode = 1;
|
||||||
sp.allowkeys = 1;
|
sp.allowkeys = 1;
|
||||||
|
@ -608,7 +631,9 @@ void handle(void) {
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
readargs(argc, argv); // start by reading arguments
|
readargs(argc, argv); // start by reading arguments
|
||||||
|
|
||||||
// pledge limits what programs can do, so here we specify what spmenu should be allowed to do
|
/* pledge limits what programs can do, so here we specify what spmenu should be allowed to do
|
||||||
|
* TODO: test this on a openbsd operating system
|
||||||
|
*/
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
if (pledge("stdio rpath wpath cpath", NULL) == -1)
|
if (pledge("stdio rpath wpath cpath", NULL) == -1)
|
||||||
die("pledge");
|
die("pledge");
|
||||||
|
|
Loading…
Reference in a new issue