static int th = 0; /* tab bar geometry */

void
drawtabs(void)
{
	Monitor *m;

	for (m = mons; m; m = m->next)
		drawtab(m);
}

static int
cmpint(const void *p1, const void *p2)
{
  /* The actual arguments to this function are "pointers to
     pointers to char", but strcmp(3) arguments are "pointers
     to char", hence the following cast plus dereference */
  return *((int*) p1) > * (int*) p2;
}

void
drawtab(Monitor *m)
{
	Client *c;
	int i;
	int itag = -1;
	char view_info[50];
	int view_info_w = 0;
	int sorted_label_widths[MAXTABS];
	int tot_width;
	int maxsize = bh;
	int x = 0;
	int w = 0;

	// view_info: indicate the tag which is displayed in the view
	for (i = 0; i < NUMTAGS; ++i) {
		if ((selmon->tagset[selmon->seltags] >> i) & 1) {
			if (itag >=0) { // more than one tag selected
				itag = -1;
				break;
			}
			itag = i;
		}
	}

	if (0 <= itag  && itag < NUMTAGS) {
		snprintf(view_info, sizeof view_info, "[%s]", tagicon(m, itag));
	} else {
		strncpy(view_info, "[...]", sizeof view_info);
	}
	view_info[sizeof(view_info) - 1 ] = 0;
	view_info_w = TEXTW(view_info);
	tot_width = view_info_w;

	/* Calculates number of labels and their width */
	m->ntabs = 0;
	for (c = m->clients; c; c = c->next) {
		if (!ISVISIBLE(c) || HIDDEN(c))
			continue;
		m->tab_widths[m->ntabs] = TEXTW(c->name);
		tot_width += m->tab_widths[m->ntabs];
		++m->ntabs;
		if (m->ntabs >= MAXTABS)
			break;
	}

	if (tot_width > m->ww) { // not enough space to display the labels, they need to be truncated
		memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs);
		qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint);
		tot_width = view_info_w;
		for (i = 0; i < m->ntabs; ++i) {
			if (tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww)
				break;
			tot_width += sorted_label_widths[i];
		}
		maxsize = (m->ww - tot_width) / (m->ntabs - i);
	} else {
		maxsize = m->ww;
	}
	i = 0;
	for (c = m->clients; c; c = c->next) {
		if (!ISVISIBLE(c) || HIDDEN(c))
			continue;
		if (i >= m->ntabs)
			break;
		if (m->tab_widths[i] > maxsize)
			m->tab_widths[i] = maxsize;
		w = m->tab_widths[i];
		drw_setscheme(drw, scheme[(c == m->sel) ? SchemeSel : SchemeNorm]);
		drw_text(drw, x, 0, w, th, 0, c->name, 0, False);
		x += w;
		++i;
	}

	drw_setscheme(drw, scheme[SchemeNorm]);

	/* cleans interspace between window names and current viewed tag label */
	w = m->ww - view_info_w - x;
	drw_text(drw, x, 0, w, th, 0, "", 0, False);

	/* view info */
	x += w;
	w = view_info_w;
	drw_text(drw, x, 0, w, th, 0, view_info, 0, False);

	drw_map(drw, m->tabwin, 0, 0, m->ww, th);
}

void
focuswin(const Arg* arg)
{
	int iwin = arg->i;
	Client* c = NULL;
	for (c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next) {
		if (ISVISIBLE(c) && !HIDDEN(c))
			--iwin;
	};
	if (c) {
		focus(c);
		restack(selmon);
	}
}

void
tabmode(const Arg *arg)
{
	if (arg && arg->i >= 0)
		selmon->showtab = arg->ui % showtab_nmodes;
	else
		selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes;
	arrange(selmon);
}