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 struct name_list_struct
65 name_list *next; /* pointer to the next name */
66 char *name; /* the name of the window */
67 #ifndef NO_REGEX_SUPPORT
68 regex_t re; /* compile only once */
70 char re; /* not used */
72 short type; /* what type of match */
73 Atom property; /* if (type == property) */
74 char *ptr; /* list dependent data */
77 #ifndef NO_REGEX_SUPPORT
78 static char buffer[256];
83 /***********************************************************************
85 * Wrappers to allow code to step through a list
87 ***********************************************************************/
97 contents_of_entry(list)
103 /**********************************************************************/
107 printNameList(name, nptr)
111 printf("printNameList(): %s=[", name);
115 printf(" '%s':%d", nptr->name, nptr->type);
123 /***********************************************************************
126 * AddToList - add a window name to the appropriate list
129 * list - the address of the pointer to the head of a list
130 * name - a pointer to the name of the window
131 * type - a bitmask of what to match against
132 * property- a window propery to match against
133 * ptr - pointer to list dependent data
135 * Special Considerations
136 * If the list does not use the ptr value, a non-null value
137 * should be placed in it. LookInList returns this ptr value
138 * and procedures calling LookInList will check for a non-null
139 * return value as an indication of success.
141 ***********************************************************************
145 AddToList(list_head, name, type, /*property, */ptr)
146 name_list **list_head;
152 Atom property = None;
155 if (!list_head) return; /* ignore empty inserts */
157 nptr = (name_list *)malloc(sizeof(name_list));
160 fprintf (stderr, "%s: unable to allocate %d bytes for name_list\n",
161 ProgramName, sizeof(name_list));
167 list_head = &((*list_head)->next);
171 nptr->next = *list_head;
174 nptr->name = (char *)strdup(name);
175 if (type & LTYPE_HOST)
177 nptr->type = (type & ~LTYPE_HOST) | LTYPE_PROPERTY;
178 nptr->property = XA_WM_CLIENT_MACHINE;
183 nptr->property = property;
185 nptr->ptr = (ptr == NULL) ? (char *)TRUE : ptr;
190 /********************************************************************\
192 * New LookInList code by RJC. *
194 * Since we want to be able to look for multiple matches (eg, to *
195 * check which relevant icon regions are on the screen), the basic *
196 * procedure is now MultiLookInList and uses a (pseudo-)continuation *
197 * to keep track of where it is. *
199 * LookInList is a trivial specialisation of that. *
201 * Also, we now allow regular expressions in lists, so here we use *
202 * Henry Spencer's regular expression code. It is possible that we *
203 * should pre-compile all the regular expressions for maximum *
206 \********************************************************************/
209 MatchName(name, pattern, compiled, type)
212 #ifndef NO_REGEX_SUPPORT
220 fprintf(stderr, "MatchName(): compare '%s' with '%s'\n", name, pattern);
223 if (type & LTYPE_ANYTHING)
226 if (type & LTYPE_REGEXP)
228 #ifndef NO_REGEX_SUPPORT
232 if ((result = regcomp(&re, pattern, REGCOMP_FLAGS)) != 0)
234 regerror(result, &re, buffer, sizeof(buffer));
237 fprintf(stderr, "%s: (1) regcomp(\"%s\") error: %s\n",
238 ProgramName, pattern, buffer);
242 result = regexec(&re, name, 0, NULL, 0);
247 fprintf(stderr, "%s: (1) no support for regcomp(\"%s\")\n",
248 ProgramName, pattern);
253 if (type & LTYPE_C_REGEXP)
255 #ifndef NO_REGEX_SUPPORT
256 return (regexec(compiled, name, 0, NULL, 0));
258 fprintf(stderr, "%s: no support for regexec(\"%s\")\n",
264 if (type & LTYPE_STRING)
265 return (match(pattern, name));
267 fprintf(stderr, "%s: bad list type (%d) comparing \"%s\" with \"%s\"\n",
268 ProgramName, type, name, pattern);
273 MultiLookInList(list_head, name, class, /*win, */continuation)
274 name_list *list_head;
278 name_list **continuation;
286 fprintf(stderr, "MultiLookInList(): looking for '%s'\n", name);
289 for (nptr = list_head ; nptr ; nptr = nptr->next)
291 /* pre-compile and cache the regex_t */
292 if (nptr->type & LTYPE_REGEXP)
294 #ifndef NO_REGEX_SUPPORT
297 if ((result = regcomp(&nptr->re, nptr->name, REGCOMP_FLAGS)) != 0)
299 regerror(result, &nptr->re, buffer, sizeof(buffer));
302 fprintf(stderr, "%s: (2) regcomp(\"%s\") error: %s\n",
303 ProgramName, nptr->name, buffer);
305 nptr->type |= LTYPE_NOTHING;
308 nptr->type |= LTYPE_C_REGEXP;
310 fprintf(stderr, "%s: (2) no support for regcomp(\"%s\")\n",
311 ProgramName, nptr->name);
313 nptr->type |= LTYPE_NOTHING;
316 nptr->type &= ~LTYPE_REGEXP;
319 if (nptr->type & LTYPE_NOTHING)
320 continue; /* skip illegal entry */
322 if (nptr->type & LTYPE_ANYTHING)
324 *continuation = nptr->next;
328 if (nptr->type & LTYPE_NAME)
329 if (MatchName(name, nptr->name, &nptr->re, nptr->type) == 0)
331 *continuation = nptr->next;
337 if (nptr->type & LTYPE_RES_NAME)
338 if (MatchName(class->res_name, nptr->name, &nptr->re,
341 *continuation = nptr->next;
345 if (nptr->type & LTYPE_RES_CLASS)
346 if (MatchName(class->res_class, nptr->name, &nptr->re,
349 *continuation = nptr->next;
355 if (win && (nptr->type & LTYPE_PROPERTY))
357 char *s = GetPropertyString(win, nptr->property);
359 if (s && MatchName(s, nptr->name, &nptr->re, nptr->type) == 0)
363 *continuation = nptr->next;
372 *continuation = NULL;
377 LookInList(list_head, name, class/*, win*/)
378 name_list *list_head;
387 char *return_name = MultiLookInList(list_head, name, class, /*win, */&rest);
390 if ((Scr->ListRings == TRUE) && (return_name != NULL)
391 && (list_head->next != NULL))
393 /* To implement a ring on the linked list where we cant change the */
394 /* list_head, use a simple unlink/link-at-end alg. unless you need */
395 /* to move the first link. In that case swap the contents of the */
396 /* first link with the contents of the second then proceed as */
398 name_list *tmp_namelist;
400 if (list_head->ptr == return_name)
406 tmp_name = list_head->name;
407 tmp_type = list_head->type;
408 tmp_ptr = list_head->ptr;
410 list_head->name = list_head->next->name;
411 list_head->type = list_head->next->type;
412 list_head->ptr = list_head->next->ptr;
414 list_head->next->name = tmp_name;
415 list_head->next->type = tmp_type;
416 list_head->next->ptr = tmp_ptr;
419 for (nptr = list_head; nptr->next != NULL; nptr = nptr->next)
421 if (nptr->next->ptr == return_name)
425 if (nptr->next->next != NULL)
427 tmp_namelist = nptr->next;
428 nptr->next = nptr->next->next;
430 for (nptr = nptr->next; nptr->next != NULL; nptr = nptr->next);
431 nptr->next = tmp_namelist;
432 nptr->next->next = NULL;
437 return (return_name);
442 MultiLookInNameList(list_head, name, continuation)
443 name_list *list_head;
445 name_list **continuation;
447 return (MultiLookInList(list_head, name, NULL, /*None, */continuation));
452 LookInNameList(list_head, name)
453 name_list *list_head;
456 return (MultiLookInList(list_head, name, NULL, /*None, */&list_head));
459 /***********************************************************************
462 * GetColorFromList - look through a list for a window name, or class
465 * TRUE if the name was found
466 * FALSE if the name was not found
469 * list - a pointer to the head of a list
470 * name - a pointer to the name to look for
471 * class - a pointer to the class to look for
474 * ptr - fill in the list value if the name was found
476 ***********************************************************************
479 int GetColorFromList(list_head, name, class, /*win, */ptr)
480 name_list *list_head;
487 char *val = LookInList(list_head, name, class/*, win*/);
491 save = Scr->FirstTime;
492 Scr->FirstTime = TRUE;
493 GetColor(Scr->Monochrome, ptr, val);
494 Scr->FirstTime = save;
502 /***********************************************************************
505 * FreeList - free up a list
507 ***********************************************************************
516 for (nptr = *list; nptr != NULL; )
520 #ifndef NO_REGEX_SUPPORT
521 if (nptr->type & LTYPE_C_REGEXP)
533 /***********************************************************************
535 * MSDOS-ish, Unix-ish, VTWM 5.3 wildcard support
537 **********************************************************************/
540 static int is_pattern(p)
552 if (!*p++) return (FALSE);
562 static int regex_match();
564 static int regex_match_after_star(p, t)
570 while ((*p == '?') || (*p == '*'))
573 if (!*t++) return (ABORT);
577 if (!*p) return (TRUE);
580 if (nextp == '\\') nextp = p[1];
583 while (match == FALSE)
585 if (nextp == *t || nextp == '[')
586 match = regex_match(p, t);
588 if (!*t++) match = ABORT;
594 static int regex_match(p, t)
597 register char range_start, range_end;
604 if (!*t) return ((*p == '*' && *++p == '\0') ? TRUE : ABORT);
611 return (regex_match_after_star(p, t));
616 if (*p == '!' || *p == '^')
622 if (*p == ']') return (ABORT);
624 member_match = FALSE;
635 range_start = range_end = *++p;
637 range_start = range_end = *p;
638 if (!range_start) return (ABORT);
643 if (range_end == '\0' || range_end == ']')
646 if (range_end == '\\')
651 if (range_start < range_end)
653 if (*t >= range_start && *t <= range_end)
661 if (*t >= range_end && *t <= range_start)
669 if ((invert && member_match) || !(invert || member_match))
676 if (!*p) return (ABORT);
688 if (*p != *t) return (FALSE);
698 if ((p == NULL) || (t == NULL)) return (TRUE);
700 return ((regex_match(p, t) == TRUE) ? FALSE : TRUE);