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