list.c revision 645f5050
1645f5050Syouri/*****************************************************************************/
2645f5050Syouri/**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
3645f5050Syouri/**                          Salt Lake City, Utah                           **/
4645f5050Syouri/**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **/
5645f5050Syouri/**                        Cambridge, Massachusetts                         **/
6645f5050Syouri/**                                                                         **/
7645f5050Syouri/**                           All Rights Reserved                           **/
8645f5050Syouri/**                                                                         **/
9645f5050Syouri/**    Permission to use, copy, modify, and distribute this software and    **/
10645f5050Syouri/**    its documentation  for  any  purpose  and  without  fee is hereby    **/
11645f5050Syouri/**    granted, provided that the above copyright notice appear  in  all    **/
12645f5050Syouri/**    copies and that both  that  copyright  notice  and  this  permis-    **/
13645f5050Syouri/**    sion  notice appear in supporting  documentation,  and  that  the    **/
14645f5050Syouri/**    names of Evans & Sutherland and M.I.T. not be used in advertising    **/
15645f5050Syouri/**    in publicity pertaining to distribution of the  software  without    **/
16645f5050Syouri/**    specific, written prior permission.                                  **/
17645f5050Syouri/**                                                                         **/
18645f5050Syouri/**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **/
19645f5050Syouri/**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
20645f5050Syouri/**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **/
21645f5050Syouri/**    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
22645f5050Syouri/**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
23645f5050Syouri/**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
24645f5050Syouri/**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
25645f5050Syouri/**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
26645f5050Syouri/*****************************************************************************/
27645f5050Syouri/*
28645f5050Syouri *  [ ctwm ]
29645f5050Syouri *
30645f5050Syouri *  Copyright 1992 Claude Lecommandeur.
31645f5050Syouri *
32645f5050Syouri * Permission to use, copy, modify  and distribute this software  [ctwm] and
33645f5050Syouri * its documentation for any purpose is hereby granted without fee, provided
34645f5050Syouri * that the above  copyright notice appear  in all copies and that both that
35645f5050Syouri * copyright notice and this permission notice appear in supporting documen-
36645f5050Syouri * tation, and that the name of  Claude Lecommandeur not be used in adverti-
37645f5050Syouri * sing or  publicity  pertaining to  distribution of  the software  without
38645f5050Syouri * specific, written prior permission. Claude Lecommandeur make no represen-
39645f5050Syouri * tations  about the suitability  of this software  for any purpose.  It is
40645f5050Syouri * provided "as is" without express or implied warranty.
41645f5050Syouri *
42645f5050Syouri * Claude Lecommandeur DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
43645f5050Syouri * INCLUDING ALL  IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS.  IN NO
44645f5050Syouri * EVENT SHALL  Claude Lecommandeur  BE LIABLE FOR ANY SPECIAL,  INDIRECT OR
45645f5050Syouri * CONSEQUENTIAL  DAMAGES OR ANY  DAMAGES WHATSOEVER  RESULTING FROM LOSS OF
46645f5050Syouri * USE, DATA  OR PROFITS,  WHETHER IN AN ACTION  OF CONTRACT,  NEGLIGENCE OR
47645f5050Syouri * OTHER  TORTIOUS ACTION,  ARISING OUT OF OR IN  CONNECTION WITH THE USE OR
48645f5050Syouri * PERFORMANCE OF THIS SOFTWARE.
49645f5050Syouri *
50645f5050Syouri * Author:  Claude Lecommandeur [ lecom@sic.epfl.ch ][ April 1992 ]
51645f5050Syouri */
52645f5050Syouri
53645f5050Syouri
54645f5050Syouri/**********************************************************************
55645f5050Syouri *
56645f5050Syouri * $XConsortium: list.c,v 1.20 91/01/09 17:13:30 rws Exp $
57645f5050Syouri *
58645f5050Syouri * TWM code to deal with the name lists for the NoTitle list and
59645f5050Syouri * the AutoRaise list
60645f5050Syouri *
61645f5050Syouri * 11-Apr-88 Tom LaStrange        Initial Version.
62645f5050Syouri *
63645f5050Syouri * Do the necessary modification to be integrated in ctwm.
64645f5050Syouri * Can no longer be used for the standard twm.
65645f5050Syouri *
66645f5050Syouri * 22-April-92 Claude Lecommandeur.
67645f5050Syouri *
68645f5050Syouri *
69645f5050Syouri **********************************************************************/
70645f5050Syouri
71645f5050Syouri#include <stdio.h>
72645f5050Syouri#ifdef VMS
73645f5050Syouri#include <string.h>
74645f5050Syouri#endif
75645f5050Syouri#include "twm.h"
76645f5050Syouri#include "screen.h"
77645f5050Syouri#include "gram.tab.h"
78645f5050Syouri#include "list.h"
79645f5050Syouri#include "util.h"
80645f5050Syouri
81645f5050Syouri#ifdef USE_GNU_REGEX
82645f5050Syouri# include <regex.h>
83645f5050Syouri#endif /* USE_GNU_REGEX */
84645f5050Syouri
85645f5050Syouri
86645f5050Syouriextern void twmrc_error_prefix(void);
87645f5050Syouri
88645f5050Syouri/***********************************************************************
89645f5050Syouri *
90645f5050Syouri *  Procedure:
91645f5050Syouri *	AddToList - add a window name to the appropriate list
92645f5050Syouri *
93645f5050Syouri *  Inputs:
94645f5050Syouri *	list	- the address of the pointer to the head of a list
95645f5050Syouri *	name	- a pointer to the name of the window
96645f5050Syouri *	ptr	- pointer to list dependent data
97645f5050Syouri *
98645f5050Syouri *  Special Considerations
99645f5050Syouri *	If the list does not use the ptr value, a non-null value
100645f5050Syouri *	should be placed in it.  LookInList returns this ptr value
101645f5050Syouri *	and procedures calling LookInList will check for a non-null
102645f5050Syouri *	return value as an indication of success.
103645f5050Syouri *
104645f5050Syouri ***********************************************************************
105645f5050Syouri */
106645f5050Syouri
107645f5050Syouri#if 0				/* appears not to be used anywhere */
108645f5050Syouristatic int is_pattern (char *p);
109645f5050Syouri#endif
110645f5050Syouri
111645f5050Syourivoid AddToList(name_list **list_head, char *name, char *ptr)
112645f5050Syouri{
113645f5050Syouri    name_list *nptr;
114645f5050Syouri
115645f5050Syouri    if (!list_head) return;	/* ignore empty inserts */
116645f5050Syouri
117645f5050Syouri    nptr = (name_list *)malloc(sizeof(name_list));
118645f5050Syouri    if (nptr == NULL)
119645f5050Syouri    {
120645f5050Syouri	twmrc_error_prefix();
121645f5050Syouri	fprintf (stderr, "unable to allocate %lu bytes for name_list\n",
122645f5050Syouri		 (unsigned long) sizeof(name_list));
123645f5050Syouri	Done(0);
124645f5050Syouri    }
125645f5050Syouri
126645f5050Syouri    nptr->next = *list_head;
127645f5050Syouri#ifdef VMS
128645f5050Syouri    {
129645f5050Syouri        char *ftemp;
130645f5050Syouri        ftemp = (char *) malloc((strlen(name)+1)*sizeof(char));
131645f5050Syouri        nptr->name = strcpy (ftemp,name);
132645f5050Syouri    }
133645f5050Syouri#else
134645f5050Syouri    nptr->name = (char*) strdup (name);
135645f5050Syouri#endif
136645f5050Syouri    nptr->ptr = (ptr == NULL) ? (char *)TRUE : ptr;
137645f5050Syouri    *list_head = nptr;
138645f5050Syouri}
139645f5050Syouri
140645f5050Syouri/***********************************************************************
141645f5050Syouri *
142645f5050Syouri *  Procedure:
143645f5050Syouri *	LookInList - look through a list for a window name, or class
144645f5050Syouri *
145645f5050Syouri *  Returned Value:
146645f5050Syouri *	the ptr field of the list structure or NULL if the name
147645f5050Syouri *	or class was not found in the list
148645f5050Syouri *
149645f5050Syouri *  Inputs:
150645f5050Syouri *	list	- a pointer to the head of a list
151645f5050Syouri *	name	- a pointer to the name to look for
152645f5050Syouri *	class	- a pointer to the class to look for
153645f5050Syouri *
154645f5050Syouri ***********************************************************************
155645f5050Syouri */
156645f5050Syouri
157645f5050Syourivoid *LookInList(name_list *list_head, char *name, XClassHint *class)
158645f5050Syouri{
159645f5050Syouri    name_list *nptr;
160645f5050Syouri
161645f5050Syouri    /* look for the name first */
162645f5050Syouri    for (nptr = list_head; nptr != NULL; nptr = nptr->next)
163645f5050Syouri	if (match (nptr->name, name))
164645f5050Syouri	    return (nptr->ptr);
165645f5050Syouri
166645f5050Syouri    if (class)
167645f5050Syouri    {
168645f5050Syouri	/* look for the res_name next */
169645f5050Syouri	for (nptr = list_head; nptr != NULL; nptr = nptr->next)
170645f5050Syouri	    if (match (nptr->name, class->res_name))
171645f5050Syouri		return (nptr->ptr);
172645f5050Syouri
173645f5050Syouri	/* finally look for the res_class */
174645f5050Syouri	for (nptr = list_head; nptr != NULL; nptr = nptr->next)
175645f5050Syouri	    if (match (nptr->name, class->res_class))
176645f5050Syouri		return (nptr->ptr);
177645f5050Syouri    }
178645f5050Syouri    return (NULL);
179645f5050Syouri}
180645f5050Syouri
181645f5050Syourivoid *LookInNameList(name_list *list_head, char *name)
182645f5050Syouri{
183645f5050Syouri    return (LookInList(list_head, name, NULL));
184645f5050Syouri}
185645f5050Syouri
186645f5050Syourivoid *LookPatternInList(name_list *list_head, char *name, XClassHint *class)
187645f5050Syouri{
188645f5050Syouri    name_list *nptr;
189645f5050Syouri
190645f5050Syouri    for (nptr = list_head; nptr != NULL; nptr = nptr->next)
191645f5050Syouri	if (match (nptr->name, name))
192645f5050Syouri	    return (nptr->name);
193645f5050Syouri
194645f5050Syouri    if (class)
195645f5050Syouri    {
196645f5050Syouri	for (nptr = list_head; nptr != NULL; nptr = nptr->next)
197645f5050Syouri	    if (match (nptr->name, class->res_name))
198645f5050Syouri		return (nptr->name);
199645f5050Syouri
200645f5050Syouri	for (nptr = list_head; nptr != NULL; nptr = nptr->next)
201645f5050Syouri	    if (match (nptr->name, class->res_class))
202645f5050Syouri		return (nptr->name);
203645f5050Syouri    }
204645f5050Syouri    return (NULL);
205645f5050Syouri}
206645f5050Syouri
207645f5050Syourivoid *LookPatternInNameList (name_list *list_head, char *name)
208645f5050Syouri{
209645f5050Syouri    return (LookPatternInList(list_head, name, NULL));
210645f5050Syouri}
211645f5050Syouri
212645f5050Syouri/***********************************************************************
213645f5050Syouri *
214645f5050Syouri *  Procedure:
215645f5050Syouri *	GetColorFromList - look through a list for a window name, or class
216645f5050Syouri *
217645f5050Syouri *  Returned Value:
218645f5050Syouri *	TRUE if the name was found
219645f5050Syouri *	FALSE if the name was not found
220645f5050Syouri *
221645f5050Syouri *  Inputs:
222645f5050Syouri *	list	- a pointer to the head of a list
223645f5050Syouri *	name	- a pointer to the name to look for
224645f5050Syouri *	class	- a pointer to the class to look for
225645f5050Syouri *
226645f5050Syouri *  Outputs:
227645f5050Syouri *	ptr	- fill in the list value if the name was found
228645f5050Syouri *
229645f5050Syouri ***********************************************************************
230645f5050Syouri */
231645f5050Syouri
232645f5050Syouriint GetColorFromList(name_list *list_head, char *name,
233645f5050Syouri		     XClassHint *class, Pixel *ptr)
234645f5050Syouri{
235645f5050Syouri    int save;
236645f5050Syouri    name_list *nptr;
237645f5050Syouri
238645f5050Syouri    for (nptr = list_head; nptr != NULL; nptr = nptr->next)
239645f5050Syouri	if (match (nptr->name, name))
240645f5050Syouri	{
241645f5050Syouri	    save = Scr->FirstTime;
242645f5050Syouri	    Scr->FirstTime = TRUE;
243645f5050Syouri	    GetColor(Scr->Monochrome, ptr, nptr->ptr);
244645f5050Syouri	    Scr->FirstTime = save;
245645f5050Syouri	    return (TRUE);
246645f5050Syouri	}
247645f5050Syouri
248645f5050Syouri    if (class)
249645f5050Syouri    {
250645f5050Syouri	for (nptr = list_head; nptr != NULL; nptr = nptr->next)
251645f5050Syouri	    if (match (nptr->name, class->res_name))
252645f5050Syouri	    {
253645f5050Syouri		save = Scr->FirstTime;
254645f5050Syouri		Scr->FirstTime = TRUE;
255645f5050Syouri		GetColor(Scr->Monochrome, ptr, nptr->ptr);
256645f5050Syouri		Scr->FirstTime = save;
257645f5050Syouri		return (TRUE);
258645f5050Syouri	    }
259645f5050Syouri
260645f5050Syouri	for (nptr = list_head; nptr != NULL; nptr = nptr->next)
261645f5050Syouri	    if (match (nptr->name, class->res_class))
262645f5050Syouri	    {
263645f5050Syouri		save = Scr->FirstTime;
264645f5050Syouri		Scr->FirstTime = TRUE;
265645f5050Syouri		GetColor(Scr->Monochrome, ptr, nptr->ptr);
266645f5050Syouri		Scr->FirstTime = save;
267645f5050Syouri		return (TRUE);
268645f5050Syouri	    }
269645f5050Syouri    }
270645f5050Syouri    return (FALSE);
271645f5050Syouri}
272645f5050Syouri
273645f5050Syouri/***********************************************************************
274645f5050Syouri *
275645f5050Syouri *  Procedure:
276645f5050Syouri *	FreeList - free up a list
277645f5050Syouri *
278645f5050Syouri ***********************************************************************
279645f5050Syouri */
280645f5050Syouri
281645f5050Syourivoid FreeList(name_list **list)
282645f5050Syouri{
283645f5050Syouri    name_list *nptr;
284645f5050Syouri    name_list *tmp;
285645f5050Syouri
286645f5050Syouri    for (nptr = *list; nptr != NULL; )
287645f5050Syouri    {
288645f5050Syouri	tmp = nptr->next;
289645f5050Syouri	free((char *) nptr);
290645f5050Syouri	nptr = tmp;
291645f5050Syouri    }
292645f5050Syouri    *list = NULL;
293645f5050Syouri}
294645f5050Syouri
295645f5050Syouri#ifdef USE_GNU_REGEX
296645f5050Syouri
297645f5050Syouri#define MAXPATLEN 256
298645f5050Syouri
299645f5050Syouriint match (pattern, string)
300645f5050Syouri     char *pattern, *string;
301645f5050Syouri{
302645f5050Syouri  regex_t preg;
303645f5050Syouri  int error;
304645f5050Syouri
305645f5050Syouri  if ((pattern == NULL) || (string == NULL)) return 0;
306645f5050Syouri  error = regcomp (&preg, pattern, REG_EXTENDED | REG_NOSUB);
307645f5050Syouri  if (error != 0) {
308645f5050Syouri    char buf [256];
309645f5050Syouri    (void) regerror (error, &preg, buf, sizeof buf);
310645f5050Syouri    fprintf (stderr, "%s : %s\n", buf, pattern);
311645f5050Syouri    return 0;
312645f5050Syouri  }
313645f5050Syouri  error = regexec (&preg, string, 5, 0, 0);
314645f5050Syouri  regfree (&preg);
315645f5050Syouri  if (error == 0) return 1;
316645f5050Syouri  return 0;
317645f5050Syouri}
318645f5050Syouri
319645f5050Syouri#else
320645f5050Syouri
321645f5050Syouri
322645f5050Syouri
323645f5050Syouriint regex_match (char *p, char *t);
324645f5050Syouriint regex_match_after_star (char *p, char *t);
325645f5050Syouri
326645f5050Syouri#if 0				/* appears not to be used anywhere */
327645f5050Syouristatic int is_pattern (char *p)
328645f5050Syouri{
329645f5050Syouri    while ( *p ) {
330645f5050Syouri	switch ( *p++ ) {
331645f5050Syouri	    case '?':
332645f5050Syouri	    case '*':
333645f5050Syouri	    case '[':
334645f5050Syouri		return TRUE;
335645f5050Syouri	    case '\\':
336645f5050Syouri		if ( !*p++ ) return FALSE;
337645f5050Syouri	}
338645f5050Syouri    }
339645f5050Syouri    return FALSE;
340645f5050Syouri}
341645f5050Syouri#endif
342645f5050Syouri
343645f5050Syouri#define ABORT 2
344645f5050Syouri
345645f5050Syouriint regex_match (char *p, char *t)
346645f5050Syouri{
347645f5050Syouri    register char range_start, range_end;
348645f5050Syouri    int invert;
349645f5050Syouri    int member_match;
350645f5050Syouri    int loop;
351645f5050Syouri
352645f5050Syouri    for ( ; *p; p++, t++ ) {
353645f5050Syouri	if (!*t)  return ( *p == '*' && *++p == '\0' ) ? TRUE : ABORT;
354645f5050Syouri	switch ( *p ) {
355645f5050Syouri	    case '?':
356645f5050Syouri		break;
357645f5050Syouri	    case '*':
358645f5050Syouri		return regex_match_after_star (p, t);
359645f5050Syouri	    case '[': {
360645f5050Syouri		p++;
361645f5050Syouri		invert = FALSE;
362645f5050Syouri		if ( *p == '!' || *p == '^') {
363645f5050Syouri		    invert = TRUE;
364645f5050Syouri		    p++;
365645f5050Syouri		}
366645f5050Syouri		if ( *p == ']' ) return ABORT;
367645f5050Syouri		member_match = FALSE;
368645f5050Syouri		loop = TRUE;
369645f5050Syouri		while ( loop ) {
370645f5050Syouri		    if (*p == ']') {
371645f5050Syouri			loop = FALSE;
372645f5050Syouri			continue;
373645f5050Syouri		    }
374645f5050Syouri		    if (*p == '\\') range_start = range_end = *++p;
375645f5050Syouri		    else range_start = range_end = *p;
376645f5050Syouri		    if (!range_start) return ABORT;
377645f5050Syouri		    if (*++p == '-') {
378645f5050Syouri			range_end = *++p;
379645f5050Syouri			if (range_end == '\0' || range_end == ']') return ABORT;
380645f5050Syouri			if (range_end == '\\') range_end = *++p;
381645f5050Syouri			p++;
382645f5050Syouri		    }
383645f5050Syouri		    if ( range_start < range_end  ) {
384645f5050Syouri			if (*t >= range_start && *t <= range_end) {
385645f5050Syouri			    member_match = TRUE;
386645f5050Syouri			    loop = FALSE;
387645f5050Syouri			}
388645f5050Syouri		    }
389645f5050Syouri		    else {
390645f5050Syouri			if (*t >= range_end && *t <= range_start) {
391645f5050Syouri			    member_match = TRUE;
392645f5050Syouri			    loop = FALSE;
393645f5050Syouri			}
394645f5050Syouri		    }
395645f5050Syouri		}
396645f5050Syouri		if ((invert && member_match) || !(invert || member_match)) return (FALSE);
397645f5050Syouri		if (member_match) {
398645f5050Syouri		    while (*p != ']') {
399645f5050Syouri			if (!*p) return (ABORT);
400645f5050Syouri			if (*p == '\\')  p++;
401645f5050Syouri			p++;
402645f5050Syouri		    }
403645f5050Syouri		}
404645f5050Syouri		break;
405645f5050Syouri	    }
406645f5050Syouri	    case '\\':
407645f5050Syouri		p++;
408645f5050Syouri
409645f5050Syouri	    default:
410645f5050Syouri		if (*p != *t) return (FALSE);
411645f5050Syouri	}
412645f5050Syouri    }
413645f5050Syouri    return (!*t);
414645f5050Syouri}
415645f5050Syouri
416645f5050Syouriint regex_match_after_star (char *p, char *t)
417645f5050Syouri{
418645f5050Syouri    register int mat;
419645f5050Syouri    register int nextp;
420645f5050Syouri
421645f5050Syouri    while ((*p == '?') || (*p == '*')) {
422645f5050Syouri	if (*p == '?') {
423645f5050Syouri	    if ( !*t++ ) return ABORT;
424645f5050Syouri	}
425645f5050Syouri	p++;
426645f5050Syouri    }
427645f5050Syouri    if ( !*p ) return TRUE;
428645f5050Syouri
429645f5050Syouri    nextp = *p;
430645f5050Syouri    if (nextp == '\\') nextp = p[1];
431645f5050Syouri
432645f5050Syouri    mat = FALSE;
433645f5050Syouri    while (mat == FALSE) {
434645f5050Syouri	if ( nextp == *t || nextp == '[' ) mat = regex_match(p, t);
435645f5050Syouri	if ( !*t++ ) mat = ABORT;
436645f5050Syouri    }
437645f5050Syouri    return (mat);
438645f5050Syouri}
439645f5050Syouri
440645f5050Syouriint match (char *p, char *t)
441645f5050Syouri{
442645f5050Syouri    if ((p == NULL) || (t == NULL)) return (FALSE);
443645f5050Syouri    return ((regex_match (p,t) == TRUE) ? TRUE : FALSE);
444645f5050Syouri}
445645f5050Syouri
446645f5050Syouri#endif
447645f5050Syouri
448645f5050Syouri
449645f5050Syouri
450645f5050Syouri
451