You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
3.5 KiB

17 years ago
17 years ago
17 years ago
18 years ago
17 years ago
17 years ago
18 years ago
18 years ago
  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. }