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 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) {
|
||||
moveup(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (columns > 1) {
|
||||
if (!sel)
|
||||
if (!sel) {
|
||||
return;
|
||||
}
|
||||
|
||||
tmpsel = sel;
|
||||
for (i = 0; i < lines; i++) {
|
||||
if (!tmpsel->left || tmpsel->left->right != tmpsel) {
|
||||
|
@ -40,7 +43,7 @@ void moveright(Arg *arg) {
|
|||
int i, offscreen = 0;
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -75,7 +78,7 @@ void movedown(Arg *arg) {
|
|||
|
||||
for (int j = 0; j < argu; j++) {
|
||||
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++) {
|
||||
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;
|
||||
unsigned int digest_len = EVP_MD_size(EVP_md5());
|
||||
unsigned char *digest = (unsigned char *)OPENSSL_malloc(digest_len);
|
||||
char *xdg_cache, *home = NULL, *dsize, *buf = NULL;
|
||||
struct passwd *pw = NULL;
|
||||
char *xdg_cache, *home = NULL, *cachesize, *buf = NULL;
|
||||
struct passwd *user_id = NULL;
|
||||
|
||||
if (hideimage) {
|
||||
return x;
|
||||
|
@ -19,15 +19,17 @@ int draw_icon(struct item *item, int x, int y, int w, int h) {
|
|||
if (item->image) {
|
||||
if (generatecache) {
|
||||
if(!(xdg_cache = getenv("XDG_CACHE_HOME"))) {
|
||||
if(!(home = getenv("HOME")) && (pw = getpwuid(getuid())))
|
||||
home = pw->pw_dir;
|
||||
if(!home) {
|
||||
if(!(home = getenv("HOME")) && (user_id = getpwuid(getuid()))) {
|
||||
home = user_id->pw_dir;
|
||||
}
|
||||
|
||||
if(!home) { // no home directory.. somehow
|
||||
fprintf(stderr, "spmenu: could not find home directory");
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
dsize = "icon";
|
||||
cachesize = "icon";
|
||||
|
||||
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);
|
||||
|
||||
char md5[digest_len*2+1];
|
||||
char md5sum[digest_len*2+1];
|
||||
|
||||
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"))
|
||||
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
|
||||
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 {
|
||||
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))) {
|
||||
return x;
|
||||
}
|
||||
|
||||
if (!cachedir || !strcmp(cachedir, "default")) {
|
||||
if (!cachedir || !strcmp(cachedir, "default")) { // "default" here is from the config file
|
||||
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
|
||||
sprintf(buf, "%s/.cache/thumbnails/%s/%s.png", home, dsize, md5);
|
||||
sprintf(buf, "%s/.cache/thumbnails/%s/%s.png", home, cachesize, md5sum);
|
||||
} 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) {
|
||||
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) {
|
||||
image = NULL;
|
||||
}
|
||||
|
||||
// load regular image, because an image was not loaded from cache
|
||||
if (!image || !generatecache) {
|
||||
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_context_set_image(image);
|
||||
|
||||
// get new width/height
|
||||
icw = imlib_image_get_width();
|
||||
ich = imlib_image_get_height();
|
||||
}
|
||||
|
||||
imlib_image_set_format("png");
|
||||
|
||||
// create directory and write cache file
|
||||
if (buf && generatecache && image) {
|
||||
createifnexist_rec(buf);
|
||||
imlib_save_image(buf);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
// Draw the image
|
||||
// draw the image
|
||||
draw_set_img(draw, imlib_image_get_data(), w, h);
|
||||
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;
|
||||
unsigned int digest_len = EVP_MD_size(EVP_md5());
|
||||
unsigned char *digest = (unsigned char *)OPENSSL_malloc(digest_len);
|
||||
char *xdg_cache, *home = NULL, *dsize, *buf = NULL;
|
||||
struct passwd *pw = NULL;
|
||||
char *xdg_cache, *home = NULL, *cachesize, *buf = NULL;
|
||||
struct passwd *user_id = NULL;
|
||||
|
||||
// just load and don't store or try cache
|
||||
if (img.longestedge > maxcache) {
|
||||
|
@ -204,18 +204,20 @@ void loadimagecache(const char *file, int *width, int *height) {
|
|||
if (generatecache) {
|
||||
// try find image from cache first
|
||||
if(!(xdg_cache = getenv("XDG_CACHE_HOME"))) {
|
||||
if(!(home = getenv("HOME")) && (pw = getpwuid(getuid())))
|
||||
home = pw->pw_dir;
|
||||
if(!home) {
|
||||
if(!(home = getenv("HOME")) && (user_id = getpwuid(getuid()))) {
|
||||
home = user_id->pw_dir;
|
||||
}
|
||||
|
||||
if(!home) { // no home directory could be grabbed.. somehow
|
||||
fprintf(stderr, "spmenu: could not find home directory");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// which cache do we try?
|
||||
dsize = "normal";
|
||||
cachesize = "normal";
|
||||
if (img.longestedge > 128)
|
||||
dsize = "large";
|
||||
cachesize = "large";
|
||||
|
||||
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
|
||||
if (!cachedir || !strcmp(cachedir, "default")) {
|
||||
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
|
||||
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 {
|
||||
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))) {
|
||||
|
@ -256,11 +258,11 @@ void loadimagecache(const char *file, int *width, int *height) {
|
|||
|
||||
if (!cachedir || !strcmp(cachedir, "default")) {
|
||||
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
|
||||
sprintf(buf, "%s/.cache/thumbnails/%s/%s.png", home, dsize, md5);
|
||||
sprintf(buf, "%s/.cache/thumbnails/%s/%s.png", home, cachesize, md5);
|
||||
} else {
|
||||
sprintf(buf, "%s/%s/%s.png", cachedir, dsize, md5);
|
||||
sprintf(buf, "%s/%s/%s.png", cachedir, cachesize, md5);
|
||||
}
|
||||
|
||||
loadimage(buf, width, height);
|
||||
|
@ -298,7 +300,7 @@ void jumptoindex(unsigned int index) {
|
|||
|
||||
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) {
|
||||
curr = next;
|
||||
calcoffsets();
|
||||
|
|
83
spmenu.c
83
spmenu.c
|
@ -95,7 +95,7 @@
|
|||
// include macros and other defines
|
||||
#include "libs/define.c"
|
||||
|
||||
enum {
|
||||
enum { // click enum
|
||||
ClickWindow,
|
||||
ClickPrompt,
|
||||
ClickInput,
|
||||
|
@ -159,7 +159,7 @@ struct mo {
|
|||
struct img {
|
||||
int setlines; // actual lines
|
||||
int flip; // %=
|
||||
int longestedge; // MAX(imagewidth, imagheight)
|
||||
int longestedge; // MAX(imagewidth, imageheight)
|
||||
int imagewidth; // current image width
|
||||
int imageheight; // current image height
|
||||
int imagegaps; // current image gaps
|
||||
|
@ -206,12 +206,12 @@ static struct item *prev, *curr, *next, *sel;
|
|||
#include "libs/stream.h"
|
||||
#include "libs/schemes.h"
|
||||
#include "libs/arg.h"
|
||||
#include "libs/x11/inc.h" // include x11
|
||||
#include "libs/wl/inc.h" // include wayland
|
||||
#include "libs/x11/inc.h"
|
||||
#include "libs/wl/inc.h"
|
||||
#include "libs/sort.h"
|
||||
#include "libs/history.h"
|
||||
|
||||
static Draw_t *draw;
|
||||
static Draw_t *draw; // Draw_t type, see libs/draw/draw.c
|
||||
|
||||
// high priority
|
||||
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 int max_textw(void);
|
||||
static size_t nextrune(int inc);
|
||||
|
||||
// matching
|
||||
static char * cistrstr(const char *s, const char *sub);
|
||||
static int (*fstrncmp)(const char *, const char *, size_t) = strncasecmp;
|
||||
static char *(*fstrstr)(const char *, const char *) = cistrstr;
|
||||
|
||||
#if USEX
|
||||
static void pastesel(void);
|
||||
static void grabfocus(void);
|
||||
static void pastesel(void); // TODO: wayland clipboard
|
||||
static void grabfocus(void); // focus doesn't need to be grabbed on wayland
|
||||
#endif
|
||||
|
||||
static char **list;
|
||||
|
@ -298,7 +300,7 @@ static char *fonts[] = { font };
|
|||
int is_selected(size_t index) {
|
||||
for (int i = 0; i < sel_size; i++) {
|
||||
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) {
|
||||
unsigned int numer = 0, denom = 0, selected = 0;
|
||||
struct item *item;
|
||||
|
||||
if (matchend) {
|
||||
numer++;
|
||||
|
||||
|
@ -328,8 +331,9 @@ void recalculatenumbers(void) {
|
|||
}
|
||||
|
||||
// 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++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < sel_size; i++) {
|
||||
if (sel_index[i] == -1) {
|
||||
|
@ -347,37 +351,38 @@ void recalculatenumbers(void) {
|
|||
}
|
||||
|
||||
void calcoffsets(void) {
|
||||
int i, n;
|
||||
int i, offset;
|
||||
|
||||
if (lines > 0)
|
||||
n = lines * columns * sp.bh;
|
||||
else { // no lines, therefore the size of items must be decreased to fit the menu elements
|
||||
if (lines > 0) {
|
||||
offset = lines * columns * sp.bh;
|
||||
} else { // no lines, therefore the size of items must be decreased to fit the menu elements
|
||||
int numberw = 0;
|
||||
int modeWidth = 0;
|
||||
int modew = 0;
|
||||
int larroww = 0;
|
||||
int rarrowWidth = 0;
|
||||
int rarroww = 0;
|
||||
int capsw = 0;
|
||||
|
||||
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 (!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 (!strcmp(tx.capstext, ""))
|
||||
if (!strcmp(tx.capstext, "")) {
|
||||
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
|
||||
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;
|
||||
|
||||
// calculate which items will begin the previous page
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -413,6 +418,7 @@ void cleanup(void) {
|
|||
free(sel_index);
|
||||
}
|
||||
|
||||
// This function handles case insensitive matching
|
||||
char * cistrstr(const char *h, const char *n) {
|
||||
size_t i;
|
||||
|
||||
|
@ -438,17 +444,25 @@ void grabfocus(void) {
|
|||
|
||||
void insert(const char *str, ssize_t n) {
|
||||
if (strlen(tx.text) + n > sizeof tx.text - 1)
|
||||
return;
|
||||
return; // length of text should not exceed size
|
||||
|
||||
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
|
||||
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
|
||||
if (n > 0 && str && n)
|
||||
if (n > 0 && str && n) {
|
||||
memcpy(&tx.text[sp.cursor], str, n);
|
||||
}
|
||||
|
||||
// add to cursor position and continue matching
|
||||
sp.cursor += n;
|
||||
|
@ -460,6 +474,7 @@ void insert(const char *str, ssize_t n) {
|
|||
match();
|
||||
}
|
||||
|
||||
// output on insertion
|
||||
if (incremental) {
|
||||
puts(tx.text);
|
||||
fflush(stdout);
|
||||
|
@ -467,12 +482,13 @@ void insert(const char *str, ssize_t n) {
|
|||
}
|
||||
|
||||
size_t nextrune(int inc) {
|
||||
ssize_t n;
|
||||
ssize_t rune;
|
||||
|
||||
// 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
|
||||
|
@ -497,6 +513,10 @@ void resizeclient(void) {
|
|||
#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) {
|
||||
sp.inputw = sp.mw / 3;
|
||||
}
|
||||
|
@ -507,12 +527,14 @@ void get_mh(void) {
|
|||
sp.mh = (lines + 1) * sp.bh;
|
||||
sp.mh += 2 * menumarginv;
|
||||
|
||||
// subtract 1 line if there's nothing to draw on the top line
|
||||
if ((hideprompt && hideinput && hidemode && hidematchcount && hidecaps) && lines) {
|
||||
sp.mh -= sp.bh;
|
||||
}
|
||||
|
||||
epad = 2 * menupaddingv;
|
||||
|
||||
// the spmenu window should not exceed the screen resolution height
|
||||
if (mo.output_height && !xpos && !ypos) {
|
||||
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));
|
||||
}
|
||||
|
||||
// normal mode disabled
|
||||
if (sp.forceinsertmode) {
|
||||
sp.mode = 1;
|
||||
sp.allowkeys = 1;
|
||||
|
@ -608,7 +631,9 @@ void handle(void) {
|
|||
int main(int argc, char *argv[]) {
|
||||
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__
|
||||
if (pledge("stdio rpath wpath cpath", NULL) == -1)
|
||||
die("pledge");
|
||||
|
|
Loading…
Reference in a new issue