tab.c (3029B)
1 static int th = 0; /* tab bar geometry */ 2 3 void 4 drawtabs(void) 5 { 6 Monitor *m; 7 8 for (m = mons; m; m = m->next) 9 drawtab(m); 10 } 11 12 static int 13 cmpint(const void *p1, const void *p2) 14 { 15 /* The actual arguments to this function are "pointers to 16 pointers to char", but strcmp(3) arguments are "pointers 17 to char", hence the following cast plus dereference */ 18 return *((int*) p1) > * (int*) p2; 19 } 20 21 void 22 drawtab(Monitor *m) 23 { 24 Client *c; 25 int i; 26 int itag = -1; 27 char view_info[50]; 28 int view_info_w = 0; 29 int sorted_label_widths[MAXTABS]; 30 int tot_width; 31 int maxsize = bh; 32 int x = 0; 33 int w = 0; 34 35 // view_info: indicate the tag which is displayed in the view 36 for (i = 0; i < NUMTAGS; ++i) { 37 if ((selmon->tagset[selmon->seltags] >> i) & 1) { 38 if (itag >=0) { // more than one tag selected 39 itag = -1; 40 break; 41 } 42 itag = i; 43 } 44 } 45 46 if (0 <= itag && itag < NUMTAGS) { 47 snprintf(view_info, sizeof view_info, "[%s]", tagicon(m, itag)); 48 } else { 49 strncpy(view_info, "[...]", sizeof view_info); 50 } 51 view_info[sizeof(view_info) - 1 ] = 0; 52 view_info_w = TEXTW(view_info); 53 tot_width = view_info_w; 54 55 /* Calculates number of labels and their width */ 56 m->ntabs = 0; 57 for (c = m->clients; c; c = c->next) { 58 if (!ISVISIBLE(c) || HIDDEN(c)) 59 continue; 60 m->tab_widths[m->ntabs] = TEXTW(c->name); 61 tot_width += m->tab_widths[m->ntabs]; 62 ++m->ntabs; 63 if (m->ntabs >= MAXTABS) 64 break; 65 } 66 67 if (tot_width > m->ww) { // not enough space to display the labels, they need to be truncated 68 memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); 69 qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); 70 tot_width = view_info_w; 71 for (i = 0; i < m->ntabs; ++i) { 72 if (tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) 73 break; 74 tot_width += sorted_label_widths[i]; 75 } 76 maxsize = (m->ww - tot_width) / (m->ntabs - i); 77 } else { 78 maxsize = m->ww; 79 } 80 i = 0; 81 for (c = m->clients; c; c = c->next) { 82 if (!ISVISIBLE(c) || HIDDEN(c)) 83 continue; 84 if (i >= m->ntabs) 85 break; 86 if (m->tab_widths[i] > maxsize) 87 m->tab_widths[i] = maxsize; 88 w = m->tab_widths[i]; 89 drw_setscheme(drw, scheme[(c == m->sel) ? SchemeSel : SchemeNorm]); 90 drw_text(drw, x, 0, w, th, 0, c->name, 0, False); 91 x += w; 92 ++i; 93 } 94 95 drw_setscheme(drw, scheme[SchemeNorm]); 96 97 /* cleans interspace between window names and current viewed tag label */ 98 w = m->ww - view_info_w - x; 99 drw_text(drw, x, 0, w, th, 0, "", 0, False); 100 101 /* view info */ 102 x += w; 103 w = view_info_w; 104 drw_text(drw, x, 0, w, th, 0, view_info, 0, False); 105 106 drw_map(drw, m->tabwin, 0, 0, m->ww, th); 107 } 108 109 void 110 focuswin(const Arg* arg) 111 { 112 int iwin = arg->i; 113 Client* c = NULL; 114 for (c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next) { 115 if (ISVISIBLE(c) && !HIDDEN(c)) 116 --iwin; 117 }; 118 if (c) { 119 focus(c); 120 restack(selmon); 121 } 122 } 123 124 void 125 tabmode(const Arg *arg) 126 { 127 if (arg && arg->i >= 0) 128 selmon->showtab = arg->ui % showtab_nmodes; 129 else 130 selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; 131 arrange(selmon); 132 } 133