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
32df1c27a6Snia#include "ctwm_shutdown.h"
33645f5050Syouri#include "screen.h"
34645f5050Syouri#include "list.h"
35645f5050Syouri#include "util.h"
360bbfda8aSnia#include "parse.h"
37645f5050Syouri
380bbfda8aSnia#ifdef USE_SYS_REGEX
39645f5050Syouri# include <regex.h>
400bbfda8aSnia#endif /* USE_SYS_REGEX */
41645f5050Syouri
42645f5050Syouri
43645f5050Syouri
44645f5050Syouri/***********************************************************************
45645f5050Syouri *
46645f5050Syouri *  Procedure:
470bbfda8aSnia *      AddToList - add a window name to the appropriate list
48645f5050Syouri *
49645f5050Syouri *  Inputs:
500bbfda8aSnia *      list    - the address of the pointer to the head of a list
510bbfda8aSnia *      name    - a pointer to the name of the window
520bbfda8aSnia *      ptr     - pointer to list dependent data
53645f5050Syouri *
54645f5050Syouri *  Special Considerations
550bbfda8aSnia *      If the list does not use the ptr value, a non-null value
560bbfda8aSnia *      should be placed in it.  LookInList returns this ptr value
570bbfda8aSnia *      and procedures calling LookInList will check for a non-null
580bbfda8aSnia *      return value as an indication of success.
59645f5050Syouri *
60645f5050Syouri ***********************************************************************
61645f5050Syouri */
62645f5050Syouri
630bbfda8aSniavoid AddToList(name_list **list_head, const char *name, void *ptr)
64645f5050Syouri{
650bbfda8aSnia	name_list *nptr;
660bbfda8aSnia
670bbfda8aSnia	if(!list_head) {
680bbfda8aSnia		return;        /* ignore empty inserts */
690bbfda8aSnia	}
700bbfda8aSnia
710bbfda8aSnia	nptr = malloc(sizeof(name_list));
720bbfda8aSnia	if(nptr == NULL) {
730bbfda8aSnia		fprintf(stderr, "unable to allocate %lu bytes for name_list\n",
740bbfda8aSnia		        (unsigned long) sizeof(name_list));
75df1c27a6Snia		DoShutdown();
760bbfda8aSnia	}
770bbfda8aSnia
780bbfda8aSnia	nptr->next = *list_head;
790bbfda8aSnia	nptr->name = strdup(name);
800bbfda8aSnia	nptr->ptr = (ptr == NULL) ? (char *)1 : ptr;
810bbfda8aSnia	*list_head = nptr;
820bbfda8aSnia}
83645f5050Syouri
84645f5050Syouri/***********************************************************************
85645f5050Syouri *
86645f5050Syouri *  Procedure:
870bbfda8aSnia *      LookInList - look through a list for a window name, or class
88645f5050Syouri *
89645f5050Syouri *  Returned Value:
900bbfda8aSnia *      the ptr field of the list structure or NULL if the name
910bbfda8aSnia *      or class was not found in the list
92645f5050Syouri *
93645f5050Syouri *  Inputs:
940bbfda8aSnia *      list    - a pointer to the head of a list
950bbfda8aSnia *      name    - a pointer to the name to look for
960bbfda8aSnia *      class   - a pointer to the class to look for
97645f5050Syouri *
98645f5050Syouri ***********************************************************************
99645f5050Syouri */
100645f5050Syouri
1010bbfda8aSniavoid *LookInList(name_list *list_head, const char *name, XClassHint *class)
1020bbfda8aSnia{
1030bbfda8aSnia	name_list *nptr;
1040bbfda8aSnia
1050bbfda8aSnia	/* look for the name first */
1060bbfda8aSnia	for(nptr = list_head; nptr != NULL; nptr = nptr->next) {
1070bbfda8aSnia		if(match(nptr->name, name)) {
1080bbfda8aSnia			return (nptr->ptr);
1090bbfda8aSnia		}
1100bbfda8aSnia	}
1110bbfda8aSnia
1120bbfda8aSnia	if(class) {
1130bbfda8aSnia		/* look for the res_name next */
1140bbfda8aSnia		for(nptr = list_head; nptr != NULL; nptr = nptr->next) {
1150bbfda8aSnia			if(match(nptr->name, class->res_name)) {
1160bbfda8aSnia				return (nptr->ptr);
1170bbfda8aSnia			}
1180bbfda8aSnia		}
1190bbfda8aSnia
1200bbfda8aSnia		/* finally look for the res_class */
1210bbfda8aSnia		for(nptr = list_head; nptr != NULL; nptr = nptr->next) {
1220bbfda8aSnia			if(match(nptr->name, class->res_class)) {
1230bbfda8aSnia				return (nptr->ptr);
1240bbfda8aSnia			}
1250bbfda8aSnia		}
1260bbfda8aSnia	}
1270bbfda8aSnia	return (NULL);
1280bbfda8aSnia}
1290bbfda8aSnia
1300bbfda8aSniavoid *LookInNameList(name_list *list_head, const char *name)
131645f5050Syouri{
1320bbfda8aSnia	return (LookInList(list_head, name, NULL));
133645f5050Syouri}
134645f5050Syouri
1350bbfda8aSniavoid *LookInListWin(name_list *list_head, TwmWindow *twin)
136645f5050Syouri{
1370bbfda8aSnia	return LookInList(list_head, twin->name, &(twin->class));
138645f5050Syouri}
139645f5050Syouri
1400bbfda8aSniabool IsInList(name_list *list_head, TwmWindow *twin)
141645f5050Syouri{
1420bbfda8aSnia	return (bool)LookInList(list_head, twin->name, &(twin->class));
143645f5050Syouri}
144645f5050Syouri
1450bbfda8aSniavoid *LookPatternInList(name_list *list_head, const char *name,
1460bbfda8aSnia                        XClassHint *class)
147645f5050Syouri{
1480bbfda8aSnia	name_list *nptr;
1490bbfda8aSnia
1500bbfda8aSnia	for(nptr = list_head; nptr != NULL; nptr = nptr->next)
1510bbfda8aSnia		if(match(nptr->name, name)) {
1520bbfda8aSnia			return (nptr->name);
1530bbfda8aSnia		}
1540bbfda8aSnia
1550bbfda8aSnia	if(class) {
1560bbfda8aSnia		for(nptr = list_head; nptr != NULL; nptr = nptr->next)
1570bbfda8aSnia			if(match(nptr->name, class->res_name)) {
1580bbfda8aSnia				return (nptr->name);
1590bbfda8aSnia			}
1600bbfda8aSnia
1610bbfda8aSnia		for(nptr = list_head; nptr != NULL; nptr = nptr->next)
1620bbfda8aSnia			if(match(nptr->name, class->res_class)) {
1630bbfda8aSnia				return (nptr->name);
1640bbfda8aSnia			}
1650bbfda8aSnia	}
1660bbfda8aSnia	return (NULL);
1670bbfda8aSnia}
1680bbfda8aSnia
1690bbfda8aSniavoid *LookPatternInNameList(name_list *list_head, const char *name)
1700bbfda8aSnia{
1710bbfda8aSnia	return (LookPatternInList(list_head, name, NULL));
172645f5050Syouri}
173645f5050Syouri
174645f5050Syouri/***********************************************************************
175645f5050Syouri *
176645f5050Syouri *  Procedure:
1770bbfda8aSnia *      GetColorFromList - look through a list for a window name, or class
178645f5050Syouri *
179645f5050Syouri *  Returned Value:
1800bbfda8aSnia *      true  if the name was found
1810bbfda8aSnia *      false if the name was not found
182645f5050Syouri *
183645f5050Syouri *  Inputs:
1840bbfda8aSnia *      list    - a pointer to the head of a list
1850bbfda8aSnia *      name    - a pointer to the name to look for
1860bbfda8aSnia *      class   - a pointer to the class to look for
187645f5050Syouri *
188645f5050Syouri *  Outputs:
1890bbfda8aSnia *      ptr     - fill in the list value if the name was found
190645f5050Syouri *
191645f5050Syouri ***********************************************************************
192645f5050Syouri */
193645f5050Syouri
1940bbfda8aSniabool GetColorFromList(name_list *list_head, char *name,
1950bbfda8aSnia                      XClassHint *class, Pixel *ptr)
196645f5050Syouri{
1970bbfda8aSnia	bool save;
1980bbfda8aSnia	name_list *nptr;
1990bbfda8aSnia
2000bbfda8aSnia	for(nptr = list_head; nptr != NULL; nptr = nptr->next)
2010bbfda8aSnia		if(match(nptr->name, name)) {
2020bbfda8aSnia			save = Scr->FirstTime;
2030bbfda8aSnia			Scr->FirstTime = true;
2040bbfda8aSnia			GetColor(Scr->Monochrome, ptr, nptr->ptr);
2050bbfda8aSnia			Scr->FirstTime = save;
2060bbfda8aSnia			return true;
2070bbfda8aSnia		}
208645f5050Syouri
2090bbfda8aSnia	if(class) {
2100bbfda8aSnia		for(nptr = list_head; nptr != NULL; nptr = nptr->next)
2110bbfda8aSnia			if(match(nptr->name, class->res_name)) {
2120bbfda8aSnia				save = Scr->FirstTime;
2130bbfda8aSnia				Scr->FirstTime = true;
2140bbfda8aSnia				GetColor(Scr->Monochrome, ptr, nptr->ptr);
2150bbfda8aSnia				Scr->FirstTime = save;
2160bbfda8aSnia				return true;
2170bbfda8aSnia			}
2180bbfda8aSnia
2190bbfda8aSnia		for(nptr = list_head; nptr != NULL; nptr = nptr->next)
2200bbfda8aSnia			if(match(nptr->name, class->res_class)) {
2210bbfda8aSnia				save = Scr->FirstTime;
2220bbfda8aSnia				Scr->FirstTime = true;
2230bbfda8aSnia				GetColor(Scr->Monochrome, ptr, nptr->ptr);
2240bbfda8aSnia				Scr->FirstTime = save;
2250bbfda8aSnia				return true;
2260bbfda8aSnia			}
2270bbfda8aSnia	}
2280bbfda8aSnia	return false;
229645f5050Syouri}
230645f5050Syouri
231645f5050Syouri/***********************************************************************
232645f5050Syouri *
233645f5050Syouri *  Procedure:
2340bbfda8aSnia *      FreeList - free up a list
235645f5050Syouri *
236645f5050Syouri ***********************************************************************
237645f5050Syouri */
238645f5050Syouri
239645f5050Syourivoid FreeList(name_list **list)
240645f5050Syouri{
2410bbfda8aSnia	name_list *nptr;
2420bbfda8aSnia	name_list *tmp;
2430bbfda8aSnia
2440bbfda8aSnia	for(nptr = *list; nptr != NULL;) {
2450bbfda8aSnia		tmp = nptr->next;
2460bbfda8aSnia		free(nptr->name);
2470bbfda8aSnia		free(nptr);
2480bbfda8aSnia		nptr = tmp;
2490bbfda8aSnia	}
2500bbfda8aSnia	*list = NULL;
251645f5050Syouri}
252645f5050Syouri
2530bbfda8aSnia#ifdef USE_SYS_REGEX
254645f5050Syouri
2550bbfda8aSniabool match(const char *pattern, const char *string)
256645f5050Syouri{
2570bbfda8aSnia	regex_t preg;
2580bbfda8aSnia	int error;
2590bbfda8aSnia
2600bbfda8aSnia	if((pattern == NULL) || (string == NULL)) {
2610bbfda8aSnia		return false;
2620bbfda8aSnia	}
2630bbfda8aSnia	error = regcomp(&preg, pattern, REG_EXTENDED | REG_NOSUB);
2640bbfda8aSnia	if(error != 0) {
2650bbfda8aSnia		char buf [256];
2660bbfda8aSnia		regerror(error, &preg, buf, sizeof buf);
2670bbfda8aSnia		fprintf(stderr, "%s : %s\n", buf, pattern);
2680bbfda8aSnia		return false;
2690bbfda8aSnia	}
2700bbfda8aSnia	error = regexec(&preg, string, 5, 0, 0);
2710bbfda8aSnia	regfree(&preg);
2720bbfda8aSnia	if(error == 0) {
2730bbfda8aSnia		return true;
2740bbfda8aSnia	}
2750bbfda8aSnia	return false;
276645f5050Syouri}
277645f5050Syouri
278645f5050Syouri#else
279645f5050Syouri
280645f5050Syouri
281645f5050Syouri
2820bbfda8aSniaint regex_match(const char *p, const char *t);
2830bbfda8aSniaint regex_match_after_star(const char *p, const char *t);
284645f5050Syouri
2850bbfda8aSnia#if 0                           /* appears not to be used anywhere */
2860bbfda8aSniastatic int is_pattern(char *p)
287645f5050Syouri{
2880bbfda8aSnia	while(*p) {
2890bbfda8aSnia		switch(*p++) {
2900bbfda8aSnia			case '?':
2910bbfda8aSnia			case '*':
2920bbfda8aSnia			case '[':
2930bbfda8aSnia				return TRUE;
2940bbfda8aSnia			case '\\':
2950bbfda8aSnia				if(!*p++) {
2960bbfda8aSnia					return FALSE;
2970bbfda8aSnia				}
2980bbfda8aSnia		}
299645f5050Syouri	}
3000bbfda8aSnia	return FALSE;
301645f5050Syouri}
302645f5050Syouri#endif
303645f5050Syouri
304645f5050Syouri#define ABORT 2
305645f5050Syouri
3060bbfda8aSniaint regex_match(const char *p, const char *t)
307645f5050Syouri{
3080bbfda8aSnia	char range_start, range_end;
3090bbfda8aSnia	int invert;
3100bbfda8aSnia	int member_match;
3110bbfda8aSnia	int loop;
3120bbfda8aSnia
3130bbfda8aSnia	for(; *p; p++, t++) {
3140bbfda8aSnia		if(!*t) {
3150bbfda8aSnia			return (*p == '*' && *++p == '\0') ? TRUE : ABORT;
316645f5050Syouri		}
3170bbfda8aSnia		switch(*p) {
3180bbfda8aSnia			case '?':
3190bbfda8aSnia				break;
3200bbfda8aSnia			case '*':
3210bbfda8aSnia				return regex_match_after_star(p, t);
3220bbfda8aSnia			case '[': {
3230bbfda8aSnia				p++;
3240bbfda8aSnia				invert = FALSE;
3250bbfda8aSnia				if(*p == '!' || *p == '^') {
3260bbfda8aSnia					invert = TRUE;
3270bbfda8aSnia					p++;
3280bbfda8aSnia				}
3290bbfda8aSnia				if(*p == ']') {
3300bbfda8aSnia					return ABORT;
3310bbfda8aSnia				}
3320bbfda8aSnia				member_match = FALSE;
3330bbfda8aSnia				loop = TRUE;
3340bbfda8aSnia				while(loop) {
3350bbfda8aSnia					if(*p == ']') {
3360bbfda8aSnia						loop = FALSE;
3370bbfda8aSnia						continue;
3380bbfda8aSnia					}
3390bbfda8aSnia					if(*p == '\\') {
3400bbfda8aSnia						range_start = range_end = *++p;
3410bbfda8aSnia					}
3420bbfda8aSnia					else {
3430bbfda8aSnia						range_start = range_end = *p;
3440bbfda8aSnia					}
3450bbfda8aSnia					if(!range_start) {
3460bbfda8aSnia						return ABORT;
3470bbfda8aSnia					}
3480bbfda8aSnia					if(*++p == '-') {
3490bbfda8aSnia						range_end = *++p;
3500bbfda8aSnia						if(range_end == '\0' || range_end == ']') {
3510bbfda8aSnia							return ABORT;
3520bbfda8aSnia						}
3530bbfda8aSnia						if(range_end == '\\') {
3540bbfda8aSnia							range_end = *++p;
3550bbfda8aSnia						}
3560bbfda8aSnia						p++;
3570bbfda8aSnia					}
3580bbfda8aSnia					if(range_start < range_end) {
3590bbfda8aSnia						if(*t >= range_start && *t <= range_end) {
3600bbfda8aSnia							member_match = TRUE;
3610bbfda8aSnia							loop = FALSE;
3620bbfda8aSnia						}
3630bbfda8aSnia					}
3640bbfda8aSnia					else {
3650bbfda8aSnia						if(*t >= range_end && *t <= range_start) {
3660bbfda8aSnia							member_match = TRUE;
3670bbfda8aSnia							loop = FALSE;
3680bbfda8aSnia						}
3690bbfda8aSnia					}
3700bbfda8aSnia				}
3710bbfda8aSnia				if((invert && member_match) || !(invert || member_match)) {
3720bbfda8aSnia					return (FALSE);
3730bbfda8aSnia				}
3740bbfda8aSnia				if(member_match) {
3750bbfda8aSnia					while(*p != ']') {
3760bbfda8aSnia						if(!*p) {
3770bbfda8aSnia							return (ABORT);
3780bbfda8aSnia						}
3790bbfda8aSnia						if(*p == '\\') {
3800bbfda8aSnia							p++;
3810bbfda8aSnia						}
3820bbfda8aSnia						p++;
3830bbfda8aSnia					}
3840bbfda8aSnia				}
3850bbfda8aSnia				break;
386645f5050Syouri			}
3870bbfda8aSnia			case '\\':
3880bbfda8aSnia				p++;
389645f5050Syouri
3900bbfda8aSnia			default:
3910bbfda8aSnia				if(*p != *t) {
3920bbfda8aSnia					return (FALSE);
3930bbfda8aSnia				}
3940bbfda8aSnia		}
395645f5050Syouri	}
3960bbfda8aSnia	return (!*t);
397645f5050Syouri}
398645f5050Syouri
3990bbfda8aSniaint regex_match_after_star(const char *p, const char *t)
400645f5050Syouri{
4010bbfda8aSnia	int mat;
4020bbfda8aSnia	int nextp;
403645f5050Syouri
4040bbfda8aSnia	while((*p == '?') || (*p == '*')) {
4050bbfda8aSnia		if(*p == '?') {
4060bbfda8aSnia			if(!*t++) {
4070bbfda8aSnia				return ABORT;
4080bbfda8aSnia			}
4090bbfda8aSnia		}
4100bbfda8aSnia		p++;
411645f5050Syouri	}
4120bbfda8aSnia	if(!*p) {
4130bbfda8aSnia		return TRUE;
4140bbfda8aSnia	}
4150bbfda8aSnia
4160bbfda8aSnia	nextp = *p;
4170bbfda8aSnia	if(nextp == '\\') {
4180bbfda8aSnia		nextp = p[1];
4190bbfda8aSnia	}
4200bbfda8aSnia
4210bbfda8aSnia	mat = FALSE;
4220bbfda8aSnia	while(mat == FALSE) {
4230bbfda8aSnia		if(nextp == *t || nextp == '[') {
4240bbfda8aSnia			mat = regex_match(p, t);
4250bbfda8aSnia		}
4260bbfda8aSnia		if(!*t++) {
4270bbfda8aSnia			mat = ABORT;
4280bbfda8aSnia		}
4290bbfda8aSnia	}
4300bbfda8aSnia	return (mat);
431645f5050Syouri}
432645f5050Syouri
4330bbfda8aSniaint match(const char *p, const char *t)
434645f5050Syouri{
4350bbfda8aSnia	if((p == NULL) || (t == NULL)) {
4360bbfda8aSnia		return (FALSE);
4370bbfda8aSnia	}
4380bbfda8aSnia	return ((regex_match(p, t) == TRUE) ? TRUE : FALSE);
439645f5050Syouri}
440645f5050Syouri
441645f5050Syouri#endif
442645f5050Syouri
443645f5050Syouri
444645f5050Syouri
445645f5050Syouri
446