/*
 * Pop-up menus.
 */

/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
#define _SVID_SOURCE 1	/* putenv in glibc */
#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;
}
