/*
 * 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, 0);
				fprintf(stderr, "rio: exec %s", shell);
				perror(" failed");
			}
			execlp("9term", "9term", scrolling ? "-ws" : "-w", 0);
			execlp("xterm", "xterm", "-ut", 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 && 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;
}
