mirror of https://github.com/0intro/wmii
[menu] Add vertical mode.
This commit is contained in:
parent
8ca9f3ca3a
commit
ed809b8471
|
@ -29,14 +29,14 @@ def message(message):
|
||||||
call(*args, input=message)
|
call(*args, input=message)
|
||||||
|
|
||||||
def program_list(path):
|
def program_list(path):
|
||||||
names = []
|
names = set()
|
||||||
for d in path:
|
for d in path:
|
||||||
try:
|
try:
|
||||||
for f in os.listdir(d):
|
for f in os.listdir(d):
|
||||||
p = '%s/%s' % (d, f)
|
p = '%s/%s' % (d, f)
|
||||||
if f not in names and os.access(p, os.X_OK) and (
|
if (f not in names and os.access(p, os.X_OK) and
|
||||||
os.path.isfile(p) or os.path.islink(p)):
|
os.path.isfile(p)):
|
||||||
names.append(f)
|
names.add(f)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return sorted(names)
|
return sorted(names)
|
||||||
|
|
|
@ -5,12 +5,13 @@ include $(ROOT)/mk/wmii.mk
|
||||||
main.c: $(ROOT)/mk/wmii.mk
|
main.c: $(ROOT)/mk/wmii.mk
|
||||||
|
|
||||||
bindings.c: keys.txt Makefile
|
bindings.c: keys.txt Makefile
|
||||||
( echo "char binding_spec[] = "; \
|
( echo "char binding_spec[] ="; \
|
||||||
sed 's/.*/ "&\\n"/' keys.txt; \
|
sed 's/.*/ "&\\n"/' keys.txt; \
|
||||||
echo " ;" ) >bindings.c
|
echo " ;" ) >$@
|
||||||
|
|
||||||
TARG = wimenu
|
TARG = wimenu
|
||||||
HFILES= dat.h fns.h
|
HFILES= dat.h fns.h
|
||||||
|
TAGFILES= dat.h
|
||||||
|
|
||||||
PACKAGES += $(X11PACKAGES)
|
PACKAGES += $(X11PACKAGES)
|
||||||
|
|
||||||
|
|
|
@ -69,9 +69,7 @@ caret_find(int dir, int type) {
|
||||||
p = next;
|
p = next;
|
||||||
return p;
|
return p;
|
||||||
case CHAR:
|
case CHAR:
|
||||||
if(p < end)
|
return next_rune(p, &r);
|
||||||
return p+1;
|
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(dir == BACKWARD) {
|
else if(dir == BACKWARD) {
|
||||||
|
@ -88,9 +86,7 @@ caret_find(int dir, int type) {
|
||||||
p = next;
|
p = next;
|
||||||
return p;
|
return p;
|
||||||
case CHAR:
|
case CHAR:
|
||||||
if(p > end)
|
return prev_rune(end, p, &r);
|
||||||
return prev_rune(end, p, &r);
|
|
||||||
return end;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
input.pos_end = nil;
|
input.pos_end = nil;
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
#include <stuff/x.h>
|
#include <stuff/x.h>
|
||||||
#include <stuff/util.h>
|
#include <stuff/util.h>
|
||||||
|
|
||||||
#define BLOCK(x) do { x; }while(0)
|
|
||||||
|
|
||||||
#ifndef EXTERN
|
#ifndef EXTERN
|
||||||
# define EXTERN extern
|
# define EXTERN extern
|
||||||
#endif
|
#endif
|
||||||
|
@ -69,38 +67,40 @@ EXTERN struct {
|
||||||
int filter_start;
|
int filter_start;
|
||||||
} input;
|
} input;
|
||||||
|
|
||||||
|
EXTERN struct {
|
||||||
|
Window* win;
|
||||||
|
Image* buf;
|
||||||
|
char* prompt;
|
||||||
|
int height;
|
||||||
|
int rows;
|
||||||
|
bool ontop;
|
||||||
|
Rectangle itemr;
|
||||||
|
Point arrow;
|
||||||
|
} menu;
|
||||||
|
|
||||||
extern char binding_spec[];
|
extern char binding_spec[];
|
||||||
|
|
||||||
EXTERN int numlock;
|
|
||||||
|
|
||||||
EXTERN long xtime;
|
|
||||||
EXTERN Image* ibuf;
|
|
||||||
EXTERN Font* font;
|
|
||||||
EXTERN CTuple cnorm, csel;
|
|
||||||
EXTERN bool ontop;
|
|
||||||
|
|
||||||
EXTERN Cursor cursor[1];
|
|
||||||
EXTERN Visual* render_visual;
|
|
||||||
|
|
||||||
EXTERN IxpServer srv;
|
EXTERN IxpServer srv;
|
||||||
|
|
||||||
EXTERN Window* barwin;
|
EXTERN struct {
|
||||||
|
Item* all;
|
||||||
|
Item* first;
|
||||||
|
Item* start;
|
||||||
|
Item* end;
|
||||||
|
Item* sel;
|
||||||
|
int maxwidth;
|
||||||
|
} match;
|
||||||
|
|
||||||
EXTERN Item* items;
|
Font* font;
|
||||||
EXTERN Item* matchfirst;
|
CTuple cnorm;
|
||||||
EXTERN Item* matchstart;
|
CTuple csel;
|
||||||
EXTERN Item* matchend;
|
|
||||||
EXTERN Item* matchidx;
|
|
||||||
|
|
||||||
EXTERN Item hist;
|
EXTERN Item hist;
|
||||||
EXTERN Item* histidx;
|
EXTERN Item* histsel;
|
||||||
|
|
||||||
EXTERN int maxwidth;
|
EXTERN int itempad;
|
||||||
EXTERN int result;
|
EXTERN int result;
|
||||||
|
|
||||||
EXTERN char* (*find)(const char*, const char*);
|
EXTERN char* (*find)(const char*, const char*);
|
||||||
EXTERN int (*compare)(const char*, const char*, size_t);
|
EXTERN int (*compare)(const char*, const char*, size_t);
|
||||||
|
|
||||||
EXTERN char* prompt;
|
|
||||||
EXTERN int promptw;
|
|
||||||
|
|
||||||
|
|
|
@ -19,25 +19,25 @@ history_search(int dir, char *string, int n) {
|
||||||
Item *i;
|
Item *i;
|
||||||
|
|
||||||
if(dir == FORWARD) {
|
if(dir == FORWARD) {
|
||||||
if(histidx == &hist)
|
if(histsel == &hist)
|
||||||
return hist.string;
|
return hist.string;
|
||||||
for(i=histidx->next; i != hist.next; i=i->next)
|
for(i=histsel->next; i != hist.next; i=i->next)
|
||||||
if(!i->string || !compare(i->string, string, n)) {
|
if(!i->string || !compare(i->string, string, n)) {
|
||||||
histidx = i;
|
histsel = i;
|
||||||
return i->string;
|
return i->string;
|
||||||
}
|
}
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
assert(dir == BACKWARD);
|
assert(dir == BACKWARD);
|
||||||
|
|
||||||
if(histidx == &hist) {
|
if(histsel == &hist) {
|
||||||
free(hist.string);
|
free(hist.string);
|
||||||
hist.string = estrdup(input.string);
|
hist.string = estrdup(input.string);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=histidx->prev; i != &hist; i=i->prev)
|
for(i=histsel->prev; i != &hist; i=i->prev)
|
||||||
if(!compare(i->string, string, n)) {
|
if(!compare(i->string, string, n)) {
|
||||||
histidx = i;
|
histsel = i;
|
||||||
return i->string;
|
return i->string;
|
||||||
}
|
}
|
||||||
return string;
|
return string;
|
||||||
|
|
|
@ -13,7 +13,8 @@ struct Key {
|
||||||
char** action;
|
char** action;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Key* bindings;
|
static Key* bindings;
|
||||||
|
static int numlock;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To do: Find my red black tree implementation.
|
* To do: Find my red black tree implementation.
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
|
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
|
||||||
* See LICENSE file for license details.
|
* See LICENSE file for license details.
|
||||||
*/
|
*/
|
||||||
#define IXP_NO_P9_
|
|
||||||
#define IXP_P9_STRUCTS
|
|
||||||
#define EXTERN
|
#define EXTERN
|
||||||
#include "dat.h"
|
#include "dat.h"
|
||||||
#include <X11/Xproto.h>
|
#include <X11/Xproto.h>
|
||||||
|
@ -23,7 +21,9 @@ static int screen_hint;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage(void) {
|
usage(void) {
|
||||||
fatal("usage: wimenu -i [-h <history>] [-a <address>] [-p <prompt>] [-s <screen>]\n");
|
fprint(2, "usage: %s -i [-a <address>] [-h <history>] [-p <prompt>] [-r <rows>] [-s <screen>]\n", argv0);
|
||||||
|
fprint(2, " See manual page for full usage details.\n");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -50,13 +50,13 @@ populate_list(Biobuf *buf, bool hist) {
|
||||||
bool stop;
|
bool stop;
|
||||||
|
|
||||||
stop = !hist && !isatty(buf->fid);
|
stop = !hist && !isatty(buf->fid);
|
||||||
|
ret.next_link = nil;
|
||||||
i = &ret;
|
i = &ret;
|
||||||
while((p = Brdstr(buf, '\n', true))) {
|
while((p = Brdstr(buf, '\n', true))) {
|
||||||
if(stop && p[0] == '\0')
|
if(stop && p[0] == '\0')
|
||||||
break;
|
break;
|
||||||
link(i, emallocz(sizeof *i));
|
i->next_link = emallocz(sizeof *i);
|
||||||
i->next_link = i->next;
|
i = i->next_link;
|
||||||
i = i->next;
|
|
||||||
i->string = p;
|
i->string = p;
|
||||||
i->retstring = p;
|
i->retstring = p;
|
||||||
if(cmdsep && (p = strstr(p, cmdsep))) {
|
if(cmdsep && (p = strstr(p, cmdsep))) {
|
||||||
|
@ -65,15 +65,12 @@ populate_list(Biobuf *buf, bool hist) {
|
||||||
}
|
}
|
||||||
if(!hist) {
|
if(!hist) {
|
||||||
i->len = strlen(i->string);
|
i->len = strlen(i->string);
|
||||||
i->width = textwidth_l(font, i->string, i->len);
|
i->width = textwidth_l(font, i->string, i->len) + itempad;
|
||||||
if(i->width > maxwidth)
|
match.maxwidth = max(i->width, match.maxwidth);
|
||||||
maxwidth = i->width;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
link(i, &ret);
|
return ret.next_link;
|
||||||
splice(&ret);
|
|
||||||
return ret.next != &ret ? ret.next : nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -86,7 +83,7 @@ check_competions(IxpConn *c) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
input.filter_start = strtol(s, nil, 10);
|
input.filter_start = strtol(s, nil, 10);
|
||||||
items = populate_list(cmplbuf, false);
|
match.all = populate_list(cmplbuf, false);
|
||||||
update_filter(false);
|
update_filter(false);
|
||||||
menu_draw();
|
menu_draw();
|
||||||
}
|
}
|
||||||
|
@ -143,8 +140,8 @@ update_filter(bool print) {
|
||||||
if(input.pos < input.end)
|
if(input.pos < input.end)
|
||||||
filter = freelater(estrndup(filter, input.pos - filter));
|
filter = freelater(estrndup(filter, input.pos - filter));
|
||||||
|
|
||||||
matchidx = nil;
|
match.sel = nil;
|
||||||
matchfirst = matchstart = filter_list(items, filter);
|
match.first = match.start = filter_list(match.all, filter);
|
||||||
if(print)
|
if(print)
|
||||||
update_input();
|
update_input();
|
||||||
}
|
}
|
||||||
|
@ -158,8 +155,7 @@ init_screens(void) {
|
||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
rects = xinerama_screens(&n);
|
rects = xinerama_screens(&n);
|
||||||
if (screen_hint >= 0 && screen_hint < n)
|
if(screen_hint >= 0 && screen_hint < n)
|
||||||
/* We were given a valid screen index, use that. */
|
|
||||||
i = screen_hint;
|
i = screen_hint;
|
||||||
else {
|
else {
|
||||||
/* Pick the screen with the pointer, for now. Later,
|
/* Pick the screen with the pointer, for now. Later,
|
||||||
|
@ -178,11 +174,11 @@ init_screens(void) {
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[]) {
|
main(int argc, char *argv[]) {
|
||||||
Item *item;
|
|
||||||
static char *address;
|
static char *address;
|
||||||
static char *histfile;
|
static char *histfile;
|
||||||
static char *keyfile;
|
static char *keyfile;
|
||||||
static bool nokeys;
|
static bool nokeys;
|
||||||
|
Item *item;
|
||||||
int i;
|
int i;
|
||||||
long ndump;
|
long ndump;
|
||||||
|
|
||||||
|
@ -220,7 +216,10 @@ main(int argc, char *argv[]) {
|
||||||
ndump = strtol(EARGF(usage()), nil, 10);
|
ndump = strtol(EARGF(usage()), nil, 10);
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
prompt = EARGF(usage());
|
menu.prompt = EARGF(usage());
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
menu.rows = strtol(EARGF(usage()), nil, 10);
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
screen_hint = strtol(EARGF(usage()), nil, 10);
|
screen_hint = strtol(EARGF(usage()), nil, 10);
|
||||||
|
@ -249,11 +248,13 @@ main(int argc, char *argv[]) {
|
||||||
srv.preselect = event_preselect;
|
srv.preselect = event_preselect;
|
||||||
ixp_listen(&srv, ConnectionNumber(display), nil, event_fdready, event_fdclosed);
|
ixp_listen(&srv, ConnectionNumber(display), nil, event_fdready, event_fdclosed);
|
||||||
|
|
||||||
ontop = !strcmp(readctl("bar on "), "top");
|
menu.ontop = !strcmp(readctl("/ctl", "bar "), "on top");
|
||||||
client_readconfig(&cnorm, &csel, &font);
|
client_readconfig(&cnorm, &csel, &font);
|
||||||
|
|
||||||
|
itempad = (font->height & ~1) + font->pad.min.x + font->pad.max.x;
|
||||||
|
|
||||||
cmplbuf = Bfdopen(0, OREAD);
|
cmplbuf = Bfdopen(0, OREAD);
|
||||||
items = populate_list(cmplbuf, false);
|
match.all = populate_list(cmplbuf, false);
|
||||||
if(!isatty(cmplbuf->fid))
|
if(!isatty(cmplbuf->fid))
|
||||||
ixp_listen(&srv, cmplbuf->fid, inbuf, check_competions, nil);
|
ixp_listen(&srv, cmplbuf->fid, inbuf, check_competions, nil);
|
||||||
|
|
||||||
|
@ -268,21 +269,18 @@ main(int argc, char *argv[]) {
|
||||||
parse_keys(buffer);
|
parse_keys(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
histidx = &hist;
|
histsel = &hist;
|
||||||
link(&hist, &hist);
|
link(&hist, &hist);
|
||||||
if(histfile) {
|
if(histfile && (inbuf = Bopen(histfile, OREAD))) {
|
||||||
inbuf = Bopen(histfile, OREAD);
|
item = filter_list(populate_list(inbuf, true), "");
|
||||||
if(inbuf) {
|
if(item->string) {
|
||||||
item = populate_list(inbuf, true);
|
link(item->prev, &hist);
|
||||||
if(item) {
|
link(&hist, item);
|
||||||
link(item->prev, &hist);
|
|
||||||
link(&hist, item);
|
|
||||||
}
|
|
||||||
Bterm(inbuf);
|
|
||||||
}
|
}
|
||||||
|
Bterm(inbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(barwin == nil)
|
if(menu.win == nil)
|
||||||
menu_init();
|
menu_init();
|
||||||
|
|
||||||
init_screens();
|
init_screens();
|
||||||
|
|
465
cmd/menu/menu.c
465
cmd/menu/menu.c
|
@ -4,270 +4,220 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
|
|
||||||
static Handlers handlers;
|
static Handlers handlers;
|
||||||
|
static int promptw;
|
||||||
static int ltwidth;
|
|
||||||
|
|
||||||
static void _menu_draw(bool);
|
|
||||||
|
|
||||||
enum {
|
|
||||||
ACCEPT = CARET_LAST,
|
|
||||||
REJECT,
|
|
||||||
HIST,
|
|
||||||
KILL,
|
|
||||||
CMPL_NEXT,
|
|
||||||
CMPL_PREV,
|
|
||||||
CMPL_FIRST,
|
|
||||||
CMPL_LAST,
|
|
||||||
CMPL_NEXT_PAGE,
|
|
||||||
CMPL_PREV_PAGE,
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
menu_init(void) {
|
menu_init(void) {
|
||||||
WinAttr wa;
|
WinAttr wa;
|
||||||
|
|
||||||
wa.event_mask = ExposureMask | KeyPressMask;
|
wa.event_mask = ExposureMask | KeyPressMask;
|
||||||
barwin = createwindow(&scr.root, Rect(-1, -1, 1, 1), scr.depth, InputOutput,
|
menu.win = createwindow(&scr.root, Rect(-1, -1, 1, 1), scr.depth, InputOutput,
|
||||||
&wa, CWEventMask);
|
&wa, CWEventMask);
|
||||||
if(scr.xim)
|
if(scr.xim)
|
||||||
barwin->xic = XCreateIC(scr.xim,
|
menu.win->xic = XCreateIC(scr.xim,
|
||||||
XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
|
XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
|
||||||
XNClientWindow, barwin->xid,
|
XNClientWindow, menu.win->xid,
|
||||||
XNFocusWindow, barwin->xid,
|
XNFocusWindow, menu.win->xid,
|
||||||
nil);
|
nil);
|
||||||
|
|
||||||
changeprop_long(barwin, Net("WM_WINDOW_TYPE"), "ATOM",
|
changeprop_long(menu.win, Net("WM_WINDOW_TYPE"), "ATOM", (long[]){ TYPE("MENU") }, 1);
|
||||||
(long[]){ TYPE("MENU") }, 1);
|
changeprop_string(menu.win, "_WMII_TAGS", "sel");
|
||||||
changeprop_string(barwin, "_WMII_TAGS", "sel");
|
changeprop_textlist(menu.win, "WM_CLASS", "STRING", (char*[3]){ "wimenu", "wimenu" });
|
||||||
changeprop_textlist(barwin, "WM_CLASS", "STRING",
|
|
||||||
(char*[3]){ "wimenu", "wimenu", nil });
|
|
||||||
|
|
||||||
sethandler(barwin, &handlers);
|
sethandler(menu.win, &handlers);
|
||||||
mapwin(barwin);
|
mapwin(menu.win);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(!grabkeyboard(barwin)) {
|
while(!grabkeyboard(menu.win)) {
|
||||||
if(i++ > 1000)
|
if(i++ > 1000)
|
||||||
fatal("can't grab keyboard");
|
fatal("can't grab keyboard");
|
||||||
usleep(1000);
|
usleep(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
menu_unmap(long id, void *p) {
|
menu_show(void) {
|
||||||
|
Rectangle r;
|
||||||
|
|
||||||
USED(id, p);
|
if(menu.prompt)
|
||||||
unmapwin(barwin);
|
promptw = textwidth(font, menu.prompt) + itempad;
|
||||||
XFlush(display);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
r = textextents_l(font, "<", 1, nil);
|
||||||
selectitem(Item *i) {
|
menu.arrow = Pt(Dy(r) + itempad/2, Dx(r) + itempad/2);
|
||||||
if(i != matchidx) {
|
|
||||||
caret_set(input.filter_start, input.pos - input.string);
|
|
||||||
caret_insert(i->string, 0);
|
|
||||||
matchidx = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
menu.height = labelh(font);
|
||||||
menu_cmd(int op, int motion) {
|
|
||||||
int n;
|
|
||||||
|
|
||||||
switch(op) {
|
freeimage(menu.buf);
|
||||||
case HIST:
|
menu.buf = allocimage(Dx(scr.rect),
|
||||||
n = input.pos - input.string;
|
!!menu.rows * 2 * menu.arrow.y + (menu.rows + 1) * menu.height,
|
||||||
caret_insert(history_search(motion, input.string, n), true);
|
menu.win->depth);
|
||||||
input.pos = input.string + n;
|
|
||||||
break;
|
mapwin(menu.win);
|
||||||
case KILL:
|
raisewin(menu.win);
|
||||||
caret_delete(BACKWARD, motion);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
update_filter(true);
|
|
||||||
next:
|
|
||||||
switch(op) {
|
|
||||||
case ACCEPT:
|
|
||||||
srv.running = false;
|
|
||||||
if(!matchidx && matchfirst->retstring && !motion)
|
|
||||||
if(input.filter_start == 0 && input.pos == input.end)
|
|
||||||
menu_cmd(CMPL_FIRST, 0);
|
|
||||||
if(!motion && matchidx && !strcmp(input.string, matchidx->string))
|
|
||||||
lprint(1, "%s", matchidx->retstring);
|
|
||||||
else
|
|
||||||
lprint(1, "%s", input.string);
|
|
||||||
break;
|
|
||||||
case REJECT:
|
|
||||||
srv.running = false;
|
|
||||||
result = 1;
|
|
||||||
break;
|
|
||||||
case BACKWARD:
|
|
||||||
case FORWARD:
|
|
||||||
caret_move(op, motion);
|
|
||||||
update_input();
|
|
||||||
break;
|
|
||||||
case CMPL_NEXT:
|
|
||||||
selectitem(matchidx ? matchidx->next : matchfirst);
|
|
||||||
break;
|
|
||||||
case CMPL_PREV:
|
|
||||||
selectitem((matchidx ? matchidx : matchstart)->prev);
|
|
||||||
break;
|
|
||||||
case CMPL_FIRST:
|
|
||||||
matchstart = matchfirst;
|
|
||||||
matchend = nil;
|
|
||||||
selectitem(matchstart);
|
|
||||||
break;
|
|
||||||
case CMPL_LAST:
|
|
||||||
selectitem(matchfirst->prev);
|
|
||||||
break;
|
|
||||||
case CMPL_NEXT_PAGE:
|
|
||||||
if(matchend)
|
|
||||||
selectitem(matchend->next);
|
|
||||||
break;
|
|
||||||
case CMPL_PREV_PAGE:
|
|
||||||
matchend = matchstart->prev;
|
|
||||||
matchidx = nil;
|
|
||||||
_menu_draw(false);
|
|
||||||
selectitem(matchstart);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
menu_draw();
|
menu_draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* I'd prefer to use ⌃ and ⌄, but few fonts support them. */
|
||||||
static void
|
static void
|
||||||
_menu_draw(bool draw) {
|
drawarrow(Image *img, Rectangle r, int up, Color *col) {
|
||||||
Rectangle r, rd, rp, r2, extent;
|
Point p[3], pt;
|
||||||
CTuple *c;
|
|
||||||
Item *i;
|
|
||||||
int inputw, itemoff, end, pad, n, offset;
|
|
||||||
|
|
||||||
r = barwin->r;
|
pt = Pt(menu.arrow.x - itempad/2, menu.arrow.y - itempad/2 & ~1);
|
||||||
r = rectsetorigin(r, ZP);
|
|
||||||
|
|
||||||
pad = (font->height & ~1) + font->pad.min.x + font->pad.max.x;
|
p[1] = Pt(r.min.x + Dx(r)/2, up ? r.min.y + itempad/4 : r.max.y - itempad/4);
|
||||||
|
p[0] = Pt(p[1].x - pt.x/2, up ? p[1].y + pt.y : p[1].y - pt.y);
|
||||||
|
p[2] = Pt(p[1].x + pt.x/2, p[0].y);
|
||||||
|
drawpoly(img, p, nelem(p), CapProjecting, 1, col);
|
||||||
|
}
|
||||||
|
|
||||||
rd = r;
|
static Rectangle
|
||||||
rp = ZR; // SET(rp)
|
slice(Rectangle *rp, int x, int y) {
|
||||||
if (prompt) {
|
Rectangle r;
|
||||||
if (!promptw)
|
|
||||||
promptw = textwidth(font, prompt) + 2 * ltwidth + pad;
|
|
||||||
rd.min.x += promptw;
|
|
||||||
|
|
||||||
rp = r;
|
r = *rp;
|
||||||
rp.max.x = promptw;
|
if(x)
|
||||||
}
|
rp->min.x += x, r.max.x = min(rp->min.x, rp->max.x);
|
||||||
|
if(y)
|
||||||
|
rp->min.y += y, r.max.y = min(rp->min.y, rp->max.y);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
inputw = min(Dx(rd) / 3, maxwidth);
|
static bool
|
||||||
inputw = max(inputw, textwidth(font, input.string)) + pad;
|
nextrect(Item *i, Rectangle *rp, Rectangle *src) {
|
||||||
itemoff = inputw + 2 * ltwidth;
|
Rectangle r;
|
||||||
end = Dx(rd) - ltwidth;
|
|
||||||
|
|
||||||
fill(ibuf, r, &cnorm.bg);
|
if(menu.rows)
|
||||||
|
r = slice(src, 0, menu.height);
|
||||||
if(matchend && matchidx == matchend->next)
|
else
|
||||||
matchstart = matchidx;
|
r = slice(src, i->width, 0);
|
||||||
else if(matchidx == matchstart->prev)
|
return (Dx(*src) >= 0 && Dy(*src) >= 0) && (*rp = r, 1);
|
||||||
matchend = matchidx;
|
|
||||||
if (matchend == nil)
|
|
||||||
matchend = matchstart;
|
|
||||||
|
|
||||||
if(matchend == matchstart->prev && matchstart != matchidx) {
|
|
||||||
n = itemoff;
|
|
||||||
matchstart = matchend;
|
|
||||||
for(i=matchend; ; i=i->prev) {
|
|
||||||
n += i->width + pad;
|
|
||||||
if(n > end)
|
|
||||||
break;
|
|
||||||
matchstart = i;
|
|
||||||
if(i == matchfirst)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!draw)
|
|
||||||
return;
|
|
||||||
|
|
||||||
r2 = rd;
|
|
||||||
for(i=matchstart; i->string; i=i->next) {
|
|
||||||
r2.min.x = promptw + itemoff;
|
|
||||||
itemoff = itemoff + i->width + pad;
|
|
||||||
r2.max.x = promptw + min(itemoff, end);
|
|
||||||
if(i != matchstart && itemoff > end)
|
|
||||||
break;
|
|
||||||
|
|
||||||
c = (i == matchidx) ? &csel : &cnorm;
|
|
||||||
fill(ibuf, r2, &c->bg);
|
|
||||||
drawstring(ibuf, font, r2, Center, i->string, &c->fg);
|
|
||||||
matchend = i;
|
|
||||||
if(i->next == matchfirst)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
r2 = rd;
|
|
||||||
r2.min.x = promptw + inputw;
|
|
||||||
if(matchstart != matchfirst)
|
|
||||||
drawstring(ibuf, font, r2, West, "<", &cnorm.fg);
|
|
||||||
if(matchend->next != matchfirst)
|
|
||||||
drawstring(ibuf, font, r2, East, ">", &cnorm.fg);
|
|
||||||
|
|
||||||
r2 = rd;
|
|
||||||
r2.max.x = promptw + inputw;
|
|
||||||
drawstring(ibuf, font, r2, West, input.string, &cnorm.fg);
|
|
||||||
|
|
||||||
extent = textextents_l(font, input.string, input.pos - input.string, &offset);
|
|
||||||
r2.min.x = promptw + offset + font->pad.min.x - extent.min.x + pad/2 - 1;
|
|
||||||
r2.max.x = r2.min.x + 2;
|
|
||||||
r2.min.y++;
|
|
||||||
r2.max.y--;
|
|
||||||
border(ibuf, r2, 1, &cnorm.border);
|
|
||||||
|
|
||||||
if (prompt)
|
|
||||||
drawstring(ibuf, font, rp, West, prompt, &cnorm.fg);
|
|
||||||
|
|
||||||
border(ibuf, rd, 1, &cnorm.border);
|
|
||||||
copyimage(barwin, r, ibuf, ZP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
menu_draw(void) {
|
menu_draw(void) {
|
||||||
_menu_draw(true);
|
Rectangle barr, extent, itemr, inputr, r, r2;
|
||||||
|
Item *item;
|
||||||
|
int inputw, offset;
|
||||||
|
|
||||||
|
barr = r2 = Rect(0, 0, Dx(menu.win->r), menu.height);
|
||||||
|
|
||||||
|
inputw = max(match.maxwidth + textwidth_l(font, input.string, min(input.filter_start, strlen(input.string))),
|
||||||
|
max(itempad + textwidth(font, input.string),
|
||||||
|
Dx(barr) / 3));
|
||||||
|
|
||||||
|
/* Calculate items box, w/ and w/o arrows */
|
||||||
|
if(menu.rows) {
|
||||||
|
menu.itemr = barr;
|
||||||
|
menu.itemr.max.y += Dy(barr) * (menu.rows - 1);
|
||||||
|
if(menu.ontop)
|
||||||
|
menu.itemr = rectaddpt(menu.itemr, Pt(0, Dy(barr)));
|
||||||
|
itemr = menu.itemr;
|
||||||
|
if(match.start != match.first)
|
||||||
|
menu.itemr = rectaddpt(menu.itemr, Pt(0, menu.arrow.y));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
itemr = r2;
|
||||||
|
slice(&itemr, inputw + promptw, 0);
|
||||||
|
menu.itemr = Rect(itemr.min.x + menu.arrow.x, itemr.min.y,
|
||||||
|
itemr.max.x - menu.arrow.x, itemr.max.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
fill(menu.buf, menu.buf->r, &cnorm.bg);
|
||||||
|
|
||||||
|
/* Draw items */
|
||||||
|
item = match.start, r2 = menu.itemr;
|
||||||
|
nextrect(item, &r, &r2);
|
||||||
|
do {
|
||||||
|
match.end = item;
|
||||||
|
if(item->string)
|
||||||
|
fillstring(menu.buf, font, r, West, item->string,
|
||||||
|
(item == match.sel ? &csel : &cnorm), 0);
|
||||||
|
item = item->next;
|
||||||
|
} while(item != match.first && nextrect(item, &r, &r2));
|
||||||
|
|
||||||
|
/* Adjust dimensions for arrows/number of items */
|
||||||
|
if(menu.rows)
|
||||||
|
itemr.max.y = r.max.y + (match.end->next != match.first ? menu.arrow.y : 0);
|
||||||
|
else
|
||||||
|
itemr.max.x = r.max.x + menu.arrow.x;
|
||||||
|
if(menu.rows && !menu.ontop)
|
||||||
|
barr = rectaddpt(barr, Pt(0, itemr.max.y));
|
||||||
|
|
||||||
|
/* Draw indicators */
|
||||||
|
if(!menu.rows && match.start != match.first)
|
||||||
|
drawstring(menu.buf, font, itemr, West, "<", &cnorm.fg);
|
||||||
|
if(!menu.rows && match.end->next != match.first)
|
||||||
|
drawstring(menu.buf, font, itemr, East, ">", &cnorm.fg);
|
||||||
|
|
||||||
|
if(menu.rows && match.start != match.first)
|
||||||
|
drawarrow(menu.buf, itemr, 1, &cnorm.fg);
|
||||||
|
if(menu.rows && match.end->next != match.first)
|
||||||
|
drawarrow(menu.buf, itemr, 0, &cnorm.fg);
|
||||||
|
|
||||||
|
/* Draw prompt */
|
||||||
|
r2 = barr;
|
||||||
|
if(menu.prompt)
|
||||||
|
drawstring(menu.buf, font, slice(&r2, promptw, 0),
|
||||||
|
West, menu.prompt, &cnorm.fg);
|
||||||
|
|
||||||
|
/* Border input/horizontal items */
|
||||||
|
border(menu.buf, r2, 1, &cnorm.border);
|
||||||
|
|
||||||
|
/* Draw input */
|
||||||
|
inputr = slice(&r2, inputw, 0);
|
||||||
|
drawstring(menu.buf, font, inputr, West, input.string, &cnorm.fg);
|
||||||
|
|
||||||
|
/* Draw cursor */
|
||||||
|
extent = textextents_l(font, input.string, input.pos - input.string, &offset);
|
||||||
|
r2 = insetrect(inputr, 2);
|
||||||
|
r2.min.x = inputr.min.x - extent.min.x + offset + font->pad.min.x + itempad/2 - 1;
|
||||||
|
r2.max.x = r2.min.x + 1;
|
||||||
|
fill(menu.buf, r2, &cnorm.border);
|
||||||
|
|
||||||
|
/* Reshape window */
|
||||||
|
r = scr.rect;
|
||||||
|
if(menu.ontop)
|
||||||
|
r.max.y = r.min.y + itemr.max.y;
|
||||||
|
else
|
||||||
|
r.min.y = r.max.y - barr.max.y;
|
||||||
|
reshapewin(menu.win, r);
|
||||||
|
|
||||||
|
/* Border window */
|
||||||
|
r = rectsubpt(r, r.min);
|
||||||
|
border(menu.buf, r, 1, &cnorm.border);
|
||||||
|
copyimage(menu.win, r, menu.buf, ZP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static Item*
|
||||||
menu_show(void) {
|
pagestart(Item *i) {
|
||||||
Rectangle r;
|
Rectangle r, r2;
|
||||||
int height, pad;
|
|
||||||
|
|
||||||
USED(menu_unmap);
|
r = menu.itemr;
|
||||||
|
nextrect(i, &r2, &r);
|
||||||
|
while(i->prev != match.first->prev && nextrect(i->prev, &r2, &r))
|
||||||
|
i = i->prev;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
ltwidth = textwidth(font, "<");
|
static void
|
||||||
|
selectitem(Item *i) {
|
||||||
pad = (font->height & ~1)/2;
|
if(i != match.sel) {
|
||||||
height = labelh(font);
|
caret_set(input.filter_start, input.pos - input.string);
|
||||||
|
caret_insert(i->string, 0);
|
||||||
r = scr.rect;
|
match.sel = i;
|
||||||
if(ontop)
|
if(i == match.start->prev)
|
||||||
r.max.y = r.min.y + height;
|
match.start = pagestart(i);
|
||||||
else
|
if(i == match.end->next)
|
||||||
r.min.y = r.max.y - height;
|
match.start = i;
|
||||||
reshapewin(barwin, r);
|
}
|
||||||
|
|
||||||
freeimage(ibuf);
|
|
||||||
ibuf = allocimage(Dx(r), Dy(r), scr.depth);
|
|
||||||
|
|
||||||
mapwin(barwin);
|
|
||||||
raisewin(barwin);
|
|
||||||
menu_draw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
kdown_event(Window *w, void *aux, XKeyEvent *e) {
|
kdown_event(Window *w, void *aux, XKeyEvent *e) {
|
||||||
char **action, **p;
|
char **action, **p;
|
||||||
char *key;
|
char *key;
|
||||||
char buf[32];
|
char buf[128];
|
||||||
int num, status;
|
int num, status;
|
||||||
KeySym ksym;
|
KeySym ksym;
|
||||||
|
|
||||||
|
@ -276,8 +226,7 @@ kdown_event(Window *w, void *aux, XKeyEvent *e) {
|
||||||
|
|
||||||
status = XLookupBoth;
|
status = XLookupBoth;
|
||||||
if(w->xic)
|
if(w->xic)
|
||||||
num = Xutf8LookupString(w->xic, e, buf, sizeof buf - 1, &ksym,
|
num = Xutf8LookupString(w->xic, e, buf, sizeof buf - 1, &ksym, &status);
|
||||||
&status);
|
|
||||||
else
|
else
|
||||||
num = XLookupString(e, buf, sizeof buf - 1, &ksym, nil);
|
num = XLookupString(e, buf, sizeof buf - 1, &ksym, nil);
|
||||||
|
|
||||||
|
@ -319,37 +268,65 @@ kdown_event(Window *w, void *aux, XKeyEvent *e) {
|
||||||
have(LWORD) ? WORD :
|
have(LWORD) ? WORD :
|
||||||
have(LLINE) ? LINE :
|
have(LLINE) ? LINE :
|
||||||
-1);
|
-1);
|
||||||
|
|
||||||
switch(getsym(action[0])) {
|
switch(getsym(action[0])) {
|
||||||
case LACCEPT:
|
default:
|
||||||
menu_cmd(ACCEPT, have(LLITERAL));
|
return false;
|
||||||
break;
|
|
||||||
case LBACKWARD:
|
|
||||||
menu_cmd(BACKWARD, amount);
|
|
||||||
break;
|
|
||||||
case LCOMPLETE:
|
|
||||||
amount = (
|
|
||||||
have(LNEXT) ? CMPL_NEXT :
|
|
||||||
have(LPREV) ? CMPL_PREV :
|
|
||||||
have(LNEXTPAGE) ? CMPL_NEXT_PAGE :
|
|
||||||
have(LPREVPAGE) ? CMPL_PREV_PAGE :
|
|
||||||
have(LFIRST) ? CMPL_FIRST :
|
|
||||||
have(LLAST) ? CMPL_LAST :
|
|
||||||
CMPL_NEXT);
|
|
||||||
menu_cmd(amount, 0);
|
|
||||||
break;
|
|
||||||
case LFORWARD:
|
|
||||||
menu_cmd(FORWARD, amount);
|
|
||||||
break;
|
|
||||||
case LHISTORY:
|
case LHISTORY:
|
||||||
menu_cmd(HIST, have(LBACKWARD) ? BACKWARD : FORWARD);
|
num = input.pos - input.string;
|
||||||
|
amount = have(LBACKWARD) ? BACKWARD : FORWARD;
|
||||||
|
caret_insert(history_search(amount, input.string, num), true);
|
||||||
|
input.pos = input.string + num;
|
||||||
|
update_filter(true);
|
||||||
break;
|
break;
|
||||||
case LKILL:
|
case LKILL:
|
||||||
menu_cmd(KILL, amount);
|
caret_delete(BACKWARD, amount);
|
||||||
|
update_filter(true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LACCEPT:
|
||||||
|
srv.running = false;
|
||||||
|
if(!have(LLITERAL) && !match.sel && match.start->retstring)
|
||||||
|
if(input.filter_start == 0 && input.pos == input.end)
|
||||||
|
selectitem(match.start);
|
||||||
|
|
||||||
|
if(!have(LLITERAL) && match.sel && !strcmp(input.string, match.sel->string))
|
||||||
|
lprint(1, "%s", match.sel->retstring);
|
||||||
|
else
|
||||||
|
lprint(1, "%s", input.string);
|
||||||
|
break;
|
||||||
|
case LBACKWARD:
|
||||||
|
caret_move(BACKWARD, amount);
|
||||||
|
update_input();
|
||||||
|
break;
|
||||||
|
case LCOMPLETE:
|
||||||
|
if(have(LNEXT))
|
||||||
|
selectitem(match.sel ? match.sel->next : match.first);
|
||||||
|
else if(have(LPREV))
|
||||||
|
selectitem((match.sel ? match.sel : match.start)->prev);
|
||||||
|
else if(have(LFIRST)) {
|
||||||
|
match.start = match.first;
|
||||||
|
selectitem(match.start);
|
||||||
|
}
|
||||||
|
else if(have(LLAST))
|
||||||
|
selectitem(match.first->prev);
|
||||||
|
else if(have(LNEXTPAGE))
|
||||||
|
selectitem(match.end->next);
|
||||||
|
else if(have(LPREVPAGE)) {
|
||||||
|
match.start = pagestart(match.start->prev);
|
||||||
|
selectitem(match.start);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LFORWARD:
|
||||||
|
caret_move(FORWARD, amount);
|
||||||
|
update_input();
|
||||||
break;
|
break;
|
||||||
case LREJECT:
|
case LREJECT:
|
||||||
menu_cmd(REJECT, 0);
|
srv.running = false;
|
||||||
|
result = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
menu_draw();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,7 +191,7 @@ main(int argc, char *argv[]) {
|
||||||
client_init(nil);
|
client_init(nil);
|
||||||
|
|
||||||
if(tray.edge == 0)
|
if(tray.edge == 0)
|
||||||
tray.edge = West | (!strcmp(readctl("bar on "), "top") ? North : South);
|
tray.edge = West | (!strcmp(readctl("/ctl", "bar on "), "top") ? North : South);
|
||||||
|
|
||||||
client_readconfig(&tray.normcolors, &tray.selcolors, &tray.font);
|
client_readconfig(&tray.normcolors, &tray.selcolors, &tray.font);
|
||||||
|
|
||||||
|
|
|
@ -195,9 +195,7 @@ bar_draw(WMScreen *s) {
|
||||||
align = Center;
|
align = Center;
|
||||||
if(b == s->bar[BRight])
|
if(b == s->bar[BRight])
|
||||||
align = East;
|
align = East;
|
||||||
fill(ibuf, b->r, &b->colors.bg);
|
fillstring(ibuf, def.font, b->r, align, b->text, &b->colors, 1);
|
||||||
drawstring(ibuf, def.font, b->r, align, b->text, &b->colors.fg);
|
|
||||||
border(ibuf, b->r, 1, &b->colors.border);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(s->barwin_rgba != (s->barwin->depth == 32))
|
if(s->barwin_rgba != (s->barwin->depth == 32))
|
||||||
|
|
|
@ -220,7 +220,8 @@ apply_rules(Client *c) {
|
||||||
bool ret, more;
|
bool ret, more;
|
||||||
|
|
||||||
ret = true;
|
ret = true;
|
||||||
for(r=def.rules.rule; r; r=r->next)
|
more = true;
|
||||||
|
for(r=def.rules.rule; r && more; r=r->next)
|
||||||
if(regexec(r->regex, c->props, nil, 0)) {
|
if(regexec(r->regex, c->props, nil, 0)) {
|
||||||
more = false;
|
more = false;
|
||||||
for(rv=r->values; rv; rv=rv->next) {
|
for(rv=r->values; rv; rv=rv->next) {
|
||||||
|
@ -234,15 +235,15 @@ apply_rules(Client *c) {
|
||||||
}else {
|
}else {
|
||||||
bufclear();
|
bufclear();
|
||||||
bufprint("%s %s", rv->key, rv->value);
|
bufprint("%s %s", rv->key, rv->value);
|
||||||
m = ixp_message(buffer, sizeof buffer, MsgPack);
|
m = ixp_message(buffer, _buf_end - buffer, MsgPack);
|
||||||
if(!waserror()) {
|
if(waserror())
|
||||||
|
warning("processing rule %q=%q: %r", rv->key, rv->value);
|
||||||
|
else {
|
||||||
message_client(c, &m);
|
message_client(c, &m);
|
||||||
poperror();
|
poperror();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!more)
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1093,6 +1094,11 @@ client_extratags(Client *c) {
|
||||||
toks[i] = nil;
|
toks[i] = nil;
|
||||||
tags = comm(CLeft, toks, c->retags);
|
tags = comm(CLeft, toks, c->retags);
|
||||||
|
|
||||||
|
if(i == 1 && !c->tagre.regex && !c->tagvre.regex) {
|
||||||
|
free(tags);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
fmtstrinit(&fmt);
|
fmtstrinit(&fmt);
|
||||||
if(i > 1)
|
if(i > 1)
|
||||||
join(tags, "+", &fmt);
|
join(tags, "+", &fmt);
|
||||||
|
@ -1131,17 +1137,16 @@ client_applytags(Client *c, const char *tags) {
|
||||||
/* Check for regex. */
|
/* Check for regex. */
|
||||||
if(cur[0] == '/') {
|
if(cur[0] == '/') {
|
||||||
cur++;
|
cur++;
|
||||||
*strchr(cur, '/') = '\0';
|
*strrchr(cur, '/') = '\0';
|
||||||
if(add == '+')
|
if(add == '+')
|
||||||
reinit(&c->tagre, cur);
|
reinit(&c->tagre, cur);
|
||||||
else if(add == '-')
|
else if(add == '-')
|
||||||
reinit(&c->tagvre, cur);
|
reinit(&c->tagvre, cur);
|
||||||
}
|
}
|
||||||
|
else if(!strcmp(cur, "~"))
|
||||||
trim(cur, " \t\r\n");
|
|
||||||
if(!strcmp(cur, "~"))
|
|
||||||
c->floating = add ? On : Never;
|
c->floating = add ? On : Never;
|
||||||
else {
|
else {
|
||||||
|
trim(cur, " \t\r\n");
|
||||||
if(!strcmp(cur, "sel"))
|
if(!strcmp(cur, "sel"))
|
||||||
cur = selview->name;
|
cur = selview->name;
|
||||||
else if(Mbsearch(cur, badtags, bsstrcmp))
|
else if(Mbsearch(cur, badtags, bsstrcmp))
|
||||||
|
|
|
@ -313,8 +313,7 @@ EXTERN struct Defs {
|
||||||
uint keyssz;
|
uint keyssz;
|
||||||
Ruleset colrules;
|
Ruleset colrules;
|
||||||
Ruleset rules;
|
Ruleset rules;
|
||||||
char grabmod[5];
|
long mod;
|
||||||
ulong mod;
|
|
||||||
uint border;
|
uint border;
|
||||||
uint snap;
|
uint snap;
|
||||||
int colmode;
|
int colmode;
|
||||||
|
|
|
@ -398,6 +398,7 @@ pushlabel(Image *img, Rectangle *rp, char *s, CTuple *col) {
|
||||||
w = min(w, Dx(*rp) - 30); /* Magic number. */
|
w = min(w, Dx(*rp) - 30); /* Magic number. */
|
||||||
if(w > 0) {
|
if(w > 0) {
|
||||||
r = *rp;
|
r = *rp;
|
||||||
|
r.min.x = r.max.x - w;
|
||||||
rp->max.x -= w;
|
rp->max.x -= w;
|
||||||
if(0)
|
if(0)
|
||||||
drawline(img, Pt(rp->max.x, r.min.y+2),
|
drawline(img, Pt(rp->max.x, r.min.y+2),
|
||||||
|
@ -406,6 +407,7 @@ pushlabel(Image *img, Rectangle *rp, char *s, CTuple *col) {
|
||||||
drawstring(img, def.font, r, East,
|
drawstring(img, def.font, r, East,
|
||||||
s, &col->fg);
|
s, &col->fg);
|
||||||
}
|
}
|
||||||
|
free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -415,7 +417,6 @@ frame_draw(Frame *f) {
|
||||||
CTuple *col;
|
CTuple *col;
|
||||||
Image *img;
|
Image *img;
|
||||||
char *s;
|
char *s;
|
||||||
uint w;
|
|
||||||
int n, m;
|
int n, m;
|
||||||
|
|
||||||
if(f == nil || f->view != selview || f->area == nil)
|
if(f == nil || f->view != selview || f->area == nil)
|
||||||
|
@ -443,6 +444,9 @@ frame_draw(Frame *f) {
|
||||||
f->titlebar = insetrect(r, 3);
|
f->titlebar = insetrect(r, 3);
|
||||||
f->titlebar.max.y += 3;
|
f->titlebar.max.y += 3;
|
||||||
|
|
||||||
|
f->grabbox = insetrect(r, 2);
|
||||||
|
f->grabbox.max.x = f->grabbox.min.x + Dy(f->grabbox);
|
||||||
|
|
||||||
/* Odd focus. Unselected, with keyboard focus. */
|
/* Odd focus. Unselected, with keyboard focus. */
|
||||||
/* Draw a border just inside the titlebar. */
|
/* Draw a border just inside the titlebar. */
|
||||||
if(c != selclient() && c == disp.focus) {
|
if(c != selclient() && c == disp.focus) {
|
||||||
|
@ -450,15 +454,9 @@ frame_draw(Frame *f) {
|
||||||
border(img, insetrect(r, 2), 1, &def.focuscolor.border);
|
border(img, insetrect(r, 2), 1, &def.focuscolor.border);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* grabbox */
|
|
||||||
r.min = Pt(2, 2);
|
|
||||||
r.max.y -= 2;
|
|
||||||
r.max.x = r.min.x + Dy(r);
|
|
||||||
f->grabbox = r;
|
|
||||||
|
|
||||||
if(c->urgent)
|
if(c->urgent)
|
||||||
fill(img, r, &col->fg);
|
fill(img, f->grabbox, &col->fg);
|
||||||
border(img, r, 1, &col->border);
|
border(img, f->grabbox, 1, &col->border);
|
||||||
|
|
||||||
/* Odd focus. Selected, without keyboard focus. */
|
/* Odd focus. Selected, without keyboard focus. */
|
||||||
/* Draw a border around the grabbox. */
|
/* Draw a border around the grabbox. */
|
||||||
|
@ -466,38 +464,34 @@ frame_draw(Frame *f) {
|
||||||
border(img, insetrect(r, -1), 1, &def.normcolor.bg);
|
border(img, insetrect(r, -1), 1, &def.normcolor.bg);
|
||||||
|
|
||||||
/* Draw a border on borderless+titleless selected apps. */
|
/* Draw a border on borderless+titleless selected apps. */
|
||||||
if(f->area->floating && c->borderless && c->titleless && !c->fullscreen && c == selclient())
|
if(c->borderless && c->titleless && f->area->floating && !c->fullscreen && c == selclient())
|
||||||
setborder(c->framewin, def.border, &def.focuscolor.border);
|
setborder(c->framewin, def.border, &def.focuscolor.border);
|
||||||
else
|
else
|
||||||
setborder(c->framewin, 0, &def.focuscolor.border);
|
setborder(c->framewin, 0, &def.focuscolor.border);
|
||||||
|
|
||||||
/* Label */
|
/* Label */
|
||||||
r.min.x = r.max.x;
|
r = Rect(f->grabbox.max.x, 0, fr.max.x, labelh(def.font));
|
||||||
r.max.x = fr.max.x;
|
|
||||||
r.min.y = 0;
|
|
||||||
r.max.y = labelh(def.font);
|
|
||||||
/* Draw count on frames in 'max' columns. */
|
/* Draw count on frames in 'max' columns. */
|
||||||
if(f->area->max && !resizing) {
|
if(f->area->max && !resizing) {
|
||||||
/* XXX */
|
|
||||||
n = stack_count(f, &m);
|
n = stack_count(f, &m);
|
||||||
s = smprint("%d/%d", m, n);
|
pushlabel(img, &r, smprint("%d/%d", m, n), col);
|
||||||
pushlabel(img, &r, s, col);
|
|
||||||
free(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Label clients with extra tags. */
|
/* Label clients with extra tags. */
|
||||||
if((s = client_extratags(c))) {
|
if((s = client_extratags(c)))
|
||||||
pushlabel(img, &r, s, col);
|
pushlabel(img, &r, s, col);
|
||||||
free(s);
|
|
||||||
}else if(f->area->floating) /* Make sure floating clients have room for their indicators. */
|
if(f->area->floating) /* Make sure floating clients have room for their indicators. */
|
||||||
r.max.x -= Dx(f->grabbox);
|
r.max.x -= f->grabbox.max.x;
|
||||||
|
|
||||||
if(!ewmh_responsive_p(c))
|
if(!ewmh_responsive_p(c))
|
||||||
r.min.x += drawstring(img, def.font, r, West, "(wedged) ", &col->fg);
|
r.min.x += drawstring(img, def.font, r, West, "(wedged) ", &col->fg);
|
||||||
w = drawstring(img, def.font, r, West, c->name, &col->fg);
|
r.min.x += drawstring(img, def.font, r, West, c->name, &col->fg);
|
||||||
|
|
||||||
/* Draw inner border on floating clients. */
|
/* Draw inner border on floating clients. */
|
||||||
if(f->area->floating) {
|
if(f->area->floating) {
|
||||||
r.min.x = r.min.x + w + 10;
|
r.min.x += 10;
|
||||||
r.max.x += Dx(f->grabbox);
|
r.max.x += Dx(f->grabbox);
|
||||||
r.min.y = f->grabbox.min.y;
|
r.min.y = f->grabbox.min.y;
|
||||||
r.max.y = f->grabbox.max.y;
|
r.max.y = f->grabbox.max.y;
|
||||||
|
|
|
@ -372,8 +372,7 @@ main(int argc, char *argv[]) {
|
||||||
initdisplay();
|
initdisplay();
|
||||||
|
|
||||||
traperrors(true);
|
traperrors(true);
|
||||||
selectinput(&scr.root, EnterWindowMask
|
selectinput(&scr.root, SubstructureRedirectMask);
|
||||||
| SubstructureRedirectMask);
|
|
||||||
if(traperrors(false))
|
if(traperrors(false))
|
||||||
fatal("another window manager is already running");
|
fatal("another window manager is already running");
|
||||||
|
|
||||||
|
@ -388,7 +387,7 @@ main(int argc, char *argv[]) {
|
||||||
|
|
||||||
sock = ixp_announce(address);
|
sock = ixp_announce(address);
|
||||||
if(sock < 0)
|
if(sock < 0)
|
||||||
fatal("Can't create socket '%s': %r", address);
|
fatal("Can't create socket %q: %r", address);
|
||||||
closeexec(ConnectionNumber(display));
|
closeexec(ConnectionNumber(display));
|
||||||
closeexec(sock);
|
closeexec(sock);
|
||||||
|
|
||||||
|
@ -413,7 +412,6 @@ main(int argc, char *argv[]) {
|
||||||
def.incmode = ISqueeze;
|
def.incmode = ISqueeze;
|
||||||
|
|
||||||
def.mod = Mod1Mask;
|
def.mod = Mod1Mask;
|
||||||
strcpy(def.grabmod, "Mod1");
|
|
||||||
|
|
||||||
loadcolor(&def.focuscolor, FOCUSCOLORS, nil);
|
loadcolor(&def.focuscolor, FOCUSCOLORS, nil);
|
||||||
loadcolor(&def.normcolor, NORMCOLORS, nil);
|
loadcolor(&def.normcolor, NORMCOLORS, nil);
|
||||||
|
|
|
@ -656,7 +656,6 @@ message_root(void *p, IxpMsg *m) {
|
||||||
if(!parsekey(s, &i, nil) || i == 0)
|
if(!parsekey(s, &i, nil) || i == 0)
|
||||||
return Ebadvalue;
|
return Ebadvalue;
|
||||||
|
|
||||||
utflcpy(def.grabmod, s, sizeof def.grabmod);
|
|
||||||
def.mod = i;
|
def.mod = i;
|
||||||
break;
|
break;
|
||||||
case LINCMODE:
|
case LINCMODE:
|
||||||
|
@ -700,7 +699,7 @@ readctl_root(void) {
|
||||||
bufprint("font %s\n", def.font->name);
|
bufprint("font %s\n", def.font->name);
|
||||||
bufprint("fontpad %d %d %d %d\n", def.font->pad.min.x, def.font->pad.max.x,
|
bufprint("fontpad %d %d %d %d\n", def.font->pad.min.x, def.font->pad.max.x,
|
||||||
def.font->pad.max.y, def.font->pad.min.y);
|
def.font->pad.max.y, def.font->pad.min.y);
|
||||||
bufprint("grabmod %s\n", def.grabmod);
|
bufprint("grabmod %s\n", (Mask){&def.mod, modkey_names});
|
||||||
bufprint("incmode %s\n", incmodetab[def.incmode]);
|
bufprint("incmode %s\n", incmodetab[def.incmode]);
|
||||||
bufprint("normcolors %s\n", def.normcolor.colstr);
|
bufprint("normcolors %s\n", def.normcolor.colstr);
|
||||||
bufprint("view %s\n", selview->name);
|
bufprint("view %s\n", selview->name);
|
||||||
|
|
|
@ -426,7 +426,7 @@ xnamespace(int argc, char *argv[]) {
|
||||||
path = ixp_namespace();
|
path = ixp_namespace();
|
||||||
if(path == nil)
|
if(path == nil)
|
||||||
fatal("can't find namespace: %r\n");
|
fatal("can't find namespace: %r\n");
|
||||||
Blprint(outbuf, "%s\n", path);
|
Blprint(outbuf, "%s", path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,15 +58,8 @@ static Font* font;
|
||||||
|
|
||||||
static int wborder;
|
static int wborder;
|
||||||
|
|
||||||
char buffer[8092];
|
static char* initial = "";
|
||||||
char* _buffer;
|
static int cur;
|
||||||
|
|
||||||
/* for XSetWMProperties to use */
|
|
||||||
int g_argc;
|
|
||||||
char **g_argv;
|
|
||||||
|
|
||||||
char *initial = "";
|
|
||||||
int cur;
|
|
||||||
|
|
||||||
static char** labels; /* list of labels and commands */
|
static char** labels; /* list of labels and commands */
|
||||||
static char** commands;
|
static char** commands;
|
||||||
|
@ -78,13 +71,7 @@ void create_window(void);
|
||||||
void size_window(int, int);
|
void size_window(int, int);
|
||||||
void redraw(int, int);
|
void redraw(int, int);
|
||||||
void warpmouse(int, int);
|
void warpmouse(int, int);
|
||||||
void memory(void);
|
|
||||||
int args(void);
|
|
||||||
|
|
||||||
Cursor cursor[1];
|
|
||||||
Visual* render_visual;
|
|
||||||
|
|
||||||
void init_screens(void);
|
|
||||||
void
|
void
|
||||||
init_screens(void) {
|
init_screens(void) {
|
||||||
Rectangle *rects;
|
Rectangle *rects;
|
||||||
|
@ -111,9 +98,6 @@ main(int argc, char **argv)
|
||||||
char *cp;
|
char *cp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
g_argc = argc;
|
|
||||||
g_argv = argv;
|
|
||||||
|
|
||||||
ARGBEGIN{
|
ARGBEGIN{
|
||||||
case 'v':
|
case 'v':
|
||||||
lprint(1, "%s\n", version);
|
lprint(1, "%s\n", version);
|
||||||
|
@ -137,29 +121,24 @@ main(int argc, char **argv)
|
||||||
create_window();
|
create_window();
|
||||||
|
|
||||||
numitems = argc;
|
numitems = argc;
|
||||||
|
|
||||||
labels = emalloc(numitems * sizeof *labels);
|
labels = emalloc(numitems * sizeof *labels);
|
||||||
commands = emalloc(numitems * sizeof *labels);
|
commands = emalloc(numitems * sizeof *labels);
|
||||||
|
|
||||||
for(i = 0; i < numitems; i++) {
|
for(i = 0; i < numitems; i++) {
|
||||||
labels[i] = argv[i];
|
labels[i] = argv[i];
|
||||||
|
commands[i] = argv[i];
|
||||||
if((cp = strchr(labels[i], ':')) != nil) {
|
if((cp = strchr(labels[i], ':')) != nil) {
|
||||||
*cp++ = '\0';
|
*cp++ = '\0';
|
||||||
commands[i] = cp;
|
commands[i] = cp;
|
||||||
} else
|
}
|
||||||
commands[i] = labels[i];
|
|
||||||
if(strcmp(labels[i], initial) == 0)
|
if(strcmp(labels[i], initial) == 0)
|
||||||
cur = i;
|
cur = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
client_init(address);
|
client_init(address);
|
||||||
|
|
||||||
wborder = strtol(readctl("border "), nil, 10);
|
wborder = strtol(readctl("/ctl", "border "), nil, 10);
|
||||||
loadcolor(&cnorm, readctl("normcolors "), nil);
|
client_readconfig(&cnorm, &csel, &font);
|
||||||
loadcolor(&csel, readctl("focuscolors "), nil);
|
|
||||||
font = loadfont(readctl("font "));
|
|
||||||
if(!font)
|
|
||||||
fatal("Can't load font");
|
|
||||||
|
|
||||||
run_menu();
|
run_menu();
|
||||||
|
|
||||||
|
@ -167,28 +146,22 @@ main(int argc, char **argv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* usage --- print a usage message and die */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
lprint(2, "usage: %s -v\n", argv0);
|
lprint(2, "usage: %s [-a <address>] [-i <arg>] <menitem>[:<command>] ...\n", argv0);
|
||||||
lprint(2, " %s [-a <address>] [-i <arg>] menitem[:command] ...\n", argv0);
|
lprint(2, " %s -v\n", argv0);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* run_menu --- put up the window, execute selected commands */
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MouseMask =
|
MouseMask = ButtonPressMask
|
||||||
ButtonPressMask
|
| ButtonReleaseMask
|
||||||
| ButtonReleaseMask
|
| ButtonMotionMask
|
||||||
| ButtonMotionMask
|
| PointerMotionMask,
|
||||||
| PointerMotionMask,
|
MenuMask = MouseMask
|
||||||
MenuMask =
|
| StructureNotifyMask
|
||||||
MouseMask
|
| ExposureMask
|
||||||
| StructureNotifyMask
|
|
||||||
| ExposureMask
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -197,8 +170,8 @@ run_menu(void)
|
||||||
XEvent ev;
|
XEvent ev;
|
||||||
int i, old, wide, high;
|
int i, old, wide, high;
|
||||||
|
|
||||||
wide = 0;
|
|
||||||
high = labelh(font);
|
high = labelh(font);
|
||||||
|
wide = 0;
|
||||||
for(i = 0; i < numitems; i++)
|
for(i = 0; i < numitems; i++)
|
||||||
wide = max(wide, textwidth(font, labels[i]));
|
wide = max(wide, textwidth(font, labels[i]));
|
||||||
wide += font->height & ~1;
|
wide += font->height & ~1;
|
||||||
|
@ -231,12 +204,10 @@ run_menu(void)
|
||||||
break;
|
break;
|
||||||
redraw(high, wide);
|
redraw(high, wide);
|
||||||
break;
|
break;
|
||||||
case MapNotify:
|
|
||||||
redraw(high, wide);
|
|
||||||
break;
|
|
||||||
case Expose:
|
case Expose:
|
||||||
redraw(high, wide);
|
redraw(high, wide);
|
||||||
break;
|
break;
|
||||||
|
case MapNotify:
|
||||||
case ConfigureNotify:
|
case ConfigureNotify:
|
||||||
case MappingNotify:
|
case MappingNotify:
|
||||||
break;
|
break;
|
||||||
|
@ -244,13 +215,10 @@ run_menu(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set_wm_hints --- set all the window manager hints */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
create_window(void)
|
create_window(void)
|
||||||
{
|
{
|
||||||
WinAttr wa = { 0 };
|
WinAttr wa = { 0 };
|
||||||
XEvent e;
|
|
||||||
|
|
||||||
wa.override_redirect = true;
|
wa.override_redirect = true;
|
||||||
menuwin = createwindow(&scr.root, Rect(-1, -1, 0, 0),
|
menuwin = createwindow(&scr.root, Rect(-1, -1, 0, 0),
|
||||||
|
@ -258,10 +226,8 @@ create_window(void)
|
||||||
&wa, CWOverrideRedirect);
|
&wa, CWOverrideRedirect);
|
||||||
selectinput(menuwin, MenuMask);
|
selectinput(menuwin, MenuMask);
|
||||||
mapwin(menuwin);
|
mapwin(menuwin);
|
||||||
XMaskEvent(display, StructureNotifyMask, &e);
|
|
||||||
if(!grabpointer(menuwin, nil, 0, MouseMask))
|
if(!grabpointer(menuwin, nil, 0, MouseMask))
|
||||||
fatal("Failed to grab the mouse\n");
|
fatal("Failed to grab the mouse\n");
|
||||||
XSetCommand(display, menuwin->xid, g_argv, g_argc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -284,34 +250,22 @@ size_window(int wide, int high)
|
||||||
p.y = min(p.y, scr.rect.max.y - h);
|
p.y = min(p.y, scr.rect.max.y - h);
|
||||||
|
|
||||||
reshapewin(menuwin, rectaddpt(r, p));
|
reshapewin(menuwin, rectaddpt(r, p));
|
||||||
|
|
||||||
//XSetWindowBackground(display, menuwin->xid, cnorm.bg);
|
|
||||||
setborder(menuwin, 1, &cnorm.border);
|
setborder(menuwin, 1, &cnorm.border);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* redraw --- actually redraw the menu */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
redraw(int high, int wide)
|
redraw(int high, int wide)
|
||||||
{
|
{
|
||||||
Rectangle r;
|
Rectangle r;
|
||||||
CTuple *c;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
r = Rect(0, 0, wide, high);
|
r = Rect(0, 0, wide, high);
|
||||||
for(i = 0; i < numitems; i++) {
|
for(i = 0; i < numitems; i++) {
|
||||||
if(cur == i)
|
|
||||||
c = &csel;
|
|
||||||
else
|
|
||||||
c = &cnorm;
|
|
||||||
r = rectsetorigin(r, Pt(0, i * high));
|
r = rectsetorigin(r, Pt(0, i * high));
|
||||||
fill(menuwin, r, &c->bg);
|
fillstring(menuwin, font, r, Center, labels[i], (cur == i ? &csel : &cnorm), 0);
|
||||||
drawstring(menuwin, font, r, Center, labels[i], &c->fg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* warpmouse --- bring the mouse to the menu */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
warpmouse(int wide, int high)
|
warpmouse(int wide, int high)
|
||||||
{
|
{
|
||||||
|
|
45
img/mkfile
45
img/mkfile
|
@ -2,37 +2,22 @@ MKSHELL=rc
|
||||||
path=$PLAN9/bin $path
|
path=$PLAN9/bin $path
|
||||||
|
|
||||||
eps = wmii.eps
|
eps = wmii.eps
|
||||||
calc = rc -c 'hoc -e $"*'
|
calc = rc -c 'echo 4k $* p | dc}
|
||||||
|
|
||||||
epsbox = `{sed -n '/^%%BoundingBox:/{s/.*://p; q;}' $eps}
|
iconwidth = 16
|
||||||
iconwidth = 154
|
imagewidth = 154
|
||||||
iconscale = `{*=$epsbox; $calc $iconwidth / '('$3 - $1')'}
|
|
||||||
iconheight = `{*=$epsbox; $calc '('$4 - $2') *' $iconscale}
|
|
||||||
|
|
||||||
%.png: %.eps
|
|
||||||
* = `{hoc -e'-('$epsbox')'}
|
|
||||||
x = $1
|
|
||||||
y = $2
|
|
||||||
gs -q -dBATCH -dNOPAUSE -s'DEVICE=pngalpha' -s'OutputFile='$target -g$iconwidth'x'$iconheight - <<!
|
|
||||||
$iconscale $iconscale scale
|
|
||||||
$x $y translate
|
|
||||||
($eps) run
|
|
||||||
showpage
|
|
||||||
quit
|
|
||||||
!
|
|
||||||
optipng -fix $target
|
|
||||||
|
|
||||||
%.pdf: %.eps
|
%.pdf: %.eps
|
||||||
sh epstopdf $stem.eps
|
sh epstopdf $stem.eps
|
||||||
|
|
||||||
%-small.png: %.eps
|
%-small.png: %.eps
|
||||||
iconwidth = 16
|
epsbox = `{sed -n '/^%%BoundingBox:/{s/.*://p; q;}' $stem.eps}
|
||||||
iconscale = `{*=$epsbox; hoc -e $iconwidth/'('$3-' '$1')'}
|
iconscale = `{*=$epsbox; $calc $iconwidth $3 $1 -/}
|
||||||
iconheight = `{*=$epsbox; hoc -e '('$4-' '$2')*'$iconscale}
|
iconheight = `{*=$epsbox; $calc $4 $2 - $iconscale '*'}
|
||||||
* = `{hoc -e'-('$epsbox')'}
|
* = `{hoc -e'-('$epsbox')'}
|
||||||
x = $1
|
x = $1
|
||||||
y = $2
|
y = $2
|
||||||
gs -q -dBATCH -dNOPAUSE -s'DEVICE=pngalpha' -s'OutputFile='$target -g$iconwidth'x'$iconheight - <<!
|
gs -q -dBATCH -dNOPAUSE -s'DEVICE=pngalpha' -s'OutputFile='$target -g$iconwidth^x^$iconheight - <<!
|
||||||
$iconscale $iconscale scale
|
$iconscale $iconscale scale
|
||||||
$x $y translate
|
$x $y translate
|
||||||
($eps) run
|
($eps) run
|
||||||
|
@ -41,3 +26,19 @@ iconheight = `{*=$epsbox; $calc '('$4 - $2') *' $iconscale}
|
||||||
!
|
!
|
||||||
optipng -fix $target
|
optipng -fix $target
|
||||||
|
|
||||||
|
%.png: %.eps
|
||||||
|
epsbox = `{sed -n '/^%%BoundingBox:/{s/.*://p; q;}' $stem.eps}
|
||||||
|
imagescale = `{*=$epsbox; $calc $imagewidth $3 $1 -/}
|
||||||
|
imageheight = `{*=$epsbox; $calc $4 $2 - $imagescale '*'}
|
||||||
|
* = `{hoc -e'-('$epsbox')'}
|
||||||
|
x = $1
|
||||||
|
y = $2
|
||||||
|
gs -q -dBATCH -dNOPAUSE -s'DEVICE=pngalpha' -s'OutputFile='$target -g$imagewidth^x^$imageheight - <<!
|
||||||
|
$imagescale $imagescale scale
|
||||||
|
$x $y translate
|
||||||
|
($eps) run
|
||||||
|
showpage
|
||||||
|
quit
|
||||||
|
!
|
||||||
|
optipng -fix $target
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
# define CLIENTEXTERN extern
|
# define CLIENTEXTERN extern
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char* readctl(char*);
|
char* readctl(char*, char*);
|
||||||
void client_init(char*);
|
void client_init(char*);
|
||||||
|
|
||||||
CLIENTEXTERN IxpClient* client;
|
CLIENTEXTERN IxpClient* client;
|
||||||
|
|
|
@ -30,8 +30,8 @@ typedef enum Align Align;
|
||||||
#define Dx(r) ((r).max.x - (r).min.x)
|
#define Dx(r) ((r).max.x - (r).min.x)
|
||||||
#define Dy(r) ((r).max.y - (r).min.y)
|
#define Dy(r) ((r).max.y - (r).min.y)
|
||||||
#define Pt(x, y) ((Point){(x), (y)})
|
#define Pt(x, y) ((Point){(x), (y)})
|
||||||
#define Rpt(p, q) ((Rectangle){p, q})
|
#define Rpt(p, q) ((Rectangle){(p), (q)})
|
||||||
#define Rect(x0, y0, x1, y1) ((Rectangle){Pt(x0, y0), Pt(x1, y1)})
|
#define Rect(x0, y0, x1, y1) Rpt(Pt(x0, y0), Pt(x1, y1))
|
||||||
|
|
||||||
Point addpt(Point, Point);
|
Point addpt(Point, Point);
|
||||||
Point divpt(Point, Point);
|
Point divpt(Point, Point);
|
||||||
|
|
|
@ -42,13 +42,10 @@ enum {
|
||||||
|
|
||||||
int Blprint(Biobuf*, const char*, ...);
|
int Blprint(Biobuf*, const char*, ...);
|
||||||
int Bvlprint(Biobuf*, const char*, va_list);
|
int Bvlprint(Biobuf*, const char*, va_list);
|
||||||
extern char* _buffer;
|
|
||||||
void _die(char*, int, char*, ...);
|
void _die(char*, int, char*, ...);
|
||||||
void backtrace(char*);
|
void backtrace(char*);
|
||||||
extern char buffer[8092];
|
|
||||||
void closeexec(int);
|
void closeexec(int);
|
||||||
char** comm(int, char**, char**);
|
char** comm(int, char**, char**);
|
||||||
extern char* const _buf_end;
|
|
||||||
int doublefork(void);
|
int doublefork(void);
|
||||||
void* emalloc(uint);
|
void* emalloc(uint);
|
||||||
void* emallocz(uint);
|
void* emallocz(uint);
|
||||||
|
@ -90,6 +87,10 @@ int unquote(char*, char*[], int);
|
||||||
int utflcpy(char*, const char*, int);
|
int utflcpy(char*, const char*, int);
|
||||||
int vlprint(int, const char*, va_list);
|
int vlprint(int, const char*, va_list);
|
||||||
char* vsxprint(const char*, va_list);
|
char* vsxprint(const char*, va_list);
|
||||||
|
|
||||||
|
extern char* _buffer;
|
||||||
|
extern char buffer[8092];
|
||||||
|
extern char* const _buf_end;
|
||||||
#define bufclear() \
|
#define bufclear() \
|
||||||
BLOCK( _buffer = buffer; _buffer[0] = '\0' )
|
BLOCK( _buffer = buffer; _buffer[0] = '\0' )
|
||||||
#define bufprint(...) \
|
#define bufprint(...) \
|
||||||
|
|
|
@ -261,6 +261,7 @@ void drawpoly(Image*, Point*, int, int cap, int w, Color*);
|
||||||
uint drawstring(Image*, Font*, Rectangle, Align, const char*, Color*);
|
uint drawstring(Image*, Font*, Rectangle, Align, const char*, Color*);
|
||||||
void fill(Image*, Rectangle, Color*);
|
void fill(Image*, Rectangle, Color*);
|
||||||
void fillpoly(Image*, Point*, int, Color*);
|
void fillpoly(Image*, Point*, int, Color*);
|
||||||
|
uint fillstring(Image*, Font*, Rectangle, Align, const char*, CTuple*, int border);
|
||||||
Window* findwin(XWindow);
|
Window* findwin(XWindow);
|
||||||
void freefont(Font*);
|
void freefont(Font*);
|
||||||
void freeimage(Image *);
|
void freeimage(Image *);
|
||||||
|
|
|
@ -11,13 +11,13 @@ void
|
||||||
client_readconfig(CTuple *norm, CTuple *focus, Font **font) {
|
client_readconfig(CTuple *norm, CTuple *focus, Font **font) {
|
||||||
|
|
||||||
if(norm)
|
if(norm)
|
||||||
loadcolor(norm, readctl("normcolors "), nil);
|
loadcolor(norm, readctl("/ctl", "normcolors "), nil);
|
||||||
if(focus)
|
if(focus)
|
||||||
loadcolor(focus, readctl("focuscolors "), nil);
|
loadcolor(focus, readctl("/ctl", "focuscolors "), nil);
|
||||||
*font = loadfont(readctl("font "));
|
*font = loadfont(readctl("/ctl", "font "));
|
||||||
if(!*font)
|
if(!*font)
|
||||||
fatal("Can't load font %q", readctl("font "));
|
fatal("Can't load font %q", readctl("/ctl", "font "));
|
||||||
sscanf(readctl("fontpad "), "%d %d %d %d",
|
sscanf(readctl("/ctl", "fontpad "), "%d %d %d %d",
|
||||||
&(*font)->pad.min.x, &(*font)->pad.max.x,
|
&(*font)->pad.min.x, &(*font)->pad.max.x,
|
||||||
&(*font)->pad.min.x, &(*font)->pad.max.y);
|
&(*font)->pad.min.x, &(*font)->pad.max.y);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,20 +10,21 @@
|
||||||
#include <stuff/clientutil.h>
|
#include <stuff/clientutil.h>
|
||||||
#include <stuff/util.h>
|
#include <stuff/util.h>
|
||||||
|
|
||||||
static IxpCFid* ctlfid;
|
|
||||||
static char ctl[1024];
|
|
||||||
static char* ectl;
|
|
||||||
|
|
||||||
char*
|
char*
|
||||||
readctl(char *key) {
|
readctl(char *ctlname, char *key) {
|
||||||
|
static char ctlfile[128];
|
||||||
|
static char ctl[1024];
|
||||||
|
static char* ectl;
|
||||||
|
IxpCFid *fid;
|
||||||
char *s, *p;
|
char *s, *p;
|
||||||
int nkey, n;
|
int nkey, n;
|
||||||
|
|
||||||
if(ctlfid == nil) {
|
if(strcmp(ctlname, ctlfile)) {
|
||||||
ctlfid = ixp_open(client, "ctl", OREAD);
|
strncpy(ctlfile, ctlname, sizeof ctlfile);
|
||||||
n = ixp_read(ctlfid, ctl, 1023);
|
fid = ixp_open(client, ctlfile, OREAD);
|
||||||
|
n = ixp_read(fid, ctl, sizeof ctl - 1);
|
||||||
ectl = ctl + n;
|
ectl = ctl + n;
|
||||||
ixp_close(ctlfid);
|
ixp_close(fid);
|
||||||
}
|
}
|
||||||
|
|
||||||
nkey = strlen(key);
|
nkey = strlen(key);
|
||||||
|
@ -36,7 +37,7 @@ readctl(char *key) {
|
||||||
n = (s ? s : ectl) - p;
|
n = (s ? s : ectl) - p;
|
||||||
s = freelater(emalloc(n + 1));
|
s = freelater(emalloc(n + 1));
|
||||||
s[n] = '\0';
|
s[n] = '\0';
|
||||||
return strncpy(s, p, n);
|
return memcpy(s, p, n);
|
||||||
}
|
}
|
||||||
} while((p = strchr(p, '\n')));
|
} while((p = strchr(p, '\n')));
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -4,6 +4,17 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "../x11.h"
|
#include "../x11.h"
|
||||||
|
|
||||||
|
uint
|
||||||
|
fillstring(Image *dst, Font *font,
|
||||||
|
Rectangle r, Align align,
|
||||||
|
const char *text, CTuple *col, int borderw) {
|
||||||
|
|
||||||
|
fill(dst, r, &col->bg);
|
||||||
|
if(borderw)
|
||||||
|
border(dst, r, borderw, &col->border);
|
||||||
|
return drawstring(dst, font, r, align, text, &col->fg);
|
||||||
|
}
|
||||||
|
|
||||||
uint
|
uint
|
||||||
drawstring(Image *dst, Font *font,
|
drawstring(Image *dst, Font *font,
|
||||||
Rectangle r, Align align,
|
Rectangle r, Align align,
|
||||||
|
|
|
@ -41,8 +41,8 @@ tags:
|
||||||
for f in $(OBJ); do \
|
for f in $(OBJ); do \
|
||||||
[ -f "$$f.c" ] && files="$$files $$f.c"; \
|
[ -f "$$f.c" ] && files="$$files $$f.c"; \
|
||||||
done; \
|
done; \
|
||||||
echo CTAGS $$files $(TAGFILES) || \
|
echo CTAGS $$files $(TAGFILES); \
|
||||||
ctags $$files $(TAGFILES)
|
$(DEBUG) $(CTAGS) $$files $(TAGFILES)
|
||||||
|
|
||||||
.PHONY: all options clean dist install uninstall depend cleandep tags
|
.PHONY: all options clean dist install uninstall depend cleandep tags
|
||||||
.PHONY: simpleuninstall simpleinstall
|
.PHONY: simpleuninstall simpleinstall
|
||||||
|
|
|
@ -49,7 +49,7 @@ undup() { # GCC is crap.
|
||||||
nl=0
|
nl=0
|
||||||
maxl=6
|
maxl=6
|
||||||
}
|
}
|
||||||
/: (error|note): .?Each undeclared identifier|: error: for each function it appears|is dangerous, better use|is almost always misused|: In function |: At top level:|support .long long.|use of C99 long long|ISO C forbids conversion|warning:.*warn_unused_result/ {
|
tolower($0) ~ /: (error|note): .?each undeclared identifier|: error: for each function it appears|is dangerous, better use|is almost always misused|: in function |: at top level:|support .long long.|use of c99 long long|iso c forbids conversion|warning:.*warn_unused_result/ {
|
||||||
next
|
next
|
||||||
}
|
}
|
||||||
$1 == "warning:" {
|
$1 == "warning:" {
|
||||||
|
|
Loading…
Reference in New Issue