list.c revision 0bbfda8a
10bbfda8aSnia/*
20bbfda8aSnia *       Copyright 1988 by Evans & Sutherland Computer Corporation,
30bbfda8aSnia *                          Salt Lake City, Utah
40bbfda8aSnia *  Portions Copyright 1989 by the Massachusetts Institute of Technology
50bbfda8aSnia *                        Cambridge, Massachusetts
6645f5050Syouri *
70bbfda8aSnia * Copyright 1992 Claude Lecommandeur.
8645f5050Syouri */
9645f5050Syouri
10645f5050Syouri/**********************************************************************
11645f5050Syouri *
12645f5050Syouri * $XConsortium: list.c,v 1.20 91/01/09 17:13:30 rws Exp $
13645f5050Syouri *
14645f5050Syouri * TWM code to deal with the name lists for the NoTitle list and
15645f5050Syouri * the AutoRaise list
16645f5050Syouri *
17645f5050Syouri * 11-Apr-88 Tom LaStrange        Initial Version.
18645f5050Syouri *
19645f5050Syouri * Do the necessary modification to be integrated in ctwm.
20645f5050Syouri * Can no longer be used for the standard twm.
21645f5050Syouri *
22645f5050Syouri * 22-April-92 Claude Lecommandeur.
23645f5050Syouri *
24645f5050Syouri *
25645f5050Syouri **********************************************************************/
26645f5050Syouri
270bbfda8aSnia#include "ctwm.h"
280bbfda8aSnia
29645f5050Syouri#include <stdio.h>
300bbfda8aSnia#include <stdlib.h>
310bbfda8aSnia
32645f5050Syouri#include "screen.h"
33645f5050Syouri#include "list.h"
34645f5050Syouri#include "util.h"
350bbfda8aSnia#include "parse.h"
36645f5050Syouri
370bbfda8aSnia#ifdef USE_SYS_REGEX
38645f5050Syouri# include <regex.h>
390bbfda8aSnia#endif /* USE_SYS_REGEX */
40645f5050Syouri
41645f5050Syouri
42645f5050Syouri
43645f5050Syouri/***********************************************************************
44645f5050Syouri *
45645f5050Syouri *  Procedure:
460bbfda8aSnia *      AddToList - add a window name to the appropriate list
47645f5050Syouri *
48645f5050Syouri *  Inputs:
490bbfda8aSnia *      list    - the address of the pointer to the head of a list
500bbfda8aSnia *      name    - a pointer to the name of the window
510bbfda8aSnia *      ptr     - pointer to list dependent data
52645f5050Syouri *
53645f5050Syouri *  Special Considerations
540bbfda8aSnia *      If the list does not use the ptr value, a non-null value
550bbfda8aSnia *      should be placed in it.  LookInList returns this ptr value
560bbfda8aSnia *      and procedures calling LookInList will check for a non-null
570bbfda8aSnia *      return value as an indication of success.
58645f5050Syouri *
59645f5050Syouri ***********************************************************************
60645f5050Syouri */
61645f5050Syouri
620bbfda8aSniavoid AddToList(name_list **list_head, const char *name, void *ptr)
63645f5050Syouri{
640bbfda8aSnia	name_list *nptr;
650bbfda8aSnia
660bbfda8aSnia	if(!list_head) {
670bbfda8aSnia		return;        /* ignore empty inserts */
680bbfda8aSnia	}
690bbfda8aSnia
700bbfda8aSnia	nptr = malloc(sizeof(name_list));
710bbfda8aSnia	if(nptr == NULL) {
720bbfda8aSnia		fprintf(stderr, "unable to allocate %lu bytes for name_list\n",
730bbfda8aSnia		        (unsigned long) sizeof(name_list));
740bbfda8aSnia		Done(0);
750bbfda8aSnia	}
760bbfda8aSnia
770bbfda8aSnia	nptr->next = *list_head;
780bbfda8aSnia	nptr->name = strdup(name);
790bbfda8aSnia	nptr->ptr = (ptr == NULL) ? (char *)1 : ptr;
800bbfda8aSnia	*list_head = nptr;
810bbfda8aSnia}
82645f5050Syouri
83645f5050Syouri/***********************************************************************
84645f5050Syouri *
85645f5050Syouri *  Procedure:
860bbfda8aSnia *      LookInList - look through a list for a window name, or class
87645f5050Syouri *
88645f5050Syouri *  Returned Value:
890bbfda8aSnia *      the ptr field of the list structure or NULL if the name
900bbfda8aSnia *      or class was not found in the list
91645f5050Syouri *
92645f5050Syouri *  Inputs:
930bbfda8aSnia *      list    - a pointer to the head of a list
940bbfda8aSnia *      name    - a pointer to the name to look for
950bbfda8aSnia *      class   - a pointer to the class to look for
96645f5050Syouri *
97645f5050Syouri ***********************************************************************
98645f5050Syouri */
99645f5050Syouri
1000bbfda8aSniavoid *LookInList(name_list *list_head, const char *name, XClassHint *class)
1010bbfda8aSnia{
1020bbfda8aSnia	name_list *nptr;
1030bbfda8aSnia
1040bbfda8aSnia	/* look for the name first */
1050bbfda8aSnia	for(nptr = list_head; nptr != NULL; nptr = nptr->next) {
1060bbfda8aSnia		if(match(nptr->name, name)) {
1070bbfda8aSnia			return (nptr->ptr);
1080bbfda8aSnia		}
1090bbfda8aSnia	}
1100bbfda8aSnia
1110bbfda8aSnia	if(class) {
1120bbfda8aSnia		/* look for the res_name next */
1130bbfda8aSnia		for(nptr = list_head; nptr != NULL; nptr = nptr->next) {
1140bbfda8aSnia			if(match(nptr->name, class->res_name)) {
1150bbfda8aSnia				return (nptr->ptr);
1160bbfda8aSnia			}
1170bbfda8aSnia		}
1180bbfda8aSnia
1190bbfda8aSnia		/* finally look for the res_class */
1200bbfda8aSnia		for(nptr = list_head; nptr != NULL; nptr = nptr->next) {
1210bbfda8aSnia			if(match(nptr->name, class->res_class)) {
1220bbfda8aSnia				return (nptr->ptr);
1230bbfda8aSnia			}
1240bbfda8aSnia		}
1250bbfda8aSnia	}
1260bbfda8aSnia	return (NULL);
1270bbfda8aSnia}
1280bbfda8aSnia
1290bbfda8aSniavoid *LookInNameList(name_list *list_head, const char *name)
130645f5050Syouri{
1310bbfda8aSnia	return (LookInList(list_head, name, NULL));
132645f5050Syouri}
133645f5050Syouri
1340bbfda8aSniavoid *LookInListWin(name_list *list_head, TwmWindow *twin)
135645f5050Syouri{
1360bbfda8aSnia	return LookInList(list_head, twin->name, &(twin->class));
137645f5050Syouri}
138645f5050Syouri
1390bbfda8aSniabool IsInList(name_list *list_head, TwmWindow *twin)
140645f5050Syouri{
1410bbfda8aSnia	return (bool)LookInList(list_head, twin->name, &(twin->class));
142645f5050Syouri}
143645f5050Syouri
1440bbfda8aSniavoid *LookPatternInList(name_list *list_head, const char *name,
1450bbfda8aSnia                        XClassHint *class)
146645f5050Syouri{
1470bbfda8aSnia	name_list *nptr;
1480bbfda8aSnia
1490bbfda8aSnia	for(nptr = list_head; nptr != NULL; nptr = nptr->next)
1500bbfda8aSnia		if(match(nptr->name, name)) {
1510bbfda8aSnia			return (nptr->name);
1520bbfda8aSnia		}
1530bbfda8aSnia
1540bbfda8aSnia	if(class) {
1550bbfda8aSnia		for(nptr = list_head; nptr != NULL; nptr = nptr->next)
1560bbfda8aSnia			if(match(nptr->name, class->res_name)) {
1570bbfda8aSnia				return (nptr->name);
1580bbfda8aSnia			}
1590bbfda8aSnia
1600bbfda8aSnia		for(nptr = list_head; nptr != NULL; nptr = nptr->next)
1610bbfda8aSnia			if(match(nptr->name, class->res_class)) {
1620bbfda8aSnia				return (nptr->name);
1630bbfda8aSnia			}
1640bbfda8aSnia	}
1650bbfda8aSnia	return (NULL);
1660bbfda8aSnia}
1670bbfda8aSnia
1680bbfda8aSniavoid *LookPatternInNameList(name_list *list_head, const char *name)
1690bbfda8aSnia{
1700bbfda8aSnia	return (LookPatternInList(list_head, name, NULL));
171645f5050Syouri}
172645f5050Syouri
173645f5050Syouri/***********************************************************************
174645f5050Syouri *
175645f5050Syouri *  Procedure:
1760bbfda8aSnia *      GetColorFromList - look through a list for a window name, or class
177645f5050Syouri *
178645f5050Syouri *  Returned Value:
1790bbfda8aSnia *      true  if the name was found
1800bbfda8aSnia *      false if the name was not found
181645f5050Syouri *
182645f5050Syouri *  Inputs:
1830bbfda8aSnia *      list    - a pointer to the head of a list
1840bbfda8aSnia *      name    - a pointer to the name to look for
1850bbfda8aSnia *      class   - a pointer to the class to look for
186645f5050Syouri *
187645f5050Syouri *  Outputs:
1880bbfda8aSnia *      ptr     - fill in the list value if the name was found
189645f5050Syouri *
190645f5050Syouri ***********************************************************************
191645f5050Syouri */
192645f5050Syouri
1930bbfda8aSniabool GetColorFromList(name_list *list_head, char *name,
1940bbfda8aSnia                      XClassHint *class, Pixel *ptr)
195645f5050Syouri{
1960bbfda8aSnia	bool save;
1970bbfda8aSnia	name_list *nptr;
1980bbfda8aSnia
1990bbfda8aSnia	for(nptr = list_head; nptr != NULL; nptr = nptr->next)
2000bbfda8aSnia		if(match(nptr->name, name)) {
2010bbfda8aSnia			save = Scr->FirstTime;
2020bbfda8aSnia			Scr->FirstTime = true;
2030bbfda8aSnia			GetColor(Scr->Monochrome, ptr, nptr->ptr);
2040bbfda8aSnia			Scr->FirstTime = save;
2050bbfda8aSnia			return true;
2060bbfda8aSnia		}
207645f5050Syouri
2080bbfda8aSnia	if(class) {
2090bbfda8aSnia		for(nptr = list_head; nptr != NULL; nptr = nptr->next)
2100bbfda8aSnia			if(match(nptr->name, class->res_name)) {
2110bbfda8aSnia				save = Scr->FirstTime;
2120bbfda8aSnia				Scr->FirstTime = true;
2130bbfda8aSnia				GetColor(Scr->Monochrome, ptr, nptr->ptr);
2140bbfda8aSnia				Scr->FirstTime = save;
2150bbfda8aSnia				return true;
2160bbfda8aSnia			}
2170bbfda8aSnia
2180bbfda8aSnia		for(nptr = list_head; nptr != NULL; nptr = nptr->next)
2190bbfda8aSnia			if(match(nptr->name, class->res_class)) {
2200bbfda8aSnia				save = Scr->FirstTime;
2210bbfda8aSnia				Scr->FirstTime = true;
2220bbfda8aSnia				GetColor(Scr->Monochrome, ptr, nptr->ptr);
2230bbfda8aSnia				Scr->FirstTime = save;
2240bbfda8aSnia				return true;
2250bbfda8aSnia			}
2260bbfda8aSnia	}
2270bbfda8aSnia	return false;
228645f5050Syouri}
229645f5050Syouri
230645f5050Syouri/***********************************************************************
231645f5050Syouri *
232645f5050Syouri *  Procedure:
2330bbfda8aSnia *      FreeList - free up a list
234645f5050Syouri *
235645f5050Syouri ***********************************************************************
236645f5050Syouri */
237645f5050Syouri
238645f5050Syourivoid FreeList(name_list **list)
239645f5050Syouri{
2400bbfda8aSnia	name_list *nptr;
2410bbfda8aSnia	name_list *tmp;
2420bbfda8aSnia
2430bbfda8aSnia	for(nptr = *list; nptr != NULL;) {
2440bbfda8aSnia		tmp = nptr->next;
2450bbfda8aSnia		free(nptr->name);
2460bbfda8aSnia		free(nptr);
2470bbfda8aSnia		nptr = tmp;
2480bbfda8aSnia	}
2490bbfda8aSnia	*list = NULL;
250645f5050Syouri}
251645f5050Syouri
2520bbfda8aSnia#ifdef USE_SYS_REGEX
253645f5050Syouri
2540bbfda8aSniabool match(const char *pattern, const char *string)
255645f5050Syouri{
2560bbfda8aSnia	regex_t preg;
2570bbfda8aSnia	int error;
2580bbfda8aSnia
2590bbfda8aSnia	if((pattern == NULL) || (string == NULL)) {
2600bbfda8aSnia		return false;
2610bbfda8aSnia	}
2620bbfda8aSnia	error = regcomp(&preg, pattern, REG_EXTENDED | REG_NOSUB);
2630bbfda8aSnia	if(error != 0) {
2640bbfda8aSnia		char buf [256];
2650bbfda8aSnia		regerror(error, &preg, buf, sizeof buf);
2660bbfda8aSnia		fprintf(stderr, "%s : %s\n", buf, pattern);
2670bbfda8aSnia		return false;
2680bbfda8aSnia	}
2690bbfda8aSnia	error = regexec(&preg, string, 5, 0, 0);
2700bbfda8aSnia	regfree(&preg);
2710bbfda8aSnia	if(error == 0) {
2720bbfda8aSnia		return true;
2730bbfda8aSnia	}
2740bbfda8aSnia	return false;
275645f5050Syouri}
276645f5050Syouri
277645f5050Syouri#else
278645f5050Syouri
279645f5050Syouri
280645f5050Syouri
2810bbfda8aSniaint regex_match(const char *p, const char *t);
2820bbfda8aSniaint regex_match_after_star(const char *p, const char *t);
283645f5050Syouri
2840bbfda8aSnia#if 0                           /* appears not to be used anywhere */
2850bbfda8aSniastatic int is_pattern(char *p)
286645f5050Syouri{
2870bbfda8aSnia	while(*p) {
2880bbfda8aSnia		switch(*p++) {
2890bbfda8aSnia			case '?':
2900bbfda8aSnia			case '*':
2910bbfda8aSnia			case '[':
2920bbfda8aSnia				return TRUE;
2930bbfda8aSnia			case '\\':
2940bbfda8aSnia				if(!*p++) {
2950bbfda8aSnia					return FALSE;
2960bbfda8aSnia				}
2970bbfda8aSnia		}
298645f5050Syouri	}
2990bbfda8aSnia	return FALSE;
300645f5050Syouri}
301645f5050Syouri#endif
302645f5050Syouri
303645f5050Syouri#define ABORT 2
304645f5050Syouri
3050bbfda8aSniaint regex_match(const char *p, const char *t)
306645f5050Syouri{
3070bbfda8aSnia	char range_start, range_end;
3080bbfda8aSnia	int invert;
3090bbfda8aSnia	int member_match;
3100bbfda8aSnia	int loop;
3110bbfda8aSnia
3120bbfda8aSnia	for(; *p; p++, t++) {
3130bbfda8aSnia		if(!*t) {
3140bbfda8aSnia			return (*p == '*' && *++p == '\0') ? TRUE : ABORT;
315645f5050Syouri		}
3160bbfda8aSnia		switch(*p) {
3170bbfda8aSnia			case '?':
3180bbfda8aSnia				break;
3190bbfda8aSnia			case '*':
3200bbfda8aSnia				return regex_match_after_star(p, t);
3210bbfda8aSnia			case '[': {
3220bbfda8aSnia				p++;
3230bbfda8aSnia				invert = FALSE;
3240bbfda8aSnia				if(*p == '!' || *p == '^') {
3250bbfda8aSnia					invert = TRUE;
3260bbfda8aSnia					p++;
3270bbfda8aSnia				}
3280bbfda8aSnia				if(*p == ']') {
3290bbfda8aSnia					return ABORT;
3300bbfda8aSnia				}
3310bbfda8aSnia				member_match = FALSE;
3320bbfda8aSnia				loop = TRUE;
3330bbfda8aSnia				while(loop) {
3340bbfda8aSnia					if(*p == ']') {
3350bbfda8aSnia						loop = FALSE;
3360bbfda8aSnia						continue;
3370bbfda8aSnia					}
3380bbfda8aSnia					if(*p == '\\') {
3390bbfda8aSnia						range_start = range_end = *++p;
3400bbfda8aSnia					}
3410bbfda8aSnia					else {
3420bbfda8aSnia						range_start = range_end = *p;
3430bbfda8aSnia					}
3440bbfda8aSnia					if(!range_start) {
3450bbfda8aSnia						return ABORT;
3460bbfda8aSnia					}
3470bbfda8aSnia					if(*++p == '-') {
3480bbfda8aSnia						range_end = *++p;
3490bbfda8aSnia						if(range_end == '\0' || range_end == ']') {
3500bbfda8aSnia							return ABORT;
3510bbfda8aSnia						}
3520bbfda8aSnia						if(range_end == '\\') {
3530bbfda8aSnia							range_end = *++p;
3540bbfda8aSnia						}
3550bbfda8aSnia						p++;
3560bbfda8aSnia					}
3570bbfda8aSnia					if(range_start < range_end) {
3580bbfda8aSnia						if(*t >= range_start && *t <= range_end) {
3590bbfda8aSnia							member_match = TRUE;
3600bbfda8aSnia							loop = FALSE;
3610bbfda8aSnia						}
3620bbfda8aSnia					}
3630bbfda8aSnia					else {
3640bbfda8aSnia						if(*t >= range_end && *t <= range_start) {
3650bbfda8aSnia							member_match = TRUE;
3660bbfda8aSnia							loop = FALSE;
3670bbfda8aSnia						}
3680bbfda8aSnia					}
3690bbfda8aSnia				}
3700bbfda8aSnia				if((invert && member_match) || !(invert || member_match)) {
3710bbfda8aSnia					return (FALSE);
3720bbfda8aSnia				}
3730bbfda8aSnia				if(member_match) {
3740bbfda8aSnia					while(*p != ']') {
3750bbfda8aSnia						if(!*p) {
3760bbfda8aSnia							return (ABORT);
3770bbfda8aSnia						}
3780bbfda8aSnia						if(*p == '\\') {
3790bbfda8aSnia							p++;
3800bbfda8aSnia						}
3810bbfda8aSnia						p++;
3820bbfda8aSnia					}
3830bbfda8aSnia				}
3840bbfda8aSnia				break;
385645f5050Syouri			}
3860bbfda8aSnia			case '\\':
3870bbfda8aSnia				p++;
388645f5050Syouri
3890bbfda8aSnia			default:
3900bbfda8aSnia				if(*p != *t) {
3910bbfda8aSnia					return (FALSE);
3920bbfda8aSnia				}
3930bbfda8aSnia		}
394645f5050Syouri	}
3950bbfda8aSnia	return (!*t);
396645f5050Syouri}
397645f5050Syouri
3980bbfda8aSniaint regex_match_after_star(const char *p, const char *t)
399645f5050Syouri{
4000bbfda8aSnia	int mat;
4010bbfda8aSnia	int nextp;
402645f5050Syouri
4030bbfda8aSnia	while((*p == '?') || (*p == '*')) {
4040bbfda8aSnia		if(*p == '?') {
4050bbfda8aSnia			if(!*t++) {
4060bbfda8aSnia				return ABORT;
4070bbfda8aSnia			}
4080bbfda8aSnia		}
4090bbfda8aSnia		p++;
410645f5050Syouri	}
4110bbfda8aSnia	if(!*p) {
4120bbfda8aSnia		return TRUE;
4130bbfda8aSnia	}
4140bbfda8aSnia
4150bbfda8aSnia	nextp = *p;
4160bbfda8aSnia	if(nextp == '\\') {
4170bbfda8aSnia		nextp = p[1];
4180bbfda8aSnia	}
4190bbfda8aSnia
4200bbfda8aSnia	mat = FALSE;
4210bbfda8aSnia	while(mat == FALSE) {
4220bbfda8aSnia		if(nextp == *t || nextp == '[') {
4230bbfda8aSnia			mat = regex_match(p, t);
4240bbfda8aSnia		}
4250bbfda8aSnia		if(!*t++) {
4260bbfda8aSnia			mat = ABORT;
4270bbfda8aSnia		}
4280bbfda8aSnia	}
4290bbfda8aSnia	return (mat);
430645f5050Syouri}
431645f5050Syouri
4320bbfda8aSniaint match(const char *p, const char *t)
433645f5050Syouri{
4340bbfda8aSnia	if((p == NULL) || (t == NULL)) {
4350bbfda8aSnia		return (FALSE);
4360bbfda8aSnia	}
4370bbfda8aSnia	return ((regex_match(p, t) == TRUE) ? TRUE : FALSE);
438645f5050Syouri}
439645f5050Syouri
440645f5050Syouri#endif
441645f5050Syouri
442645f5050Syouri
443645f5050Syouri
444645f5050Syouri
445