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