1 /*****************************************************************************/
2 /** Copyright 1988 by Evans & Sutherland Computer Corporation, **/
3 /** Salt Lake City, Utah **/
4 /** Portions Copyright 1989 by the Massachusetts Institute of Technology **/
5 /** Cambridge, Massachusetts **/
7 /** All Rights Reserved **/
9 /** Permission to use, copy, modify, and distribute this software and **/
10 /** its documentation for any purpose and without fee is hereby **/
11 /** granted, provided that the above copyright notice appear in all **/
12 /** copies and that both that copyright notice and this permis- **/
13 /** sion notice appear in supporting documentation, and that the **/
14 /** names of Evans & Sutherland and M.I.T. not be used in advertising **/
15 /** in publicity pertaining to distribution of the software without **/
16 /** specific, written prior permission. **/
18 /** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/
19 /** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/
20 /** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/
21 /** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/
22 /** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/
23 /** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/
24 /** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/
25 /** OR PERFORMANCE OF THIS SOFTWARE. **/
26 /*****************************************************************************/
29 /**********************************************************************
31 * $XConsortium: list.c,v 1.20 91/01/09 17:13:30 rws Exp $
33 * TWM code to deal with the name lists for the NoTitle list and
36 * 11-Apr-88 Tom LaStrange Initial Version.
38 **********************************************************************/
41 * Stolen from TVTWM pl11, updated it to conform to the POSIX 1003.2
42 * regex spec, backported VTWM 5.3's internal wildcarding code, and
43 * made it work without regex support.
45 * D. J. Hawkey Jr. - 10/20/01
49 #include <X11/Xatom.h>
51 #ifndef NO_REGEX_SUPPORT
52 #include <sys/types.h>
61 #define REGCOMP_FLAGS (REG_EXTENDED | REG_NOSUB)
63 #define strdup Strdup /* avoid conflict with system header files */
64 extern char *strdup(char *);
66 struct name_list_struct
68 name_list *next; /* pointer to the next name */
69 char *name; /* the name of the window */
70 #ifndef NO_REGEX_SUPPORT
71 regex_t re; /* compile only once */
73 char re; /* not used */
75 short type; /* what type of match */
76 Atom property; /* if (type == property) */
77 char *ptr; /* list dependent data */
80 #ifndef NO_REGEX_SUPPORT
81 static char buffer[256];
86 /***********************************************************************
88 * Wrappers to allow code to step through a list
90 ***********************************************************************/
100 contents_of_entry(list)
106 /**********************************************************************/
110 printNameList(name, nptr)
114 printf("printNameList(): %s=[", name);
118 printf(" '%s':%d", nptr->name, nptr->type);
126 /***********************************************************************
129 * AddToList - add a window name to the appropriate list
132 * list - the address of the pointer to the head of a list
133 * name - a pointer to the name of the window
134 * type - a bitmask of what to match against
135 * property- a window propery to match against
136 * ptr - pointer to list dependent data
138 * Special Considerations
139 * If the list does not use the ptr value, a non-null value
140 * should be placed in it. LookInList returns this ptr value
141 * and procedures calling LookInList will check for a non-null
142 * return value as an indication of success.
144 ***********************************************************************
148 AddToList(list_head, name, type, /*property, */ptr)
149 name_list **list_head;
155 Atom property = None;
158 if (!list_head) return; /* ignore empty inserts */
160 nptr = (name_list *)malloc(sizeof(name_list));
163 fprintf (stderr, "%s: unable to allocate %d bytes for name_list\n",
164 ProgramName, sizeof(name_list));
170 list_head = &((*list_head)->next);
174 nptr->next = *list_head;
177 nptr->name = (char *)strdup(name);
178 if (type & LTYPE_HOST)
180 nptr->type = (type & ~LTYPE_HOST) | LTYPE_PROPERTY;
181 nptr->property = XA_WM_CLIENT_MACHINE;
186 nptr->property = property;
188 nptr->ptr = (ptr == NULL) ? (char *)TRUE : ptr;
193 /********************************************************************\
195 * New LookInList code by RJC. *
197 * Since we want to be able to look for multiple matches (eg, to *
198 * check which relevant icon regions are on the screen), the basic *
199 * procedure is now MultiLookInList and uses a (pseudo-)continuation *
200 * to keep track of where it is. *
202 * LookInList is a trivial specialisation of that. *
204 * Also, we now allow regular expressions in lists, so here we use *
205 * Henry Spencer's regular expression code. It is possible that we *
206 * should pre-compile all the regular expressions for maximum *
209 \********************************************************************/
212 MatchName(name, pattern, compiled, type)
215 #ifndef NO_REGEX_SUPPORT
223 fprintf(stderr, "MatchName(): compare '%s' with '%s'\n", name, pattern);
226 if (type & LTYPE_ANYTHING)
229 if (type & LTYPE_REGEXP)
231 #ifndef NO_REGEX_SUPPORT
235 if ((result = regcomp(&re, pattern, REGCOMP_FLAGS)) != 0)
237 regerror(result, &re, buffer, sizeof(buffer));
240 fprintf(stderr, "%s: (1) regcomp(\"%s\") error: %s\n",
241 ProgramName, pattern, buffer);
245 result = regexec(&re, name, 0, NULL, 0);
250 fprintf(stderr, "%s: (1) no support for regcomp(\"%s\")\n",
251 ProgramName, pattern);
256 if (type & LTYPE_C_REGEXP)
258 #ifndef NO_REGEX_SUPPORT
259 return (regexec(compiled, name, 0, NULL, 0));
261 fprintf(stderr, "%s: no support for regexec(\"%s\")\n",
267 if (type & LTYPE_STRING)
268 return (match(pattern, name));
270 fprintf(stderr, "%s: bad list type (%d) comparing \"%s\" with \"%s\"\n",
271 ProgramName, type, name, pattern);
276 MultiLookInList(list_head, name, class, /*win, */continuation)
277 name_list *list_head;
281 name_list **continuation;
289 fprintf(stderr, "MultiLookInList(): looking for '%s'\n", name);
292 for (nptr = list_head ; nptr ; nptr = nptr->next)
294 /* pre-compile and cache the regex_t */
295 if (nptr->type & LTYPE_REGEXP)
297 #ifndef NO_REGEX_SUPPORT
300 if ((result = regcomp(&nptr->re, nptr->name, REGCOMP_FLAGS)) != 0)
302 regerror(result, &nptr->re, buffer, sizeof(buffer));
305 fprintf(stderr, "%s: (2) regcomp(\"%s\") error: %s\n",
306 ProgramName, nptr->name, buffer);
308 nptr->type |= LTYPE_NOTHING;
311 nptr->type |= LTYPE_C_REGEXP;
313 fprintf(stderr, "%s: (2) no support for regcomp(\"%s\")\n",
314 ProgramName, nptr->name);
316 nptr->type |= LTYPE_NOTHING;
319 nptr->type &= ~LTYPE_REGEXP;
322 if (nptr->type & LTYPE_NOTHING)
323 continue; /* skip illegal entry */
325 if (nptr->type & LTYPE_ANYTHING)
327 *continuation = nptr->next;
331 if (nptr->type & LTYPE_NAME)
332 if (MatchName(name, nptr->name, &nptr->re, nptr->type) == 0)
334 *continuation = nptr->next;
340 if (nptr->type & LTYPE_RES_NAME)
341 if (MatchName(class->res_name, nptr->name, &nptr->re,
344 *continuation = nptr->next;
348 if (nptr->type & LTYPE_RES_CLASS)
349 if (MatchName(class->res_class, nptr->name, &nptr->re,
352 *continuation = nptr->next;
358 if (win && (nptr->type & LTYPE_PROPERTY))
360 char *s = GetPropertyString(win, nptr->property);
362 if (s && MatchName(s, nptr->name, &nptr->re, nptr->type) == 0)
366 *continuation = nptr->next;
375 *continuation = NULL;
380 LookInList(list_head, name, class/*, win*/)
381 name_list *list_head;
390 char *return_name = MultiLookInList(list_head, name, class, /*win, */&rest);
393 if ((Scr->ListRings == TRUE) && (return_name != NULL)
394 && (list_head->next != NULL))
396 /* To implement a ring on the linked list where we cant change the */
397 /* list_head, use a simple unlink/link-at-end alg. unless you need */
398 /* to move the first link. In that case swap the contents of the */
399 /* first link with the contents of the second then proceed as */
401 name_list *tmp_namelist;
403 if (list_head->ptr == return_name)
409 tmp_name = list_head->name;
410 tmp_type = list_head->type;
411 tmp_ptr = list_head->ptr;
413 list_head->name = list_head->next->name;
414 list_head->type = list_head->next->type;
415 list_head->ptr = list_head->next->ptr;
417 list_head->next->name = tmp_name;
418 list_head->next->type = tmp_type;
419 list_head->next->ptr = tmp_ptr;
422 for (nptr = list_head; nptr->next != NULL; nptr = nptr->next)
424 if (nptr->next->ptr == return_name)
428 if (nptr->next->next != NULL)
430 tmp_namelist = nptr->next;
431 nptr->next = nptr->next->next;
433 for (nptr = nptr->next; nptr->next != NULL; nptr = nptr->next);
434 nptr->next = tmp_namelist;
435 nptr->next->next = NULL;
440 return (return_name);
445 MultiLookInNameList(list_head, name, continuation)
446 name_list *list_head;
448 name_list **continuation;
450 return (MultiLookInList(list_head, name, NULL, /*None, */continuation));
455 LookInNameList(list_head, name)
456 name_list *list_head;
459 return (MultiLookInList(list_head, name, NULL, /*None, */&list_head));
462 /***********************************************************************
465 * GetColorFromList - look through a list for a window name, or class
468 * TRUE if the name was found
469 * FALSE if the name was not found
472 * list - a pointer to the head of a list
473 * name - a pointer to the name to look for
474 * class - a pointer to the class to look for
477 * ptr - fill in the list value if the name was found
479 ***********************************************************************
482 int GetColorFromList(list_head, name, class, /*win, */ptr)
483 name_list *list_head;
490 char *val = LookInList(list_head, name, class/*, win*/);
494 save = Scr->FirstTime;
495 Scr->FirstTime = TRUE;
496 GetColor(Scr->Monochrome, ptr, val);
497 Scr->FirstTime = save;
505 /***********************************************************************
508 * FreeList - free up a list
510 ***********************************************************************
519 for (nptr = *list; nptr != NULL; )
523 #ifndef NO_REGEX_SUPPORT
524 if (nptr->type & LTYPE_C_REGEXP)
536 /***********************************************************************
538 * MSDOS-ish, Unix-ish, VTWM 5.3 wildcard support
540 **********************************************************************/
543 static int is_pattern(p)
555 if (!*p++) return (FALSE);
565 static int regex_match();
567 static int regex_match_after_star(p, t)
573 while ((*p == '?') || (*p == '*'))
576 if (!*t++) return (ABORT);
580 if (!*p) return (TRUE);
583 if (nextp == '\\') nextp = p[1];
586 while (match == FALSE)
588 if (nextp == *t || nextp == '[')
589 match = regex_match(p, t);
591 if (!*t++) match = ABORT;
597 static int regex_match(p, t)
600 register char range_start, range_end;
607 if (!*t) return ((*p == '*' && *++p == '\0') ? TRUE : ABORT);
614 return (regex_match_after_star(p, t));
619 if (*p == '!' || *p == '^')
625 if (*p == ']') return (ABORT);
627 member_match = FALSE;
638 range_start = range_end = *++p;
640 range_start = range_end = *p;
641 if (!range_start) return (ABORT);
646 if (range_end == '\0' || range_end == ']')
649 if (range_end == '\\')
654 if (range_start < range_end)
656 if (*t >= range_start && *t <= range_end)
664 if (*t >= range_end && *t <= range_start)
672 if ((invert && member_match) || !(invert || member_match))
679 if (!*p) return (ABORT);
691 if (*p != *t) return (FALSE);
701 if ((p == NULL) || (t == NULL)) return (TRUE);
703 return ((regex_match(p, t) == TRUE) ? FALSE : TRUE);