add virtual desktop patch from andrey
diff --git a/src/cmd/rio/client.c b/src/cmd/rio/client.c
index 22d74dd..077106b 100644
--- a/src/cmd/rio/client.c
+++ b/src/cmd/rio/client.c
@@ -166,6 +166,7 @@
 	c->cmapwins = 0;
 	c->wmcmaps = 0;
 	c->next = clients;
+	c->virt = virt;
 	clients = c;
 	return c;
 }
diff --git a/src/cmd/rio/dat.h b/src/cmd/rio/dat.h
index df4f1ea..e590384 100644
--- a/src/cmd/rio/dat.h
+++ b/src/cmd/rio/dat.h
@@ -5,6 +5,7 @@
 #define	INSET		_inset
 #define MAXHIDDEN	128
 #define B3FIXED 	5
+#define NUMVIRTUALS	12
 
 #define AllButtonMask	(Button1Mask|Button2Mask|Button3Mask \
 			|Button4Mask|Button5Mask)
@@ -46,6 +47,7 @@
 	int 		is9term;
 	int 		hold;
 	int 		proto;
+	int			virt;
 
 	char		*label;
 	char		*instance;
@@ -146,6 +148,7 @@
 extern int			curtime;
 extern int			debug;
 extern int			solidsweep;
+extern int			numvirtuals;
 
 extern Atom		exit_rio;
 extern Atom		restart_rio;
@@ -161,12 +164,16 @@
 /* client.c */
 extern Client		*clients;
 extern Client		*current;
+extern Client		*currents[];
 
 /* menu.c */
 extern Client		*hiddenc[];
 extern int 			numhidden;
+extern char 		*b2items[];
+extern Menu 		b2menu;
 extern char 		*b3items[];
 extern Menu 		b3menu;
+extern int			virt;
 
 /* manage.c */
 extern int			isNew;
diff --git a/src/cmd/rio/event.c b/src/cmd/rio/event.c
index 5b13e87..2e72889 100644
--- a/src/cmd/rio/event.c
+++ b/src/cmd/rio/event.c
@@ -514,7 +514,7 @@
 			return BorderWSW;
 		}
 		if (y > CORNER &&
-	        y < (c->dy + 2*BORDER) - CORNER) {
+			y < (c->dy + 2*BORDER) - CORNER) {
 			if (debug) fprintf(stderr, "left\n");
 			return BorderW;
 		}
@@ -551,7 +551,7 @@
 			return BorderSSE;
 		}
 	} else if (x > CORNER &&
-		       x < (c->dx + 2*BORDER) - CORNER) {
+			x < (c->dx + 2*BORDER) - CORNER) {
 		if (y <= BORDER) {
 			if (debug) fprintf(stderr, "top\n");
 			return BorderN;
diff --git a/src/cmd/rio/fns.h b/src/cmd/rio/fns.h
index 59422d6..a9693f4 100644
--- a/src/cmd/rio/fns.h
+++ b/src/cmd/rio/fns.h
@@ -71,6 +71,12 @@
 void	unhide();
 void	unhidec();
 void	renamec();
+void	button2();
+void	initb2menu();
+void	switch_to();
+void	switch_to_c();
+
+
 
 /* client.c */
 void	setactive();
diff --git a/src/cmd/rio/grab.c b/src/cmd/rio/grab.c
index dc1e2e5..3a1f031 100644
--- a/src/cmd/rio/grab.c
+++ b/src/cmd/rio/grab.c
@@ -366,8 +366,8 @@
 		break;
 	}
 	if (!init
-	    || xoff < 0 || (xcorn && xoff > CORNER) || (!xcorn && xoff > BORDER)
-	    || yoff < 0 || (ycorn && yoff > CORNER) || (!ycorn && yoff > BORDER)) {
+		|| xoff < 0 || (xcorn && xoff > CORNER) || (!xcorn && xoff > BORDER)
+		|| yoff < 0 || (ycorn && yoff > CORNER) || (!ycorn && yoff > BORDER)) {
 		xoff = 0;
 		yoff = 0;
 		init = 0;
@@ -385,8 +385,8 @@
 	}
 
 	/* remember requested size;
-           * after applying size hints we may have to correct position
-	  */
+	 * after applying size hints we may have to correct position
+	 */
 	rdx = sx*dx;
 	rdy = sy*dy;
 
diff --git a/src/cmd/rio/main.c b/src/cmd/rio/main.c
index d2da22b..0e64905 100644
--- a/src/cmd/rio/main.c
+++ b/src/cmd/rio/main.c
@@ -38,6 +38,7 @@
 int 			signalled;
 int 			num_screens;
 int			solidsweep = 0;
+int			numvirtuals = 0;
 
 Atom		exit_rio;
 Atom		restart_rio;
@@ -65,7 +66,7 @@
 void
 usage(void)
 {
-	fprintf(stderr, "usage: rio [-grey] [-version] [-font fname] [-term prog] [exit|restart]\n");
+	fprintf(stderr, "usage: rio [-grey] [-version] [-font fname] [-term prog] [-virtuals num] [exit|restart]\n");
 	exit(1);
 }
 
@@ -99,7 +100,13 @@
 		}
 		else if (strcmp(argv[i], "-term") == 0 && i+1<argc)
 			termprog = argv[++i];
-		else if (strcmp(argv[i], "-version") == 0) {
+		else if (strcmp(argv[i], "-virtuals") == 0 && i+1<argc) {
+			numvirtuals = atoi(argv[++i]);
+			if(numvirtuals < 0 || numvirtuals > 12) {
+				fprintf(stderr, "rio: wrong number of virtual displays, defaulting to 4\n");
+				numvirtuals = 4;
+			}
+		} else if (strcmp(argv[i], "-version") == 0) {
 			fprintf(stderr, "%s", version[0]);
 			if (PATCHLEVEL > 0)
 				fprintf(stderr, "; patch level %d", PATCHLEVEL);
@@ -197,6 +204,8 @@
 	for (i = 0; i < num_screens; i++)
 		initscreen(&screens[i], i, background);
 
+	initb2menu(numvirtuals);
+
 	/* set selection so that 9term knows we're running */
 	curtime = CurrentTime;
 	XSetSelectionOwner(dpy, _rio_running, screens[0].menuwin, timestamp());
diff --git a/src/cmd/rio/menu.c b/src/cmd/rio/menu.c
index 81ad960..d313f5e 100644
--- a/src/cmd/rio/menu.c
+++ b/src/cmd/rio/menu.c
@@ -14,6 +14,35 @@
 
 int	numhidden;
 
+int virt;
+
+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",
@@ -80,8 +109,14 @@
 		}
 		return;
 	case Button2:
-		if ((e->state&(ShiftMask|ControlMask))==(ShiftMask|ControlMask))
+		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;
 	default:
 		return;
@@ -130,7 +165,7 @@
 	 */
 	isNew = 1;
 	/*
-	 * ugly dance to avoid leaving zombies.  Could use SIGCHLD,
+	 * ugly dance to avoid leaving zombies. Could use SIGCHLD,
 	 * but it's not very portable.
 	 */
 	if (fork() == 0) {
@@ -286,3 +321,60 @@
 			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;
+	switch_to_c(n, clients);
+	current = currents[virt];
+}
+
+void
+initb2menu(int n)
+{ 
+	b2items[n] = 0;
+}