diff --git a/dvtm.c b/dvtm.c
index 2b7ebdc..10274a8 100644
--- a/dvtm.c
+++ b/dvtm.c
@@ -231,9 +231,20 @@ static char *title;
 
 #include "config.h"
 
+typedef struct {
+	unsigned int curtag, prevtag;
+	int nmaster[LENGTH(tags) + 1];
+	float mfact[LENGTH(tags) + 1];
+	Layout *layout[LENGTH(tags) + 1];
+	int barpos[LENGTH(tags) + 1];
+	int barlastpos[LENGTH(tags) + 1];
+	bool runinall[LENGTH(tags) + 1];
+} Pertag;
+
 /* global variables */
 static const char *dvtm_name = "dvtm";
 Screen screen = { .mfact = MFACT, .nmaster = NMASTER, .history = SCROLL_HISTORY };
+static Pertag pertag;
 static Client *stack = NULL;
 static Client *sel = NULL;
 static Client *lastsel = NULL;
@@ -310,15 +321,15 @@ updatebarpos(void) {
 static void
 hidebar(void) {
 	if (bar.pos != BAR_OFF) {
-		bar.lastpos = bar.pos;
-		bar.pos = BAR_OFF;
+		bar.lastpos = pertag.barlastpos[pertag.curtag] = bar.pos;
+		bar.pos = pertag.barpos[pertag.curtag] = BAR_OFF;
 	}
 }
 
 static void
 showbar(void) {
 	if (bar.pos == BAR_OFF)
-		bar.pos = bar.lastpos;
+		bar.pos = pertag.barpos[pertag.curtag] = bar.lastpos;
 }
 
 static void
@@ -350,7 +361,7 @@ drawbar(void) {
 		printw(TAG_SYMBOL, tags[i]);
 	}
 
-	attrset(runinall ? TAG_SEL : TAG_NORMAL);
+	attrset(pertag.runinall[pertag.curtag] ? TAG_SEL : TAG_NORMAL);
 	addstr(layout->symbol);
 	attrset(TAG_NORMAL);
 
@@ -400,7 +411,7 @@ draw_border(Client *c) {
 		return;
 	if (sel != c && c->urgent)
 		attrs = URGENT_ATTR;
-	if (sel == c || (runinall && !c->minimized))
+	if (sel == c || (pertag.runinall[pertag.curtag] && !c->minimized))
 		attrs = SELECTED_ATTR;
 
 	wattrset(c->window, attrs);
@@ -843,10 +854,34 @@ toggletag(const char *args[]) {
 	}
 }
 
+static void
+setpertag(void) {
+	screen.nmaster = pertag.nmaster[pertag.curtag];
+	screen.mfact = pertag.mfact[pertag.curtag];
+	layout = pertag.layout[pertag.curtag];
+	if (bar.pos != pertag.barpos[pertag.curtag]) {
+		bar.pos = pertag.barpos[pertag.curtag];
+		updatebarpos();
+	}
+	bar.lastpos = pertag.barlastpos[pertag.curtag];
+	runinall = pertag.runinall[pertag.curtag];
+}
+
 static void
 toggleview(const char *args[]) {
+	int i;
+
 	unsigned int newtagset = tagset[seltags] ^ (bitoftag(args[0]) & TAGMASK);
 	if (newtagset) {
+		if(newtagset == TAGMASK) {
+			pertag.prevtag = pertag.curtag;
+			pertag.curtag = 0;
+		} else if(!(newtagset & 1 << (pertag.curtag - 1))) {
+			pertag.prevtag = pertag.curtag;
+			for (i=0; !(newtagset &1 << i); i++) ;
+			pertag.curtag = i + 1;
+		}
+		setpertag();
 		tagset[seltags] = newtagset;
 		tagschanged();
 	}
@@ -854,9 +889,19 @@ toggleview(const char *args[]) {
 
 static void
 view(const char *args[]) {
+	int i;
+
 	unsigned int newtagset = bitoftag(args[0]) & TAGMASK;
 	if (tagset[seltags] != newtagset && newtagset) {
 		seltags ^= 1; /* toggle sel tagset */
+		pertag.prevtag = pertag.curtag;
+		if(args[0] == NULL)
+			pertag.curtag = 0;
+		else {
+			for (i = 0; (i < LENGTH(tags)) && (tags[i] != args[0]); i++) ;
+			pertag.curtag = i + 1;
+		}
+		setpertag();
 		tagset[seltags] = newtagset;
 		tagschanged();
 	}
@@ -864,7 +909,13 @@ view(const char *args[]) {
 
 static void
 viewprevtag(const char *args[]) {
+	unsigned int tmptag;
+
 	seltags ^= 1;
+	tmptag = pertag.prevtag;
+	pertag.prevtag = pertag.curtag;
+	pertag.curtag = tmptag;
+	setpertag();
 	tagschanged();
 }
 
@@ -887,7 +938,7 @@ keypress(int code) {
 		nodelay(stdscr, FALSE);
 	}
 
-	for (Client *c = runinall ? nextvisible(clients) : sel; c; c = nextvisible(c->next)) {
+	for (Client *c = pertag.runinall[pertag.curtag] ? nextvisible(clients) : sel; c; c = nextvisible(c->next)) {
 		if (is_content_visible(c)) {
 			c->urgent = false;
 			if (code == '\e')
@@ -897,7 +948,7 @@ keypress(int code) {
 			if (key != -1)
 				vt_keypress(c->term, key);
 		}
-		if (!runinall)
+		if (!pertag.runinall[pertag.curtag])
 			break;
 	}
 }
@@ -916,6 +967,21 @@ mouse_setup(void) {
 #endif /* CONFIG_MOUSE */
 }
 
+static void
+initpertag(void) {
+	int i;
+
+	pertag.curtag = pertag.prevtag = 1;
+	for(i=0; i <= LENGTH(tags); i++) {
+		pertag.nmaster[i] = screen.nmaster;
+		pertag.mfact[i] = screen.mfact;
+		pertag.layout[i] = layout;
+		pertag.barpos[i] = bar.pos;
+		pertag.barlastpos[i] = bar.lastpos;
+		pertag.runinall[i] = runinall;
+	}
+}
+
 static bool
 checkshell(const char *shell) {
 	if (shell == NULL || *shell == '\0' || *shell != '/')
@@ -961,6 +1027,7 @@ setup(void) {
 		}
 		colors[i].pair = vt_color_reserve(colors[i].fg, colors[i].bg);
 	}
+	initpertag();
 	resize_screen();
 	struct sigaction sa;
 	memset(&sa, 0, sizeof sa);
@@ -1351,6 +1418,7 @@ setlayout(const char *args[]) {
 			return;
 		layout = &layouts[i];
 	}
+	pertag.layout[pertag.curtag] = layout;
 	arrange();
 }
 
@@ -1371,6 +1439,7 @@ incnmaster(const char *args[]) {
 		if (screen.nmaster < 1)
 			screen.nmaster = 1;
 	}
+	pertag.nmaster[pertag.curtag] = screen.nmaster;
 	arrange();
 }
 
@@ -1393,6 +1462,7 @@ setmfact(const char *args[]) {
 		else if (screen.mfact > 0.9)
 			screen.mfact = 0.9;
 	}
+	pertag.mfact[pertag.curtag] = screen.mfact;
 	arrange();
 }
 
@@ -1417,10 +1487,10 @@ static void
 togglebarpos(const char *args[]) {
 	switch (bar.pos == BAR_OFF ? bar.lastpos : bar.pos) {
 	case BAR_TOP:
-		bar.pos = BAR_BOTTOM;
+		bar.pos = pertag.barpos[pertag.curtag] = BAR_BOTTOM;
 		break;
 	case BAR_BOTTOM:
-		bar.pos = BAR_TOP;
+		bar.pos = pertag.barpos[pertag.curtag] = BAR_TOP;
 		break;
 	}
 	updatebarpos();
@@ -1475,7 +1545,7 @@ togglemouse(const char *args[]) {
 
 static void
 togglerunall(const char *args[]) {
-	runinall = !runinall;
+	pertag.runinall[pertag.curtag] = !pertag.runinall[pertag.curtag];
 	drawbar();
 	draw_all();
 }
