2007-04-27 11:58:48 -06:00
|
|
|
/*
|
|
|
|
* calmwm - the calm window manager
|
|
|
|
*
|
|
|
|
* Copyright (c) 2004 Marius Aamodt Eriksen <marius@monkey.org>
|
2011-05-11 07:53:51 -06:00
|
|
|
*
|
2008-01-11 09:06:44 -07:00
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
2007-04-27 11:58:48 -06:00
|
|
|
*
|
2008-01-11 09:06:44 -07:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*
|
2017-04-24 07:35:25 -06:00
|
|
|
* $OpenBSD: search.c,v 1.60 2017/04/24 13:35:25 okan Exp $
|
2007-04-27 11:58:48 -06:00
|
|
|
*/
|
|
|
|
|
2015-01-19 07:54:16 -07:00
|
|
|
#include <sys/types.h>
|
2009-12-14 21:10:42 -07:00
|
|
|
#include <sys/queue.h>
|
|
|
|
|
|
|
|
#include <err.h>
|
|
|
|
#include <errno.h>
|
2009-06-26 06:45:12 -06:00
|
|
|
#include <fnmatch.h>
|
2012-11-08 20:52:02 -07:00
|
|
|
#include <glob.h>
|
2015-01-19 07:54:16 -07:00
|
|
|
#include <limits.h>
|
2012-11-08 20:52:02 -07:00
|
|
|
#include <stdio.h>
|
2009-12-14 21:10:42 -07:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
2009-12-14 20:24:36 -07:00
|
|
|
|
2007-04-27 11:58:48 -06:00
|
|
|
#include "calmwm.h"
|
|
|
|
|
2013-04-05 11:36:02 -06:00
|
|
|
#define PATH_ANY 0x0001
|
|
|
|
#define PATH_EXEC 0x0002
|
2012-11-07 07:39:44 -07:00
|
|
|
|
2016-12-01 13:28:19 -07:00
|
|
|
static void search_match_path_type(struct menu_q *, struct menu_q *,
|
2013-04-05 11:36:02 -06:00
|
|
|
char *, int);
|
2009-05-17 18:23:35 -06:00
|
|
|
static int strsubmatch(char *, char *, int);
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
void
|
|
|
|
search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
|
|
|
|
{
|
2008-07-11 08:21:28 -06:00
|
|
|
struct winname *wn;
|
|
|
|
struct menu *mi, *tierp[4], *before = NULL;
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
TAILQ_INIT(resultq);
|
|
|
|
|
2011-07-25 09:10:24 -06:00
|
|
|
(void)memset(tierp, 0, sizeof(tierp));
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
TAILQ_FOREACH(mi, menuq, entry) {
|
|
|
|
int tier = -1, t;
|
2015-06-30 12:42:50 -06:00
|
|
|
struct client_ctx *cc = (struct client_ctx *)mi->ctx;
|
2007-04-27 11:58:48 -06:00
|
|
|
|
2016-10-22 13:16:43 -06:00
|
|
|
/* Match on label. */
|
2016-10-24 12:57:12 -06:00
|
|
|
if (strsubmatch(search, cc->label, 0))
|
2007-04-27 11:58:48 -06:00
|
|
|
tier = 0;
|
|
|
|
|
2016-10-22 13:16:43 -06:00
|
|
|
/* Match on window name history, from present to past. */
|
2007-04-27 11:58:48 -06:00
|
|
|
if (tier < 0) {
|
2016-10-18 11:03:30 -06:00
|
|
|
TAILQ_FOREACH_REVERSE(wn, &cc->nameq, name_q, entry)
|
2009-05-17 18:23:35 -06:00
|
|
|
if (strsubmatch(search, wn->name, 0)) {
|
2008-04-15 14:24:41 -06:00
|
|
|
tier = 2;
|
|
|
|
break;
|
|
|
|
}
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
2016-10-24 12:57:12 -06:00
|
|
|
/* Match on window resource class. */
|
2016-10-24 11:16:23 -06:00
|
|
|
if ((tier < 0) && strsubmatch(search, cc->ch.res_class, 0))
|
2007-04-27 11:58:48 -06:00
|
|
|
tier = 3;
|
|
|
|
|
|
|
|
if (tier < 0)
|
|
|
|
continue;
|
|
|
|
|
2016-10-22 13:16:43 -06:00
|
|
|
/* Current window is ranked down. */
|
|
|
|
if ((tier < nitems(tierp) - 1) && (cc->flags & CLIENT_ACTIVE))
|
2007-04-27 11:58:48 -06:00
|
|
|
tier++;
|
|
|
|
|
2016-10-22 13:16:43 -06:00
|
|
|
/* Hidden window is ranked up. */
|
|
|
|
if ((tier > 0) && (cc->flags & CLIENT_HIDDEN))
|
2007-04-27 11:58:48 -06:00
|
|
|
tier--;
|
|
|
|
|
2015-06-28 13:50:46 -06:00
|
|
|
if (tier >= nitems(tierp))
|
2016-10-24 11:39:38 -06:00
|
|
|
errx(1, "%s: invalid tier", __func__);
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If you have a tierp, insert after it, and make it
|
|
|
|
* the new tierp. If you don't have a tierp, find the
|
|
|
|
* first nonzero tierp above you, insert after it.
|
|
|
|
* Always make your current tierp the newly inserted
|
|
|
|
* entry.
|
|
|
|
*/
|
|
|
|
for (t = tier; t >= 0 && ((before = tierp[t]) == NULL); t--)
|
|
|
|
;
|
|
|
|
|
|
|
|
if (before == NULL)
|
|
|
|
TAILQ_INSERT_HEAD(resultq, mi, resultentry);
|
|
|
|
else
|
|
|
|
TAILQ_INSERT_AFTER(resultq, before, mi, resultentry);
|
|
|
|
|
|
|
|
tierp[tier] = mi;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-30 12:54:12 -06:00
|
|
|
void
|
2016-12-06 14:54:10 -07:00
|
|
|
search_print_text(struct menu *mi, int listing)
|
|
|
|
{
|
|
|
|
(void)snprintf(mi->print, sizeof(mi->print), "%s", mi->text);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
search_print_cmd(struct menu *mi, int listing)
|
2015-06-30 12:54:12 -06:00
|
|
|
{
|
2016-10-18 11:03:30 -06:00
|
|
|
struct cmd_ctx *cmd = (struct cmd_ctx *)mi->ctx;
|
2015-06-30 12:54:12 -06:00
|
|
|
|
2015-08-21 10:05:55 -06:00
|
|
|
(void)snprintf(mi->print, sizeof(mi->print), "%s", cmd->name);
|
2015-06-30 12:54:12 -06:00
|
|
|
}
|
|
|
|
|
2015-07-12 08:31:47 -06:00
|
|
|
void
|
2016-12-06 14:54:10 -07:00
|
|
|
search_print_group(struct menu *mi, int listing)
|
2015-07-12 08:31:47 -06:00
|
|
|
{
|
|
|
|
struct group_ctx *gc = (struct group_ctx *)mi->ctx;
|
|
|
|
|
|
|
|
(void)snprintf(mi->print, sizeof(mi->print),
|
|
|
|
(group_holds_only_hidden(gc)) ? "%d: [%s]" : "%d: %s",
|
|
|
|
gc->num, gc->name);
|
|
|
|
}
|
|
|
|
|
2007-04-27 11:58:48 -06:00
|
|
|
void
|
2016-12-06 14:54:10 -07:00
|
|
|
search_print_client(struct menu *mi, int listing)
|
2007-04-27 11:58:48 -06:00
|
|
|
{
|
2015-06-30 12:42:50 -06:00
|
|
|
struct client_ctx *cc = (struct client_ctx *)mi->ctx;
|
2008-07-11 08:21:28 -06:00
|
|
|
char flag = ' ';
|
|
|
|
|
2016-09-14 13:45:33 -06:00
|
|
|
if (cc->flags & CLIENT_ACTIVE)
|
2007-04-27 11:58:48 -06:00
|
|
|
flag = '!';
|
|
|
|
else if (cc->flags & CLIENT_HIDDEN)
|
|
|
|
flag = '&';
|
|
|
|
|
2015-06-08 09:34:03 -06:00
|
|
|
(void)snprintf(mi->print, sizeof(mi->print), "(%d) %c[%s] %s",
|
2015-08-27 12:53:14 -06:00
|
|
|
(cc->gc) ? cc->gc->num : 0, flag,
|
2016-10-24 11:16:23 -06:00
|
|
|
(cc->label) ? cc->label : "", cc->name);
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|
|
|
|
|
2012-11-07 07:39:44 -07:00
|
|
|
static void
|
2016-12-01 13:28:19 -07:00
|
|
|
search_match_path_type(struct menu_q *menuq, struct menu_q *resultq,
|
|
|
|
char *search, int flag)
|
2012-11-07 07:39:44 -07:00
|
|
|
{
|
2015-01-19 07:54:16 -07:00
|
|
|
char pattern[PATH_MAX];
|
2014-01-20 11:58:03 -07:00
|
|
|
glob_t g;
|
|
|
|
int i;
|
2012-11-07 07:39:44 -07:00
|
|
|
|
|
|
|
(void)strlcpy(pattern, search, sizeof(pattern));
|
|
|
|
(void)strlcat(pattern, "*", sizeof(pattern));
|
|
|
|
|
|
|
|
if (glob(pattern, GLOB_MARK, NULL, &g) != 0)
|
|
|
|
return;
|
|
|
|
for (i = 0; i < g.gl_pathc; i++) {
|
|
|
|
if ((flag & PATH_EXEC) && access(g.gl_pathv[i], X_OK))
|
|
|
|
continue;
|
2014-01-20 11:58:03 -07:00
|
|
|
menuq_add(resultq, NULL, "%s", g.gl_pathv[i]);
|
2012-11-07 07:39:44 -07:00
|
|
|
}
|
|
|
|
globfree(&g);
|
|
|
|
}
|
|
|
|
|
2013-04-05 11:07:25 -06:00
|
|
|
void
|
2016-12-01 13:28:19 -07:00
|
|
|
search_match_path(struct menu_q *menuq, struct menu_q *resultq, char *search)
|
2012-11-07 07:39:44 -07:00
|
|
|
{
|
2017-04-24 07:35:25 -06:00
|
|
|
TAILQ_INIT(resultq);
|
|
|
|
|
2016-12-01 13:28:19 -07:00
|
|
|
return(search_match_path_type(menuq, resultq, search, PATH_ANY));
|
2012-11-07 07:39:44 -07:00
|
|
|
}
|
|
|
|
|
2007-04-27 11:58:48 -06:00
|
|
|
void
|
|
|
|
search_match_text(struct menu_q *menuq, struct menu_q *resultq, char *search)
|
|
|
|
{
|
2008-07-11 08:21:28 -06:00
|
|
|
struct menu *mi;
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
TAILQ_INIT(resultq);
|
|
|
|
|
|
|
|
TAILQ_FOREACH(mi, menuq, entry)
|
2009-05-17 18:23:35 -06:00
|
|
|
if (strsubmatch(search, mi->text, 0))
|
2007-06-26 13:34:26 -06:00
|
|
|
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
search_match_exec(struct menu_q *menuq, struct menu_q *resultq, char *search)
|
|
|
|
{
|
2008-09-02 22:39:12 -06:00
|
|
|
struct menu *mi, *mj;
|
2013-04-03 13:28:00 -06:00
|
|
|
int r;
|
2007-06-26 13:34:26 -06:00
|
|
|
|
|
|
|
TAILQ_INIT(resultq);
|
|
|
|
|
2008-09-02 22:39:12 -06:00
|
|
|
TAILQ_FOREACH(mi, menuq, entry) {
|
2009-06-26 06:45:12 -06:00
|
|
|
if (strsubmatch(search, mi->text, 1) == 0 &&
|
|
|
|
fnmatch(search, mi->text, 0) == FNM_NOMATCH)
|
2013-03-09 14:55:56 -07:00
|
|
|
continue;
|
|
|
|
TAILQ_FOREACH(mj, resultq, resultentry) {
|
2013-04-03 13:28:00 -06:00
|
|
|
r = strcasecmp(mi->text, mj->text);
|
|
|
|
if (r < 0)
|
2008-09-02 22:39:12 -06:00
|
|
|
TAILQ_INSERT_BEFORE(mj, mi, resultentry);
|
2013-04-03 13:28:00 -06:00
|
|
|
if (r <= 0)
|
2008-09-02 22:39:12 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (mj == NULL)
|
2007-04-27 11:58:48 -06:00
|
|
|
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
|
2008-09-02 22:39:12 -06:00
|
|
|
}
|
2007-04-27 11:58:48 -06:00
|
|
|
|
2012-11-07 07:39:44 -07:00
|
|
|
if (TAILQ_EMPTY(resultq))
|
2016-12-01 13:28:19 -07:00
|
|
|
search_match_path_type(menuq, resultq, search, PATH_EXEC);
|
2012-11-07 07:39:44 -07:00
|
|
|
}
|
|
|
|
|
2007-04-27 11:58:48 -06:00
|
|
|
static int
|
2009-05-17 18:23:35 -06:00
|
|
|
strsubmatch(char *sub, char *str, int zeroidx)
|
2007-04-27 11:58:48 -06:00
|
|
|
{
|
2014-01-03 08:29:06 -07:00
|
|
|
size_t len, sublen;
|
|
|
|
unsigned int n, flen;
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
if (sub == NULL || str == NULL)
|
2014-09-07 13:27:30 -06:00
|
|
|
return(0);
|
2007-04-27 11:58:48 -06:00
|
|
|
|
|
|
|
len = strlen(str);
|
|
|
|
sublen = strlen(sub);
|
|
|
|
|
|
|
|
if (sublen > len)
|
2014-09-07 13:27:30 -06:00
|
|
|
return(0);
|
2007-04-27 11:58:48 -06:00
|
|
|
|
2007-06-26 13:34:26 -06:00
|
|
|
if (!zeroidx)
|
|
|
|
flen = len - sublen;
|
|
|
|
else
|
|
|
|
flen = 0;
|
2008-07-11 08:21:28 -06:00
|
|
|
|
2007-06-26 13:34:26 -06:00
|
|
|
for (n = 0; n <= flen; n++)
|
2007-04-27 11:58:48 -06:00
|
|
|
if (strncasecmp(sub, str + n, sublen) == 0)
|
2014-09-07 13:27:30 -06:00
|
|
|
return(1);
|
2007-04-27 11:58:48 -06:00
|
|
|
|
2014-09-07 13:27:30 -06:00
|
|
|
return(0);
|
2007-04-27 11:58:48 -06:00
|
|
|
}
|