/*
 * Pop-up menus.
 */

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