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]

Reply via email to