/* Copyright (c) 1999 Decklin Foster <fosterd@hartwick.edu>
   Copyright (c) 2000 Linus Nilsson <d96ln@efd.lth.se> */

#include "yawm.h"
#include <stdlib.h>

Client *find_client(Window w, int from_parent) {
	Client *c;
	
	if (w && w != root) {
		for (c = head_client; c; c = c->next) {
			if (from_parent == -1 && (w == c->parent || 
						  w == c->window)) {
				return c;
			}
			else if (w == (from_parent ? c->parent : c->window)) {
				return c;
			}
		}
	}
	return NULL;
}

void set_wm_state(Client *c, int state) {
	long data[2];
	
	data[0] = (long) state;
	data[1] = None; /* icon window */
	
	if (c && c->window) {
		XChangeProperty(dpy, c->window, xa_wm_state, xa_wm_state,
				32, PropModeReplace, (unsigned char *)data, 2);
	}
}

int wm_state(Client *c) {
	Atom real_type;
	int real_format, state;
	unsigned long n, extra;
	unsigned char *data;
	
	if ((XGetWindowProperty(dpy, c->window, xa_wm_state, 0L, 2L, False,
				AnyPropertyType, &real_type, &real_format, &n,
				&extra, &data) == Success) && n) {
		state = *(int *)data;
		XFree(data);
		return state;
	} 
	else {
		return WithdrawnState;
	}
}

void send_config(Client *c) {
	XConfigureEvent ce;

	ce.type = ConfigureNotify;
	ce.event = c->window;
	ce.window = c->window;
	ce.x = c->x;
	ce.y = c->y;
	ce.width = c->width;
	ce.height = c->height;
	ce.border_width = 0;
	ce.above = None;
	ce.override_redirect = 0;

	XSendEvent(dpy, c->window, False, StructureNotifyMask, (XEvent *) &ce);
}

void remove_client(Client *c, int from_cleanup) {
	Client *p;

	XGrabServer(dpy);

	if (from_cleanup) {
		if (wm_state(c) == IconicState); 
		XMapWindow(dpy, c->window);
	} 
	else {
		set_wm_state(c, WithdrawnState);
	}
	
	XRemoveFromSaveSet(dpy, c->window);
	XReparentWindow(dpy, c->window, root, c->x, c->y);
 	if (c->window) XSetWindowBorderWidth(dpy, c->window, 1);
	XDestroyWindow(dpy, c->parent);

	if (head_client == c) {
		head_client = c->next;
		if (c->next) {
			c->next->prev = c->prev;
		}
	}
	else {
		for (p = head_client; p && p->next; p = p->next) {
			if (p->next == c) {
				p->next = c->next;
			}
		}
		if (c && p) {
			p->prev = c->prev;
		}
	}

	if (c->name) {
		XFree(c->name);
	}
	if (c->size) {
		XFree(c->size);
	}
	free(c);
	XSync(dpy, False);
	XUngrabServer(dpy);
}

void redraw(Client *c) {
        GC tmp_gc;
	
	if (c == focused_client) {
		XSetWindowBackground(dpy, c->parent, focus_bg.pixel);
		XClearWindow(dpy, c->parent);
		tmp_gc = focus_string_gc;
	}
	else {
		XSetWindowBackground(dpy, c->parent, bg.pixel);
		XClearWindow(dpy, c->parent);
		tmp_gc = string_gc;
	}

	XDrawLine(dpy, c->parent, border_gc,
		  0, 
		  theight(c) - opt_bw + opt_bw/2,
		  c->width, 
		  theight(c) - opt_bw + opt_bw/2);
	
	/* Draw maximize-button */
	XDrawRectangle(dpy, c->parent, tmp_gc,
		       c->width - theight(c) + 4,
		       2,
		       theight(c)-6, 3);
	XDrawRectangle(dpy, c->parent, tmp_gc,
		       c->width - theight(c) + 4,
		       2,
		       theight(c)-6, theight(c)-6);
	
	/* Draw minimize-button */
	XDrawRectangle(dpy, c->parent, tmp_gc,
		       c->width - 2*theight(c)+5,
		       2 + theight(c) - 9,
		       theight(c)-6, 3);

	/* Draw close/killbutton */
	XDrawLine(dpy, c->parent, tmp_gc,
		  2, 2, theight(c)-5, theight(c)-5);
	XDrawLine(dpy, c->parent, tmp_gc,
		  2, theight(c)-5, theight(c)-5, 2);

	/* Write name */
	if (c == focused_client) {
		tmp_gc = focus_string_gc;
	}
	else {
		tmp_gc = string_gc;
	}
	if (c->name) {
		XDrawString(dpy, c->parent, tmp_gc,
			    SPACE + theight(c),
			    SPACE + font->ascent, 
			    c->name, 
			    strlen(c->name));
	}
}

#ifdef SHAPE
void set_shape(Client *c) {
	int n, order;
	XRectangle *rect;

	rect = XShapeGetRectangles(dpy, c->window, ShapeBounding, &n, &order);
	if (n > 1) XShapeCombineShape(dpy,
				      c->parent, ShapeBounding, 0, theight(c),
				      c->window, ShapeBounding, ShapeSet);
	XFree(rect);
}
#endif

void send_wm_delete(Client *c) {
	int i, n, found = 0;
	Atom *protocols;
	
	if (c) {
		if (XGetWMProtocols(dpy, c->window, &protocols, &n)) {
			for (i=0; i<n; i++) { 
				if (protocols[i] == xa_wm_delete) {
					found++;
				}
			}
		}
		
		if (found && c->window) {
			send_xmessage(c->window, xa_wm_protos, xa_wm_delete);
		}
		else if (c->window) {
			XKillClient(dpy, c->window);
		}
	}
}

int send_xmessage(Window w, Atom a, long x) {
	XEvent ev;
	
	ev.type = ClientMessage;
	ev.xclient.window = w;
	ev.xclient.message_type = a;
	ev.xclient.format = 32;
	ev.xclient.data.l[0] = x;
	ev.xclient.data.l[1] = CurrentTime;
	
	return XSendEvent(dpy, w, False, NoEventMask, &ev);
}


syntax highlighted by Code2HTML, v. 0.9.1