tag.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /* See LICENSE file for copyright and license details. */
  2. #include "dwm.h"
  3. #include <regex.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <X11/Xatom.h>
  8. #include <X11/Xutil.h>
  9. /* static */
  10. typedef struct {
  11. const char *prop;
  12. const char *tags;
  13. Bool isfloating;
  14. } Rule;
  15. typedef struct {
  16. regex_t *propregex;
  17. regex_t *tagregex;
  18. } Regs;
  19. TAGS
  20. RULES
  21. static Regs *regs = NULL;
  22. static unsigned int nrules = 0;
  23. static char prop[512];
  24. static void
  25. persisttags(Client *c)
  26. {
  27. unsigned int i;
  28. for(i = 0; i < ntags && i < sizeof prop - 1; i++)
  29. prop[i] = c->tags[i] ? '+' : '-';
  30. prop[i] = '\0';
  31. XChangeProperty(dpy, c->win, dwmtags, XA_STRING, 8,
  32. PropModeReplace, (unsigned char *)prop, i);
  33. }
  34. /* extern */
  35. void
  36. compileregs(void) {
  37. unsigned int i;
  38. regex_t *reg;
  39. if(regs)
  40. return;
  41. nrules = sizeof rule / sizeof rule[0];
  42. regs = emallocz(nrules * sizeof(Regs));
  43. for(i = 0; i < nrules; i++) {
  44. if(rule[i].prop) {
  45. reg = emallocz(sizeof(regex_t));
  46. if(regcomp(reg, rule[i].prop, REG_EXTENDED))
  47. free(reg);
  48. else
  49. regs[i].propregex = reg;
  50. }
  51. if(rule[i].tags) {
  52. reg = emallocz(sizeof(regex_t));
  53. if(regcomp(reg, rule[i].tags, REG_EXTENDED))
  54. free(reg);
  55. else
  56. regs[i].tagregex = reg;
  57. }
  58. }
  59. }
  60. Bool
  61. isvisible(Client *c) {
  62. unsigned int i;
  63. for(i = 0; i < ntags; i++)
  64. if(c->tags[i] && seltag[i])
  65. return True;
  66. return False;
  67. }
  68. void
  69. settags(Client *c, Client *trans) {
  70. unsigned int i, j;
  71. regmatch_t tmp;
  72. Bool matched = trans != NULL;
  73. XClassHint ch = { 0 };
  74. XTextProperty name;
  75. if(matched) {
  76. for(i = 0; i < ntags; i++)
  77. c->tags[i] = trans->tags[i];
  78. }
  79. else {
  80. /* check if window has set a property */
  81. name.nitems = 0;
  82. XGetTextProperty(dpy, c->win, &name, dwmtags);
  83. if(name.nitems && name.encoding == XA_STRING) {
  84. strncpy(prop, (char *)name.value, sizeof prop - 1);
  85. prop[sizeof prop - 1] = '\0';
  86. XFree(name.value);
  87. for(i = 0; i < ntags && i < sizeof prop - 1 && prop[i] != '\0'; i++)
  88. if((c->tags[i] = prop[i] == '+'))
  89. matched = True;
  90. }
  91. }
  92. if(!matched) {
  93. /* rule matching */
  94. XGetClassHint(dpy, c->win, &ch);
  95. snprintf(prop, sizeof prop, "%s:%s:%s",
  96. ch.res_class ? ch.res_class : "",
  97. ch.res_name ? ch.res_name : "", c->name);
  98. for(i = 0; i < nrules; i++)
  99. if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0)) {
  100. c->isfloating = rule[i].isfloating;
  101. for(j = 0; regs[i].tagregex && j < ntags; j++) {
  102. if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
  103. matched = True;
  104. c->tags[j] = True;
  105. }
  106. }
  107. }
  108. if(ch.res_class)
  109. XFree(ch.res_class);
  110. if(ch.res_name)
  111. XFree(ch.res_name);
  112. }
  113. if(!matched)
  114. for(i = 0; i < ntags; i++)
  115. c->tags[i] = seltag[i];
  116. persisttags(c);
  117. }
  118. void
  119. tag(const char *arg) {
  120. int i;
  121. if(!sel)
  122. return;
  123. for(i = 0; i < ntags; i++)
  124. sel->tags[i] = arg == NULL;
  125. i = arg ? atoi(arg) : 0;
  126. if(i >= 0 && i < ntags)
  127. sel->tags[i] = True;
  128. if(sel)
  129. persisttags(sel);
  130. arrange();
  131. }
  132. void
  133. toggletag(const char *arg) {
  134. int i, j;
  135. if(!sel)
  136. return;
  137. i = arg ? atoi(arg) : 0;
  138. sel->tags[i] = !sel->tags[i];
  139. for(j = 0; j < ntags && !sel->tags[j]; j++);
  140. if(j == ntags)
  141. sel->tags[i] = True;
  142. if(sel)
  143. persisttags(sel);
  144. arrange();
  145. }
  146. void
  147. toggleview(const char *arg) {
  148. int i, j;
  149. i = arg ? atoi(arg) : 0;
  150. seltag[i] = !seltag[i];
  151. for(j = 0; j < ntags && !seltag[j]; j++);
  152. if(j == ntags)
  153. seltag[i] = True; /* cannot toggle last view */
  154. arrange();
  155. }
  156. void
  157. view(const char *arg) {
  158. int i;
  159. for(i = 0; i < ntags; i++)
  160. seltag[i] = arg == NULL;
  161. i = arg ? atoi(arg) : 0;
  162. if(i >= 0 && i < ntags)
  163. seltag[i] = True;
  164. arrange();
  165. }