💾 Archived View for gemini.rmf-dev.com › repo › Vaati › cwm › files › 03f56e37d788802c875c468179a6e5… captured on 2023-01-29 at 04:31:45. Gemini links have been rewritten to link to archived content

View Raw

More Information

➡️ Next capture (2023-04-19)

-=-=-=-=-=-=-

0 /*

1 * calmwm - the calm window manager

2 *

3 * Copyright (c) 2004 Marius Aamodt Eriksen <marius@monkey.org>

4 *

5 * Permission to use, copy, modify, and distribute this software for any

6 * purpose with or without fee is hereby granted, provided that the above

7 * copyright notice and this permission notice appear in all copies.

8 *

9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES

10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF

11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR

12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES

13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN

14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF

15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

16 *

17 * $OpenBSD$

18 */

19

20 #include <sys/types.h>

21 #include <sys/queue.h>

22

23 #include <err.h>

24 #include <errno.h>

25 #include <fnmatch.h>

26 #include <glob.h>

27 #include <limits.h>

28 #include <stdio.h>

29 #include <stdlib.h>

30 #include <string.h>

31 #include <unistd.h>

32

33 #include "calmwm.h"

34

35 #define PATH_ANY 0x0001

36 #define PATH_EXEC 0x0002

37

38 static void match_path_type(struct menu_q *, char *, int);

39 static int match_substr(char *, char *, int);

40

41 static int

42 match_substr(char *sub, char *str, int zeroidx)

43 {

44 size_t len, sublen;

45 unsigned int n, flen;

46

47 if (sub == NULL || str == NULL)

48 return 0;

49

50 len = strlen(str);

51 sublen = strlen(sub);

52

53 if (sublen > len)

54 return 0;

55

56 if (zeroidx)

57 flen = 0;

58 else

59 flen = len - sublen;

60

61 for (n = 0; n <= flen; n++)

62 if (strncasecmp(sub, str + n, sublen) == 0)

63 return 1;

64

65 return 0;

66 }

67

68 void

69 search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)

70 {

71 struct menu *mi, *tierp[3], *before = NULL;

72 struct client_ctx *cc;

73 struct winname *wn;

74

75 (void)memset(tierp, 0, sizeof(tierp));

76

77 TAILQ_INIT(resultq);

78 TAILQ_FOREACH(mi, menuq, entry) {

79 int tier = -1, t;

80 cc = (struct client_ctx *)mi->ctx;

81

82 /* Match on label. */

83 if (match_substr(search, cc->label, 0))

84 tier = 0;

85

86 /* Match on window name history, from present to past. */

87 if (tier < 0) {

88 TAILQ_FOREACH_REVERSE(wn, &cc->nameq, name_q, entry)

89 if (match_substr(search, wn->name, 0)) {

90 tier = 1;

91 break;

92 }

93 }

94

95 /* Match on window resource class. */

96 if ((tier < 0) && match_substr(search, cc->res_class, 0))

97 tier = 2;

98

99 if (tier < 0)

100 continue;

101

102 /* Current window is ranked down. */

103 if ((tier < nitems(tierp) - 1) && (cc->flags & CLIENT_ACTIVE))

104 tier++;

105

106 /* Hidden window is ranked up. */

107 if ((tier > 0) && (cc->flags & CLIENT_HIDDEN))

108 tier--;

109

110 /*

111 * If you have a tierp, insert after it, and make it

112 * the new tierp. If you don't have a tierp, find the

113 * first nonzero tierp above you, insert after it.

114 * Always make your current tierp the newly inserted

115 * entry.

116 */

117 for (t = tier; t >= 0 && ((before = tierp[t]) == NULL); t--)

118 ;

119

120 if (before == NULL)

121 TAILQ_INSERT_HEAD(resultq, mi, resultentry);

122 else

123 TAILQ_INSERT_AFTER(resultq, before, mi, resultentry);

124

125 tierp[tier] = mi;

126 }

127 }

128

129 void

130 search_match_cmd(struct menu_q *menuq, struct menu_q *resultq, char *search)

131 {

132 struct menu *mi;

133 struct cmd_ctx *cmd;

134

135 TAILQ_INIT(resultq);

136 TAILQ_FOREACH(mi, menuq, entry) {

137 cmd = (struct cmd_ctx *)mi->ctx;

138 if (match_substr(search, cmd->name, 0))

139 TAILQ_INSERT_TAIL(resultq, mi, resultentry);

140 }

141 }

142

143 void

144 search_match_group(struct menu_q *menuq, struct menu_q *resultq, char *search)

145 {

146 struct menu *mi;

147 struct group_ctx *gc;

148 char *s;

149

150 TAILQ_INIT(resultq);

151 TAILQ_FOREACH(mi, menuq, entry) {

152 gc = (struct group_ctx *)mi->ctx;

153 xasprintf(&s, "%d %s", gc->num, gc->name);

154 if (match_substr(search, s, 0))

155 TAILQ_INSERT_TAIL(resultq, mi, resultentry);

156 free(s);

157 }

158 }

159

160 static void

161 match_path_type(struct menu_q *resultq, char *search, int flag)

162 {

163 struct menu *mi;

164 char *pattern;

165 glob_t g;

166 int i;

167

168 xasprintf(&pattern, "%s*", search);

169 if (glob(pattern, GLOB_MARK, NULL, &g) != 0)

170 return;

171 for (i = 0; i < g.gl_pathc; i++) {

172 if ((flag & PATH_EXEC) && access(g.gl_pathv[i], X_OK))

173 continue;

174 mi = xcalloc(1, sizeof(*mi));

175 (void)strlcpy(mi->text, g.gl_pathv[i], sizeof(mi->text));

176 TAILQ_INSERT_TAIL(resultq, mi, resultentry);

177 }

178 globfree(&g);

179 free(pattern);

180 }

181

182 void

183 search_match_exec(struct menu_q *menuq, struct menu_q *resultq, char *search)

184 {

185 struct menu *mi, *mj;

186 int r;

187

188 TAILQ_INIT(resultq);

189 TAILQ_FOREACH(mi, menuq, entry) {

190 if (match_substr(search, mi->text, 1) == 0 &&

191 fnmatch(search, mi->text, 0) == FNM_NOMATCH)

192 continue;

193 TAILQ_FOREACH(mj, resultq, resultentry) {

194 r = strcmp(mi->text, mj->text);

195 if (r < 0)

196 TAILQ_INSERT_BEFORE(mj, mi, resultentry);

197 if (r <= 0)

198 break;

199 }

200 if (mj == NULL)

201 TAILQ_INSERT_TAIL(resultq, mi, resultentry);

202 }

203 if (TAILQ_EMPTY(resultq))

204 match_path_type(resultq, search, PATH_EXEC);

205 }

206

207 void

208 search_match_path(struct menu_q *menuq, struct menu_q *resultq, char *search)

209 {

210 TAILQ_INIT(resultq);

211 match_path_type(resultq, search, PATH_ANY);

212 }

213

214 void

215 search_match_text(struct menu_q *menuq, struct menu_q *resultq, char *search)

216 {

217 struct menu *mi;

218

219 TAILQ_INIT(resultq);

220 TAILQ_FOREACH(mi, menuq, entry) {

221 if (match_substr(search, mi->text, 0))

222 TAILQ_INSERT_TAIL(resultq, mi, resultentry);

223 }

224 }

225

226 void

227 search_match_wm(struct menu_q *menuq, struct menu_q *resultq, char *search)

228 {

229 struct menu *mi;

230 struct cmd_ctx *wm;

231

232 TAILQ_INIT(resultq);

233 TAILQ_FOREACH(mi, menuq, entry) {

234 wm = (struct cmd_ctx *)mi->ctx;

235 if ((match_substr(search, wm->name, 0)) ||

236 (match_substr(search, wm->path, 0)))

237 TAILQ_INSERT_TAIL(resultq, mi, resultentry);

238 }

239 }

240

241 void

242 search_print_client(struct menu *mi, int listing)

243 {

244 struct client_ctx *cc = (struct client_ctx *)mi->ctx;

245 char flag = ' ';

246

247 if (cc->flags & CLIENT_ACTIVE)

248 flag = '!';

249 else if (cc->flags & CLIENT_HIDDEN)

250 flag = '&';

251

252 (void)snprintf(mi->print, sizeof(mi->print), "(%d) %c[%s] %s",

253 (cc->gc) ? cc->gc->num : 0, flag,

254 (cc->label) ? cc->label : "", cc->name);

255 }

256

257 void

258 search_print_cmd(struct menu *mi, int listing)

259 {

260 struct cmd_ctx *cmd = (struct cmd_ctx *)mi->ctx;

261

262 (void)snprintf(mi->print, sizeof(mi->print), "%s", cmd->name);

263 }

264

265 void

266 search_print_group(struct menu *mi, int listing)

267 {

268 struct group_ctx *gc = (struct group_ctx *)mi->ctx;

269

270 (void)snprintf(mi->print, sizeof(mi->print),

271 (group_holds_only_hidden(gc)) ? "%d: [%s]" : "%d: %s",

272 gc->num, gc->name);

273 }

274

275 void

276 search_print_text(struct menu *mi, int listing)

277 {

278 (void)snprintf(mi->print, sizeof(mi->print), "%s", mi->text);

279 }

280

281 void

282 search_print_wm(struct menu *mi, int listing)

283 {

284 struct cmd_ctx *wm = (struct cmd_ctx *)mi->ctx;

285

286 (void)snprintf(mi->print, sizeof(mi->print), "%s [%s]",

287 wm->name, wm->path);

288 }

289