/* Settings */
#if !PERTAG_PATCH
static int enablegaps = 1;
#endif // PERTAG_PATCH

void
setgaps(int oh, int ov, int ih, int iv)
{
	if (oh < 0)
		oh = 0;
	if (ov < 0)
		ov = 0;
	if (ih < 0)
		ih = 0;
	if (iv < 0)
		iv = 0;

	selmon->gappoh = oh;
	selmon->gappov = ov;
	selmon->gappih = ih;
	selmon->gappiv = iv;
	arrange(selmon);
}

void
togglegaps(const Arg *arg)
{
#if PERTAG_PATCH
	selmon->pertag->enablegaps[selmon->pertag->curtag] =
	        !selmon->pertag->enablegaps[selmon->pertag->curtag];
#else
	enablegaps = !enablegaps;
#endif // PERTAG_PATCH
	arrange(NULL);
}

void
defaultgaps(const Arg *arg)
{
	setgaps(gappoh, gappov, gappih, gappiv);
}

void
incrgaps(const Arg *arg)
{
	setgaps(selmon->gappoh + arg->i, selmon->gappov + arg->i, selmon->gappih + arg->i,
	        selmon->gappiv + arg->i);
}

void
incrigaps(const Arg *arg)
{
	setgaps(selmon->gappoh, selmon->gappov, selmon->gappih + arg->i, selmon->gappiv + arg->i);
}

void
incrogaps(const Arg *arg)
{
	setgaps(selmon->gappoh + arg->i, selmon->gappov + arg->i, selmon->gappih, selmon->gappiv);
}

void
incrohgaps(const Arg *arg)
{
	setgaps(selmon->gappoh + arg->i, selmon->gappov, selmon->gappih, selmon->gappiv);
}

void
incrovgaps(const Arg *arg)
{
	setgaps(selmon->gappoh, selmon->gappov + arg->i, selmon->gappih, selmon->gappiv);
}

void
incrihgaps(const Arg *arg)
{
	setgaps(selmon->gappoh, selmon->gappov, selmon->gappih + arg->i, selmon->gappiv);
}

void
incrivgaps(const Arg *arg)
{
	setgaps(selmon->gappoh, selmon->gappov, selmon->gappih, selmon->gappiv + arg->i);
}

void
getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc)
{
	unsigned int n, oe, ie;
#if PERTAG_PATCH
	oe = ie = selmon->pertag->enablegaps[selmon->pertag->curtag];
#else
	oe = ie = enablegaps;
#endif // PERTAG_PATCH
	Client *c;

	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
		;
	if (smartgaps && n == 1) {
		oe = 0; // outer gaps disabled when only one client
	}

	*oh = m->gappoh * oe; // outer horizontal gap
	*ov = m->gappov * oe; // outer vertical gap
	*ih = m->gappih * ie; // inner horizontal gap
	*iv = m->gappiv * ie; // inner vertical gap
	*nc = n; // number of clients
}

void
getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr)
{
	unsigned int n;
	float mfacts = 0, sfacts = 0;
	int mtotal = 0, stotal = 0;
	Client *c;

	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
		if (n < m->nmaster)
			mfacts += c->cfact;
		else
			sfacts += c->cfact;

	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
		if (n < m->nmaster)
			mtotal += msize * (c->cfact / mfacts);
		else
			stotal += ssize * (c->cfact / sfacts);

	*mf = mfacts; // total factor of master area
	*sf = sfacts; // total factor of stack area
	*mr = msize - mtotal; // the remainder (rest) of pixels after a cfacts master split
	*sr = ssize - stotal; // the remainder (rest) of pixels after a cfacts stack split
}

/***
 * Layouts
 */

/*
 * Bottomstack layout + gaps
 * https://dwm.suckless.org/patches/bottomstack/
 */
static void
bstack(Monitor *m)
{
	unsigned int i, n;
	int oh, ov, ih, iv;
	int mx = 0, my = 0, mh = 0, mw = 0;
	int sx = 0, sy = 0, sh = 0, sw = 0;
	float mfacts, sfacts;
	int mrest, srest;
	Client *c;

	getgaps(m, &oh, &ov, &ih, &iv, &n);
	if (n == 0)
		return;

	sx = mx = m->wx + ov;
	sy = my = m->wy + oh;
	sh = mh = m->wh - 2 * oh;
	mw = m->ww - 2 * ov - iv * (MIN(n, m->nmaster) - 1);
	sw = m->ww - 2 * ov - iv * (n - m->nmaster - 1);

	if (m->nmaster && n > m->nmaster) {
		sh = (mh - ih) * (1 - m->mfact);
		mh = mh - ih - sh;
		sx = mx;
		sy = my + mh + ih;
	}

	getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);

	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
		if (i < m->nmaster) {
			resize(c, mx, my,
			       mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2 * c->bw),
			       mh - (2 * c->bw), 0);
			mx += WIDTH(c) + iv;
		}
		else {
			resize(c, sx, sy,
			       sw * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0)
			               - (2 * c->bw),
			       sh - (2 * c->bw), 0);
			sx += WIDTH(c) + iv;
		}
	}
}

static void
bstackhoriz(Monitor *m)
{
	unsigned int i, n;
	int oh, ov, ih, iv;
	int mx = 0, my = 0, mh = 0, mw = 0;
	int sx = 0, sy = 0, sh = 0, sw = 0;
	float mfacts, sfacts;
	int mrest, srest;
	Client *c;

	getgaps(m, &oh, &ov, &ih, &iv, &n);
	if (n == 0)
		return;

	sx = mx = m->wx + ov;
	sy = my = m->wy + oh;
	mh = m->wh - 2 * oh;
	sh = m->wh - 2 * oh - ih * (n - m->nmaster - 1);
	mw = m->ww - 2 * ov - iv * (MIN(n, m->nmaster) - 1);
	sw = m->ww - 2 * ov;

	if (m->nmaster && n > m->nmaster) {
		sh = (mh - ih) * (1 - m->mfact);
		mh = mh - ih - sh;
		sy = my + mh + ih;
		sh = m->wh - mh - 2 * oh - ih * (n - m->nmaster);
	}

	getfacts(m, mw, sh, &mfacts, &sfacts, &mrest, &srest);

	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
		if (i < m->nmaster) {
			resize(c, mx, my,
			       mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2 * c->bw),
			       mh - (2 * c->bw), 0);
			mx += WIDTH(c) + iv;
		}
		else {
			resize(c, sx, sy, sw - (2 * c->bw),
			       sh * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0)
			               - (2 * c->bw),
			       0);
			sy += HEIGHT(c) + ih;
		}
	}
}

/*
 * Centred master layout + gaps
 * https://dwm.suckless.org/patches/centeredmaster/
 */
void
centeredmaster(Monitor *m)
{
	unsigned int i, n;
	int oh, ov, ih, iv;
	int mx = 0, my = 0, mh = 0, mw = 0;
	int lx = 0, ly = 0, lw = 0, lh = 0;
	int rx = 0, ry = 0, rw = 0, rh = 0;
	float mfacts = 0, lfacts = 0, rfacts = 0;
	int mtotal = 0, ltotal = 0, rtotal = 0;
	int mrest = 0, lrest = 0, rrest = 0;
	Client *c;

	getgaps(m, &oh, &ov, &ih, &iv, &n);
	if (n == 0)
		return;

	/* initialize areas */
	mx = m->wx + ov;
	my = m->wy + oh;
	mh = m->wh - 2 * oh - ih * ((!m->nmaster ? n : MIN(n, m->nmaster)) - 1);
	mw = m->ww - 2 * ov;
	lh = m->wh - 2 * oh - ih * (((n - m->nmaster) / 2) - 1);
	rh = m->wh - 2 * oh - ih * (((n - m->nmaster) / 2) - ((n - m->nmaster) % 2 ? 0 : 1));

	if (m->nmaster && n > m->nmaster) {
		/* go mfact box in the center if more than nmaster clients */
		if (n - m->nmaster > 1) {
			/* ||<-S->|<---M--->|<-S->|| */
			mw = (m->ww - 2 * ov - 2 * iv) * m->mfact;
			lw = (m->ww - mw - 2 * ov - 2 * iv) / 2;
			rw = (m->ww - mw - 2 * ov - 2 * iv) - lw;
			mx += lw + iv;
		}
		else {
			/* ||<---M--->|<-S->|| */
			mw = (mw - iv) * m->mfact;
			lw = 0;
			rw = m->ww - mw - iv - 2 * ov;
		}
		lx = m->wx + ov;
		ly = m->wy + oh;
		rx = mx + mw + iv;
		ry = m->wy + oh;
	}

	/* calculate facts */
	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) {
		if (!m->nmaster || n < m->nmaster)
			mfacts += c->cfact;
		else if ((n - m->nmaster) % 2)
			lfacts += c->cfact; // total factor of left hand stack area
		else
			rfacts += c->cfact; // total factor of right hand stack area
	}

	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
		if (!m->nmaster || n < m->nmaster)
			mtotal += mh * (c->cfact / mfacts);
		else if ((n - m->nmaster) % 2)
			ltotal += lh * (c->cfact / lfacts);
		else
			rtotal += rh * (c->cfact / rfacts);

	mrest = mh - mtotal;
	lrest = lh - ltotal;
	rrest = rh - rtotal;

	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
		if (!m->nmaster || i < m->nmaster) {
			/* nmaster clients are stacked vertically, in the center of the screen */
			resize(c, mx, my, mw - (2 * c->bw),
			       mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2 * c->bw), 0);
			my += HEIGHT(c) + ih;
		}
		else {
			/* stack clients are stacked vertically */
			if ((i - m->nmaster) % 2) {
				resize(c, lx, ly, lw - (2 * c->bw),
				       lh * (c->cfact / lfacts)
				               + ((i - 2 * m->nmaster) < 2 * lrest ? 1 : 0)
				               - (2 * c->bw),
				       0);
				ly += HEIGHT(c) + ih;
			}
			else {
				resize(c, rx, ry, rw - (2 * c->bw),
				       rh * (c->cfact / rfacts)
				               + ((i - 2 * m->nmaster) < 2 * rrest ? 1 : 0)
				               - (2 * c->bw),
				       0);
				ry += HEIGHT(c) + ih;
			}
		}
	}
}

void
centeredfloatingmaster(Monitor *m)
{
	unsigned int i, n;
	float mfacts, sfacts;
	float mivf = 1.0; // master inner vertical gap factor
	int oh, ov, ih, iv, mrest, srest;
	int mx = 0, my = 0, mh = 0, mw = 0;
	int sx = 0, sy = 0, sh = 0, sw = 0;
	Client *c;

	getgaps(m, &oh, &ov, &ih, &iv, &n);
	if (n == 0)
		return;

	sx = mx = m->wx + ov;
	sy = my = m->wy + oh;
	sh = mh = m->wh - 2 * oh;
	mw = m->ww - 2 * ov - iv * (n - 1);
	sw = m->ww - 2 * ov - iv * (n - m->nmaster - 1);

	if (m->nmaster && n > m->nmaster) {
		mivf = 0.8;
		/* go mfact box in the center if more than nmaster clients */
		if (m->ww > m->wh) {
			mw = m->ww * m->mfact - iv * mivf * (MIN(n, m->nmaster) - 1);
			mh = m->wh * 0.9;
		}
		else {
			mw = m->ww * 0.9 - iv * mivf * (MIN(n, m->nmaster) - 1);
			mh = m->wh * m->mfact;
		}
		mx = m->wx + (m->ww - mw) / 2;
		my = m->wy + (m->wh - mh - 2 * oh) / 2;

		sx = m->wx + ov;
		sy = m->wy + oh;
		sh = m->wh - 2 * oh;
	}

	getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);

	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
		if (i < m->nmaster) {
			/* nmaster clients are stacked horizontally, in the center of the screen */
			resize(c, mx, my,
			       mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2 * c->bw),
			       mh - (2 * c->bw), 0);
			mx += WIDTH(c) + iv * mivf;
		}
		else {
			/* stack clients are stacked horizontally */
			resize(c, sx, sy,
			       sw * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0)
			               - (2 * c->bw),
			       sh - (2 * c->bw), 0);
			sx += WIDTH(c) + iv;
		}
}

/*
 * Deck layout + gaps
 * https://dwm.suckless.org/patches/deck/
 */
void
deck(Monitor *m)
{
	unsigned int i, n;
	int oh, ov, ih, iv;
	int mx = 0, my = 0, mh = 0, mw = 0;
	int sx = 0, sy = 0, sh = 0, sw = 0;
	float mfacts, sfacts;
	int mrest, srest;
	Client *c;

	getgaps(m, &oh, &ov, &ih, &iv, &n);
	if (n == 0)
		return;

	sx = mx = m->wx + ov;
	sy = my = m->wy + oh;
	sh = mh = m->wh - 2 * oh - ih * (MIN(n, m->nmaster) - 1);
	sw = mw = m->ww - 2 * ov;

	if (m->nmaster && n > m->nmaster) {
		sw = (mw - iv) * (1 - m->mfact);
		mw = mw - iv - sw;
		sx = mx + mw + iv;
		sh = m->wh - 2 * oh;
	}

	getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);

	if (n - m->nmaster > 0) /* override layout symbol */
		snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster);

	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
		if (i < m->nmaster) {
			resize(c, mx, my, mw - (2 * c->bw),
			       mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2 * c->bw), 0);
			my += HEIGHT(c) + ih;
		}
		else {
			resize(c, sx, sy, sw - (2 * c->bw), sh - (2 * c->bw), 0);
		}
}

/*
 * Fibonacci layout + gaps
 * https://dwm.suckless.org/patches/fibonacci/
 */
void
fibonacci(Monitor *m, int s)
{
	unsigned int i, n;
	int nx, ny, nw, nh;
	int oh, ov, ih, iv;
	int nv, hrest = 0, wrest = 0, r = 1;
	Client *c;

	getgaps(m, &oh, &ov, &ih, &iv, &n);
	if (n == 0)
		return;

	nx = m->wx + ov;
	ny = m->wy + oh;
	nw = m->ww - 2 * ov;
	nh = m->wh - 2 * oh;

	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
		if (r) {
			if ((i % 2 && (nh - ih) / 2 <= (bh + 2 * c->bw))
			    || (!(i % 2) && (nw - iv) / 2 <= (bh + 2 * c->bw))) {
				r = 0;
			}
			if (r && i < n - 1) {
				if (i % 2) {
					nv = (nh - ih) / 2;
					hrest = nh - 2 * nv - ih;
					nh = nv;
				}
				else {
					nv = (nw - iv) / 2;
					wrest = nw - 2 * nv - iv;
					nw = nv;
				}

				if ((i % 4) == 2 && !s)
					nx += nw + iv;
				else if ((i % 4) == 3 && !s)
					ny += nh + ih;
			}

			if ((i % 4) == 0) {
				if (s) {
					ny += nh + ih;
					nh += hrest;
				}
				else {
					nh -= hrest;
					ny -= nh + ih;
				}
			}
			else if ((i % 4) == 1) {
				nx += nw + iv;
				nw += wrest;
			}
			else if ((i % 4) == 2) {
				ny += nh + ih;
				nh += hrest;
				if (i < n - 1)
					nw += wrest;
			}
			else if ((i % 4) == 3) {
				if (s) {
					nx += nw + iv;
					nw -= wrest;
				}
				else {
					nw -= wrest;
					nx -= nw + iv;
					nh += hrest;
				}
			}
			if (i == 0) {
				if (n != 1) {
					nw = (m->ww - iv - 2 * ov)
					     - (m->ww - iv - 2 * ov) * (1 - m->mfact);
					wrest = 0;
				}
				ny = m->wy + oh;
			}
			else if (i == 1)
				nw = m->ww - nw - iv - 2 * ov;
			i++;
		}

		resize(c, nx, ny, nw - (2 * c->bw), nh - (2 * c->bw), False);
	}
}

void
dwindle(Monitor *m)
{
	fibonacci(m, 1);
}

void
spiral(Monitor *m)
{
	fibonacci(m, 0);
}

/*
 * Gappless grid layout + gaps (ironically)
 * https://dwm.suckless.org/patches/gaplessgrid/
 */
void
gaplessgrid(Monitor *m)
{
	unsigned int i, n;
	int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters
	int oh, ov, ih, iv;
	Client *c;

	getgaps(m, &oh, &ov, &ih, &iv, &n);
	if (n == 0)
		return;

	/* grid dimensions */
	for (cols = 0; cols <= n / 2; cols++)
		if (cols * cols >= n)
			break;
	if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
		cols = 2;
	rows = n / cols;
	cn = rn = 0; // reset column no, row no, client count

	ch = (m->wh - 2 * oh - ih * (rows - 1)) / rows;
	cw = (m->ww - 2 * ov - iv * (cols - 1)) / cols;
	rrest = (m->wh - 2 * oh - ih * (rows - 1)) - ch * rows;
	crest = (m->ww - 2 * ov - iv * (cols - 1)) - cw * cols;
	x = m->wx + ov;
	y = m->wy + oh;

	for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) {
		if (i / rows + 1 > cols - n % cols) {
			rows = n / cols + 1;
			ch = (m->wh - 2 * oh - ih * (rows - 1)) / rows;
			rrest = (m->wh - 2 * oh - ih * (rows - 1)) - ch * rows;
		}
		resize(c, x, y + rn * (ch + ih) + MIN(rn, rrest),
		       cw + (cn < crest ? 1 : 0) - 2 * c->bw, ch + (rn < rrest ? 1 : 0) - 2 * c->bw,
		       0);
		rn++;
		if (rn >= rows) {
			rn = 0;
			x += cw + ih + (cn < crest ? 1 : 0);
			cn++;
		}
	}
}

/*
 * Gridmode layout + gaps
 * https://dwm.suckless.org/patches/gridmode/
 */
void
grid(Monitor *m)
{
	unsigned int i, n;
	int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows;
	int oh, ov, ih, iv;
	Client *c;

	getgaps(m, &oh, &ov, &ih, &iv, &n);

	/* grid dimensions */
	for (rows = 0; rows <= n / 2; rows++)
		if (rows * rows >= n)
			break;
	cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;

	/* window geoms (cell height/width) */
	ch = (m->wh - 2 * oh - ih * (rows - 1)) / (rows ? rows : 1);
	cw = (m->ww - 2 * ov - iv * (cols - 1)) / (cols ? cols : 1);
	chrest = (m->wh - 2 * oh - ih * (rows - 1)) - ch * rows;
	cwrest = (m->ww - 2 * ov - iv * (cols - 1)) - cw * cols;
	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
		cc = i / rows;
		cr = i % rows;
		cx = m->wx + ov + cc * (cw + iv) + MIN(cc, cwrest);
		cy = m->wy + oh + cr * (ch + ih) + MIN(cr, chrest);
		resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2 * c->bw,
		       ch + (cr < chrest ? 1 : 0) - 2 * c->bw, False);
	}
}

/*
 * Horizontal grid layout + gaps
 * https://dwm.suckless.org/patches/horizgrid/
 */
void
horizgrid(Monitor *m)
{
	Client *c;
	unsigned int n, i;
	int oh, ov, ih, iv;
	int mx = 0, my = 0, mh = 0, mw = 0;
	int sx = 0, sy = 0, sh = 0, sw = 0;
	int ntop, nbottom = 1;
	float mfacts = 0, sfacts = 0;
	int mrest, srest, mtotal = 0, stotal = 0;

	/* Count windows */
	getgaps(m, &oh, &ov, &ih, &iv, &n);
	if (n == 0)
		return;

	if (n <= 2)
		ntop = n;
	else {
		ntop = n / 2;
		nbottom = n - ntop;
	}
	sx = mx = m->wx + ov;
	sy = my = m->wy + oh;
	sh = mh = m->wh - 2 * oh;
	sw = mw = m->ww - 2 * ov;

	if (n > ntop) {
		sh = (mh - ih) / 2;
		mh = mh - ih - sh;
		sy = my + mh + ih;
		mw = m->ww - 2 * ov - iv * (ntop - 1);
		sw = m->ww - 2 * ov - iv * (nbottom - 1);
	}

	/* calculate facts */
	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
		if (i < ntop)
			mfacts += c->cfact;
		else
			sfacts += c->cfact;

	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
		if (i < ntop)
			mtotal += mh * (c->cfact / mfacts);
		else
			stotal += sw * (c->cfact / sfacts);

	mrest = mh - mtotal;
	srest = sw - stotal;

	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
		if (i < ntop) {
			resize(c, mx, my,
			       mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2 * c->bw),
			       mh - (2 * c->bw), 0);
			mx += WIDTH(c) + iv;
		}
		else {
			resize(c, sx, sy,
			       sw * (c->cfact / sfacts) + ((i - ntop) < srest ? 1 : 0)
			               - (2 * c->bw),
			       sh - (2 * c->bw), 0);
			sx += WIDTH(c) + iv;
		}
}

/*
 * nrowgrid layout + gaps
 * https://dwm.suckless.org/patches/nrowgrid/
 */
void
nrowgrid(Monitor *m)
{
	unsigned int n;
	int ri = 0, ci = 0; /* counters */
	int oh, ov, ih, iv; /* vanitygap settings */
	unsigned int cx, cy, cw, ch; /* client geometry */
	unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */
	unsigned int cols, rows = m->nmaster + 1;
	Client *c;

	/* count clients */
	getgaps(m, &oh, &ov, &ih, &iv, &n);

	/* nothing to do here */
	if (n == 0)
		return;

	/* force 2 clients to always split vertically */
	if (FORCE_VSPLIT && n == 2)
		rows = 1;

	/* never allow empty rows */
	if (n < rows)
		rows = n;

	/* define first row */
	cols = n / rows;
	uc = cols;
	cy = m->wy + oh;
	ch = (m->wh - 2 * oh - ih * (rows - 1)) / rows;
	uh = ch;

	for (c = nexttiled(m->clients); c; c = nexttiled(c->next), ci++) {
		if (ci == cols) {
			uw = 0;
			ci = 0;
			ri++;

			/* next row */
			cols = (n - uc) / (rows - ri);
			uc += cols;
			cy = m->wy + oh + uh + ih;
			uh += ch + ih;
		}

		cx = m->wx + ov + uw;
		cw = (m->ww - 2 * ov - uw) / (cols - ci);
		uw += cw + iv;

		resize(c, cx, cy, cw - (2 * c->bw), ch - (2 * c->bw), 0);
	}
}

/*
 * Default tile layout + gaps
 */
static void
tile(Monitor *m)
{
	unsigned int i, n;
	int oh, ov, ih, iv;
	int mx = 0, my = 0, mh = 0, mw = 0;
	int sx = 0, sy = 0, sh = 0, sw = 0;
	float mfacts, sfacts;
	int mrest, srest;
	Client *c;

	getgaps(m, &oh, &ov, &ih, &iv, &n);
	if (n == 0)
		return;

	sx = mx = m->wx + ov;
	sy = my = m->wy + oh;
	mh = m->wh - 2 * oh - ih * (MIN(n, m->nmaster) - 1);
	sh = m->wh - 2 * oh - ih * (n - m->nmaster - 1);
	sw = mw = m->ww - 2 * ov;

	if (m->nmaster && n > m->nmaster) {
		sw = (mw - iv) * (1 - m->mfact);
		mw = mw - iv - sw;
		sx = mx + mw + iv;
	}

	getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);

	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
		if (i < m->nmaster) {
			resize(c, mx, my, mw - (2 * c->bw),
			       mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2 * c->bw), 0);
			my += HEIGHT(c) + ih;
		}
		else {
			resize(c, sx, sy, sw - (2 * c->bw),
			       sh * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0)
			               - (2 * c->bw),
			       0);
			sy += HEIGHT(c) + ih;
		}
}