list.c revision 0bbfda8a
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
6 *
7 * Copyright 1992 Claude Lecommandeur.
8 */
9
10/**********************************************************************
11 *
12 * $XConsortium: list.c,v 1.20 91/01/09 17:13:30 rws Exp $
13 *
14 * TWM code to deal with the name lists for the NoTitle list and
15 * the AutoRaise list
16 *
17 * 11-Apr-88 Tom LaStrange        Initial Version.
18 *
19 * Do the necessary modification to be integrated in ctwm.
20 * Can no longer be used for the standard twm.
21 *
22 * 22-April-92 Claude Lecommandeur.
23 *
24 *
25 **********************************************************************/
26
27#include "ctwm.h"
28
29#include <stdio.h>
30#include <stdlib.h>
31
32#include "screen.h"
33#include "list.h"
34#include "util.h"
35#include "parse.h"
36
37#ifdef USE_SYS_REGEX
38# include <regex.h>
39#endif /* USE_SYS_REGEX */
40
41
42
43/***********************************************************************
44 *
45 *  Procedure:
46 *      AddToList - add a window name to the appropriate list
47 *
48 *  Inputs:
49 *      list    - the address of the pointer to the head of a list
50 *      name    - a pointer to the name of the window
51 *      ptr     - pointer to list dependent data
52 *
53 *  Special Considerations
54 *      If the list does not use the ptr value, a non-null value
55 *      should be placed in it.  LookInList returns this ptr value
56 *      and procedures calling LookInList will check for a non-null
57 *      return value as an indication of success.
58 *
59 ***********************************************************************
60 */
61
62void AddToList(name_list **list_head, const char *name, void *ptr)
63{
64	name_list *nptr;
65
66	if(!list_head) {
67		return;        /* ignore empty inserts */
68	}
69
70	nptr = malloc(sizeof(name_list));
71	if(nptr == NULL) {
72		fprintf(stderr, "unable to allocate %lu bytes for name_list\n",
73		        (unsigned long) sizeof(name_list));
74		Done(0);
75	}
76
77	nptr->next = *list_head;
78	nptr->name = strdup(name);
79	nptr->ptr = (ptr == NULL) ? (char *)1 : ptr;
80	*list_head = nptr;
81}
82
83/***********************************************************************
84 *
85 *  Procedure:
86 *      LookInList - look through a list for a window name, or class
87 *
88 *  Returned Value:
89 *      the ptr field of the list structure or NULL if the name
90 *      or class was not found in the list
91 *
92 *  Inputs:
93 *      list    - a pointer to the head of a list
94 *      name    - a pointer to the name to look for
95 *      class   - a pointer to the class to look for
96 *
97 ***********************************************************************
98 */
99
100void *LookInList(name_list *list_head, const char *name, XClassHint *class)
101{
102	name_list *nptr;
103
104	/* look for the name first */
105	for(nptr = list_head; nptr != NULL; nptr = nptr->next) {
106		if(match(nptr->name, name)) {
107			return (nptr->ptr);
108		}
109	}
110
111	if(class) {
112		/* look for the res_name next */
113		for(nptr = list_head; nptr != NULL; nptr = nptr->next) {
114			if(match(nptr->name, class->res_name)) {
115				return (nptr->ptr);
116			}
117		}
118
119		/* finally look for the res_class */
120		for(nptr = list_head; nptr != NULL; nptr = nptr->next) {
121			if(match(nptr->name, class->res_class)) {
122				return (nptr->ptr);
123			}
124		}
125	}
126	return (NULL);
127}
128
129void *LookInNameList(name_list *list_head, const char *name)
130{
131	return (LookInList(list_head, name, NULL));
132}
133
134void *LookInListWin(name_list *list_head, TwmWindow *twin)
135{
136	return LookInList(list_head, twin->name, &(twin->class));
137}
138
139bool IsInList(name_list *list_head, TwmWindow *twin)
140{
141	return (bool)LookInList(list_head, twin->name, &(twin->class));
142}
143
144void *LookPatternInList(name_list *list_head, const char *name,
145                        XClassHint *class)
146{
147	name_list *nptr;
148
149	for(nptr = list_head; nptr != NULL; nptr = nptr->next)
150		if(match(nptr->name, name)) {
151			return (nptr->name);
152		}
153
154	if(class) {
155		for(nptr = list_head; nptr != NULL; nptr = nptr->next)
156			if(match(nptr->name, class->res_name)) {
157				return (nptr->name);
158			}
159
160		for(nptr = list_head; nptr != NULL; nptr = nptr->next)
161			if(match(nptr->name, class->res_class)) {
162				return (nptr->name);
163			}
164	}
165	return (NULL);
166}
167
168void *LookPatternInNameList(name_list *list_head, const char *name)
169{
170	return (LookPatternInList(list_head, name, NULL));
171}
172
173/***********************************************************************
174 *
175 *  Procedure:
176 *      GetColorFromList - look through a list for a window name, or class
177 *
178 *  Returned Value:
179 *      true  if the name was found
180 *      false if the name was not found
181 *
182 *  Inputs:
183 *      list    - a pointer to the head of a list
184 *      name    - a pointer to the name to look for
185 *      class   - a pointer to the class to look for
186 *
187 *  Outputs:
188 *      ptr     - fill in the list value if the name was found
189 *
190 ***********************************************************************
191 */
192
193bool GetColorFromList(name_list *list_head, char *name,
194                      XClassHint *class, Pixel *ptr)
195{
196	bool save;
197	name_list *nptr;
198
199	for(nptr = list_head; nptr != NULL; nptr = nptr->next)
200		if(match(nptr->name, name)) {
201			save = Scr->FirstTime;
202			Scr->FirstTime = true;
203			GetColor(Scr->Monochrome, ptr, nptr->ptr);
204			Scr->FirstTime = save;
205			return true;
206		}
207
208	if(class) {
209		for(nptr = list_head; nptr != NULL; nptr = nptr->next)
210			if(match(nptr->name, class->res_name)) {
211				save = Scr->FirstTime;
212				Scr->FirstTime = true;
213				GetColor(Scr->Monochrome, ptr, nptr->ptr);
214				Scr->FirstTime = save;
215				return true;
216			}
217
218		for(nptr = list_head; nptr != NULL; nptr = nptr->next)
219			if(match(nptr->name, class->res_class)) {
220				save = Scr->FirstTime;
221				Scr->FirstTime = true;
222				GetColor(Scr->Monochrome, ptr, nptr->ptr);
223				Scr->FirstTime = save;
224				return true;
225			}
226	}
227	return false;
228}
229
230/***********************************************************************
231 *
232 *  Procedure:
233 *      FreeList - free up a list
234 *
235 ***********************************************************************
236 */
237
238void FreeList(name_list **list)
239{
240	name_list *nptr;
241	name_list *tmp;
242
243	for(nptr = *list; nptr != NULL;) {
244		tmp = nptr->next;
245		free(nptr->name);
246		free(nptr);
247		nptr = tmp;
248	}
249	*list = NULL;
250}
251
252#ifdef USE_SYS_REGEX
253
254bool match(const char *pattern, const char *string)
255{
256	regex_t preg;
257	int error;
258
259	if((pattern == NULL) || (string == NULL)) {
260		return false;
261	}
262	error = regcomp(&preg, pattern, REG_EXTENDED | REG_NOSUB);
263	if(error != 0) {
264		char buf [256];
265		regerror(error, &preg, buf, sizeof buf);
266		fprintf(stderr, "%s : %s\n", buf, pattern);
267		return false;
268	}
269	error = regexec(&preg, string, 5, 0, 0);
270	regfree(&preg);
271	if(error == 0) {
272		return true;
273	}
274	return false;
275}
276
277#else
278
279
280
281int regex_match(const char *p, const char *t);
282int regex_match_after_star(const char *p, const char *t);
283
284#if 0                           /* appears not to be used anywhere */
285static int is_pattern(char *p)
286{
287	while(*p) {
288		switch(*p++) {
289			case '?':
290			case '*':
291			case '[':
292				return TRUE;
293			case '\\':
294				if(!*p++) {
295					return FALSE;
296				}
297		}
298	}
299	return FALSE;
300}
301#endif
302
303#define ABORT 2
304
305int regex_match(const char *p, const char *t)
306{
307	char range_start, range_end;
308	int invert;
309	int member_match;
310	int loop;
311
312	for(; *p; p++, t++) {
313		if(!*t) {
314			return (*p == '*' && *++p == '\0') ? TRUE : ABORT;
315		}
316		switch(*p) {
317			case '?':
318				break;
319			case '*':
320				return regex_match_after_star(p, t);
321			case '[': {
322				p++;
323				invert = FALSE;
324				if(*p == '!' || *p == '^') {
325					invert = TRUE;
326					p++;
327				}
328				if(*p == ']') {
329					return ABORT;
330				}
331				member_match = FALSE;
332				loop = TRUE;
333				while(loop) {
334					if(*p == ']') {
335						loop = FALSE;
336						continue;
337					}
338					if(*p == '\\') {
339						range_start = range_end = *++p;
340					}
341					else {
342						range_start = range_end = *p;
343					}
344					if(!range_start) {
345						return ABORT;
346					}
347					if(*++p == '-') {
348						range_end = *++p;
349						if(range_end == '\0' || range_end == ']') {
350							return ABORT;
351						}
352						if(range_end == '\\') {
353							range_end = *++p;
354						}
355						p++;
356					}
357					if(range_start < range_end) {
358						if(*t >= range_start && *t <= range_end) {
359							member_match = TRUE;
360							loop = FALSE;
361						}
362					}
363					else {
364						if(*t >= range_end && *t <= range_start) {
365							member_match = TRUE;
366							loop = FALSE;
367						}
368					}
369				}
370				if((invert && member_match) || !(invert || member_match)) {
371					return (FALSE);
372				}
373				if(member_match) {
374					while(*p != ']') {
375						if(!*p) {
376							return (ABORT);
377						}
378						if(*p == '\\') {
379							p++;
380						}
381						p++;
382					}
383				}
384				break;
385			}
386			case '\\':
387				p++;
388
389			default:
390				if(*p != *t) {
391					return (FALSE);
392				}
393		}
394	}
395	return (!*t);
396}
397
398int regex_match_after_star(const char *p, const char *t)
399{
400	int mat;
401	int nextp;
402
403	while((*p == '?') || (*p == '*')) {
404		if(*p == '?') {
405			if(!*t++) {
406				return ABORT;
407			}
408		}
409		p++;
410	}
411	if(!*p) {
412		return TRUE;
413	}
414
415	nextp = *p;
416	if(nextp == '\\') {
417		nextp = p[1];
418	}
419
420	mat = FALSE;
421	while(mat == FALSE) {
422		if(nextp == *t || nextp == '[') {
423			mat = regex_match(p, t);
424		}
425		if(!*t++) {
426			mat = ABORT;
427		}
428	}
429	return (mat);
430}
431
432int match(const char *p, const char *t)
433{
434	if((p == NULL) || (t == NULL)) {
435		return (FALSE);
436	}
437	return ((regex_match(p, t) == TRUE) ? TRUE : FALSE);
438}
439
440#endif
441
442
443
444
445