Mikhael Goikhman <[EMAIL PROTECTED]> wrote: >Like other posters, I don't quite like that names are sudently work >using logical OR while all other options in conditional commands work >using logical AND. And the nagations of names work using AND again. > >Here is the proposal that should solve all these ambiguities, but it is >a bit backward incompatible in that one character is treated specially. >I don't think there is any fvwm user that has a conditional in his config >that will be broken however, so this is mostly the theoretical problem. > >1) All condition options always work using logical AND, as usual. >2) Any option is either keyword or window name/resource/class, as usual. >3) Options (with possible argument) are separated by commas, as usual. >4) In the future we will have (Name "name1", Class "name2") syntax. >5) The leading character "!" means logical NOT of that option, as usual. >6) Any name may contain a spacial character "|" meaning logical OR. > >Here are examples: > > Next ("Netscape|konqueror|Mozilla*") WarpToWindow 99 90 # go to browser > > All (CurrentPage, "xterm|rvxt", !Iconified) Iconify # iconify terminals > > Next (!"FvwmPager|FvwmForm*|FvwmButtons") Raise # raise next non-module > > Next (!FvwmPager, !FvwmForm*, !FvwmButtons) Raise > >The last 2 commands are equivalent. So basically, we don't really need >to support more than one name options like in the last example. I am >not against to add such extended support though. > >I think this syntax naturally extends the current syntax and allows most >of the logical expressions a user may want to have. This can't be said >about the original proposed syntax.
Thanks for the proposal. I was contemplating adding full boolean expressions, but looking at the code, that gets a bit complicated if backwards compatibility is to be preserved. The code change required by your proposal is not much bigger than my original patch; and it doesn't have the user interface weirdness that mine did. So I implemented it. Here's the patch: Index: ChangeLog =================================================================== RCS file: /home/cvs/fvwm/fvwm/ChangeLog,v retrieving revision 1.2518 diff -u -u -r1.2518 ChangeLog --- ChangeLog 10 Jul 2004 09:13:25 -0000 1.2518 +++ ChangeLog 10 Jul 2004 17:47:13 -0000 @@ -1,3 +1,11 @@ +2004-07-10 Norman Yarvin <[EMAIL PROTECTED]> + + * fvwm/conditional.c: + * fvwm/fvwm.h: + * fvwm/fvwm.1.in: + modified the code for conditions so that multiple window names may + be specified in each condition + 2004-07-09 Dominik Vogt <[EMAIL PROTECTED]> * fvwm/module_interface.c (CONFIGARGS): Index: fvwm/conditional.c =================================================================== RCS file: /home/cvs/fvwm/fvwm/fvwm/conditional.c,v retrieving revision 1.95 diff -u -u -r1.95 conditional.c --- fvwm/conditional.c 8 Jul 2004 10:08:09 -0000 1.95 +++ fvwm/conditional.c 10 Jul 2004 17:47:14 -0000 @@ -376,22 +376,31 @@ } /* - * The name field of the mask is allocated in CreateConditionMask. + * The name_condition field of the mask is allocated in CreateConditionMask. * It must be freed. * NOTE - exported via .h */ void FreeConditionMask(WindowConditionMask *mask) { - if (mask->my_flags.needs_name) - { - free(mask->name); - } - else if (mask->my_flags.needs_not_name) + struct name_condition *pp,*pp2; + struct namelist *p,*p2; + + for (pp=mask->name_condition; pp; ) { - free(mask->name - 1); + for (p=pp->namelist; p; ) + { + p2=p->next; + if(!p2) + { + free(p->name - (pp->invert ? 1 : 0)); + } + free(p); + p=p2; + } + pp2=pp->next; + free(pp); + pp=pp2; } - - return; } /* Assign the default values for the window mask @@ -614,21 +623,36 @@ } mask->my_flags.needs_same_layer = on; } - else if (!mask->my_flags.needs_name && - !mask->my_flags.needs_not_name) - { - /* only 1st name to avoid mem leak */ - mask->name = condition; - condition = NULL; - if (on == 0) - { - mask->my_flags.needs_not_name = 1; - mask->name++; - } - else - { - mask->my_flags.needs_name = 1; + else + { + struct name_condition *pp; + struct namelist *p; + char *condp; + + pp = (struct name_condition *) + safemalloc(sizeof(struct name_condition)); + pp->invert = !on; + pp->namelist = NULL; + pp->next = mask->name_condition; + mask->name_condition = pp; + for(condp=cond; ; ) + { + p = (struct namelist *) + safemalloc(sizeof(struct namelist)); + p->name=condp; + p->next=pp->namelist; + pp->namelist=p; + while(*condp && *condp != '|') + { + condp++; + } + if(!*condp) + { + break; + } + *condp++='\0'; } + condition = NULL; /* so it won't be freed */ } if (prev_condition) @@ -654,15 +678,14 @@ */ Bool MatchesConditionMask(FvwmWindow *fw, WindowConditionMask *mask) { - int does_name_match; - int does_icon_name_match; - int does_class_match; - int does_resource_match; int does_match; int is_on_desk; int is_on_page; int is_on_global_page; FvwmWindow *sf = get_focus_window(); + struct name_condition *pp; + struct namelist *p; + char *name; /* match FixedSize conditional */ /* special treatment for FixedSize, because more than just @@ -822,27 +845,28 @@ } } - /* Yes, I know this could be shorter, but it's hard to understand then - */ - does_name_match = matchWildcards(mask->name, fw->name.name); - does_icon_name_match = matchWildcards(mask->name, fw->icon_name.name); - does_class_match = - (fw->class.res_class && matchWildcards( - mask->name,fw->class.res_class)); - does_resource_match = - (fw->class.res_name && matchWildcards( - mask->name, fw->class.res_name)); - does_match = - (does_name_match || does_icon_name_match || does_class_match || - does_resource_match); - if (mask->my_flags.needs_name && !does_match) - { - return False; - } - if (mask->my_flags.needs_not_name && does_match) + for(pp=mask->name_condition; pp; pp=pp->next) { - return False; - } + does_match = 0; + for(p=pp->namelist; p; p=p->next) + { + name=p->name; + does_match |= matchWildcards(name, fw->name.name); + does_match |= matchWildcards(name, fw->icon_name.name); + if(fw->class.res_class) + does_match |= matchWildcards(name, + fw->class.res_class); + if(fw->class.res_name) + does_match |= matchWildcards(name, + fw->class.res_name); + } + if(( pp->invert && does_match) || + (!pp->invert && !does_match)) + { + return False; + } + } + if (mask->layer == -1 && sf) { int is_same_layer; Index: fvwm/fvwm.1.in =================================================================== RCS file: /home/cvs/fvwm/fvwm/fvwm/fvwm.1.in,v retrieving revision 1.143 diff -u -u -r1.143 fvwm.1.in --- fvwm/fvwm.1.in 6 Jul 2004 13:05:04 -0000 1.143 +++ fvwm/fvwm.1.in 10 Jul 2004 17:47:28 -0000 @@ -10384,12 +10384,42 @@ In addition, the .I conditions -may include one window name to match to. The window name may -include the wildcards '*' and '?'. The window name, icon name, -class, and resource are considered when attempting to find a -match. The window name can begin with '!' which prevents +may include one or more window names to match to. If more than one +window name is given, all of them must match. The window name, icon +name, class, and resource are considered when attempting to find a match. +Each name may include the wildcards '*' and '?', and may consist +of two or more alternatives, separated by the character '|', which acts +as an OR operator. (If OR operators are used, they must not be separated +by spaces from the names.) Each window name can begin with '!', which prevents .I command -if any of the window name, icon name, class or resource match. +if any of the window name, icon name, class or resource match. However, +'!' must not be applied to individual names in a group separated by OR +operators; it may only be applied to the beginning of the group, and +then it operates on the whole group. + +Examples: +.EX + Next ("Netscape|konqueror|Mozilla*") WarpToWindow 99 90 +.EE +This goes to the next web browser window, no matter which of the three +named web browsers is being used. +.EX + Next ("Mozilla*" "Bookmark*") WarpToWindow 99 90 +.EE +This goes to Mozilla's bookmark manager window, ignoring other Mozilla +windows and other browsers' bookmark windows. +.EX + All ("XTerm|rxvt" !console) Iconify +.EE +This iconifies all the xterm and rxvt windows on the current page, +except that the one named "console" (with the -name option to xterm) +is excluded. +.EX + Next (!"FvwmPager|FvwmForm*|FvwmButtons") Raise + Next (!FvwmPager, !FvwmForm*, !FvwmButtons) Raise +.EE +These two commands are equivalent; either one raises the next window +which is not one of the named fvwm modules. Any condition can be negated by using a an exclamation mark ('!') directly in front of its name. Index: fvwm/fvwm.h =================================================================== RCS file: /home/cvs/fvwm/fvwm/fvwm/fvwm.h,v retrieving revision 1.231 diff -u -u -r1.231 fvwm.h --- fvwm/fvwm.h 30 May 2004 14:05:48 -0000 1.231 +++ fvwm/fvwm.h 10 Jul 2004 17:47:29 -0000 @@ -399,6 +399,23 @@ unsigned has_ewmh_init_wm_desktop : 2; } window_flags; +/* Window name data structure for window conditions: a list of lists + of names to match, the boolean operation on the matches being an + AND of ORs. */ +struct namelist /* matches to names in this list are ORed */ +{ + char *name; + struct namelist *next; +}; + +struct name_condition /* matches to namelists in this list are + ANDed, after possibly inverting each */ +{ + Bool invert; + struct namelist *namelist; + struct name_condition *next; +}; + /* Window mask for Circulate and Direction functions */ typedef struct WindowConditionMask { @@ -419,8 +436,6 @@ #define NEEDS_TRUE 1 #define NEEDS_FALSE 2 unsigned needs_focus : 2; - unsigned needs_name : 1; - unsigned needs_not_name : 1; unsigned needs_pointer : 2; unsigned needs_same_layer : 1; unsigned use_circulate_hit : 1; @@ -430,7 +445,7 @@ } my_flags; window_flags flags; window_flags flag_mask; - char *name; + struct name_condition *name_condition; int layer; } WindowConditionMask; -- Visit the official FVWM web page at <URL:http://www.fvwm.org/>. To unsubscribe from the list, send "unsubscribe fvwm-workers" in the body of a message to [EMAIL PROTECTED] To report problems, send mail to [EMAIL PROTECTED]