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