/* Copyright ©2007-2010 Kris Maglione <jg@suckless.org>
 * See LICENSE file for license details.
 */

#ifdef VARARGCK
# pragma varargck	argpos	debug	2
# pragma varargck	argpos	dprint	1
# pragma varargck	argpos	event	1
# pragma varargck	argpos	warning	1
#
# pragma varargck	type	"a"	Area*	
# pragma varargck	type	"C"	Client*	
# pragma varargck	type	"r"	void
#endif

#define _cond(cond, n) (cond) && __alive++ == n
#define _cont(cont) (void)(__alive--, cont)

#define with(type, var) \
	for(type var=(type)-1; (var == (type)-1) && ((var=0) || true);)

/* Grotesque, but worth it. */

#define foreach_area(v, s, a) \
	with(int, __alive)                            \
	with(Area*, __anext)                          \
	for(s=0; _cond(s <= nscreens, 0); _cont(s++)) \
		for((a)=(s < nscreens ? (v)->areas[s] : v->floating), __anext=(a)->next; _cond(a, 1); _cont(((a)=__anext) && (__anext=(a)->next)))

#define foreach_column(v, s, a) \
	with(int, __alive)                           \
	with(Area*, __anext)                         \
	for(s=0; _cond(s < nscreens, 0); _cont(s++)) \
		for((a)=(v)->areas[s], __anext=(a)->next; _cond(a, 1); _cont(((a)=__anext) && (__anext=(a)->next)))

#define foreach_frame(v, s, a, f) \
	with(Frame*, __fnext)     \
	foreach_area(v, s, a)     \
		for((void)(((f)=(a)->frame) && (__fnext=(f)->anext)); _cond(f, 2); _cont(((f)=__fnext) && (__fnext=(f)->anext)))

#define btassert(arg, cond) \
	(cond ? fprint(1, __FILE__":%d: failed assertion: " #cond "\n", __LINE__), backtrace(arg), true : false)

/* area.c */
int	afmt(Fmt*);
void	area_attach(Area*, Frame*);
Area*	area_create(View*, Area *pos, int scrn, uint w);
void	area_destroy(Area*);
void	area_detach(Frame*);
Area*	area_find(View*, Rectangle, int, bool);
void	area_focus(Area*);
int	area_idx(Area*);
void	area_moveto(Area*, Frame*);
char*	area_name(Area*);
Client*	area_selclient(Area*);
void	area_setsel(Area*, Frame*);

/* bar.c */
Bar*	bar_create(Bar**, const char*);
void	bar_destroy(Bar**, Bar*);
void	bar_draw(WMScreen*);
Bar*	bar_find(Bar*, const char*);
void	bar_init(WMScreen*);
void	bar_load(Bar*);
void	bar_resize(WMScreen*);
void	bar_sety(WMScreen*, int);
void	bar_setbounds(WMScreen*, int, int);

/* client.c */
int	Cfmt(Fmt *f);
bool	client_applytags(Client*, const char*);
void	client_configure(Client*);
Client*	client_create(XWindow, XWindowAttributes*);
void	client_destroy(Client*);
char*	client_extratags(Client*);
bool	client_floats_p(Client*);
void	client_focus(Client*);
Frame*	client_groupframe(Client*, View*);
void	client_kill(Client*, bool);
void	client_manage(Client*);
void	client_map(Client*);
void	client_message(Client*, char*, long);
void	client_prop(Client*, Atom);
void	client_reparent(Client*, Window*, Point);
void	client_resize(Client*, Rectangle);
void	client_setcursor(Client*, Cursor);
void	client_seturgent(Client*, int, int);
void	client_setviews(Client*, char**);
void	client_unmap(Client*, int state);
Frame*	client_viewframe(Client *c, View *v);
char*	clientname(Client*);
void	focus(Client*, bool restack);
void	fullscreen(Client*, int, long);
Client*	group_leader(Group*);
int	map_frame(Client*);
Client*	selclient(void);
int	unmap_frame(Client*);
void	update_class(Client*);
Client*	win2client(XWindow);
Rectangle	client_grav(Client*, Rectangle);

/* column.c */
bool	column_setmode(Area*, const char*);
char*	column_getmode(Area*);
void	column_arrange(Area*, bool dirty);
void	column_attach(Area*, Frame*);
void	column_attachrect(Area*, Frame*, Rectangle);
void	column_detach(Frame*);
void	column_frob(Area*);
void	column_insert(Area*, Frame*, Frame*);
int	column_minwidth(void);
Area*	column_new(View*, Area*, int, uint);
void	column_remove(Frame*);
void	column_resize(Area*, int);
void	column_resizeframe(Frame*, Rectangle);
void	column_settle(Area*);
void	div_draw(Divide*);
void	div_set(Divide*, int x);
void	div_update_all(void);
bool	find(Area**, Frame**, int, bool, bool);
int	stack_count(Frame*, int*);
Frame*	stack_find(Area*, Frame*, int, bool);

/* error.c */
#define waserror() setjmp(pusherror())
void	error(char*, ...);
void	nexterror(void);
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	print_focus(const char*, Client*, const char*);
void	xtime_kludge(void);

/* ewmh.c */
int	ewmh_clientmessage(XClientMessageEvent*);
void	ewmh_destroyclient(Client*);
void	ewmh_framesize(Client*);
void	ewmh_getstrut(Client*);
void	ewmh_getwintype(Client*);
void	ewmh_init(void);
void	ewmh_initclient(Client*);
void	ewmh_pingclient(Client*);
int	ewmh_prop(Client*, Atom);
long	ewmh_protocols(Window*);
void	ewmh_updateclient(Client*);
void	ewmh_updateclientlist(void);
void	ewmh_updateclients(void);
void	ewmh_updatestacking(void);
void	ewmh_updatestate(Client*);
void	ewmh_updateview(void);
void	ewmh_updateviews(void);

/* float.c */
void	float_arrange(Area*);
void	float_attach(Area*, Frame*);
void	float_detach(Frame*);
void	float_resizeframe(Frame*, Rectangle);
Vector_rect*	unique_rects(Vector_rect*, Rectangle);
Rectangle	max_rect(Vector_rect*);

/* frame.c */
Frame*	frame_create(Client*, View*);
int	frame_delta_h(void);
void	frame_draw(Frame*);
void	frame_draw_all(void);
void	frame_focus(Frame*);
uint	frame_idx(Frame*);
void	frame_insert(Frame*, Frame *pos);
void	frame_remove(Frame*);
void	frame_resize(Frame*, Rectangle);
bool	frame_restack(Frame*, Frame*);
void	frame_swap(Frame*, Frame*);
int	ingrabbox_p(Frame*, int x, int y);
void	move_focus(Frame*, Frame*);
Rectangle constrain(Rectangle, int);
Rectangle frame_client2rect(Client*, Rectangle, bool);
WinHints  frame_gethints(Frame*);
Rectangle frame_hints(Frame*, Rectangle, Align);
Rectangle frame_rect2client(Client*, Rectangle, bool);

/* fs.c */
void	fs_attach(Ixp9Req*);
void	fs_clunk(Ixp9Req*);
void	fs_create(Ixp9Req*);
void	fs_flush(Ixp9Req*);
void	fs_freefid(Fid*);
void	fs_open(Ixp9Req*);
void	fs_read(Ixp9Req*);
void	fs_remove(Ixp9Req*);
void	fs_stat(Ixp9Req*);
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);
void	update_keys(void);

/* main.c */
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*);
char*	msg_debug(IxpMsg*);
char*	msg_getword(IxpMsg*);
char*	msg_parsecolors(IxpMsg*, CTuple*);
char*	msg_selectarea(Area*, IxpMsg*);
char*	msg_sendclient(View*, IxpMsg*, bool swap);
char*	readctl_client(Client*);
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*, ...);
void	dwrite(int, void*, int, bool);
bool	setdebug(int);
void	vdebug(int, const char*, va_list);

/* mouse.c */
Window*	constraintwin(Rectangle);
void	destroyconstraintwin(Window*);
void	grab_button(XWindow, uint button, ulong mod);
void	mouse_checkresize(Frame*, Point, bool);
void	mouse_movegrabbox(Client*, bool);
void	mouse_resize(Client*, Align, bool);
void	mouse_resizecol(Divide*);
bool	readmotion(Point*);
int	readmouse(Point*, uint*);
Align	snap_rect(const Rectangle *rects, int num, Rectangle *current, Align *mask, int snapw);

/* print.c */
int	Ffmt(Fmt*);

/* printevent.c */
void	printevent(XEvent*);

/* root.c */
void	root_init(void);

/* screen.c */
void*	findthing(Rectangle, int, Vector_ptr*, Rectangle(*)(void*), bool);
int	ownerscreen(Rectangle);

/* rule.c */
void	trim(char *str, const char *chars);
void	update_rules(Rule**, const char*);

/* view.c */
void	view_arrange(View*);
void	view_attach(View*, Frame*);
View*	view_create(const char*);
void	view_destroy(View*);
void	view_detach(Frame*);
Area*	view_findarea(View*, int, int, bool);
void	view_focus(WMScreen*, View*);
bool	view_fullscreen_p(View*, int);
char*	view_index(View*);
void	view_init(View*, int iscreen);
char**	view_names(void);
uint	view_newcolwidth(View*, int i);
void	view_restack(View*);
void	view_scale(View*, int, int);
Client*	view_selclient(View*);
void	view_select(const char*);
void	view_update(View*);
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);

/* xdnd.c */
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*);

