/*
 * Pop-up menus.
 */

/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "dat.h"
#include "fns.h"

Client	*hiddenc[MAXHIDDEN];

int	numhidden;

int virt;
int reversehide = 1;

Client * currents[NUMVIRTUALS] =
{
	NULL, NULL, NULL, NULL, 
};

char	*b2items[NUMVIRTUALS+1] =
{
	"One",
	"Two",
	"Three",
	"Four",
	"Five",
	"Six",
	"Seven",
	"Eight",
	"Nine",
	"Ten",
	"Eleven",
	"Twelve",
	0,
};

Menu b2menu = 
{
	b2items,
};

char	*b3items[B3FIXED+MAXHIDDEN+1] =
{
	"New",
	"Reshape",
	"Move",
	"Delete",
	"Hide",
	0,
};

enum
{
	New,
	Reshape,
	Move,
	Delete,
	Hide
};

Menu	b3menu =
{
	b3items,
};

Menu	egg =
{
	version,
};

void
button(XButtonEvent *e)
{
	int n, shift;
	Client *c;
	Window dw;
	ScreenInfo *s;

	curtime = e->time;
	s = getscreen(e->root);
	if(s == 0)
		return;
	c = getclient(e->window, 0);
	if(c){
		if(debug) fprintf(stderr, "but: e x=%d y=%d c x=%d y=%d dx=%d dy=%d BORDR %d\n",
				e->x, e->y, c->x, c->y, c->dx, c->dy, BORDER);
		if(borderorient(c, e->x, e->y) != BorderUnknown){
			switch (e->button){
			case Button1:
			case Button2:
				reshape(c, e->button, pull, e);
				return;
			case Button3:
				move(c, Button3);
				return;
			default:
				return;
			}
		}
		e->x += c->x - BORDER;
		e->y += c->y - BORDER;
	} else if(e->window != e->root){
		if(debug) fprintf(stderr, "but no client: e x=%d y=%d\n",
				e->x, e->y);
		XTranslateCoordinates(dpy, e->window, s->root, e->x, e->y,
				&e->x, &e->y, &dw);
	}		
	switch (e->button){
	case Button1:
		if(c){
			XMapRaised(dpy, c->parent);
			top(c);
			active(c);
		}
		return;
	case Button2:
		if(c){
			XMapRaised(dpy, c->parent);
			active(c);
			XAllowEvents (dpy, ReplayPointer, curtime);
		} else if((e->state&(ShiftMask|ControlMask))==(ShiftMask|ControlMask)){
			menuhit(e, &egg);
		} else if(numvirtuals > 1 && (n = menuhit(e, &b2menu)) > -1) 
				button2(n);
		return;
	case Button3:
		break;
	case Button4:
		/* scroll up changes to previous virtual screen */
		if(!c && e->type == ButtonPress)
			if(numvirtuals > 1 && virt > 0)
				switch_to(virt - 1);
		return;
	case Button5:
		/* scroll down changes to next virtual screen */
		if(!c && e->type == ButtonPress)
			if(numvirtuals > 1 && virt < numvirtuals - 1)
				switch_to(virt + 1);
		return;
	default:
		return;
	}

	if(current && current->screen == s)
		cmapnofocus(s);
	switch (n = menuhit(e, &b3menu)){
	case New:
		spawn(s);
		break;
	case Reshape:
		reshape(selectwin(1, 0, s), Button3, sweep, 0);
		break;
	case Move:
		move(selectwin(0, 0, s), Button3);
		break;
	case Delete:
		shift = 0;
		c = selectwin(1, &shift, s);
		delete(c, shift);
		break;
	case Hide:
		hide(selectwin(1, 0, s));
		break;
	default:	/* unhide window */
		unhide(n - B3FIXED, 1);
		break;
	case -1:	/* nothing */
		break;
	}
	if(current && current->screen == s)
		cmapfocus(current);
}

void
spawn(ScreenInfo *s)
{
	/*
	 * ugly dance to cause sweeping for terminals.
	 * the very next window created will require sweeping.
	 * hope it's created by the program we're about to
	 * exec!
	 */
	isNew = 1;
	/*
	 * ugly dance to avoid leaving zombies. Could use SIGCHLD,
	 * but it's not very portable.
	 */
	if(fork() == 0){
		if(fork() == 0){
			close(ConnectionNumber(dpy));
			if(s->display[0] != '\0')
				putenv(s->display);
			signal(SIGINT, SIG_DFL);
			signal(SIGTERM, SIG_DFL);
			signal(SIGHUP, SIG_DFL);
			if(termprog != NULL){
				execl(shell, shell, "-c", termprog, (char*)0);
				fprintf(stderr, "rio: exec %s", shell);
				perror(" failed");
			}
			execlp("9term", "9term", scrolling ? "-ws" : "-w", (char*)0);
			execlp("xterm", "xterm", "-ut", (char*)0);
			perror("rio: exec 9term/xterm failed");
			exit(1);
		}
		exit(0);
	}
	wait((int *) 0);
}

void
reshape(Client *c, int but, int (*fn)(Client*, int, XButtonEvent *), XButtonEvent *e)
{
	int odx, ody;

	if(c == 0)
		return;
	odx = c->dx;
	ody = c->dy;
	if(fn(c, but, e) == 0)
		return;
	active(c);
	top(c);
	XRaiseWindow(dpy, c->parent);
	XMoveResizeWindow(dpy, c->parent, c->x-BORDER, c->y-BORDER,
					c->dx+2*BORDER, c->dy+2*BORDER);
	if(c->dx == odx && c->dy == ody)
		sendconfig(c);
	else
		XMoveResizeWindow(dpy, c->window, BORDER, BORDER, c->dx, c->dy);
}

void
move(Client *c, int but)
{
	if(c == 0)
		return;
	if(drag(c, but) == 0)
		return;
	active(c);
	top(c);
	XRaiseWindow(dpy, c->parent);
	XMoveWindow(dpy, c->parent, c->x-BORDER, c->y-BORDER);
	sendconfig(c);
}

void
delete(Client *c, int shift)
{
	if(c == 0)
		return;
	if((c->proto & Pdelete) && !shift)
		sendcmessage(c->window, wm_protocols, wm_delete, 0, 0);
	else
		XKillClient(dpy, c->window);		/* let event clean up */
}

void
hide(Client *c)
{
	if(c == 0 || numhidden == MAXHIDDEN)
		return;
	if(hidden(c)){
		fprintf(stderr, "rio: already hidden: %s\n", c->label);
		return;
	}
	XUnmapWindow(dpy, c->parent);
	XUnmapWindow(dpy, c->window);
	setstate(c, IconicState);
	if(c == current)
		nofocus();
	if(reversehide){
		memmove(hiddenc+1, hiddenc, numhidden*sizeof hiddenc[0]);
		memmove(b3items+B3FIXED+1, b3items+B3FIXED, numhidden*sizeof b3items[0]);
		hiddenc[0] = c;
		b3items[B3FIXED] = c->label;
	}else{
		hiddenc[numhidden] = c;
		b3items[B3FIXED+numhidden] = c->label;
	}
	numhidden++;
	b3items[B3FIXED+numhidden] = 0;
}

void
unhide(int n, int map)
{
	Client *c;
	int i;

	if(n >= numhidden){
		fprintf(stderr, "rio: unhide: n %d numhidden %d\n", n, numhidden);
		return;
	}
	c = hiddenc[n];
	if(!hidden(c)){
		fprintf(stderr, "rio: unhide: not hidden: %s(0x%x)\n",
			c->label, (int)c->window);
		return;
	}
	c->virt = virt;

	if(map){
		XMapWindow(dpy, c->window);
		XMapRaised(dpy, c->parent);
		setstate(c, NormalState);
		active(c);
		top(c);
	}

	numhidden--;
	for(i = n; i < numhidden; i++){
		hiddenc[i] = hiddenc[i+1];
		b3items[B3FIXED+i] = b3items[B3FIXED+i+1];
	}
	b3items[B3FIXED+numhidden] = 0;
}

void
unhidec(Client *c, int map)
{
	int i;

	for(i = 0; i < numhidden; i++)
		if(c == hiddenc[i]){
			unhide(i, map);
			return;
		}
	fprintf(stderr, "rio: unhidec: not hidden: %s(0x%x)\n",
		c->label, (int)c->window);
}

void
renamec(Client *c, char *name)
{
	int i;

	if(name == 0)
		name = "???";
	c->label = name;
	if(!hidden(c))
		return;
	for(i = 0; i < numhidden; i++)
		if(c == hiddenc[i]){
			b3items[B3FIXED+i] = name;
			return;
		}
}

void
button2(int n)
{
	switch_to(n);
	if(current)
		cmapfocus(current);
}

void
switch_to_c(int n, Client *c)
{
	if(c == 0)
		return;

	if(c->next)
		switch_to_c(n, c->next);

	if(c->parent == DefaultRootWindow(dpy))
		return;

	if(c->virt != virt && c->state == NormalState){
		XUnmapWindow(dpy, c->parent);
		XUnmapWindow(dpy, c->window);
		setstate(c, IconicState);
		if(c == current)
			nofocus();
	} else if(c->virt == virt && c->state == IconicState){
		int i;

		for(i = 0; i < numhidden; i++)
			if(c == hiddenc[i]) 
				break;

		if(i == numhidden){
			XMapWindow(dpy, c->window);
			XMapWindow(dpy, c->parent);
			setstate(c, NormalState);
			if(currents[virt] == c)
				active(c); 
		}
	}
}

void
switch_to(int n)
{
	if(n == virt)
		return;
	currents[virt] = current;
	virt = n;

	/* redundant when called from a menu switch
	 * but needed for scroll-button switches
	 */
	b2menu.lasthit = n;

	switch_to_c(n, clients);
	current = currents[virt];
}

void
initb2menu(int n)
{ 
	b2items[n] = 0;
}
