Factor out common code into library.

This commit is contained in:
Kris Maglione 2010-05-21 22:52:47 -04:00
parent 3550e7afef
commit ab2d1760f8
215 changed files with 3656 additions and 3559 deletions

View File

@ -1,7 +1,7 @@
syntax: regexp
(^|/)\.((.*\.)?sw.|depend|hgignore)$
(^|/)(tags|mkfile)$
\.([oa]|out|o_pic|so|pyc|pyo)$
(^|/)(tags|mkfile|diff)$
\.([oa]|out|o_pic|so|pyc|pyo|diff)$
\.(diff|orig|rej|bak)$
\.(aux|idx|ilg|ind|log|toc)$
^cmd/(stfo|osd|wiwarp|setfocus)(/|$)

View File

@ -11,6 +11,7 @@ PDIRS = \
alternative_wmiircs
DIRS = \
libstuff \
libbio \
libfmt \
libregexp \

View File

@ -12,8 +12,6 @@ TARG = wihack \
wmii9menu \
wmiir
OFILES = util.o
LIBS += $(LIBS9)
CFLAGS += $(INCX11)
@ -24,10 +22,7 @@ OWMIIR=wmiir.o $(OFILES) $(LIBIXP)
wmiir.out: $(OWMIIR)
$(LINK) $@ $(STATIC) $(OWMIIR)
wmii/x11.o wmii/xext.o wmii/geom.o wmii/map.o: dall
true
O9MENU=wmii9menu.o clientutil.o wmii/x11.o wmii/xext.o wmii/geom.o wmii/map.o $(OFILES) $(LIBIXP)
O9MENU=wmii9menu.o $(ROOT)/lib/libstuff.a $(LIBIXP)
wmii9menu.out: $(O9MENU)
$(LINK) $@ $(O9MENU) $$(pkg-config --libs $(X11PACKAGES) xrandr xinerama) -lXext

View File

@ -11,12 +11,8 @@ PACKAGES += $(X11PACKAGES) xext xrandr xrender xinerama
LIB = $(LIBIXP)
LIBS += -lm -lXtst $(LIBS9)
CFLAGS += -DVERSION=\"$(VERSION)\" -DIXP_NEEDAPI=86
OBJ = main \
_util \
../wmii/map \
../wmii/x11 \
../util
CFLAGS += -DIXP_NEEDAPI=86
OBJ = main
include ${ROOT}/mk/one.mk

View File

@ -3,9 +3,9 @@
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <util.h>
#include <stuff/x.h>
#include <stuff/util.h>
#include <ixp.h>
#include <x11.h>
#define BLOCK(x) do { x; }while(0)
@ -15,13 +15,3 @@
EXTERN Window win;
EXTERN char buffer[8092];
EXTERN char* _buffer;
static char* const _buf_end = buffer + sizeof buffer;
#define bufclear() \
BLOCK( _buffer = buffer; _buffer[0] = '\0' )
#define bufprint(...) \
_buffer = seprint(_buffer, _buf_end, __VA_ARGS__)

View File

@ -1,4 +1 @@
bool getlong(const char*, long*);
bool getulong(const char*, ulong*);

View File

@ -46,10 +46,10 @@ main(int argc, char *argv[]) {
initdisplay();
s = ARGF();
if(s && !getulong(s, &win.w))
if(s && !getulong(s, &win.xid))
usage();
if (!s)
win.w = getfocus();
win.xid = getfocus();
if(argc)
usage();

View File

@ -14,23 +14,14 @@ HFILES= dat.h fns.h
PACKAGES += $(X11PACKAGES) xext xrandr xrender xinerama
LIB = $(LIBIXP)
LIBS += -lm $(LIBS9)
LIBS += -lm $(LIBS9) $(LIBIXP)
CFLAGS += -DIXP_NEEDAPI=86
OBJ = main \
caret \
history \
event \
menu \
keys \
bindings \
../wmii/geom \
../wmii/map \
../wmii/printevent \
../wmii/x11 \
../wmii/xext \
../clientutil \
../util
bindings
include $(ROOT)/mk/one.mk

View File

@ -7,9 +7,9 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <util.h>
#include <stuff/x.h>
#include <stuff/util.h>
#include <ixp.h>
#include <x11.h>
#define BLOCK(x) do { x; }while(0)
@ -104,13 +104,3 @@ EXTERN int (*compare)(const char*, const char*, size_t);
EXTERN char* prompt;
EXTERN int promptw;
EXTERN char buffer[8092];
EXTERN char* _buffer;
static char* const _buf_end = buffer + sizeof buffer;
#define bufclear() \
BLOCK( _buffer = buffer; _buffer[0] = '\0' )
#define bufprint(...) \
_buffer = seprint(_buffer, _buf_end, __VA_ARGS__)

View File

@ -1,334 +0,0 @@
/* Copyright ©2006-2010 Kris Maglione <fbsdaemon@gmail.com>
* See LICENSE file for license details.
*/
#include "dat.h"
#include "fns.h"
typedef void (*EvHandler)(XEvent*);
static EvHandler handler[LASTEvent];
void
dispatch_event(XEvent *e) {
if(e->type < nelem(handler)) {
if(handler[e->type])
handler[e->type](e);
}else
xext_event(e);
}
#define handle(w, fn, ev) \
BLOCK(if((w)->handler->fn) (w)->handler->fn((w), ev))
static int
findtime(Display *d, XEvent *e, XPointer v) {
Window *w;
w = (Window*)v;
if(e->type == PropertyNotify && e->xproperty.window == w->xid) {
xtime = e->xproperty.time;
return true;
}
return false;
}
void
xtime_kludge(void) {
/* Round trip. */
static Window *w;
WinAttr wa;
XEvent e;
long l;
if(w == nil) {
w = createwindow(&scr.root, Rect(0, 0, 1, 1), 0, InputOnly, &wa, 0);
selectinput(w, PropertyChangeMask);
}
changeprop_long(w, "ATOM", "ATOM", &l, 0);
sync();
XIfEvent(display, &e, findtime, (void*)w);
}
uint
flushevents(long event_mask, bool dispatch) {
XEvent ev;
uint n = 0;
while(XCheckMaskEvent(display, event_mask, &ev)) {
if(dispatch)
dispatch_event(&ev);
n++;
}
return n;
}
static int
findenter(Display *d, XEvent *e, XPointer v) {
long *l;
USED(d);
l = (long*)v;
if(*l)
return false;
if(e->type == EnterNotify)
return true;
if(e->type == MotionNotify)
(*l)++;
return false;
}
/* This isn't perfect. If there were motion events in the queue
* before this was called, then it flushes nothing. If we don't
* check for them, we might lose a legitamate enter event.
*/
uint
flushenterevents(void) {
XEvent e;
long l;
int n;
l = 0;
n = 0;
while(XCheckIfEvent(display, &e, findenter, (void*)&l))
n++;
return n;
}
static void
buttonrelease(XButtonPressedEvent *ev) {
Window *w;
if((w = findwin(ev->window)))
handle(w, bup, ev);
}
static void
buttonpress(XButtonPressedEvent *ev) {
Window *w;
if((w = findwin(ev->window)))
handle(w, bdown, ev);
else
XAllowEvents(display, ReplayPointer, ev->time);
}
static void
configurerequest(XConfigureRequestEvent *ev) {
XWindowChanges wc;
Window *w;
if((w = findwin(ev->window)))
handle(w, configreq, ev);
else{
wc.x = ev->x;
wc.y = ev->y;
wc.width = ev->width;
wc.height = ev->height;
wc.border_width = ev->border_width;
wc.sibling = ev->above;
wc.stack_mode = ev->detail;
XConfigureWindow(display, ev->window, ev->value_mask, &wc);
}
}
static void
configurenotify(XConfigureEvent *ev) {
Window *w;
USED(ev);
if((w = findwin(ev->window)))
handle(w, config, ev);
}
static void
clientmessage(XClientMessageEvent *ev) {
USED(ev);
}
static void
destroynotify(XDestroyWindowEvent *ev) {
Window *w;
if((w = findwin(ev->window)))
handle(w, destroy, ev);
}
static void
enternotify(XCrossingEvent *ev) {
Window *w;
static int sel_screen;
xtime = ev->time;
if(ev->mode != NotifyNormal)
return;
if((w = findwin(ev->window)))
handle(w, enter, ev);
else if(ev->window == scr.root.xid)
sel_screen = true;
}
static void
leavenotify(XCrossingEvent *ev) {
xtime = ev->time;
#if 0
if((ev->window == scr.root.xid) && !ev->same_screen)
sel_screen = true;
#endif
}
static void
focusin(XFocusChangeEvent *ev) {
Window *w;
/* Yes, we're focusing in on nothing, here. */
if(ev->detail == NotifyDetailNone) {
/* FIXME: Do something. */
return;
}
if(!((ev->detail == NotifyNonlinear)
||(ev->detail == NotifyNonlinearVirtual)
||(ev->detail == NotifyVirtual)
||(ev->detail == NotifyInferior)
||(ev->detail == NotifyAncestor)))
return;
if((ev->mode == NotifyWhileGrabbed)) /* && (screen->hasgrab != &c_root)) */
return;
if((w = findwin(ev->window)))
handle(w, focusin, ev);
#if 0
else if(ev->mode == NotifyGrab) {
if(ev->window == scr.root.xid)
screen->hasgrab = &c_root;
/* Some unmanaged window has grabbed focus */
else if((c = screen->focus)) {
print_focus("focusin", &c_magic, "<magic>");
screen->focus = &c_magic;
if(c->sel)
frame_draw(c->sel);
}
}
#endif
}
static void
focusout(XFocusChangeEvent *ev) {
Window *w;
if(!((ev->detail == NotifyNonlinear)
||(ev->detail == NotifyNonlinearVirtual)
||(ev->detail == NotifyVirtual)
||(ev->detail == NotifyInferior)
||(ev->detail == NotifyAncestor)))
return;
#if 0
if(ev->mode == NotifyUngrab)
screen->hasgrab = nil;
#endif
if((w = findwin(ev->window)))
handle(w, focusout, ev);
}
static void
expose(XExposeEvent *ev) {
Window *w;
if(ev->count == 0) {
if((w = findwin(ev->window)))
handle(w, expose, ev);
}
}
static void
keypress(XKeyEvent *ev) {
Window *w;
xtime = ev->time;
if((w = findwin(ev->window)))
handle(w, kdown, ev);
}
static void
mappingnotify(XMappingEvent *ev) {
/* Why do you need me to tell you this? */
XRefreshKeyboardMapping(ev);
}
static void
maprequest(XMapRequestEvent *ev) {
USED(ev);
}
static void
motionnotify(XMotionEvent *ev) {
Window *w;
xtime = ev->time;
if((w = findwin(ev->window)))
handle(w, motion, ev);
}
static void
propertynotify(XPropertyEvent *ev) {
Window *w;
xtime = ev->time;
if((w = findwin(ev->window)))
handle(w, property, ev);
}
static void
mapnotify(XMapEvent *ev) {
Window *w;
if((w = findwin(ev->window)))
handle(w, map, ev);
}
static void
unmapnotify(XUnmapEvent *ev) {
Window *w;
if((w = findwin(ev->window)) && (ev->event == w->parent->xid)) {
w->mapped = false;
if(ev->send_event || w->unmapped-- == 0)
handle(w, unmap, ev);
}
}
static EvHandler handler[LASTEvent] = {
[ButtonPress] = (EvHandler)buttonpress,
[ButtonRelease] = (EvHandler)buttonrelease,
[ConfigureRequest] = (EvHandler)configurerequest,
[ConfigureNotify] = (EvHandler)configurenotify,
[ClientMessage] = (EvHandler)clientmessage,
[DestroyNotify] = (EvHandler)destroynotify,
[EnterNotify] = (EvHandler)enternotify,
[Expose] = (EvHandler)expose,
[FocusIn] = (EvHandler)focusin,
[FocusOut] = (EvHandler)focusout,
[KeyPress] = (EvHandler)keypress,
[LeaveNotify] = (EvHandler)leavenotify,
[MapNotify] = (EvHandler)mapnotify,
[MapRequest] = (EvHandler)maprequest,
[MappingNotify] = (EvHandler)mappingnotify,
[MotionNotify] = (EvHandler)motionnotify,
[PropertyNotify] = (EvHandler)propertynotify,
[UnmapNotify] = (EvHandler)unmapnotify,
};
void
check_x_event(IxpConn *c) {
XEvent ev;
USED(c);
while(XCheckMaskEvent(display, ~0, &ev))
dispatch_event(&ev);
}

View File

@ -19,7 +19,6 @@ char* history_search(int, char*, int);
/* main.c */
void debug(int, const char*, ...);
Item* filter_list(Item*, char*);
void init_screens(int);
void update_filter(bool);
void update_input(void);

View File

@ -10,7 +10,7 @@
#include <strings.h>
#include <unistd.h>
#include <bio.h>
#include <clientutil.h>
#include <stuff/clientutil.h>
#include "fns.h"
#define link _link
@ -19,6 +19,7 @@ static Biobuf* cmplbuf;
static Biobuf* inbuf;
static bool alwaysprint;
static char* cmdsep;
static int screen_hint;
static void
usage(void) {
@ -169,10 +170,6 @@ update_filter(bool print) {
update_input();
}
ErrorCode ignored_xerrors[] = {
{ 0, }
};
static void
end(IxpConn *c) {
@ -184,13 +181,13 @@ static void
preselect(IxpServer *s) {
USED(s);
check_x_event(nil);
event_check();
}
enum { PointerScreen = -1 };
void
init_screens(int screen_hint) {
init_screens(void) {
Rectangle *rects;
Point p;
int i, n;
@ -223,12 +220,11 @@ main(int argc, char *argv[]) {
static bool nokeys;
int i;
long ndump;
int screen;
quotefmtinstall();
fmtinstall('r', errfmt);
address = getenv("WMII_ADDRESS");
screen = PointerScreen;
screen_hint = PointerScreen;
find = strstr;
compare = strncmp;
@ -261,7 +257,7 @@ main(int argc, char *argv[]) {
prompt = EARGF(usage());
break;
case 's':
screen = strtol(EARGF(usage()), nil, 10);
screen_hint = strtol(EARGF(usage()), nil, 10);
break;
case 'S':
cmdsep = EARGF(usage());
@ -287,7 +283,7 @@ main(int argc, char *argv[]) {
client_init(address);
srv.preselect = preselect;
ixp_listen(&srv, ConnectionNumber(display), nil, check_x_event, end);
ixp_listen(&srv, ConnectionNumber(display), nil, (void (*)(IxpConn*))preselect, end);
ontop = !strcmp(readctl("bar on "), "top");
loadcolor(&cnorm, readctl("normcolors "));
@ -331,7 +327,7 @@ main(int argc, char *argv[]) {
if(barwin == nil)
menu_init();
init_screens(screen);
init_screens();
i = ixp_serverloop(&srv);
if(i)

View File

@ -13,15 +13,8 @@ LIB = $(LIBIXP)
LIBS += -lm $(LIBS9)
CFLAGS += -DIXP_NEEDAPI=86
OBJ = main \
event \
ewmh \
win \
_util \
../wmii/map \
../wmii/printevent \
printevent_kludge \
../wmii/x11 \
../util
win
include ${ROOT}/mk/one.mk

View File

@ -3,31 +3,16 @@
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <util.h>
#include <stuff/x.h>
#include <stuff/util.h>
#include <ixp.h>
#include <x11.h>
#define BLOCK(x) do { x; }while(0)
#ifndef EXTERN
# define EXTERN extern
#endif
extern Handlers handlers;
EXTERN bool running;
EXTERN Handlers handlers;
EXTERN Window win;
EXTERN Window frame;
EXTERN long xtime;
EXTERN char buffer[8092];
EXTERN char* _buffer;
static char* const _buf_end = buffer + sizeof buffer;
#define bufclear() \
BLOCK( _buffer = buffer; _buffer[0] = '\0' )
#define bufprint(...) \
_buffer = seprint(_buffer, _buf_end, __VA_ARGS__)

View File

@ -1,309 +0,0 @@
/* Copyright ©2006-2010 Kris Maglione <fbsdaemon@gmail.com>
* See LICENSE file for license details.
*/
#include "dat.h"
#include "fns.h"
static void (*handler[LASTEvent])(XEvent*);
void
dispatch_event(XEvent *e) {
/* print("%E\n", e); */
if(e->type < nelem(handler) && handler[e->type])
handler[e->type](e);
}
#define handle(w, fn, ev) \
BLOCK(if((w)->handler->fn) (w)->handler->fn((w), ev))
#ifdef notdef
uint
flushevents(long event_mask, bool dispatch) {
XEvent ev;
uint n = 0;
while(XCheckMaskEvent(display, event_mask, &ev)) {
if(dispatch)
dispatch_event(&ev);
n++;
}
return n;
}
static int
findenter(Display *d, XEvent *e, XPointer v) {
long *l;
USED(d);
l = (long*)v;
if(*l)
return false;
if(e->type == EnterNotify)
return true;
if(e->type == MotionNotify)
(*l)++;
return false;
}
/* This isn't perfect. If there were motion events in the queue
* before this was called, then it flushes nothing. If we don't
* check for them, we might lose a legitamate enter event.
*/
uint
flushenterevents(void) {
XEvent e;
long l;
int n;
l = 0;
n = 0;
while(XCheckIfEvent(display, &e, findenter, (void*)&l))
n++;
return n;
}
#endif
static int
findtime(Display *d, XEvent *e, XPointer v) {
Window *w;
w = (Window*)v;
if(e->type == PropertyNotify && e->xproperty.window == w->xid) {
xtime = e->xproperty.time;
return true;
}
return false;
}
void
xtime_kludge(void) {
Window *w;
WinAttr wa;
XEvent e;
long l;
w = createwindow(&scr.root, Rect(0, 0, 1, 1), 0, InputOnly, &wa, 0);
XSelectInput(display, w->xid, PropertyChangeMask);
changeprop_long(w, "ATOM", "ATOM", &l, 0);
XIfEvent(display, &e, findtime, (void*)w);
destroywindow(w);
}
static void
buttonrelease(XEvent *e) {
XButtonPressedEvent *ev;
Window *w;
ev = &e->xbutton;
if((w = findwin(ev->window)))
handle(w, bup, ev);
}
static void
buttonpress(XEvent *e) {
XButtonPressedEvent *ev;
Window *w;
ev = &e->xbutton;
if((w = findwin(ev->window)))
handle(w, bdown, ev);
else
XAllowEvents(display, ReplayPointer, ev->time);
}
static void
clientmessage(XEvent *e) {
XClientMessageEvent *ev;
ev = &e->xclient;
USED(ev);
}
static void
configurenotify(XEvent *e) {
XConfigureEvent *ev;
Window *w;
ev = &e->xconfigure;
if((w = findwin(ev->window)))
handle(w, config, ev);
}
static void
destroynotify(XEvent *e) {
XDestroyWindowEvent *ev;
Window *w;
ev = &e->xdestroywindow;
if((w = findwin(ev->window)))
handle(w, destroy, ev);
}
static void
enternotify(XEvent *e) {
XCrossingEvent *ev;
Window *w;
ev = &e->xcrossing;
xtime = ev->time;
if(ev->mode != NotifyNormal)
return;
if((w = findwin(ev->window)))
handle(w, enter, ev);
}
static void
leavenotify(XEvent *e) {
XCrossingEvent *ev;
ev = &e->xcrossing;
xtime = ev->time;
}
static void
focusin(XEvent *e) {
XFocusChangeEvent *ev;
Window *w;
ev = &e->xfocus;
/* Yes, we're focusing in on nothing, here. */
if(ev->detail == NotifyDetailNone) {
/* FIXME: Do something. */
return;
}
if(!((ev->detail == NotifyNonlinear)
||(ev->detail == NotifyNonlinearVirtual)
||(ev->detail == NotifyVirtual)
||(ev->detail == NotifyInferior)
||(ev->detail == NotifyAncestor)))
return;
if((ev->mode == NotifyWhileGrabbed))
return;
if((w = findwin(ev->window)))
handle(w, focusin, ev);
}
static void
focusout(XEvent *e) {
XFocusChangeEvent *ev;
Window *w;
ev = &e->xfocus;
if(!((ev->detail == NotifyNonlinear)
||(ev->detail == NotifyNonlinearVirtual)
||(ev->detail == NotifyVirtual)
||(ev->detail == NotifyInferior)
||(ev->detail == NotifyAncestor)))
return;
if((w = findwin(ev->window)))
handle(w, focusout, ev);
}
static void
expose(XEvent *e) {
XExposeEvent *ev;
Window *w;
ev = &e->xexpose;
if(ev->count == 0) {
if((w = findwin(ev->window)))
handle(w, expose, ev);
}
}
static void
keypress(XEvent *e) {
XKeyEvent *ev;
ev = &e->xkey;
xtime = ev->time;
}
static void
mappingnotify(XEvent *e) {
XMappingEvent *ev;
ev = &e->xmapping;
/* Why do you need me to tell you this? */
XRefreshKeyboardMapping(ev);
}
static void
motionnotify(XEvent *e) {
XMotionEvent *ev;
Window *w;
ev = &e->xmotion;
xtime = ev->time;
if((w = findwin(ev->window)))
handle(w, motion, ev);
}
static void
propertynotify(XEvent *e) {
XPropertyEvent *ev;
Window *w;
ev = &e->xproperty;
xtime = ev->time;
if((w = findwin(ev->window)))
handle(w, property, ev);
}
static void
mapnotify(XEvent *e) {
XMapEvent *ev;
Window *w;
ev = &e->xmap;
if((w = findwin(ev->window)))
handle(w, map, ev);
}
static void
unmapnotify(XEvent *e) {
XUnmapEvent *ev;
Window *w;
ev = &e->xunmap;
if((w = findwin(ev->window)) && w->parent && (ev->event == w->parent->xid)) {
if(ev->send_event || w->unmapped-- == 0)
handle(w, unmap, ev);
}
}
static void (*handler[LASTEvent])(XEvent*) = {
[ButtonPress] = buttonpress,
[ButtonRelease] = buttonrelease,
[ClientMessage] = clientmessage,
[ConfigureNotify] = configurenotify,
[DestroyNotify] = destroynotify,
[EnterNotify] = enternotify,
[Expose] = expose,
[FocusIn] = focusin,
[FocusOut] = focusout,
[KeyPress] = keypress,
[LeaveNotify] = leavenotify,
[MapNotify] = mapnotify,
[MappingNotify] = mappingnotify,
[MotionNotify] = motionnotify,
[PropertyNotify] = propertynotify,
[UnmapNotify] = unmapnotify,
};
void
xevent_loop(void) {
XEvent ev;
while(running) {
XNextEvent(display, &ev);
dispatch_event(&ev);
}
}

View File

@ -8,9 +8,6 @@ void xtime_kludge(void);
void restrut(void);
bool getlong(const char*, long*);
bool getulong(const char*, ulong*);
void ewmh_getstrut(Window*, Rectangle[4]);
void ewmh_setstrut(Window*, Rectangle[4]);

View File

@ -30,8 +30,6 @@ debug(int flag, const char *fmt, ...) {
va_end(ap);
}
ErrorCode ignored_xerrors[] = { {0,} };
static Window
findframe(Window *w) {
XWindow *children;
@ -39,6 +37,7 @@ findframe(Window *w) {
Window ret = {0, };
uint n;
xw = w->xid;
for(par=w->xid; par != scr.root.xid; ) {
xw = par;
XQueryTree(display, xw, &root, &par, &children, &n);
@ -93,8 +92,8 @@ extern int fmtevent(Fmt*);
sethandler(&frame, &handlers);
selectinput(&frame, StructureNotifyMask);
running = true;
xevent_loop();
event_looprunning = true;
event_loop();
XCloseDisplay(display);
return 0;

View File

@ -1,12 +0,0 @@
#include "dat.h"
void dprint(const char *fmt, ...);
void
dprint(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vfprint(2, fmt, ap);
va_end(ap);
}

View File

@ -92,7 +92,7 @@ config(Window *w, XConfigureEvent *ev) {
static void
destroy(Window *w, XDestroyWindowEvent *ev) {
USED(w, ev);
running = false;
event_looprunning = false;
}
Handlers handlers = {

View File

@ -1,272 +0,0 @@
/* Written by Kris Maglione <fbsdaemon at gmail dot com> */
/* Public domain */
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <util.h>
#include <fmt.h>
typedef struct VFmt VFmt;
struct VFmt {
const char *fmt;
va_list args;
};
#ifdef VARARGCK
# pragma varargck type "V" VFmt*
#endif
static int
Vfmt(Fmt *f) {
VFmt *vf;
int i;
vf = va_arg(f->args, VFmt*);
i = fmtvprint(f, vf->fmt, vf->args);
return i;
}
void
fatal(const char *fmt, ...) {
VFmt fp;
fmtinstall('V', Vfmt);
fmtinstall('\001', Vfmt);
fp.fmt = fmt;
va_start(fp.args, fmt);
fprint(2, "%s: fatal: %V\n", argv0, &fp);
va_end(fp.args);
exit(1);
}
void*
freelater(void *p) {
static char* obj[16];
static long nobj;
int id;
id = nobj++ % nelem(obj);
free(obj[id]);
obj[id] = p;
return p;
}
char*
vsxprint(const char *fmt, va_list ap) {
char *s;
s = vsmprint(fmt, ap);
freelater(s);
return s;
}
char*
sxprint(const char *fmt, ...) {
va_list ap;
char *ret;
va_start(ap, fmt);
ret = vsxprint(fmt, ap);
va_end(ap);
return ret;
}
void
_die(char *file, int line, char *msg, ...) {
va_list ap;
va_start(ap, msg);
fprint(2, "%s: dieing at %s:%d: %s\n",
argv0, file, line,
vsxprint(msg, ap));
va_end(ap);
kill(getpid(), SIGABRT);
abort(); /* Adds too many frames:
* _die()
* abort()
* raise(SIGABRT)
* kill(getpid(), SIGABRT)
*/
}
/* Can't malloc */
static void
mfatal(char *name, uint size) {
const char
couldnot[] = ": fatal: Could not ",
paren[] = "() ",
bytes[] = " bytes\n";
char buf[1024];
char sizestr[8];
int i;
i = sizeof sizestr;
do {
sizestr[--i] = '0' + (size%10);
size /= 10;
} while(size > 0);
strlcat(buf, argv0, sizeof buf);
strlcat(buf, couldnot, sizeof buf);
strlcat(buf, name, sizeof buf);
strlcat(buf, paren, sizeof buf);
strlcat(buf, sizestr+i, sizeof buf);
strlcat(buf, bytes, sizeof buf);
write(2, buf, strlen(buf));
exit(1);
}
void *
emalloc(uint size) {
void *ret = malloc(size);
if(!ret)
mfatal("malloc", size);
return ret;
}
void *
emallocz(uint size) {
void *ret = emalloc(size);
memset(ret, 0, size);
return ret;
}
void *
erealloc(void *ptr, uint size) {
void *ret = realloc(ptr, size);
if(!ret)
mfatal("realloc", size);
return ret;
}
char*
estrdup(const char *str) {
void *ret = strdup(str);
if(!ret)
mfatal("strdup", strlen(str));
return ret;
}
char*
estrndup(const char *str, uint len) {
char *ret;
len = min(len, strlen(str));
ret = emalloc(len + 1);
memcpy(ret, str, len);
ret[len] = '\0';
return ret;
}
uint
tokenize(char *res[], uint reslen, char *str, char delim) {
char *s;
uint i;
i = 0;
s = str;
while(i < reslen && *s) {
while(*s == delim)
*(s++) = '\0';
if(*s)
res[i++] = s;
while(*s && *s != delim)
s++;
}
return i;
}
uint
stokenize(char *res[], uint reslen, char *str, char *delim) {
char *s;
uint i;
i = 0;
s = str;
while(i < reslen && *s) {
while(strchr(delim, *s))
*(s++) = '\0';
if(*s)
res[i++] = s;
while(*s && !strchr(delim, *s))
s++;
}
return i;
}
int
max(int a, int b) {
if(a > b)
return a;
return b;
}
int
min(int a, int b) {
if(a < b)
return a;
return b;
}
int
utflcpy(char *to, const char *from, int l) {
char *p;
p = utfecpy(to, to+l, from);
return p-to;
}
uint
strlcat(char *dst, const char *src, uint size) {
const char *s;
char *d;
int n, len;
d = dst;
s = src;
n = size;
while(n-- > 0 && *d != '\0')
d++;
len = n;
while(*s != '\0') {
if(n-- > 0)
*d++ = *s;
s++;
}
if(len > 0)
*d = '\0';
return size - n - 1;
}
/* TODO: Make this UTF-8 compliant. */
char*
strcasestr(const char *dst, const char *src) {
int dc, sc;
int len;
len = strlen(src) - 1;
for(; (sc = *src) && *dst; src++) {
sc = tolower(dc);
for(; (dc = *dst); dst++) {
dc = tolower(dc);
if(sc == dc && !strncasecmp(dst+1, src+1, len))
return (char*)(uintptr_t)dst;
}
}
return nil;
}

View File

@ -24,25 +24,18 @@ OBJ = area \
float \
frame \
fs \
geom \
key \
layout \
main \
map \
message \
mouse \
print \
root \
rule \
printevent\
screen \
utf \
_util \
view \
xdnd \
x11 \
xext \
../util
xdnd
include $(ROOT)/mk/one.mk

View File

@ -1,378 +0,0 @@
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "dat.h"
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <sys/signal.h>
#include <sys/wait.h>
#include <unistd.h>
#include <bio.h>
#include "fns.h"
/* Blech. */
#define VECTOR(type, nam, c) \
void \
vector_##c##init(Vector_##nam *v) { \
memset(v, 0, sizeof *v); \
} \
\
void \
vector_##c##free(Vector_##nam *v) { \
free(v->ary); \
memset(v, 0, sizeof *v); \
} \
\
void \
vector_##c##push(Vector_##nam *v, type val) { \
if(v->n == v->size) { \
if(v->size == 0) \
v->size = 2; \
v->size <<= 2; \
v->ary = erealloc(v->ary, v->size * sizeof *v->ary); \
} \
v->ary[v->n++] = val; \
} \
VECTOR(long, long, l)
VECTOR(Rectangle, rect, r)
VECTOR(void*, ptr, p)
int
doublefork(void) {
pid_t pid;
int status;
switch(pid=fork()) {
case -1:
fatal("Can't fork(): %r");
case 0:
switch(pid=fork()) {
case -1:
fatal("Can't fork(): %r");
case 0:
return 0;
default:
exit(0);
}
default:
waitpid(pid, &status, 0);
return pid;
}
/* NOTREACHED */
}
void
closeexec(int fd) {
if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
fatal("can't set %d close on exec: %r", fd);
}
int
spawn3(int fd[3], const char *file, char *argv[]) {
/* Some ideas from Russ Cox's libthread port. */
int p[2];
int pid;
if(pipe(p) < 0)
return -1;
closeexec(p[1]);
switch(pid = doublefork()) {
case 0:
dup2(fd[0], 0);
dup2(fd[1], 1);
dup2(fd[2], 2);
execvp(file, argv);
write(p[1], &errno, sizeof errno);
exit(1);
break;
default:
close(p[1]);
if(read(p[0], &errno, sizeof errno) == sizeof errno)
pid = -1;
close(p[0]);
break;
case -1: /* can't happen */
break;
}
close(fd[0]);
/* These could fail if any of these was also a previous fd. */
close(fd[1]);
close(fd[2]);
return pid;
}
int
spawn3l(int fd[3], const char *file, ...) {
va_list ap;
char **argv;
int i, n;
va_start(ap, file);
for(n=0; va_arg(ap, char*); n++)
;
va_end(ap);
argv = emalloc((n+1) * sizeof *argv);
va_start(ap, file);
quotefmtinstall();
for(i=0; i <= n; i++)
argv[i] = va_arg(ap, char*);
va_end(ap);
i = spawn3(fd, file, argv);
free(argv);
return i;
}
#ifdef __linux__
# define PROGTXT "exe"
#else
# define PROGTXT "file"
#endif
static void
_backtrace(int pid, char *btarg) {
char *proc, *spid, *gdbcmd;
int fd[3], p[2];
int status, cmdfd;
gdbcmd = estrdup("/tmp/gdbcmd.XXXXXX");
if(pipe(p) < 0)
goto done;
closeexec(p[0]);
cmdfd = mkstemp(gdbcmd);
if(cmdfd < 0)
goto done;
fprint(cmdfd, "bt %s\n", btarg);
fprint(cmdfd, "detach\n");
close(cmdfd);
fd[0] = open("/dev/null", O_RDONLY);
fd[1] = p[1];
fd[2] = dup(2);
proc = sxprint("/proc/%d/" PROGTXT, pid);
spid = sxprint("%d", pid);
if(spawn3l(fd, "gdb", "gdb", "-batch", "-x", gdbcmd, proc, spid, nil) < 0) {
unlink(gdbcmd);
goto done;
}
Biobuf bp;
char *s;
Binit(&bp, p[0], OREAD);
while((s = Brdstr(&bp, '\n', 1))) {
Dprint(DStack, "%s\n", s);
free(s);
}
unlink(gdbcmd);
done:
free(gdbcmd);
kill(pid, SIGKILL);
waitpid(pid, &status, 0);
}
void
backtrace(char *btarg) {
int pid;
/* Fork so we can backtrace the child. Keep this stack
* frame minimal, so the trace is fairly clean.
*/
Debug(DStack)
switch(pid = fork()) {
case -1:
return;
case 0:
kill(getpid(), SIGSTOP);
_exit(0);
default:
_backtrace(pid, btarg);
break;
}
}
void
reinit(Regex *r, char *regx) {
refree(r);
if(regx[0] != '\0') {
r->regex = estrdup(regx);
r->regc = regcomp(regx);
}
}
void
refree(Regex *r) {
free(r->regex);
free(r->regc);
r->regex = nil;
r->regc = nil;
}
void
uniq(char **toks) {
char **p, **q;
q = toks;
if(*q == nil)
return;
for(p=q+1; *p; p++)
if(strcmp(*q, *p))
*++q = *p;
*++q = nil;
}
char**
comm(int cols, char **toka, char **tokb) {
Vector_ptr vec;
char **ret;
int cmp;
vector_pinit(&vec);
while(*toka || *tokb) {
if(!*toka)
cmp = 1;
else if(!*tokb)
cmp = -1;
else
cmp = strcmp(*toka, *tokb);
if(cmp < 0) {
if(cols & CLeft)
vector_ppush(&vec, *toka);
toka++;
}else if(cmp > 0) {
if(cols & CRight)
vector_ppush(&vec, *tokb);
tokb++;
}else {
if(cols & CCenter)
vector_ppush(&vec, *toka);
toka++;
tokb++;
}
}
vector_ppush(&vec, nil);
ret = strlistdup((char**)vec.ary);
free(vec.ary);
return ret;
}
void
grep(char **list, Reprog *re, int flags) {
char **p, **q;
int res;
q = list;
for(p=q; *p; p++) {
res = 0;
if(re)
res = regexec(re, *p, nil, 0);
if(res && !(flags & GInvert)
|| !res && (flags & GInvert))
*q++ = *p;
}
*q = nil;
}
char*
join(char **list, char *sep) {
Fmt f;
char **p;
if(fmtstrinit(&f) < 0)
abort();
for(p=list; *p; p++) {
if(p != list)
fmtstrcpy(&f, sep);
fmtstrcpy(&f, *p);
}
return fmtstrflush(&f);
}
int
strlcatprint(char *buf, int len, const char *fmt, ...) {
va_list ap;
int buflen;
int ret;
va_start(ap, fmt);
buflen = strlen(buf);
ret = vsnprint(buf+buflen, len-buflen, fmt, ap);
va_end(ap);
return ret;
}
char*
pathsearch(const char *path, const char *file, bool slashok) {
char *orig, *p, *s;
if(!slashok && strchr(file, '/') > file)
file = sxprint("%s/%s", getcwd(buffer, sizeof buffer), file);
else if(!strncmp(file, "./", 2))
file = sxprint("%s/%s", getcwd(buffer, sizeof buffer), file+2);
if(file[0] == '/') {
if(access(file, X_OK))
return strdup(file);
return nil;
}
orig = estrdup(path ? path : getenv("PATH"));
for(p=orig; (s=strtok(p, ":")); p=nil) {
s = smprint("%s/%s", s, file);
if(!access(s, X_OK))
break;
free(s);
}
free(orig);
return s;
}
int
unquote(char *buf, char *toks[], int ntoks) {
char *s, *t;
bool inquote;
int n;
n = 0;
s = buf;
while(*s && n < ntoks) {
while(*s && utfrune(" \t\r\n", *s))
s++;
inquote = false;
toks[n] = s;
t = s;
while(*s && (inquote || !utfrune(" \t\r\n", *s))) {
if(*s == '\'') {
if(inquote && s[1] == '\'')
*t++ = *s++;
else
inquote = !inquote;
}
else
*t++ = *s;
s++;
}
if(*s)
s++;
*t = '\0';
if(s != toks[n])
n++;
}
return n;
}

View File

@ -314,7 +314,7 @@ client_destroy(Client *c) {
if(starting > -1)
event("DestroyClient %C\n", c);
flushevents(FocusChangeMask, true);
event_flush(FocusChangeMask, true);
free(c->w.hints);
free(c);
}
@ -503,7 +503,7 @@ client_focus(Client *c) {
c->group->client = c;
sync();
flushevents(FocusChangeMask, true);
event_flush(FocusChangeMask, true);
Dprint(DFocus, "client_focus([%C]%s)\n", c, clientname(c));
Dprint(DFocus, "\t[%C]%s\n\t=> [%C]%s\n",
@ -514,14 +514,14 @@ client_focus(Client *c) {
if(!c->noinput)
setfocus(&c->w, RevertToParent);
else if(c->proto & ProtoTakeFocus) {
xtime_kludge();
event_updatextime();
client_message(c, "WM_TAKE_FOCUS", 0);
}
}else
setfocus(screen->barwin, RevertToParent);
sync();
flushevents(FocusChangeMask, true);
event_flush(FocusChangeMask, true);
}
}

View File

@ -11,11 +11,11 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <ixp.h>
#include <util.h>
#include <utf.h>
#include <fmt.h>
#include <x11.h>
#include <stuff/x.h>
#include <stuff/util.h>
#include <debug.h>
#include <ixp.h>
#define FONT "-*-fixed-medium-r-*-*-13-*-*-*-*-*-*-*"
#define FOCUSCOLORS "#ffffff #335577 #447799"
@ -25,22 +25,12 @@ enum {
PingTime = 10000,
};
enum {
CLeft = 1<<0,
CCenter = 1<<1,
CRight = 1<<2,
};
enum IncMode {
IIgnore,
IShow,
ISqueeze,
};
enum {
GInvert = 1<<0,
};
enum {
UrgManager,
UrgClient,
@ -79,15 +69,6 @@ enum Barpos {
BTop,
};
enum {
CurNormal,
CurNECorner, CurNWCorner, CurSECorner, CurSWCorner,
CurDHArrow, CurDVArrow, CurMove, CurInput, CurSizing,
CurTCross, CurIcon,
CurNone,
CurLast,
};
enum {
NCOL = 16,
};
@ -98,16 +79,16 @@ enum Protocols {
ProtoPing = 1<<2,
};
enum DebugOpt {
D9p = 1<<0,
DDnd = 1<<1,
DEvent = 1<<2,
DEwmh = 1<<3,
DFocus = 1<<4,
DGeneric= 1<<5,
DStack = 1<<6,
NDebugOpt = 7,
enum {
CurNormal,
CurNECorner, CurNWCorner, CurSECorner, CurSWCorner,
CurDHArrow, CurDVArrow, CurMove, CurInput, CurSizing,
CurTCross, CurIcon,
CurNone,
CurLast,
};
Cursor cursor[CurLast];
/* Data Structures */
typedef struct Area Area;
@ -117,9 +98,6 @@ typedef struct Divide Divide;
typedef struct Frame Frame;
typedef struct Group Group;
typedef struct Key Key;
typedef struct Map Map;
typedef struct MapEnt MapEnt;
typedef struct Regex Regex;
typedef struct Rule Rule;
typedef struct Ruleset Ruleset;
typedef struct Strut Strut;
@ -156,11 +134,6 @@ struct Bar {
WMScreen* screen;
};
struct Regex {
char* regex;
Reprog* regc;
};
struct Client {
Client* next;
Frame* frame;
@ -243,11 +216,6 @@ struct Key {
KeyCode key;
};
struct Map {
MapEnt**bucket;
uint nhash;
};
struct Rule {
Rule* next;
Reprog* regex;
@ -286,23 +254,6 @@ struct View {
Rectangle *pad;
};
/* Yuck. */
#define VECTOR(type, nam, c) \
typedef struct Vector_##nam Vector_##nam; \
struct Vector_##nam { \
type* ary; \
long n; \
long size; \
}; \
void vector_##c##free(Vector_##nam*); \
void vector_##c##init(Vector_##nam*); \
void vector_##c##push(Vector_##nam*, type); \
VECTOR(long, long, l)
VECTOR(Rectangle, rect, r)
VECTOR(void*, ptr, p)
#undef VECTOR
#ifndef EXTERN
# define EXTERN extern
#endif
@ -328,8 +279,6 @@ enum {
BLeft, BRight
};
#define BLOCK(x) do { x; }while(0)
EXTERN struct WMScreen {
Bar* bar[2];
Window* barwin;
@ -360,15 +309,6 @@ EXTERN Client c_root;
EXTERN Handlers framehandler;
EXTERN char buffer[8092];
EXTERN char* _buffer;
static char* const _buf_end = buffer + sizeof buffer;
#define bufclear() \
BLOCK( _buffer = buffer; _buffer[0] = '\0' )
#define bufprint(...) \
_buffer = seprint(_buffer, _buf_end, __VA_ARGS__)
/* IXP */
EXTERN IxpServer srv;
EXTERN Ixp9Srv p9srv;
@ -379,26 +319,15 @@ EXTERN uint numlock_mask;
EXTERN Image* ibuf;
EXTERN Image* ibuf32;
EXTERN Cursor cursor[CurLast];
typedef void (*XHandler)(XEvent*);
EXTERN XHandler handler[LASTEvent];
/* Misc */
EXTERN int starting;
EXTERN bool resizing;
EXTERN long ignoreenter;
EXTERN char* user;
EXTERN char* execstr;
EXTERN int debugflag;
EXTERN int debugfile;
EXTERN long xtime;
EXTERN Visual* render_visual;
EXTERN Client* kludge;
extern char* debugtab[];
#define Debug(x) if(((debugflag|debugfile)&(x)) && setdebug(x))
#define Dprint(x, ...) BLOCK( if((debugflag|debugfile)&(x)) debug(x, __VA_ARGS__) )

View File

@ -5,105 +5,16 @@
#include <X11/keysym.h>
#include "fns.h"
typedef void (*EvHandler)(XEvent*);
void
dispatch_event(XEvent *e) {
debug_event(XEvent *e) {
Dprint(DEvent, "%E\n", e);
if(e->type < nelem(handler)) {
if(handler[e->type])
handler[e->type](e);
}else
xext_event(e);
}
#define handle(w, fn, ev) \
BLOCK(if((w)->handler->fn) (w)->handler->fn((w), ev))
static int
findtime(Display *d, XEvent *e, XPointer v) {
Window *w;
w = (Window*)v;
if(e->type == PropertyNotify && e->xproperty.window == w->xid) {
xtime = e->xproperty.time;
return true;
}
return false;
}
void
xtime_kludge(void) {
/* Round trip. */
static Window *w;
WinAttr wa;
XEvent e;
long l;
if(w == nil) {
w = createwindow(&scr.root, Rect(0, 0, 1, 1), 0, InputOnly, &wa, 0);
selectinput(w, PropertyChangeMask);
}
changeprop_long(w, "ATOM", "ATOM", &l, 0);
sync();
XIfEvent(display, &e, findtime, (void*)w);
}
uint
flushevents(long event_mask, bool dispatch) {
XEvent ev;
uint n = 0;
while(XCheckMaskEvent(display, event_mask, &ev)) {
if(dispatch)
dispatch_event(&ev);
n++;
}
return n;
}
static Bool
findenter(Display *d, XEvent *e, XPointer v) {
long *l;
USED(d);
l = (long*)v;
if(*l)
return false;
if(e->type == EnterNotify)
return true;
if(e->type == MotionNotify)
(*l)++;
return false;
}
/* This isn't perfect. If there were motion events in the queue
* before this was called, then it flushes nothing. If we don't
* check for them, we might lose a legitamate enter event.
*/
uint
flushenterevents(void) {
XEvent e;
long l;
int n;
l = 0;
n = 0;
while(XCheckIfEvent(display, &e, findenter, (void*)&l))
n++;
return n;
}
static void
buttonrelease(XButtonPressedEvent *ev) {
Window *w;
if((w = findwin(ev->window)))
handle(w, bup, ev);
}
static void
buttonpress(XButtonPressedEvent *ev) {
event_buttonpress(XButtonPressedEvent *ev) {
Window *w;
if((w = findwin(ev->window)))
@ -112,27 +23,8 @@ buttonpress(XButtonPressedEvent *ev) {
XAllowEvents(display, ReplayPointer, ev->time);
}
static void
configurerequest(XConfigureRequestEvent *ev) {
XWindowChanges wc;
Window *w;
if((w = findwin(ev->window)))
handle(w, configreq, ev);
else{
wc.x = ev->x;
wc.y = ev->y;
wc.width = ev->width;
wc.height = ev->height;
wc.border_width = ev->border_width;
wc.sibling = ev->above;
wc.stack_mode = ev->detail;
XConfigureWindow(display, ev->window, ev->value_mask, &wc);
}
}
static void
configurenotify(XConfigureEvent *ev) {
void
event_configurenotify(XConfigureEvent *ev) {
Window *w;
ignoreenter = ev->serial;
@ -140,8 +32,8 @@ configurenotify(XConfigureEvent *ev) {
handle(w, config, ev);
}
static void
clientmessage(XClientMessageEvent *ev) {
void
event_clientmessage(XClientMessageEvent *ev) {
if(ewmh_clientmessage(ev))
return;
@ -149,40 +41,16 @@ clientmessage(XClientMessageEvent *ev) {
return;
}
static void
destroynotify(XDestroyWindowEvent *ev) {
void
event_destroynotify(XDestroyWindowEvent *ev) {
Window *w;
Client *c;
if((w = findwin(ev->window)))
handle(w, destroy, ev);
else {
if((c = win2client(ev->window)))
fprint(2, "Badness: Unhandled DestroyNotify: "
"Client: %p, Window: %W, Name: %s\n",
c, &c->w, c->name);
}
}
static void
enternotify(XCrossingEvent *ev) {
Window *w;
xtime = ev->time;
if(ev->mode != NotifyNormal)
return;
if((w = findwin(ev->window)))
handle(w, enter, ev);
}
static void
leavenotify(XCrossingEvent *ev) {
Window *w;
xtime = ev->time;
if((w = findwin(ev->window)))
handle(w, leave, ev);
else if((c = win2client(ev->window)))
fprint(2, "Badness: Unhandled DestroyNotify: Client: %p, Window: %W, Name: %s\n",
c, &c->w, c->name);
}
void
@ -192,8 +60,8 @@ print_focus(const char *fn, Client *c, const char *to) {
Dprint(DFocus, "\t%s => %s\n", clientname(disp.focus), to);
}
static void
focusin(XFocusChangeEvent *ev) {
void
event_focusin(XFocusChangeEvent *ev) {
Window *w;
Client *c;
@ -231,8 +99,8 @@ focusin(XFocusChangeEvent *ev) {
}
}
static void
focusout(XFocusChangeEvent *ev) {
void
event_focusout(XFocusChangeEvent *ev) {
XEvent me;
Window *w;
@ -247,74 +115,22 @@ focusout(XFocusChangeEvent *ev) {
if((ev->mode == NotifyGrab)
&& XCheckMaskEvent(display, KeyPressMask, &me))
dispatch_event(&me);
event_dispatch(&me);
else if((w = findwin(ev->window)))
handle(w, focusout, ev);
}
static void
expose(XExposeEvent *ev) {
Window *w;
void
event_mapnotify(XMapEvent *ev) {
Window *w;
if(ev->count == 0)
if((w = findwin(ev->window)))
handle(w, expose, ev);
ignoreenter = ev->serial;
if((w = findwin(ev->window)))
handle(w, map, ev);
}
static void
keypress(XKeyEvent *ev) {
Window *w;
xtime = ev->time;
if((w = findwin(ev->window)))
handle(w, kdown, ev);
}
static void
mappingnotify(XMappingEvent *ev) {
XRefreshKeyboardMapping(ev);
if(ev->request == MappingKeyboard)
update_keys();
}
static void
maprequest(XMapRequestEvent *ev) {
Window *w;
if((w = findwin(ev->parent)))
handle(w, mapreq, ev);
}
static void
motionnotify(XMotionEvent *ev) {
Window *w;
xtime = ev->time;
if((w = findwin(ev->window)))
handle(w, motion, ev);
}
static void
propertynotify(XPropertyEvent *ev) {
Window *w;
xtime = ev->time;
if((w = findwin(ev->window)))
handle(w, property, ev);
}
static void
mapnotify(XMapEvent *ev) {
Window *w;
ignoreenter = ev->serial;
if((w = findwin(ev->window)))
handle(w, map, ev);
}
static void
unmapnotify(XUnmapEvent *ev) {
void
event_unmapnotify(XUnmapEvent *ev) {
Window *w;
ignoreenter = ev->serial;
@ -325,35 +141,3 @@ unmapnotify(XUnmapEvent *ev) {
}
}
EvHandler handler[LASTEvent] = {
[ButtonPress] = (EvHandler)buttonpress,
[ButtonRelease] = (EvHandler)buttonrelease,
[ConfigureRequest] = (EvHandler)configurerequest,
[ConfigureNotify] = (EvHandler)configurenotify,
[ClientMessage] = (EvHandler)clientmessage,
[DestroyNotify] = (EvHandler)destroynotify,
[EnterNotify] = (EvHandler)enternotify,
[Expose] = (EvHandler)expose,
[FocusIn] = (EvHandler)focusin,
[FocusOut] = (EvHandler)focusout,
[KeyPress] = (EvHandler)keypress,
[LeaveNotify] = (EvHandler)leavenotify,
[MapNotify] = (EvHandler)mapnotify,
[MapRequest] = (EvHandler)maprequest,
[MappingNotify] = (EvHandler)mappingnotify,
[MotionNotify] = (EvHandler)motionnotify,
[PropertyNotify] = (EvHandler)propertynotify,
[UnmapNotify] = (EvHandler)unmapnotify,
};
void
check_x_event(IxpConn *c) {
XEvent ev;
USED(c);
while(XPending(display)) {
XNextEvent(display, &ev);
dispatch_event(&ev);
}
}

View File

@ -129,12 +129,8 @@ void poperror(void);
jmp_buf* pusherror(void);
/* event.c */
void check_x_event(IxpConn*);
void dispatch_event(XEvent*);
uint flushenterevents(void);
uint flushevents(long, bool dispatch);
void debug_event(XEvent*);
void print_focus(const char*, Client*, const char*);
void xtime_kludge(void);
/* ewmh.c */
int ewmh_clientmessage(XClientMessageEvent*);
@ -197,15 +193,6 @@ void fs_walk(Ixp9Req*);
void fs_write(Ixp9Req*);
void event(const char*, ...);
/* geom.c */
Align get_sticky(Rectangle src, Rectangle dst);
Cursor quad_cursor(Align);
Align quadrant(Rectangle, Point);
bool rect_contains_p(Rectangle, Rectangle);
bool rect_haspoint_p(Point, Rectangle);
bool rect_intersect_p(Rectangle, Rectangle);
Rectangle rect_intersection(Rectangle, Rectangle);
/* key.c */
void init_lock_keys(void);
void kpress(XWindow, ulong mod, KeyCode);
@ -215,15 +202,7 @@ void update_keys(void);
void init_screens(void);
void spawn_command(const char*);
/* map.c */
void** hash_get(Map*, const char*, bool create);
void* hash_rm(Map*, const char*);
void** map_get(Map*, ulong, bool create);
void* map_rm(Map*, ulong);
/* message.c */
bool getlong(const char*, long*);
bool getulong(const char*, ulong*);
char* message_client(Client*, IxpMsg*);
char* message_root(void*, IxpMsg*);
char* message_view(View*, IxpMsg*);
@ -237,6 +216,7 @@ char* readctl_root(void);
char* readctl_view(View*);
Area* strarea(View*, ulong, const char*);
void warning(const char*, ...);
/* debug */
void debug(int, const char*, ...);
void dprint(const char*, ...);
@ -259,9 +239,6 @@ Align snap_rect(const Rectangle *rects, int num, Rectangle *current, Align *mask
/* print.c */
int Ffmt(Fmt*);
/* printevent.c */
void printevent(XEvent*);
/* root.c */
void root_init(void);
@ -295,22 +272,6 @@ void view_update_all(void);
void view_update_rect(View*);
Rectangle* view_rects(View*, uint *num, Frame *ignore);
/* _util.c */
void backtrace(char*);
void closeexec(int);
char** comm(int, char**, char**);
int doublefork(void);
void grep(char**, Reprog*, int);
char* join(char**, char*);
char* pathsearch(const char*, const char*, bool);
void refree(Regex*);
void reinit(Regex*, char*);
int strlcatprint(char*, int, const char*, ...);
int spawn3(int[3], const char*, char*[]);
int spawn3l(int[3], const char*, ...);
void uniq(char**);
int unquote(char*, char*[], int);
/* utf.c */
char* toutf8(const char*);
char* toutf8n(const char*, size_t);
@ -319,10 +280,3 @@ char* toutf8n(const char*, size_t);
int xdnd_clientmessage(XClientMessageEvent*);
void xdnd_initwindow(Window*);
/* xext.c */
void randr_event(XEvent*);
bool render_argb_p(Visual*);
void xext_event(XEvent*);
void xext_init(void);
Rectangle* xinerama_screens(int*);

View File

@ -1,94 +0,0 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "dat.h"
#include "fns.h"
bool
rect_haspoint_p(Point pt, Rectangle r) {
return (pt.x >= r.min.x) && (pt.x < r.max.x)
&& (pt.y >= r.min.y) && (pt.y < r.max.y);
}
bool
rect_intersect_p(Rectangle r, Rectangle r2) {
return r.min.x <= r2.max.x
&& r.max.x >= r2.min.x
&& r.min.y <= r2.max.y
&& r.max.y >= r2.min.y;
}
Rectangle
rect_intersection(Rectangle r, Rectangle r2) {
Rectangle ret;
/* ret != canonrect(ret) ≡ no intersection. */
ret.min.x = max(r.min.x, r2.min.x);
ret.max.x = min(r.max.x, r2.max.x);
ret.min.y = max(r.min.y, r2.min.y);
ret.max.y = min(r.max.y, r2.max.y);
return ret;
}
bool
rect_contains_p(Rectangle r, Rectangle r2) {
return r2.min.x >= r.min.x
&& r2.max.x <= r.max.x
&& r2.min.y >= r.min.y
&& r2.max.y <= r.max.y;
}
Align
quadrant(Rectangle r, Point pt) {
Align ret;
pt = subpt(pt, r.min);
ret = 0;
if(pt.x >= Dx(r) * .5)
ret |= East;
if(pt.x <= Dx(r) * .5)
ret |= West;
if(pt.y <= Dy(r) * .5)
ret |= North;
if(pt.y >= Dy(r) * .5)
ret |= South;
return ret;
}
Cursor
quad_cursor(Align align) {
switch(align) {
case NEast: return cursor[CurNECorner];
case NWest: return cursor[CurNWCorner];
case SEast: return cursor[CurSECorner];
case SWest: return cursor[CurSWCorner];
case South:
case North: return cursor[CurDVArrow];
case East:
case West: return cursor[CurDHArrow];
default: return cursor[CurMove];
}
}
Align
get_sticky(Rectangle src, Rectangle dst) {
Align corner;
corner = 0;
if(src.min.x != dst.min.x
&& src.max.x == dst.max.x)
corner |= East;
else
corner |= West;
if(src.min.y != dst.min.y
&& src.max.y == dst.max.y)
corner |= South;
else
corner |= North;
return corner;
}

View File

@ -208,7 +208,7 @@ kpress(XWindow w, ulong mod, KeyCode keycode) {
event("Key %s\n", found->name);
else {
XGrabKeyboard(display, w, true, GrabModeAsync, GrabModeAsync, CurrentTime);
flushevents(FocusChangeMask, true);
event_flush(FocusChangeMask, true);
kpress_seq(w, found);
XUngrabKeyboard(display, CurrentTime);
}

View File

@ -323,7 +323,7 @@ static void
check_preselect(IxpServer *s) {
USED(s);
check_x_event(nil);
event_check();
}
static void
@ -412,9 +412,11 @@ extern int fmtevent(Fmt*);
ewmh_init();
xext_init();
event_debug = debug_event;
srv.preselect = check_preselect;
ixp_listen(&srv, sock, &p9srv, serve_9pcon, nil);
ixp_listen(&srv, ConnectionNumber(display), nil, check_x_event, closedisplay);
ixp_listen(&srv, ConnectionNumber(display), nil, (void (*)(IxpConn*))check_preselect, closedisplay);
def.border = 1;
def.colmode = Colstack;

View File

@ -231,97 +231,6 @@ msg_getword(IxpMsg *m) {
return ret;
}
#define strbcmp(str, const) (strncmp((str), (const), sizeof(const)-1))
static int
getbase(const char **s, long *sign) {
const char *p;
int ret;
ret = 10;
*sign = 1;
if(**s == '-') {
*sign = -1;
*s += 1;
}else if(**s == '+')
*s += 1;
p = *s;
if(!strbcmp(p, "0x")) {
*s += 2;
ret = 16;
}
else if(isdigit(p[0])) {
if(p[1] == 'r') {
*s += 2;
ret = p[0] - '0';
}
else if(isdigit(p[1]) && p[2] == 'r') {
*s += 3;
ret = 10*(p[0]-'0') + (p[1]-'0');
}
}
else if(p[0] == '0') {
ret = 8;
}
if(ret != 10 && (**s == '-' || **s == '+'))
*sign = 0;
return ret;
}
static bool
getint(const char *s, int *ret) {
long l;
bool res;
res = getlong(s, &l);
*ret = l;
return res;
}
bool
getlong(const char *s, long *ret) {
const char *end;
char *rend;
int base;
long sign;
if(s == nil)
return false;
end = s+strlen(s);
base = getbase(&s, &sign);
if(sign == 0)
return false;
*ret = sign * strtol(s, &rend, base);
return (end == rend);
}
bool
getulong(const char *s, ulong *ret) {
const char *end;
char *rend;
int base;
long sign;
if(s == nil)
return false;
end = s+strlen(s);
base = getbase(&s, &sign);
if(sign < 1)
return false;
*ret = strtoul(s, &rend, base);
return (end == rend);
}
static char*
strend(char *s, int n) {
int len;
len = strlen(s);
return s + max(0, len - n);
}
static Client*
strclient(View *v, char *s) {
ulong id;

View File

@ -13,6 +13,21 @@ enum {
ButtonMask | PointerMotionMask
};
static Cursor
quad_cursor(Align align) {
switch(align) {
case NEast: return cursor[CurNECorner];
case NWest: return cursor[CurNWCorner];
case SEast: return cursor[CurSECorner];
case SWest: return cursor[CurSWCorner];
case South:
case North: return cursor[CurDVArrow];
case East:
case West: return cursor[CurDHArrow];
default: return cursor[CurMove];
}
}
static void
cwin_expose(Window *w, XExposeEvent *e) {
@ -176,7 +191,7 @@ readmouse(Point *p, uint *button) {
case Expose:
case NoExpose:
case PropertyNotify:
dispatch_event(&ev);
event_dispatch(&ev);
default:
Dprint(DEvent, "readmouse(): ignored: %E\n", &ev);
continue;
@ -428,7 +443,7 @@ mouse_resize(Client *c, Align align, bool grabmod) {
warppointer(d);
}
sync();
flushevents(PointerMotionMask, false);
event_flush(PointerMotionMask, false);
while(readmotion(&d)) {
if(align == Center) {

File diff suppressed because it is too large Load Diff

View File

@ -44,9 +44,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <clientutil.h>
#include <util.h>
#include <x11.h>
#include <stuff/clientutil.h>
#include <stuff/util.h>
#include <stuff/x11.h>
char version[] = "wmii9menu-" VERSION " ©2010 Kris Maglione, ©1994 David Hogan, Arnold Robbins";
@ -81,10 +82,6 @@ void warpmouse(int, int);
void memory(void);
int args(void);
ErrorCode ignored_xerrors[] = {
{ 0, }
};
/* xext.c */
void xext_init(void);
Rectangle* xinerama_screens(int*);

View File

@ -9,7 +9,7 @@
#include <time.h>
#include <unistd.h>
#include <ixp.h>
#include <util.h>
#include <stuff/util.h>
#include <fmt.h>
static IxpClient *client;

View File

@ -45,6 +45,7 @@
\DefineShortVerb{\|}
\makeatletter
\let\idx@@heading\chapter
\let\:=:
\catcode`\:=\active
\def:{\@ifnextchar:{\coloncoloneq}{\:}}

13
include/debug.h Normal file
View File

@ -0,0 +1,13 @@
#include <stdbool.h>
#define Debug(x) if(((debugflag|debugfile)&(x)) && setdebug(x))
#define Dprint(x, ...) BLOCK( if((debugflag|debugfile)&(x)) debug(x, __VA_ARGS__) )
void debug(int, const char*, ...);
void dprint(const char*, ...);
void dwrite(int, void*, int, bool);
bool setdebug(int);
void vdebug(int, const char*, va_list);
int debugflag;
int debugfile;

View File

@ -1,3 +1,7 @@
/* Copyright ©2009-2010 Kris Maglione <fbsdaemon@gmail.com>
* See LICENSE file for license details.
*/
#ifndef CLIENTEXTERN
# define CLIENTEXTERN extern
#endif

54
include/stuff/geom.h Normal file
View File

@ -0,0 +1,54 @@
#pragma once
#include <stuff/base.h>
typedef struct Point Point;
typedef struct Rectangle Rectangle;
struct Point {
int x, y;
};
struct Rectangle {
Point min, max;
};
enum Align {
North = 0x01,
East = 0x02,
South = 0x04,
West = 0x08,
NEast = North | East,
NWest = North | West,
SEast = South | East,
SWest = South | West,
Center = NEast | SWest,
};
typedef enum Align Align;
#define Dx(r) ((r).max.x - (r).min.x)
#define Dy(r) ((r).max.y - (r).min.y)
#define Pt(x, y) ((Point){(x), (y)})
#define Rpt(p, q) ((Rectangle){p, q})
#define Rect(x0, y0, x1, y1) ((Rectangle){Pt(x0, y0), Pt(x1, y1)})
Point addpt(Point, Point);
Point divpt(Point, Point);
int eqpt(Point, Point);
int eqrect(Rectangle, Rectangle);
Rectangle gravitate(Rectangle dst, Rectangle src, Point grav);
Rectangle insetrect(Rectangle, int);
Point mulpt(Point p, Point q);
Rectangle rectaddpt(Rectangle, Point);
Rectangle rectsetorigin(Rectangle, Point);
Rectangle rectsubpt(Rectangle, Point);
Point subpt(Point, Point);
Align get_sticky(Rectangle src, Rectangle dst);
Align quadrant(Rectangle, Point);
bool rect_contains_p(Rectangle, Rectangle);
bool rect_haspoint_p(Point, Rectangle);
bool rect_intersect_p(Rectangle, Rectangle);
Rectangle rect_intersection(Rectangle, Rectangle);

150
include/stuff/util.h Normal file
View File

@ -0,0 +1,150 @@
/* Copyright ©2007-2010 Kris Maglione <fbsdaemon@gmail.com>
* See LICENSE file for license details.
*/
#include <stuff/geom.h>
#include <stdarg.h>
#include <regexp9.h>
/* Types */
typedef struct Regex Regex;
struct Regex {
char* regex;
Reprog* regc;
};
enum {
CLeft = 1<<0,
CCenter = 1<<1,
CRight = 1<<2,
};
enum DebugOpt {
D9p = 1<<0,
DDnd = 1<<1,
DEvent = 1<<2,
DEwmh = 1<<3,
DFocus = 1<<4,
DGeneric= 1<<5,
DStack = 1<<6,
NDebugOpt = 7,
};
enum {
GInvert = 1<<0,
};
#ifdef VARARGCK
# pragma varargck argpos _die 3
# pragma varargck argpos fatal 1
# pragma varargck argpos sxprint 1
#endif
#define strlcat stuff_strlcat
#define strcasestr stuff_strcasestr
void _die(char*, int, char*, ...);
void backtrace(char*);
void closeexec(int);
char** comm(int, char**, char**);
int doublefork(void);
void* emalloc(uint);
void* emallocz(uint);
void* erealloc(void*, uint);
char* estrdup(const char*);
char* estrndup(const char*, uint);
void fatal(const char*, ...);
void* freelater(void*);
int getbase(const char**, long*);
bool getint(const char*, int*);
bool getlong(const char*, long*);
bool getulong(const char*, ulong*);
void grep(char**, Reprog*, int);
char* join(char**, char*);
int max(int, int);
int min(int, int);
char* pathsearch(const char*, const char*, bool);
void refree(Regex*);
void reinit(Regex*, char*);
int spawn3(int[3], const char*, char*[]);
int spawn3l(int[3], const char*, ...);
uint stokenize(char**, uint, char*, char*);
char* strcasestr(const char*, const char*);
char* strend(char*, int);
uint strlcat(char*, const char*, uint);
int strlcatprint(char*, int, const char*, ...);
char* sxprint(const char*, ...);
uint tokenize(char**, uint, char*, char);
void uniq(char**);
int unquote(char*, char*[], int);
int utflcpy(char*, const char*, int);
char* vsxprint(const char*, va_list);
extern char buffer[8092];
extern char* _buffer;
extern char* const _buf_end;
#define bufclear() \
BLOCK( _buffer = buffer; _buffer[0] = '\0' )
#define bufprint(...) \
_buffer = seprint(_buffer, _buf_end, __VA_ARGS__)
#define die(...) \
_die(__FILE__, __LINE__, __VA_ARGS__)
char *argv0;
#undef ARGBEGIN
#undef ARGEND
#undef ARGF
#undef EARGF
#define ARGBEGIN \
int _argtmp=0, _inargv; char *_argv=nil; \
if(!argv0) argv0=*argv; argv++, argc--; \
_inargv=1; USED(_inargv); \
while(argc && argv[0][0] == '-') { \
_argv=&argv[0][1]; argv++; argc--; \
if(_argv[0] == '-' && _argv[1] == '\0') \
break; \
while(*_argv) switch(*_argv++)
#define ARGEND }_inargv=0;USED(_argtmp, _argv, _inargv)
#define EARGF(f) ((_inargv && *_argv) ? \
(_argtmp=strlen(_argv), _argv+=_argtmp, _argv-_argtmp) \
: ((argc > 0) ? \
(--argc, ++argv, _used(argc), *(argv-1)) \
: ((f), (char*)0)))
#define ARGF() EARGF(_used(0))
/* map.c */
typedef struct Map Map;
typedef struct MapEnt MapEnt;
struct Map {
MapEnt**bucket;
uint nhash;
};
void** hash_get(Map*, const char*, bool create);
void* hash_rm(Map*, const char*);
void** map_get(Map*, ulong, bool create);
void* map_rm(Map*, ulong);
/* Yuck. */
#define VECTOR(type, nam, c) \
typedef struct Vector_##nam Vector_##nam; \
struct Vector_##nam { \
type* ary; \
long n; \
long size; \
}; \
void vector_##c##free(Vector_##nam*); \
void vector_##c##init(Vector_##nam*); \
void vector_##c##push(Vector_##nam*, type); \
VECTOR(long, long, l)
VECTOR(Rectangle, rect, r)
VECTOR(void*, ptr, p)
#undef VECTOR

48
include/stuff/x.h Normal file
View File

@ -0,0 +1,48 @@
#include <stuff/base.h>
#include <stuff/x11.h>
#include <fmt.h>
extern Visual* render_visual;
extern void init_screens(void);
/* printevent.c */
int fmtevent(Fmt*);
/* xext.c */
void randr_event(XEvent*);
bool render_argb_p(Visual*);
void xext_event(XEvent*);
void xext_init(void);
Rectangle* xinerama_screens(int*);
void event_check(void);
void event_dispatch(XEvent*);
uint event_flush(long, bool dispatch);
uint event_flushenter(void);
void event_loop(void);
void event_updatextime(void);
void event_buttonpress(XButtonPressedEvent*);
void event_buttonrelease(XButtonPressedEvent*);
void event_clientmessage(XClientMessageEvent*);
void event_configurenotify(XConfigureEvent*);
void event_configurerequest(XConfigureRequestEvent*);
void event_destroynotify(XDestroyWindowEvent*);
void event_enternotify(XCrossingEvent*);
void event_expose(XExposeEvent*);
void event_focusin(XFocusChangeEvent*);
void event_focusout(XFocusChangeEvent*);
void event_keypress(XKeyEvent*);
void event_leavenotify(XCrossingEvent*);
void event_mapnotify(XMapEvent*);
void event_maprequest(XMapRequestEvent*);
void event_mappingnotify(XMappingEvent*);
void event_motionnotify(XMotionEvent*);
void event_propertynotify(XPropertyEvent*);
void event_unmapnotify(XUnmapEvent*);
extern long event_xtime;
extern bool event_looprunning;
extern void (*event_debug)(XEvent*);

View File

@ -4,6 +4,7 @@
#define Window XWindow
#define Font XFont
#define Screen XScreen
#include <stuff/geom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xft/Xft.h>
@ -17,18 +18,6 @@
#undef Font
#undef Screen
enum Align {
North = 0x01,
East = 0x02,
South = 0x04,
West = 0x08,
NEast = North | East,
NWest = North | West,
SEast = South | East,
SWest = South | West,
Center = NEast | SWest,
};
enum FontType {
FX11 = 1,
FFontSet,
@ -40,23 +29,11 @@ enum WindowType {
WImage,
};
typedef enum Align Align;
typedef enum FontType FontType;
typedef enum WindowType WindowType;
typedef XSetWindowAttributes WinAttr;
typedef struct Point Point;
typedef struct Rectangle Rectangle;
struct Point {
int x, y;
};
struct Rectangle {
Point min, max;
};
typedef struct Color Color;
typedef struct CTuple CTuple;
typedef struct ErrorCode ErrorCode;
@ -189,24 +166,14 @@ extern const Point ZP;
extern const Rectangle ZR;
extern Window* pointerwin;
Point Pt(int x, int y);
Rectangle Rect(int x0, int y0, int x1, int y1);
Rectangle Rpt(Point min, Point max);
XRectangle XRect(Rectangle r);
#define Dx(r) ((r).max.x - (r).min.x)
#define Dy(r) ((r).max.y - (r).min.y)
#define Pt(x, y) ((Point){(x), (y)})
#define Rpt(p, q) ((Rectangle){p, q})
#define Rect(x0, y0, x1, y1) ((Rectangle){Pt(x0, y0), Pt(x1, y1)})
#define changeprop(w, prop, type, data, n) \
changeproperty(w, prop, type, \
((sizeof(*(data)) == 8 ? 4 : sizeof(*(data))) * 8), \
(uchar*)(data), n)
/* x11.c */
Point addpt(Point, Point);
Image* allocimage(int w, int h, int depth);
void border(Image *dst, Rectangle, int w, Color);
void changeprop_char(Window*, char*, char*, char[], int);
@ -221,12 +188,9 @@ Window* createwindow(Window*, Rectangle, int depth, uint class, WinAttr*, int va
Window* createwindow_visual(Window*, Rectangle, int depth, Visual*, uint class, WinAttr*, int);
void delproperty(Window*, char*);
void destroywindow(Window*);
Point divpt(Point, Point);
void drawline(Image*, Point, Point, int cap, int w, Color);
void drawpoly(Image*, Point*, int, int cap, int w, Color);
uint drawstring(Image*, Font*, Rectangle, Align, char*, Color);
int eqpt(Point, Point);
int eqrect(Rectangle, Rectangle);
void fill(Image*, Rectangle, Color);
void fillpoly(Image*, Point*, int, Color);
Window* findwin(XWindow);
@ -249,7 +213,6 @@ Font* loadfont(char*);
void lowerwin(Window*);
int mapwin(Window*);
void movewin(Window*, Point);
Point mulpt(Point p, Point q);
bool namedcolor(char *name, Color*);
bool parsekey(char*, int*, char**);
int pointerscreen(void);
@ -258,14 +221,13 @@ void raisewin(Window*);
void reparentwindow(Window*, Window*, Point);
void reshapewin(Window*, Rectangle);
void selectinput(Window*, long);
void sendevent(Window*, bool propegate, long mask, XEvent*);
void sendevent(Window*, bool propagate, long mask, XEvent*);
void setborder(Window*, int, Color);
void setfocus(Window*, int mode);
void sethints(Window*);
void setshapemask(Window *dst, Image *src, Point);
void setwinattr(Window*, WinAttr*, int valmask);
char** strlistdup(char**);
Point subpt(Point, Point);
void sync(void);
uint textwidth(Font*, char*);
uint textwidth_l(Font*, char*, uint len);
@ -282,11 +244,6 @@ Atom xatom(char*);
void sendmessage(Window*, char*, long, long, long, long, long);
XRectangle XRect(Rectangle);
Rectangle getwinrect(Window*);
Rectangle gravitate(Rectangle dst, Rectangle src, Point grav);
Rectangle insetrect(Rectangle, int);
Rectangle rectaddpt(Rectangle, Point);
Rectangle rectsetorigin(Rectangle, Point);
Rectangle rectsubpt(Rectangle, Point);
Handlers* sethandler(Window*, Handlers*);
Rectangle sizehint(WinHints*, Rectangle);

View File

@ -1,91 +0,0 @@
/* Copyright ©2007-2010 Kris Maglione <fbsdaemon@gmail.com>
* See LICENSE file for license details.
*/
#define nil ((void*)0)
#define nelem(ary) (sizeof(ary) / sizeof(*ary))
/* Types */
#undef uchar
#undef ushort
#undef uint
#undef ulong
#undef uvlong
#undef vlong
#define uchar _x_uchar
#define ushort _x_ushort
#define uint _x_uint
#define ulong _x_ulong
#define uvlong _x_uvlong
#define vlong _x_vlong
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long long uvlong;
typedef long long vlong;
#ifdef VARARGCK
# pragma varargck argpos _die 3
# pragma varargck argpos fatal 1
# pragma varargck argpos sxprint 1
#endif
#define strlcat wmii_strlcat
#define strcasestr wmii_strcasestr
/* util.c */
void _die(char*, int, char*, ...);
void* emalloc(uint);
void* emallocz(uint);
void* erealloc(void*, uint);
char* estrdup(const char*);
char* estrndup(const char*, uint);
void fatal(const char*, ...);
void* freelater(void*);
int max(int, int);
int min(int, int);
uint strlcat(char*, const char*, uint);
char* strcasestr(const char*, const char*);
char* sxprint(const char*, ...);
uint tokenize(char**, uint, char*, char);
uint stokenize(char**, uint, char*, char*);
int utflcpy(char*, const char*, int);
char* vsxprint(const char*, va_list);
#define die(...) \
_die(__FILE__, __LINE__, __VA_ARGS__)
char *argv0;
#undef ARGBEGIN
#undef ARGEND
#undef ARGF
#undef EARGF
#define ARGBEGIN \
int _argtmp=0, _inargv; char *_argv=nil; \
if(!argv0) argv0=*argv; argv++, argc--; \
_inargv=1; USED(_inargv); \
while(argc && argv[0][0] == '-') { \
_argv=&argv[0][1]; argv++; argc--; \
if(_argv[0] == '-' && _argv[1] == '\0') \
break; \
while(*_argv) switch(*_argv++)
#define ARGEND }_inargv=0;USED(_argtmp, _argv, _inargv)
#define EARGF(f) ((_inargv && *_argv) ? \
(_argtmp=strlen(_argv), _argv+=_argtmp, _argv-_argtmp) \
: ((argc > 0) ? \
(--argc, ++argv, _used(argc), *(argv-1)) \
: ((f), (char*)0)))
#define ARGF() EARGF(_used(0))
static inline void
_used(long a, ...) {
if(a){}
}
#ifndef KENC
# undef USED
# undef SET
# define USED(...) _used((long)__VA_ARGS__)
# define SET(x) (x = 0)
/* # define SET(x) USED(&x) GCC 4 is 'too smart' for this. */
#endif

171
libstuff/Makefile Normal file
View File

@ -0,0 +1,171 @@
ROOT= ..
include ${ROOT}/mk/hdr.mk
TARG=libstuff
PACKAGES += $(X11PACKAGES) xext xrandr xrender xinerama
OBJ=\
buffer \
clientutil \
event/buttonpress \
event/buttonrelease \
event/clientmessage \
event/configurenotify \
event/configurerequest \
event/destroynotify \
event/enternotify \
event/event \
event/expose \
event/focusin \
event/focusout \
event/keypress \
event/leavenotify \
event/mapnotify \
event/maprequest \
event/mappingnotify \
event/motionnotify \
event/propertynotify \
event/unmapnotify \
event/xtime \
geom/get_sticky \
geom/quadrant \
geom/rect_contains_p \
geom/rect_haspoint_p \
geom/rect_intersect_p \
geom/rect_intersection \
init_screens \
map \
printevent \
util/_die \
util/backtrace \
util/closeexec \
util/comm \
util/doublefork \
util/emalloc \
util/emallocz \
util/erealloc \
util/estrdup \
util/estrndup \
util/fatal \
util/freelater \
util/getbase \
util/getint \
util/getlong \
util/getulong \
util/grep \
util/join \
util/max \
util/mfatal \
util/min \
util/pathsearch \
util/refree \
util/reinit \
util/spawn3 \
util/spawn3l \
util/stokenize \
util/strcasestr \
util/strend \
util/strlcat \
util/strlcatprint \
util/sxprint \
util/tokenize \
util/uniq \
util/unquote \
util/utflcpy \
util/vector \
util/vsxprint \
x11/convpts \
x11/errors \
x11/ignored_xerrors \
x11/freestringlist \
x11/initdisplay \
x11/sendevent \
x11/sendmessage \
x11/setgccol \
x11/sync \
x11/x11 \
x11/xatom \
x11/colors/loadcolor \
x11/colors/namedcolor \
x11/colors/xftcolor \
x11/drawing/border \
x11/drawing/drawline \
x11/drawing/drawpoly \
x11/drawing/drawstring \
x11/drawing/fill \
x11/drawing/fillpoly \
x11/focus/getfocus \
x11/focus/setfocus \
x11/geometry/XRect \
x11/geometry/addpt \
x11/geometry/divpt \
x11/geometry/eqpt \
x11/geometry/eqrect \
x11/geometry/insetrect \
x11/geometry/mulpt \
x11/geometry/rectaddpt \
x11/geometry/rectsetorigin \
x11/geometry/rectsubpt \
x11/geometry/subpt \
x11/images/allocimage \
x11/images/copyimage \
x11/images/freeimage \
x11/images/xftdrawable \
x11/insanity/gravitate \
x11/insanity/sethints \
x11/insanity/sizehint \
x11/keyboard/grabkeyboard \
x11/keyboard/ungrabkeyboard \
x11/keys/keycode \
x11/keys/parsekey \
x11/mouse/grabpointer \
x11/mouse/pointerscreen \
x11/mouse/querypointer \
x11/mouse/translate \
x11/mouse/ungrabpointer \
x11/mouse/warppointer \
x11/properties/changeprop_char \
x11/properties/changeprop_long \
x11/properties/changeprop_short \
x11/properties/changeprop_string \
x11/properties/changeprop_textlist \
x11/properties/changeprop_ulong \
x11/properties/changeproperty \
x11/properties/delproperty \
x11/properties/getprop \
x11/properties/getprop_long \
x11/properties/getprop_string \
x11/properties/getprop_textlist \
x11/properties/getprop_ulong \
x11/properties/getproperty \
x11/properties/strlistdup \
x11/shape/setshapemask \
x11/text/freefont \
x11/text/labelh \
x11/text/loadfont \
x11/text/textextents_l \
x11/text/textwidth \
x11/text/textwidth_l \
x11/windows/configwin \
x11/windows/createwindow \
x11/windows/createwindow_visual \
x11/windows/destroywindow \
x11/windows/findwin \
x11/windows/getwinrect \
x11/windows/lowerwin \
x11/windows/mapwin \
x11/windows/movewin \
x11/windows/raisewin \
x11/windows/reparentwindow \
x11/windows/reshapewin \
x11/windows/selectinput \
x11/windows/setborder \
x11/windows/sethandler \
x11/windows/setwinattr \
x11/windows/unmapwin \
x11/windows/window \
xext
include ${ROOT}/mk/lib.mk

8
libstuff/buffer.c Normal file
View File

@ -0,0 +1,8 @@
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
char buffer[8092];
char* _buffer;
char* const _buf_end = buffer + sizeof buffer;

View File

@ -3,8 +3,8 @@
#define CLIENTEXTERN
#include <string.h>
#include <ixp.h>
#include <clientutil.h>
#include <util.h>
#include <stuff/clientutil.h>
#include <stuff/util.h>
static IxpCFid* ctlfid;
static char ctl[1024];

View File

@ -0,0 +1,14 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_buttonpress(XButtonPressedEvent *ev) {
Window *w;
if((w = findwin(ev->window)))
handle(w, bdown, ev);
else
XAllowEvents(display, ReplayPointer, ev->time);
}

View File

@ -0,0 +1,12 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_buttonrelease(XButtonPressedEvent *ev) {
Window *w;
if((w = findwin(ev->window)))
handle(w, bup, ev);
}

View File

@ -0,0 +1,10 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_clientmessage(XClientMessageEvent *ev) {
USED(ev);
}

View File

@ -0,0 +1,12 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_configurenotify(XConfigureEvent *ev) {
Window *w;
if((w = findwin(ev->window)))
handle(w, config, ev);
}

View File

@ -0,0 +1,24 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_configurerequest(XConfigureRequestEvent *ev) {
XWindowChanges wc;
Window *w;
if((w = findwin(ev->window)))
handle(w, configreq, ev);
else{
wc.x = ev->x;
wc.y = ev->y;
wc.width = ev->width;
wc.height = ev->height;
wc.border_width = ev->border_width;
wc.sibling = ev->above;
wc.stack_mode = ev->detail;
XConfigureWindow(display, ev->window, ev->value_mask, &wc);
}
}

View File

@ -0,0 +1,12 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_destroynotify(XDestroyWindowEvent *ev) {
Window *w;
if((w = findwin(ev->window)))
handle(w, destroy, ev);
}

View File

@ -0,0 +1,16 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_enternotify(XCrossingEvent *ev) {
Window *w;
event_xtime = ev->time;
if(ev->mode != NotifyNormal)
return;
if((w = findwin(ev->window)))
handle(w, enter, ev);
}

107
libstuff/event/event.c Normal file
View File

@ -0,0 +1,107 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void (*event_debug)(XEvent*);
long event_xtime;
bool event_looprunning;
EventHandler event_handler[LASTEvent] = {
[ButtonPress] = (EventHandler)event_buttonpress,
[ButtonRelease] = (EventHandler)event_buttonrelease,
[ClientMessage] = (EventHandler)event_clientmessage,
[ConfigureNotify] = (EventHandler)event_configurenotify,
[ConfigureRequest] = (EventHandler)event_configurerequest,
[DestroyNotify] = (EventHandler)event_destroynotify,
[EnterNotify] = (EventHandler)event_enternotify,
[Expose] = (EventHandler)event_expose,
[FocusIn] = (EventHandler)event_focusin,
[FocusOut] = (EventHandler)event_focusout,
[KeyPress] = (EventHandler)event_keypress,
[LeaveNotify] = (EventHandler)event_leavenotify,
[MapNotify] = (EventHandler)event_mapnotify,
[MapRequest] = (EventHandler)event_maprequest,
[MappingNotify] = (EventHandler)event_mappingnotify,
[MotionNotify] = (EventHandler)event_motionnotify,
[PropertyNotify] = (EventHandler)event_propertynotify,
[UnmapNotify] = (EventHandler)event_unmapnotify,
};
void
event_dispatch(XEvent *e) {
if(event_debug)
event_debug(e);
if(e->type < nelem(event_handler)) {
if(event_handler[e->type])
event_handler[e->type](e);
}else
xext_event(e);
}
void
event_check(void) {
XEvent ev;
while(XPending(display)) {
XNextEvent(display, &ev);
event_dispatch(&ev);
}
}
void
event_loop(void) {
XEvent ev;
while(event_looprunning) {
XNextEvent(display, &ev);
event_dispatch(&ev);
}
}
uint
event_flush(long event_mask, bool dispatch) {
XEvent ev;
uint n = 0;
while(XCheckMaskEvent(display, event_mask, &ev)) {
if(dispatch)
event_dispatch(&ev);
n++;
}
return n;
}
static int
findenter(Display *d, XEvent *e, XPointer v) {
long *l;
USED(d);
l = (long*)v;
if(*l)
return false;
if(e->type == EnterNotify)
return true;
if(e->type == MotionNotify)
(*l)++;
return false;
}
/* This isn't perfect. If there were motion events in the queue
* before this was called, then it flushes nothing. If we don't
* check for them, we might lose a legitamate enter event.
*/
uint
event_flushenter(void) {
XEvent e;
long l;
int n;
l = 0;
n = 0;
while(XCheckIfEvent(display, &e, findenter, (void*)&l))
n++;
return n;
}

9
libstuff/event/event.h Normal file
View File

@ -0,0 +1,9 @@
#include <stuff/x.h>
typedef void (*EventHandler)(XEvent*);
#define handle(w, fn, ev) \
BLOCK(if((w)->handler->fn) (w)->handler->fn((w), ev))
extern EventHandler event_handler[LASTEvent];

12
libstuff/event/expose.c Normal file
View File

@ -0,0 +1,12 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_expose(XExposeEvent *ev) {
Window *w;
if(ev->count == 0 && (w = findwin(ev->window)))
handle(w, expose, ev);
}

27
libstuff/event/focusin.c Normal file
View File

@ -0,0 +1,27 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_focusin(XFocusChangeEvent *ev) {
Window *w;
/* Yes, we're focusing in on nothing, here. */
if(ev->detail == NotifyDetailNone) {
/* FIXME: Do something. */
return;
}
if(!((ev->detail == NotifyNonlinear)
||(ev->detail == NotifyNonlinearVirtual)
||(ev->detail == NotifyVirtual)
||(ev->detail == NotifyInferior)
||(ev->detail == NotifyAncestor)))
return;
if((ev->mode == NotifyWhileGrabbed))
return;
if((w = findwin(ev->window)))
handle(w, focusin, ev);
}

19
libstuff/event/focusout.c Normal file
View File

@ -0,0 +1,19 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_focusout(XFocusChangeEvent *ev) {
Window *w;
if(!((ev->detail == NotifyNonlinear)
||(ev->detail == NotifyNonlinearVirtual)
||(ev->detail == NotifyVirtual)
||(ev->detail == NotifyInferior)
||(ev->detail == NotifyAncestor)))
return;
if((w = findwin(ev->window)))
handle(w, focusout, ev);
}

13
libstuff/event/keypress.c Normal file
View File

@ -0,0 +1,13 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_keypress(XKeyEvent *ev) {
Window *w;
event_xtime = ev->time;
if((w = findwin(ev->window)))
handle(w, kdown, ev);
}

View File

@ -0,0 +1,13 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_leavenotify(XCrossingEvent *ev) {
Window *w;
event_xtime = ev->time;
if((w = findwin(ev->window)))
handle(w, leave, ev);
}

View File

@ -0,0 +1,12 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_mapnotify(XMapEvent *ev) {
Window *w;
if((w = findwin(ev->window)))
handle(w, map, ev);
}

View File

@ -0,0 +1,11 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_mappingnotify(XMappingEvent *ev) {
/* Why do you need me to tell you this? */
XRefreshKeyboardMapping(ev);
}

View File

@ -0,0 +1,12 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_maprequest(XMapRequestEvent *ev) {
Window *w;
if((w = findwin(ev->parent)))
handle(w, mapreq, ev);
}

View File

@ -0,0 +1,13 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_motionnotify(XMotionEvent *ev) {
Window *w;
event_xtime = ev->time;
if((w = findwin(ev->window)))
handle(w, motion, ev);
}

View File

@ -0,0 +1,13 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_propertynotify(XPropertyEvent *ev) {
Window *w;
event_xtime = ev->time;
if((w = findwin(ev->window)))
handle(w, property, ev);
}

View File

@ -0,0 +1,15 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "event.h"
void
event_unmapnotify(XUnmapEvent *ev) {
Window *w;
if((w = findwin(ev->window)) && (ev->event == w->parent->xid)) {
w->mapped = false;
if(w->parent && (ev->send_event || w->unmapped-- == 0))
handle(w, unmap, ev);
}
}

33
libstuff/event/xtime.c Normal file
View File

@ -0,0 +1,33 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <stuff/x.h>
static int
findtime(Display *d, XEvent *e, XPointer v) {
Window *w;
w = (Window*)v;
if(e->type == PropertyNotify && e->xproperty.window == w->xid) {
event_xtime = e->xproperty.time;
return true;
}
return false;
}
void
event_updatextime(void) {
Window *w;
WinAttr wa;
XEvent e;
long l;
w = createwindow(&scr.root, Rect(0, 0, 1, 1), 0, InputOnly, &wa, 0);
XSelectInput(display, w->xid, PropertyChangeMask);
changeprop_long(w, "ATOM", "ATOM", &l, 0);
XIfEvent(display, &e, findtime, (void*)w);
destroywindow(w);
}

View File

@ -0,0 +1,24 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <stuff/geom.h>
Align
get_sticky(Rectangle src, Rectangle dst) {
Align corner;
corner = 0;
if(src.min.x != dst.min.x
&& src.max.x == dst.max.x)
corner |= East;
else
corner |= West;
if(src.min.y != dst.min.y
&& src.max.y == dst.max.y)
corner |= South;
else
corner |= North;
return corner;
}

23
libstuff/geom/quadrant.c Normal file
View File

@ -0,0 +1,23 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <stuff/geom.h>
Align
quadrant(Rectangle r, Point pt) {
Align ret;
pt = subpt(pt, r.min);
ret = 0;
if(pt.x >= Dx(r) * .5)
ret |= East;
if(pt.x <= Dx(r) * .5)
ret |= West;
if(pt.y <= Dy(r) * .5)
ret |= North;
if(pt.y >= Dy(r) * .5)
ret |= South;
return ret;
}

View File

@ -0,0 +1,12 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <stuff/geom.h>
bool
rect_contains_p(Rectangle r, Rectangle r2) {
return r2.min.x >= r.min.x
&& r2.max.x <= r.max.x
&& r2.min.y >= r.min.y
&& r2.max.y <= r.max.y;
}

View File

@ -0,0 +1,10 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <stuff/geom.h>
bool
rect_haspoint_p(Point pt, Rectangle r) {
return (pt.x >= r.min.x) && (pt.x < r.max.x)
&& (pt.y >= r.min.y) && (pt.y < r.max.y);
}

View File

@ -0,0 +1,12 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <stuff/geom.h>
bool
rect_intersect_p(Rectangle r, Rectangle r2) {
return r.min.x <= r2.max.x
&& r.max.x >= r2.min.x
&& r.min.y <= r2.max.y
&& r.max.y >= r2.min.y;
}

View File

@ -0,0 +1,17 @@
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <stuff/geom.h>
#include <stuff/util.h>
Rectangle
rect_intersection(Rectangle r, Rectangle r2) {
Rectangle ret;
/* ret != canonrect(ret) ≡ no intersection. */
ret.min.x = max(r.min.x, r2.min.x);
ret.max.x = min(r.max.x, r2.max.x);
ret.min.y = max(r.min.y, r2.min.y);
ret.max.y = min(r.max.y, r2.max.y);
return ret;
}

9
libstuff/init_screens.c Normal file
View File

@ -0,0 +1,9 @@
/* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
void init_screens(void);
void
init_screens(void) {
}

View File

@ -1,7 +1,8 @@
/* Written by Kris Maglione */
/* Public domain */
#include "dat.h"
#include "fns.h"
#include <stdlib.h>
#include <string.h>
#include <stuff/util.h>
/* Edit s/^([a-zA-Z].*)\n([a-z].*) {/\1 \2;/g x/^([^a-zA-Z]|static|$)/-+d s/ (\*map|val|*str)//g */

View File

@ -39,10 +39,10 @@
* ken@richsun.UUCP
*/
#include "dat.h"
#include <stdarg.h>
#include <bio.h>
//#include "fns.h"
#include <stuff/x.h>
#include <stuff/util.h>
#include "printevent.h"
#define Window XWindow

27
libstuff/util/_die.c Normal file
View File

@ -0,0 +1,27 @@
/* Written by Kris Maglione <maglione.k at Gmail> */
/* Public domain */
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <fmt.h>
#include "util.h"
void
_die(char *file, int line, char *msg, ...) {
va_list ap;
va_start(ap, msg);
fprint(2, "%s: dieing at %s:%d: %s\n",
argv0, file, line,
vsxprint(msg, ap));
va_end(ap);
kill(getpid(), SIGABRT);
abort(); /* Adds too many frames:
* _die()
* abort()
* raise(SIGABRT)
* kill(getpid(), SIGABRT)
*/
}

88
libstuff/util/backtrace.c Normal file
View File

@ -0,0 +1,88 @@
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <bio.h>
#include <plan9.h>
#undef nelem
#include <debug.h>
#include "util.h"
#ifdef __linux__
# define PROGTXT "exe"
#else
# define PROGTXT "file"
#endif
static void
_backtrace(int pid, char *btarg) {
char *proc, *spid, *gdbcmd;
int fd[3], p[2];
int status, cmdfd;
gdbcmd = estrdup("/tmp/gdbcmd.XXXXXX");
if(pipe(p) < 0)
goto done;
closeexec(p[0]);
cmdfd = mkstemp(gdbcmd);
if(cmdfd < 0)
goto done;
fprint(cmdfd, "bt %s\n", btarg);
fprint(cmdfd, "detach\n");
close(cmdfd);
fd[0] = open("/dev/null", O_RDONLY);
fd[1] = p[1];
fd[2] = dup(2);
proc = sxprint("/proc/%d/" PROGTXT, pid);
spid = sxprint("%d", pid);
if(spawn3l(fd, "gdb", "gdb", "-batch", "-x", gdbcmd, proc, spid, nil) < 0) {
unlink(gdbcmd);
goto done;
}
Biobuf bp;
char *s;
Binit(&bp, p[0], OREAD);
while((s = Brdstr(&bp, '\n', 1))) {
Dprint(DStack, "%s\n", s);
free(s);
}
unlink(gdbcmd);
done:
free(gdbcmd);
kill(pid, SIGKILL);
waitpid(pid, &status, 0);
}
void
backtrace(char *btarg) {
int pid;
/* Fork so we can backtrace the child. Keep this stack
* frame minimal, so the trace is fairly clean.
*/
Debug(DStack)
switch(pid = fork()) {
case -1:
return;
case 0:
kill(getpid(), SIGSTOP);
_exit(0);
default:
_backtrace(pid, btarg);
break;
}
}

12
libstuff/util/closeexec.c Normal file
View File

@ -0,0 +1,12 @@
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <unistd.h>
#include <fcntl.h>
#include "util.h"
void
closeexec(int fd) {
if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
fatal("can't set %d close on exec: %r", fd);
}

42
libstuff/util/comm.c Normal file
View File

@ -0,0 +1,42 @@
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <string.h>
#include "util.h"
#include <stuff/x11.h>
char**
comm(int cols, char **toka, char **tokb) {
Vector_ptr vec;
char **ret;
int cmp;
vector_pinit(&vec);
while(*toka || *tokb) {
if(!*toka)
cmp = 1;
else if(!*tokb)
cmp = -1;
else
cmp = strcmp(*toka, *tokb);
if(cmp < 0) {
if(cols & CLeft)
vector_ppush(&vec, *toka);
toka++;
}else if(cmp > 0) {
if(cols & CRight)
vector_ppush(&vec, *tokb);
tokb++;
}else {
if(cols & CCenter)
vector_ppush(&vec, *toka);
toka++;
tokb++;
}
}
vector_ppush(&vec, nil);
ret = strlistdup((char**)vec.ary);
free(vec.ary);
return ret;
}

View File

@ -0,0 +1,31 @@
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include "util.h"
int
doublefork(void) {
pid_t pid;
int status;
switch(pid=fork()) {
case -1:
fatal("Can't fork(): %r");
case 0:
switch(pid=fork()) {
case -1:
fatal("Can't fork(): %r");
case 0:
return 0;
default:
exit(0);
}
default:
waitpid(pid, &status, 0);
return pid;
}
/* NOTREACHED */
}

12
libstuff/util/emalloc.c Normal file
View File

@ -0,0 +1,12 @@
/* Written by Kris Maglione <maglione.k at Gmail> */
/* Public domain */
#include <stdlib.h>
#include "util.h"
void *
emalloc(uint size) {
void *ret = malloc(size);
if(!ret)
mfatal("malloc", size);
return ret;
}

11
libstuff/util/emallocz.c Normal file
View File

@ -0,0 +1,11 @@
/* Written by Kris Maglione <maglione.k at Gmail> */
/* Public domain */
#include <string.h>
#include "util.h"
void*
emallocz(uint size) {
void *ret = emalloc(size);
memset(ret, 0, size);
return ret;
}

12
libstuff/util/erealloc.c Normal file
View File

@ -0,0 +1,12 @@
/* Written by Kris Maglione <maglione.k at Gmail> */
/* Public domain */
#include <stdlib.h>
#include "util.h"
void *
erealloc(void *ptr, uint size) {
void *ret = realloc(ptr, size);
if(!ret)
mfatal("realloc", size);
return ret;
}

12
libstuff/util/estrdup.c Normal file
View File

@ -0,0 +1,12 @@
/* Written by Kris Maglione <maglione.k at Gmail> */
/* Public domain */
#include <string.h>
#include "util.h"
char*
estrdup(const char *str) {
void *ret = strdup(str);
if(!ret)
mfatal("strdup", strlen(str));
return ret;
}

15
libstuff/util/estrndup.c Normal file
View File

@ -0,0 +1,15 @@
/* Written by Kris Maglione <maglione.k at Gmail> */
/* Public domain */
#include <string.h>
#include "util.h"
char*
estrndup(const char *str, uint len) {
char *ret;
len = min(len, strlen(str));
ret = emalloc(len + 1);
memcpy(ret, str, len);
ret[len] = '\0';
return ret;
}

40
libstuff/util/fatal.c Normal file
View File

@ -0,0 +1,40 @@
/* Written by Kris Maglione <maglione.k at Gmail> */
/* Public domain */
#include <stdlib.h>
#include <fmt.h>
#include "util.h"
typedef struct VFmt VFmt;
struct VFmt {
const char *fmt;
va_list args;
};
#ifdef VARARGCK
# pragma varargck type "V" VFmt*
#endif
static int
Vfmt(Fmt *f) {
VFmt *vf;
int i;
vf = va_arg(f->args, VFmt*);
i = fmtvprint(f, vf->fmt, vf->args);
return i;
}
void
fatal(const char *fmt, ...) {
VFmt fp;
fmtinstall('V', Vfmt);
fmtinstall('', Vfmt);
fp.fmt = fmt;
va_start(fp.args, fmt);
fprint(2, "%s: fatal: %V\n", argv0, &fp);
va_end(fp.args);
exit(1);
}

16
libstuff/util/freelater.c Normal file
View File

@ -0,0 +1,16 @@
/* Written by Kris Maglione <maglione.k at Gmail> */
/* Public domain */
#include <stdlib.h>
#include "util.h"
void*
freelater(void *p) {
static char* obj[16];
static long nobj;
int id;
id = nobj++ % nelem(obj);
free(obj[id]);
obj[id] = p;
return p;
}

View File

@ -1,13 +1,12 @@
/* Copyright ©2008-2010 Kris Maglione <fbsdaemon@gmail.com>
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "dat.h"
#include <ctype.h>
#include <string.h>
#include "fns.h"
#include <stuff/util.h>
#define strbcmp(str, const) (strncmp((str), (const), sizeof(const)-1))
static int
int
getbase(const char **s, long *sign) {
const char *p;
int ret;
@ -42,36 +41,3 @@ getbase(const char **s, long *sign) {
*sign = 0;
return ret;
}
bool
getlong(const char *s, long *ret) {
const char *end;
char *rend;
int base;
long sign;
end = s+strlen(s);
base = getbase(&s, &sign);
if(sign == 0)
return false;
*ret = sign * strtol(s, &rend, base);
return (end == rend);
}
bool
getulong(const char *s, ulong *ret) {
const char *end;
char *rend;
int base;
long sign;
end = s+strlen(s);
base = getbase(&s, &sign);
if(sign < 1)
return false;
*ret = strtoul(s, &rend, base);
return (end == rend);
}

14
libstuff/util/getint.c Normal file
View File

@ -0,0 +1,14 @@
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <stuff/util.h>
bool
getint(const char *s, int *ret) {
long l;
bool res;
res = getlong(s, &l);
*ret = l;
return res;
}

24
libstuff/util/getlong.c Normal file
View File

@ -0,0 +1,24 @@
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <stdlib.h>
#include <string.h>
#include <stuff/util.h>
bool
getlong(const char *s, long *ret) {
const char *end;
char *rend;
int base;
long sign;
if(s == nil)
return false;
end = s+strlen(s);
base = getbase(&s, &sign);
if(sign == 0)
return false;
*ret = sign * strtol(s, &rend, base);
return (end == rend);
}

24
libstuff/util/getulong.c Normal file
View File

@ -0,0 +1,24 @@
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <stdlib.h>
#include <string.h>
#include <stuff/util.h>
bool
getulong(const char *s, ulong *ret) {
const char *end;
char *rend;
int base;
long sign;
if(s == nil)
return false;
end = s+strlen(s);
base = getbase(&s, &sign);
if(sign < 1)
return false;
*ret = strtoul(s, &rend, base);
return (end == rend);
}

22
libstuff/util/grep.c Normal file
View File

@ -0,0 +1,22 @@
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "util.h"
void
grep(char **list, Reprog *re, int flags) {
char **p, **q;
int res;
q = list;
for(p=q; *p; p++) {
res = 0;
if(re)
res = regexec(re, *p, nil, 0);
if(res && !(flags & GInvert)
|| !res && (flags & GInvert))
*q++ = *p;
}
*q = nil;
}

23
libstuff/util/join.c Normal file
View File

@ -0,0 +1,23 @@
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <stdlib.h>
#include <fmt.h>
#include "util.h"
char*
join(char **list, char *sep) {
Fmt f;
char **p;
if(fmtstrinit(&f) < 0)
abort();
for(p=list; *p; p++) {
if(p != list)
fmtstrcpy(&f, sep);
fmtstrcpy(&f, *p);
}
return fmtstrflush(&f);
}

10
libstuff/util/max.c Normal file
View File

@ -0,0 +1,10 @@
/* Written by Kris Maglione <maglione.k at Gmail> */
/* Public domain */
#include "util.h"
int
max(int a, int b) {
if(a > b)
return a;
return b;
}

34
libstuff/util/mfatal.c Normal file
View File

@ -0,0 +1,34 @@
/* Written by Kris Maglione <maglione.k at Gmail> */
/* Public domain */
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "util.h"
/* Can't malloc */
void
mfatal(char *name, uint size) {
const char
couldnot[] = ": fatal: Could not ",
paren[] = "() ",
bytes[] = " bytes\n";
char buf[1024];
char sizestr[8];
int i;
i = sizeof sizestr;
do {
sizestr[--i] = '0' + (size%10);
size /= 10;
} while(size > 0);
strlcat(buf, argv0, sizeof buf);
strlcat(buf, couldnot, sizeof buf);
strlcat(buf, name, sizeof buf);
strlcat(buf, paren, sizeof buf);
strlcat(buf, sizestr+i, sizeof buf);
strlcat(buf, bytes, sizeof buf);
write(2, buf, strlen(buf));
exit(1);
}

10
libstuff/util/min.c Normal file
View File

@ -0,0 +1,10 @@
/* Written by Kris Maglione <maglione.k at Gmail> */
/* Public domain */
#include "util.h"
int
min(int a, int b) {
if(a < b)
return a;
return b;
}

View File

@ -0,0 +1,33 @@
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fmt.h>
#include "util.h"
char*
pathsearch(const char *path, const char *file, bool slashok) {
char *orig, *p, *s;
if(!slashok && strchr(file, '/') > file)
file = sxprint("%s/%s", getcwd(buffer, sizeof buffer), file);
else if(!strncmp(file, "./", 2))
file = sxprint("%s/%s", getcwd(buffer, sizeof buffer), file+2);
if(file[0] == '/') {
if(access(file, X_OK))
return strdup(file);
return nil;
}
orig = estrdup(path ? path : getenv("PATH"));
for(p=orig; (s=strtok(p, ":")); p=nil) {
s = smprint("%s/%s", s, file);
if(!access(s, X_OK))
break;
free(s);
}
free(orig);
return s;
}

14
libstuff/util/refree.c Normal file
View File

@ -0,0 +1,14 @@
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include <stdlib.h>
#include "util.h"
void
refree(Regex *r) {
free(r->regex);
free(r->regc);
r->regex = nil;
r->regc = nil;
}

16
libstuff/util/reinit.c Normal file
View File

@ -0,0 +1,16 @@
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
* See LICENSE file for license details.
*/
#include "util.h"
void
reinit(Regex *r, char *regx) {
refree(r);
if(regx[0] != '\0') {
r->regex = estrdup(regx);
r->regc = regcomp(regx);
}
}

Some files were not shown because too many files have changed in this diff Show More