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