dwm

Kris's build of dwm
git clone git clone https://git.krisyotam.com/krisyotam/dwm.git
Log | Files | Refs | README | LICENSE

layout_flextile-deluxe.c (24588B)


      1 typedef struct {
      2 	void (*arrange)(Monitor *, int, int, int, int, int, int, int);
      3 } LayoutArranger;
      4 
      5 typedef struct {
      6 	void (*arrange)(Monitor *, int, int, int, int, int, int, int, int, int);
      7 } TileArranger;
      8 
      9 static const LayoutArranger flexlayouts[] = {
     10 	{ layout_no_split },
     11 	{ layout_split_vertical },
     12 	{ layout_split_horizontal },
     13 	{ layout_split_centered_vertical },
     14 	{ layout_split_centered_horizontal },
     15 	{ layout_split_vertical_dual_stack },
     16 	{ layout_split_horizontal_dual_stack },
     17 	{ layout_floating_master },
     18 	{ layout_split_vertical_fixed },
     19 	{ layout_split_horizontal_fixed },
     20 	{ layout_split_centered_vertical_fixed },
     21 	{ layout_split_centered_horizontal_fixed },
     22 	{ layout_split_vertical_dual_stack_fixed },
     23 	{ layout_split_horizontal_dual_stack_fixed },
     24 	{ layout_floating_master_fixed },
     25 };
     26 
     27 static const TileArranger flextiles[] = {
     28 	{ arrange_top_to_bottom },
     29 	{ arrange_left_to_right },
     30 	{ arrange_monocle },
     31 	{ arrange_gapplessgrid },
     32 	{ arrange_gapplessgrid_alt1 },
     33 	{ arrange_gapplessgrid_alt2 },
     34 	{ arrange_gridmode },
     35 	{ arrange_horizgrid },
     36 	{ arrange_dwindle },
     37 	{ arrange_spiral },
     38 	{ arrange_tatami },
     39 };
     40 
     41 static void
     42 getfactsforrange(Monitor *m, int an, int ai, int size, int *rest, float *fact)
     43 {
     44 	int i;
     45 	float facts;
     46 	Client *c;
     47 	int total = 0;
     48 
     49 	facts = 0;
     50 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
     51 		if (i >= ai && i < (ai + an))
     52 			#if CFACTS_PATCH
     53 			facts += c->cfact;
     54 			#else
     55 			facts += 1;
     56 			#endif // CFACTS_PATCH
     57 
     58 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
     59 		if (i >= ai && i < (ai + an))
     60 			#if CFACTS_PATCH
     61 			total += size * (c->cfact / facts);
     62 			#else
     63 			total += size / facts;
     64 			#endif // CFACTS_PATCH
     65 
     66 	*rest = size - total;
     67 	*fact = facts;
     68 }
     69 
     70 #if IPC_PATCH || DWMC_PATCH
     71 static void
     72 setlayoutaxisex(const Arg *arg)
     73 {
     74 	int axis, arr;
     75 
     76 	axis = arg->i & 0x3; // lower two bytes indicates layout, master or stack1-2
     77 	arr = ((arg->i & 0xFC) >> 2); // remaining six upper bytes indicate arrangement
     78 
     79 	if ((axis == 0 && abs(arr) > LAYOUT_LAST)
     80 			|| (axis > 0 && (arr > AXIS_LAST || arr < 0)))
     81 		arr = 0;
     82 
     83 	selmon->ltaxis[axis] = arr;
     84 	#if PERTAG_PATCH
     85 	selmon->pertag->ltaxis[selmon->pertag->curtag][axis] = selmon->ltaxis[axis];
     86 	#endif // PERTAG_PATCH
     87 	arrange(selmon);
     88 }
     89 #endif // IPC_PATCH | DWMC_PATCH
     90 
     91 static void
     92 layout_no_split(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
     93 {
     94 	(&flextiles[m->ltaxis[m->nmaster >= n ? MASTER : STACK]])->arrange(m, x, y, h, w, ih, iv, n, n, 0);
     95 }
     96 
     97 static void
     98 layout_split_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
     99 {
    100 	/* Split master into master + stack if we have enough clients */
    101 	if (m->nmaster && n > m->nmaster) {
    102 		layout_split_vertical_fixed(m, x, y, h, w, ih, iv, n);
    103 	} else {
    104 		layout_no_split(m, x, y, h, w, ih, iv, n);
    105 	}
    106 }
    107 
    108 static void
    109 layout_split_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
    110 {
    111 	int sw, sx;
    112 
    113 	sw = (w - iv) * (1 - m->mfact);
    114 	w = (w - iv) * m->mfact;
    115 	if (m->ltaxis[LAYOUT] < 0) { // mirror
    116 		sx = x;
    117 		x += sw + iv;
    118 	} else {
    119 		sx = x + w + iv;
    120 	}
    121 
    122 	(&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0);
    123 	(&flextiles[m->ltaxis[STACK]])->arrange(m, sx, y, h, sw, ih, iv, n, n - m->nmaster, m->nmaster);
    124 }
    125 
    126 static void
    127 layout_split_vertical_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
    128 {
    129 	/* Split master into master + stack if we have enough clients */
    130 	if (!m->nmaster || n <= m->nmaster) {
    131 		layout_no_split(m, x, y, h, w, ih, iv, n);
    132 	} else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) {
    133 		layout_split_vertical(m, x, y, h, w, ih, iv, n);
    134 	} else {
    135 		layout_split_vertical_dual_stack_fixed(m, x, y, h, w, ih, iv, n);
    136 	}
    137 }
    138 
    139 static void
    140 layout_split_vertical_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
    141 {
    142 	int sh, sw, sx, oy, sc;
    143 
    144 	if (m->nstack)
    145 		sc = m->nstack;
    146 	else
    147 		sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0);
    148 
    149 	sw = (w - iv) * (1 - m->mfact);
    150 	sh = (h - ih) / 2;
    151 	w = (w - iv) * m->mfact;
    152 	oy = y + sh + ih;
    153 	if (m->ltaxis[LAYOUT] < 0) { // mirror
    154 		sx = x;
    155 		x += sw + iv;
    156 	} else {
    157 		sx = x + w + iv;
    158 	}
    159 
    160 	(&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0);
    161 	(&flextiles[m->ltaxis[STACK]])->arrange(m, sx, y, sh, sw, ih, iv, n, sc, m->nmaster);
    162 	(&flextiles[m->ltaxis[STACK2]])->arrange(m, sx, oy, sh, sw, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc);
    163 }
    164 
    165 static void
    166 layout_split_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
    167 {
    168 	/* Split master into master + stack if we have enough clients */
    169 	if (m->nmaster && n > m->nmaster) {
    170 		layout_split_horizontal_fixed(m, x, y, h, w, ih, iv, n);
    171 	} else {
    172 		layout_no_split(m, x, y, h, w, ih, iv, n);
    173 	}
    174 }
    175 
    176 static void
    177 layout_split_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
    178 {
    179 	int sh, sy;
    180 
    181 	sh = (h - ih) * (1 - m->mfact);
    182 	h = (h - ih) * m->mfact;
    183 	if (m->ltaxis[LAYOUT] < 0) { // mirror
    184 		sy = y;
    185 		y += sh + ih;
    186 	} else {
    187 		sy = y + h + ih;
    188 	}
    189 
    190 	(&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0);
    191 	(&flextiles[m->ltaxis[STACK]])->arrange(m, x, sy, sh, w, ih, iv, n, n - m->nmaster, m->nmaster);
    192 }
    193 
    194 static void
    195 layout_split_horizontal_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
    196 {
    197 	/* Split master into master + stack if we have enough clients */
    198 	if (!m->nmaster || n <= m->nmaster) {
    199 		layout_no_split(m, x, y, h, w, ih, iv, n);
    200 	} else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) {
    201 		layout_split_horizontal(m, x, y, h, w, ih, iv, n);
    202 	} else {
    203 		layout_split_horizontal_dual_stack_fixed(m, x, y, h, w, ih, iv, n);
    204 	}
    205 }
    206 
    207 static void
    208 layout_split_horizontal_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
    209 {
    210 	int sh, sy, ox, sc;
    211 
    212 	if (m->nstack)
    213 		sc = m->nstack;
    214 	else
    215 		sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0);
    216 
    217 	sh = (h - ih) * (1 - m->mfact);
    218 	h = (h - ih) * m->mfact;
    219 	sw = (w - iv) / 2;
    220 	ox = x + sw + iv;
    221 	if (m->ltaxis[LAYOUT] < 0) { // mirror
    222 		sy = y;
    223 		y += sh + ih;
    224 	} else {
    225 		sy = y + h + ih;
    226 	}
    227 
    228 	(&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0);
    229 	(&flextiles[m->ltaxis[STACK]])->arrange(m, x, sy, sh, sw, ih, iv, n, sc, m->nmaster);
    230 	(&flextiles[m->ltaxis[STACK2]])->arrange(m, ox, sy, sh, sw, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc);
    231 }
    232 
    233 static void
    234 layout_split_centered_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
    235 {
    236 	/* Split master into master + stack if we have enough clients */
    237 	if (!m->nmaster || n <= m->nmaster) {
    238 		layout_no_split(m, x, y, h, w, ih, iv, n);
    239 	} else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) {
    240 		layout_split_vertical(m, x, y, h, w, ih, iv, n);
    241 	} else {
    242 		layout_split_centered_vertical_fixed(m, x, y, h, w, ih, iv, n);
    243 	}
    244 }
    245 
    246 static void
    247 layout_split_centered_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
    248 {
    249 	int sw, sx, ox, sc;
    250 
    251 	if (m->nstack)
    252 		sc = m->nstack;
    253 	else
    254 		sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0);
    255 
    256 	sw = (w - 2*iv) * (1 - m->mfact) / 2;
    257 	w = (w - 2*iv) * m->mfact;
    258 	if (m->ltaxis[LAYOUT] < 0)  { // mirror
    259 		sx = x;
    260 		x += sw + iv;
    261 		ox = x + w + iv;
    262 	} else {
    263 		ox = x;
    264 		x += sw + iv;
    265 		sx = x + w + iv;
    266 	}
    267 
    268 	(&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0);
    269 	(&flextiles[m->ltaxis[STACK]])->arrange(m, sx, y, h, sw, ih, iv, n, sc, m->nmaster);
    270 	(&flextiles[m->ltaxis[STACK2]])->arrange(m, ox, y, h, sw, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc);
    271 }
    272 
    273 static void
    274 layout_split_centered_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
    275 {
    276 	/* Split master into master + stack if we have enough clients */
    277 	if (!m->nmaster || n <= m->nmaster) {
    278 		layout_no_split(m, x, y, h, w, ih, iv, n);
    279 	} else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) {
    280 		layout_split_horizontal(m, x, y, h, w, ih, iv, n);
    281 	} else {
    282 		layout_split_centered_horizontal_fixed(m, x, y, h, w, ih, iv, n);
    283 	}
    284 }
    285 
    286 static void
    287 layout_split_centered_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
    288 {
    289 	int sh, sy, oy, sc;
    290 
    291 	if (m->nstack)
    292 		sc = m->nstack;
    293 	else
    294 		sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0);
    295 
    296 	sh = (h - 2*ih) * (1 - m->mfact) / 2;
    297 	h = (h - 2*ih) * m->mfact;
    298 	if (m->ltaxis[LAYOUT] < 0)  { // mirror
    299 		sy = y;
    300 		y += sh + ih;
    301 		oy = y + h + ih;
    302 	} else {
    303 		oy = y;
    304 		y += sh + ih;
    305 		sy = y + h + ih;
    306 	}
    307 
    308 	(&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0);
    309 	(&flextiles[m->ltaxis[STACK]])->arrange(m, x, sy, sh, w, ih, iv, n, sc, m->nmaster);
    310 	(&flextiles[m->ltaxis[STACK2]])->arrange(m, x, oy, sh, w, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc);
    311 }
    312 
    313 static void
    314 layout_floating_master(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
    315 {
    316 	/* Split master into master + stack if we have enough clients */
    317 	if (!m->nmaster || n <= m->nmaster) {
    318 		layout_no_split(m, x, y, h, w, ih, iv, n);
    319 	} else {
    320 		layout_floating_master_fixed(m, x, y, h, w, ih, iv, n);
    321 	}
    322 }
    323 
    324 static void
    325 layout_floating_master_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
    326 {
    327 	int mh, mw;
    328 
    329 	/* Draw stack area first */
    330 	(&flextiles[m->ltaxis[STACK]])->arrange(m, x, y, h, w, ih, iv, n, n - m->nmaster, m->nmaster);
    331 
    332 	if (w > h) {
    333 		mw = w * m->mfact;
    334 		mh = h * 0.9;
    335 	} else {
    336 		mw = w * 0.9;
    337 		mh = h * m->mfact;
    338 	}
    339 	x = x + (w - mw) / 2;
    340 	y = y + (h - mh) / 2;
    341 
    342 	(&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, mh, mw, ih, iv, n, m->nmaster, 0);
    343 }
    344 
    345 static void
    346 arrange_left_to_right(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
    347 {
    348 	int i, rest;
    349 	float facts, fact = 1;
    350 	Client *c;
    351 
    352 	if (ai + an > n)
    353 		an = n - ai;
    354 
    355 	w -= iv * (an - 1);
    356 	getfactsforrange(m, an, ai, w, &rest, &facts);
    357 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
    358 		if (i >= ai && i < (ai + an)) {
    359 			#if CFACTS_PATCH
    360 			fact = c->cfact;
    361 			#endif // CFACTS_PATCH
    362 			resize(c, x, y, w * (fact / facts) + ((i - ai) < rest ? 1 : 0) - (2*c->bw), h - (2*c->bw), 0);
    363 			x += WIDTH(c) + iv;
    364 		}
    365 	}
    366 }
    367 
    368 static void
    369 arrange_top_to_bottom(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
    370 {
    371 	int i, rest;
    372 	float facts, fact = 1;
    373 	Client *c;
    374 
    375 	if (ai + an > n)
    376 		an = n - ai;
    377 
    378 	h -= ih * (an - 1);
    379 	getfactsforrange(m, an, ai, h, &rest, &facts);
    380 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
    381 		if (i >= ai && i < (ai + an)) {
    382 			#if CFACTS_PATCH
    383 			fact = c->cfact;
    384 			#endif // CFACTS_PATCH
    385 			resize(c, x, y, w - (2*c->bw), h * (fact / facts) + ((i - ai) < rest ? 1 : 0) - (2*c->bw), 0);
    386 			y += HEIGHT(c) + ih;
    387 		}
    388 	}
    389 }
    390 
    391 static void
    392 arrange_monocle(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
    393 {
    394 	int i;
    395 	Client *c;
    396 
    397 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
    398 		if (i >= ai && i < (ai + an))
    399 			resize(c, x, y, w - (2*c->bw), h - (2*c->bw), 0);
    400 }
    401 
    402 static void
    403 arrange_gridmode(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
    404 {
    405 	int i, cols, rows, ch, cw, cx, cy, cc, cr, chrest, cwrest; // counters
    406 	Client *c;
    407 
    408 	/* grid dimensions */
    409 	for (rows = 0; rows <= an/2; rows++)
    410 		if (rows*rows >= an)
    411 			break;
    412 	cols = (rows && (rows - 1) * rows >= an) ? rows - 1 : rows;
    413 
    414 	/* window geoms (cell height/width) */
    415 	ch = (h - ih * (rows - 1)) / (rows ? rows : 1);
    416 	cw = (w - iv * (cols - 1)) / (cols ? cols : 1);
    417 	chrest = h - ih * (rows - 1) - ch * rows;
    418 	cwrest = w - iv * (cols - 1) - cw * cols;
    419 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
    420 		if (i >= ai && i < (ai + an)) {
    421 			cc = ((i - ai) / rows); // client column number
    422 			cr = ((i - ai) % rows); // client row number
    423 			cx = x + cc * (cw + iv) + MIN(cc, cwrest);
    424 			cy = y + cr * (ch + ih) + MIN(cr, chrest);
    425 			resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False);
    426 		}
    427 	}
    428 }
    429 
    430 static void
    431 arrange_horizgrid(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
    432 {
    433 	int ntop, nbottom, rh, rest;
    434 
    435 	/* Exception when there is only one client; don't split into two rows */
    436 	if (an == 1) {
    437 		arrange_monocle(m, x, y, h, w, ih, iv, n, an, ai);
    438 		return;
    439 	}
    440 
    441 	ntop = an / 2;
    442 	nbottom = an - ntop;
    443 	rh = (h - ih) / 2;
    444 	rest = h - ih - rh * 2;
    445 	arrange_left_to_right(m, x, y, rh + rest, w, ih, iv, n, ntop, ai);
    446 	arrange_left_to_right(m, x, y + rh + ih + rest, rh, w, ih, iv, n, nbottom, ai + ntop);
    447 }
    448 
    449 static void
    450 arrange_gapplessgrid(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
    451 {
    452 	int i, cols, rows, ch, cw, cn, rn, cc, rrest, crest; // counters
    453 	Client *c;
    454 
    455 	/* grid dimensions */
    456 	for (cols = 1; cols <= an/2; cols++)
    457 		if (cols*cols >= an)
    458 			break;
    459 	if (an == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
    460 		cols = 2;
    461 	rows = an/cols;
    462 	cn = rn = cc = 0; // reset column no, row no, client count
    463 
    464 	ch = (h - ih * (rows - 1)) / rows;
    465 	rrest = (h - ih * (rows - 1)) - ch * rows;
    466 	cw = (w - iv * (cols - 1)) / cols;
    467 	crest = (w - iv * (cols - 1)) - cw * cols;
    468 
    469 	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
    470 		if (i >= ai && i < (ai + an)) {
    471 			if (cc/rows + 1 > cols - an%cols) {
    472 				rows = an/cols + 1;
    473 				ch = (h - ih * (rows - 1)) / rows;
    474 				rrest = (h - ih * (rows - 1)) - ch * rows;
    475 			}
    476 			resize(c,
    477 				x,
    478 				y + rn*(ch + ih) + MIN(rn, rrest),
    479 				cw + (cn < crest ? 1 : 0) - 2*c->bw,
    480 				ch + (rn < rrest ? 1 : 0) - 2*c->bw,
    481 				0);
    482 			rn++;
    483 			cc++;
    484 			if (rn >= rows) {
    485 				rn = 0;
    486 				x += cw + ih + (cn < crest ? 1 : 0);
    487 				cn++;
    488 			}
    489 		}
    490 	}
    491 }
    492 
    493 /* This version of gappless grid fills rows first */
    494 static void
    495 arrange_gapplessgrid_alt1(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
    496 {
    497 	int i, cols, rows, rest, ch;
    498 
    499 	/* grid dimensions */
    500 	for (cols = 1; cols <= an/2; cols++)
    501 		if (cols*cols >= an)
    502 			break;
    503 	rows = (cols && (cols - 1) * cols >= an) ? cols - 1 : cols;
    504 	ch = (h - ih * (rows - 1)) / (rows ? rows : 1);
    505 	rest = (h - ih * (rows - 1)) - ch * rows;
    506 
    507 	for (i = 0; i < rows; i++) {
    508 		arrange_left_to_right(m, x, y, ch + (i < rest ? 1 : 0), w, ih, iv, n, MIN(cols, an - i*cols), ai + i*cols);
    509 		y += ch + (i < rest ? 1 : 0) + ih;
    510 	}
    511 }
    512 
    513 /* This version of gappless grid fills columns first */
    514 static void
    515 arrange_gapplessgrid_alt2(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
    516 {
    517 	int i, cols, rows, rest, cw;
    518 
    519 	/* grid dimensions */
    520 	for (rows = 0; rows <= an/2; rows++)
    521 		if (rows*rows >= an)
    522 			break;
    523 	cols = (rows && (rows - 1) * rows >= an) ? rows - 1 : rows;
    524 	cw = (w - iv * (cols - 1)) / (cols ? cols : 1);
    525 	rest = (w - iv * (cols - 1)) - cw * cols;
    526 
    527 	for (i = 0; i < cols; i++) {
    528 		arrange_top_to_bottom(m, x, y, h, cw + (i < rest ? 1 : 0), ih, iv, n, MIN(rows, an - i*rows), ai + i*rows);
    529 		x += cw + (i < rest ? 1 : 0) + iv;
    530 	}
    531 }
    532 
    533 static void
    534 arrange_fibonacci(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai, int s)
    535 {
    536 	int i, j, nv, hrest = 0, wrest = 0, nx = x, ny = y, nw = w, nh = h, r = 1;
    537 	Client *c;
    538 
    539 	for (i = 0, j = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), j++) {
    540 		if (j >= ai && j < (ai + an)) {
    541 			if (r) {
    542 				if ((i % 2 && ((nh - ih) / 2) <= (bh + 2*c->bw)) || (!(i % 2) && ((nw - iv) / 2) <= (bh + 2*c->bw))) {
    543 					r = 0;
    544 				}
    545 				if (r && i < an - 1) {
    546 					if (i % 2) {
    547 						nv = (nh - ih) / 2;
    548 						hrest = nh - 2*nv - ih;
    549 						nh = nv;
    550 					} else {
    551 						nv = (nw - iv) / 2;
    552 						wrest = nw - 2*nv - iv;
    553 						nw = nv;
    554 					}
    555 
    556 					if ((i % 4) == 2 && !s)
    557 						nx += nw + iv;
    558 					else if ((i % 4) == 3 && !s)
    559 						ny += nh + ih;
    560 				}
    561 				if ((i % 4) == 0) {
    562 					if (s) {
    563 						ny += nh + ih;
    564 						nh += hrest;
    565 					} else {
    566 						nh -= hrest;
    567 						ny -= nh + ih;
    568 					}
    569 				} else if ((i % 4) == 1) {
    570 					nx += nw + iv;
    571 					nw += wrest;
    572 				} else if ((i % 4) == 2) {
    573 					ny += nh + ih;
    574 					nh += hrest;
    575 					if (i < n - 1)
    576 						nw += wrest;
    577 				} else if ((i % 4) == 3) {
    578 					if (s) {
    579 						nx += nw + iv;
    580 						nw -= wrest;
    581 					} else {
    582 						nw -= wrest;
    583 						nx -= nw + iv;
    584 						nh += hrest;
    585 					}
    586 				}
    587 				if (i == 0)	{
    588 					if (an != 1) {
    589 						nw = (w - iv) - (w - iv) * (1 - m->mfact);
    590 						wrest = 0;
    591 					}
    592 					ny = y;
    593 				} else if (i == 1)
    594 					nw = w - nw - iv;
    595 				i++;
    596 			}
    597 
    598 			resize(c, nx, ny, nw - 2 * c->bw, nh - 2*c->bw, False);
    599 		}
    600 	}
    601 }
    602 
    603 static void
    604 arrange_dwindle(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
    605 {
    606 	arrange_fibonacci(m, x, y, h, w, ih, iv, n, an, ai, 1);
    607 }
    608 
    609 static void
    610 arrange_spiral(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
    611 {
    612 	arrange_fibonacci(m, x, y, h, w, ih, iv, n, an, ai, 0);
    613 }
    614 
    615 static void
    616 arrange_tatami(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
    617 {
    618 	unsigned int i, j, nx, ny, nw, nh, tnx, tny, tnw, tnh, nhrest, hrest, wrest, areas, mats, cats;
    619 	Client *c;
    620 
    621 	nx = x;
    622 	ny = y;
    623 	nw = w;
    624 	nh = h;
    625 
    626 	mats = an / 5;
    627 	cats = an % 5;
    628 	hrest = 0;
    629 	wrest = 0;
    630 
    631 	areas = mats + (cats > 0);
    632 	nh = (h - ih * (areas - 1)) / areas;
    633 	nhrest = (h - ih * (areas - 1)) % areas;
    634 
    635 	for (i = 0, j = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), j++) {
    636 		if (j >= ai && j < (ai + an)) {
    637 
    638 			tnw = nw;
    639 			tnx = nx;
    640 			tnh = nh;
    641 			tny = ny;
    642 
    643 			if (j < ai + cats) {
    644 				/* Arrange cats (all excess clients that can't be tiled as mats). Cats sleep on mats. */
    645 
    646 				switch (cats) {
    647 				case 1: // fill
    648 					break;
    649 				case 2: // up and down
    650 					if ((i % 5) == 0) //up
    651 						tnh = (nh - ih) / 2 + (nh - ih) % 2;
    652 					else if ((i % 5) == 1) { //down
    653 						tny += (nh - ih) / 2 + (nh - ih) % 2 + ih;
    654 						tnh = (nh - ih) / 2;
    655 					}
    656 					break;
    657 				case 3: //bottom, up-left and up-right
    658 					if ((i % 5) == 0) { // up-left
    659 						tnw = (nw - iv) / 2 + (nw - iv) % 2;
    660 						tnh = (nh - ih) * 2 / 3 + (nh - ih) * 2 % 3;
    661 					} else if ((i % 5) == 1) { // up-right
    662 						tnx += (nw - iv) / 2 + (nw - iv) % 2 + iv;
    663 						tnw = (nw - iv) / 2;
    664 						tnh = (nh - ih) * 2 / 3 + (nh - ih) * 2 % 3;
    665 					} else if ((i % 5) == 2) { //bottom
    666 						tnh = (nh - ih) / 3;
    667 						tny += (nh - ih) * 2 / 3 + (nh - ih) * 2 % 3 + ih;
    668 					}
    669 					break;
    670 				case 4: // bottom, left, right and top
    671 					if ((i % 5) == 0) { //top
    672 						hrest = (nh - 2 * ih) % 4;
    673 						tnh = (nh - 2 * ih) / 4 + (hrest ? 1 : 0);
    674 					} else if ((i % 5) == 1) { // left
    675 						tnw = (nw - iv) / 2 + (nw - iv) % 2;
    676 						tny += (nh - 2 * ih) / 4 + (hrest ? 1 : 0) + ih;
    677 						tnh = (nh - 2 * ih) * 2 / 4 + (hrest > 1 ? 1 : 0);
    678 					} else if ((i % 5) == 2) { // right
    679 						tnx += (nw - iv) / 2 + (nw - iv) % 2 + iv;
    680 						tnw = (nw - iv) / 2;
    681 						tny += (nh - 2 * ih) / 4 + (hrest ? 1 : 0) + ih;
    682 						tnh = (nh - 2 * ih) * 2 / 4 + (hrest > 1 ? 1 : 0);
    683 					} else if ((i % 5) == 3) { // bottom
    684 						tny += (nh - 2 * ih) / 4 + (hrest ? 1 : 0) + (nh - 2 * ih) * 2 / 4 + (hrest > 1 ? 1 : 0) + 2 * ih;
    685 						tnh = (nh - 2 * ih) / 4 + (hrest > 2 ? 1 : 0);
    686 					}
    687 					break;
    688 				}
    689 
    690 			} else {
    691 				/* Arrange mats. One mat is a collection of five clients arranged tatami style */
    692 
    693 				if (((i - cats) % 5) == 0) {
    694 					if ((cats > 0) || ((i - cats) >= 5)) {
    695 						tny = ny = ny + nh + (nhrest > 0 ? 1 : 0) + ih;
    696 						--nhrest;
    697 					}
    698 				}
    699 
    700 				switch ((i - cats) % 5) {
    701 				case 0: // top-left-vert
    702 					wrest = (nw - 2 * iv) % 3;
    703 					hrest = (nh - 2 * ih) % 3;
    704 					tnw = (nw - 2 * iv) / 3 + (wrest ? 1 : 0);
    705 					tnh = (nh - 2 * ih) * 2 / 3 + hrest + iv;
    706 					break;
    707 				case 1: // top-right-hor
    708 					tnx += (nw - 2 * iv) / 3 + (wrest ? 1 : 0) + iv;
    709 					tnw = (nw - 2 * iv) * 2 / 3 + (wrest > 1 ? 1 : 0) + iv;
    710 					tnh = (nh - 2 * ih) / 3 + (hrest ? 1 : 0);
    711 					break;
    712 				case 2: // center
    713 					tnx += (nw - 2 * iv) / 3 + (wrest ? 1 : 0) + iv;
    714 					tnw = (nw - 2 * iv) / 3 + (wrest > 1 ? 1 : 0);
    715 					tny += (nh - 2 * ih) / 3 + (hrest ? 1 : 0) + ih;
    716 					tnh = (nh - 2 * ih) / 3 + (hrest > 1 ? 1 : 0);
    717 					break;
    718 				case 3: // bottom-right-vert
    719 					tnx += (nw - 2 * iv) * 2 / 3 + wrest + 2 * iv;
    720 					tnw = (nw - 2 * iv) / 3;
    721 					tny += (nh - 2 * ih) / 3 + (hrest ? 1 : 0) + ih;
    722 					tnh = (nh - 2 * ih) * 2 / 3 + hrest + iv;
    723 					break;
    724 				case 4: // (oldest) bottom-left-hor
    725 					tnw = (nw - 2 * iv) * 2 / 3 + wrest + iv;
    726 					tny += (nh - 2 * ih) * 2 / 3 + hrest + 2 * iv;
    727 					tnh = (nh - 2 * ih) / 3;
    728 					break;
    729 				}
    730 
    731 			}
    732 
    733 			resize(c, tnx, tny, tnw - 2 * c->bw, tnh - 2 * c->bw, False);
    734 			++i;
    735 		}
    736 	}
    737 }
    738 
    739 static void
    740 flextile(Monitor *m)
    741 {
    742 	unsigned int n;
    743 	int oh = 0, ov = 0, ih = 0, iv = 0; // gaps outer/inner horizontal/vertical
    744 
    745 	#if VANITYGAPS_PATCH
    746 	getgaps(m, &oh, &ov, &ih, &iv, &n);
    747 	#else
    748 	Client *c;
    749 	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
    750 	#endif // VANITYGAPS_PATCH
    751 
    752 	if (m->lt[m->sellt]->preset.layout != m->ltaxis[LAYOUT] ||
    753 			m->lt[m->sellt]->preset.masteraxis != m->ltaxis[MASTER] ||
    754 			m->lt[m->sellt]->preset.stack1axis != m->ltaxis[STACK] ||
    755 			m->lt[m->sellt]->preset.stack2axis != m->ltaxis[STACK2])
    756 		setflexsymbols(m, n);
    757 	else if (m->lt[m->sellt]->preset.symbolfunc != NULL)
    758 		m->lt[m->sellt]->preset.symbolfunc(m, n);
    759 
    760 	if (n == 0)
    761 		return;
    762 
    763 	#if VANITYGAPS_PATCH && !VANITYGAPS_MONOCLE_PATCH
    764 	/* No outer gap if full screen monocle */
    765 	if (abs(m->ltaxis[MASTER]) == MONOCLE && (abs(m->ltaxis[LAYOUT]) == NO_SPLIT || n <= m->nmaster)) {
    766 		oh = 0;
    767 		ov = 0;
    768 	}
    769 	#endif // VANITYGAPS_PATCH && !VANITYGAPS_MONOCLE_PATCH
    770 
    771 	(&flexlayouts[abs(m->ltaxis[LAYOUT])])->arrange(m, m->wx + ov, m->wy + oh, m->wh - 2*oh, m->ww - 2*ov, ih, iv, n);
    772 	return;
    773 }
    774 
    775 static void
    776 setflexsymbols(Monitor *m, unsigned int n)
    777 {
    778 	int l;
    779 	char sym1, sym2, sym3;
    780 	Client *c;
    781 
    782 	if (n == 0)
    783 		for (c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
    784 
    785 	l = abs(m->ltaxis[LAYOUT]);
    786 	if (m->ltaxis[MASTER] == MONOCLE && (l == NO_SPLIT || !m->nmaster || n <= m->nmaster)) {
    787 		monoclesymbols(m, n);
    788 		return;
    789 	}
    790 
    791 	if (m->ltaxis[STACK] == MONOCLE && (l == SPLIT_VERTICAL || l == SPLIT_HORIZONTAL_FIXED)) {
    792 		decksymbols(m, n);
    793 		return;
    794 	}
    795 
    796 	/* Layout symbols */
    797 	if (l == NO_SPLIT || !m->nmaster) {
    798 		sym1 = sym2 = sym3 = (int)tilesymb[m->ltaxis[MASTER]];
    799 	} else {
    800 		sym2 = layoutsymb[l];
    801 		if (m->ltaxis[LAYOUT] < 0) {
    802 			sym1 = tilesymb[m->ltaxis[STACK]];
    803 			sym3 = tilesymb[m->ltaxis[MASTER]];
    804 		} else {
    805 			sym1 = tilesymb[m->ltaxis[MASTER]];
    806 			sym3 = tilesymb[m->ltaxis[STACK]];
    807 		}
    808 	}
    809 
    810 	snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", sym1, sym2, sym3);
    811 }
    812 
    813 static void
    814 monoclesymbols(Monitor *m, unsigned int n)
    815 {
    816 	if (n > 0)
    817 		snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
    818 	else
    819 		snprintf(m->ltsymbol, sizeof m->ltsymbol, "[M]");
    820 }
    821 
    822 static void
    823 decksymbols(Monitor *m, unsigned int n)
    824 {
    825 	if (n > m->nmaster)
    826 		snprintf(m->ltsymbol, sizeof m->ltsymbol, "[]%d", n);
    827 	else
    828 		snprintf(m->ltsymbol, sizeof m->ltsymbol, "[D]");
    829 }
    830 
    831 /* Mirror layout axis for flextile */
    832 void
    833 mirrorlayout(const Arg *arg)
    834 {
    835 	if (!selmon->lt[selmon->sellt]->arrange)
    836 		return;
    837 	selmon->ltaxis[LAYOUT] *= -1;
    838 	#if PERTAG_PATCH
    839 	selmon->pertag->ltaxis[selmon->pertag->curtag][0] = selmon->ltaxis[LAYOUT];
    840 	#endif // PERTAG_PATCH
    841 	arrange(selmon);
    842 }
    843 
    844 /* Rotate layout axis for flextile */
    845 void
    846 rotatelayoutaxis(const Arg *arg)
    847 {
    848 	int incr = (arg->i > 0 ? 1 : -1);
    849 	int axis = abs(arg->i) - 1;
    850 
    851 	if (!selmon->lt[selmon->sellt]->arrange)
    852 		return;
    853 	if (axis == LAYOUT) {
    854 		if (selmon->ltaxis[LAYOUT] >= 0) {
    855 			selmon->ltaxis[LAYOUT] += incr;
    856 			if (selmon->ltaxis[LAYOUT] >= LAYOUT_LAST)
    857 				selmon->ltaxis[LAYOUT] = 0;
    858 			else if (selmon->ltaxis[LAYOUT] < 0)
    859 				selmon->ltaxis[LAYOUT] = LAYOUT_LAST - 1;
    860 		} else {
    861 			selmon->ltaxis[LAYOUT] -= incr;
    862 			if (selmon->ltaxis[LAYOUT] <= -LAYOUT_LAST)
    863 				selmon->ltaxis[LAYOUT] = 0;
    864 			else if (selmon->ltaxis[LAYOUT] > 0)
    865 				selmon->ltaxis[LAYOUT] = -LAYOUT_LAST + 1;
    866 		}
    867 	} else {
    868 		selmon->ltaxis[axis] += incr;
    869 		if (selmon->ltaxis[axis] >= AXIS_LAST)
    870 			selmon->ltaxis[axis] = 0;
    871 		else if (selmon->ltaxis[axis] < 0)
    872 			selmon->ltaxis[axis] = AXIS_LAST - 1;
    873 	}
    874 	#if PERTAG_PATCH
    875 	selmon->pertag->ltaxis[selmon->pertag->curtag][axis] = selmon->ltaxis[axis];
    876 	#endif // PERTAG_PATCH
    877 	arrange(selmon);
    878 	setflexsymbols(selmon, 0);
    879 }
    880 
    881 void
    882 incnstack(const Arg *arg)
    883 {
    884 	#if PERTAG_PATCH
    885 	selmon->nstack = selmon->pertag->nstacks[selmon->pertag->curtag] = MAX(selmon->nstack + arg->i, 0);
    886 	#else
    887 	selmon->nstack = MAX(selmon->nstack + arg->i, 0);
    888 	#endif // PERTAG_PATCH
    889 	arrange(selmon);
    890 }
    891