About a month ago, I sent in a patch to allow multiple window names in
conditions.  It was developed for my own use, but since I am a lazy guy,
I was hoping the fvwm workers would pick it up, so I wouldn't have to
keep maintaining it.  That doesn't seem to have happened.  Perhaps I
should have mentioned that the patch is backward-compatible with old
fvwm2rc files.  It is mildly half-assed in the sense that it doesn't
implement a full boolean expression parser, but in exchange it is small
and simple.  It assumes that the boolean operator the user wants is "OR",
or in the case of a window name prefixed with '!', "AND NOT".  The
following is a rehash of the patch against the current CVS tree.
ChangeLog and man page updates are included.  If something's wrong with
it, I'd appreciate hearing what.


Index: ChangeLog
===================================================================
RCS file: /home/cvs/fvwm/fvwm/ChangeLog,v
retrieving revision 1.2512
diff -u -u -r1.2512 ChangeLog
--- ChangeLog   1 Jul 2004 14:34:22 -0000       1.2512
+++ ChangeLog   4 Jul 2004 19:23:31 -0000
@@ -1,3 +1,11 @@
+2004-07-04  Norman Yarvin  <[EMAIL PROTECTED]>
+
+       * fvwm/fvwm.1.in:
+       * fvmw/fvwm.h:
+       * fvwm/conditional.c:
+       modified the code for conditions so that multiple window names may
+       be specified in each condition
+       
 2004-07-01  Dominik Vogt  <[EMAIL PROTECTED]>
 
        * fvwm/move_resize.c (GetResizeArguments):
Index: fvwm/conditional.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/fvwm/conditional.c,v
retrieving revision 1.93
diff -u -u -r1.93 conditional.c
--- fvwm/conditional.c  9 May 2004 12:59:55 -0000       1.93
+++ fvwm/conditional.c  4 Jul 2004 19:23:33 -0000
@@ -382,13 +382,14 @@
  */
 void FreeConditionMask(WindowConditionMask *mask)
 {
-       if (mask->my_flags.needs_name)
-       {
-               free(mask->name);
-       }
-       else if (mask->my_flags.needs_not_name)
-       {
-               free(mask->name - 1);
+       struct namelist *p,*p2;
+
+       for (p=mask->namelist; p;)
+       { 
+               free(p->name);
+               p2=p->next;
+               free(p);
+               p=p2;
        }
 
        return;
@@ -614,21 +615,16 @@
                        }
                        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 namelist *p;
+
+                       p = (struct namelist *)
+                               safemalloc(sizeof(struct namelist));
+                       p->name = condition;
+                       p->next = mask->namelist;
+                       mask->namelist = p;
+                       condition = NULL; 
                }
 
                if (prev_condition)
@@ -663,6 +659,9 @@
        int is_on_page;
        int is_on_global_page;
        FvwmWindow *sf = get_focus_window();
+       struct namelist *p;
+       char *name;
+       Bool invert,tried,matched;
 
        /* match FixedSize conditional */
        /* special treatment for FixedSize, because more than just
@@ -822,27 +821,52 @@
                }
        }
 
-       /* 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)
-       {
-               return False;
-       }
+       tried = False;
+       matched = False;
+
+       for(p=mask->namelist; p; p=p->next)
+       { 
+               name = p->name;
+               invert = False;
+               if(*name == '!')
+               {
+                       name++;
+                       invert = True;
+               }
+
+               /* Yes, I know this could be shorter, but it's hard to
+                * understand then
+                */
+               does_name_match = matchWildcards(name, fw->name.name);
+               does_icon_name_match = 
+                                 matchWildcards(name, fw->icon_name.name);
+               does_class_match =                    (fw->class.res_class && 
+                                 matchWildcards(name, fw->class.res_class));
+               does_resource_match =                 (fw->class.res_name &&
+                                 matchWildcards(name, fw->class.res_name));
+               does_match =
+                       (does_name_match || does_icon_name_match ||
+                        does_class_match || does_resource_match);
+
+               if(invert && does_match)
+               {
+                       return False;           /* "!window" takes priority */
+               }
+               if(!invert && does_match)
+               {
+                       matched = True;         /* this condition satisfied */
+               }
+               if(!invert)
+               {
+                       tried = True;
+               }
+       } 
+
+       if(tried && !matched)
+       { 
+               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.141
diff -u -u -r1.141 fvwm.1.in
--- fvwm/fvwm.1.in      1 Jul 2004 14:34:23 -0000       1.141
+++ fvwm/fvwm.1.in      4 Jul 2004 19:23:46 -0000
@@ -10366,15 +10366,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.  The window
+names may include the wildcards '*' and '?'.  The window name,
+icon name, class, and resource are considered when attempting to
+find a match.  If more than one window name is given, the
+implicit operator is a boolean OR -- that is, the condition will
+be satisfied if the window has any of those names.  Window names
+to avoid may also be specified: each window
+name can begin with '!' which prevents
 .I command
 if any of the window name, icon name, class or resource match.
+If a mixture of names beginning with '!' and names
+without '!' is specified, then the implicit operator is an OR
+on the names without '!' and an AND NOT on the names with '!';
+that is, the condition is satisfied if none of the names with '!'
+match, and if one or more of the names without '!' match.
 
-Any condition can be negated by using a an exclamation mark ('!')
-directly in front of its name.
+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 (!Netscape !konqueror !Mozilla*) WarpToWindow 99 90
+.EE
+This goes to the next non-browser window; if the above two commands are
+bound to two different keys, the first key pages through browser windows
+and the second through non-browser windows.
+.EX
+       Next (XTerm !console) WarpToWindow 99 90
+.EE
+This goes to the next xterm window, except that the one named
+"console" (with the -name option to xterm) is excluded.
+
+Any of the other conditions, which follow, can also be negated by using a
+an exclamation mark ('!')  directly in front of its name.
 
 .IR AcceptsFocus ,
 .IR CirculateHit ,
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 4 Jul 2004 19:23:47 -0000
@@ -400,6 +400,12 @@
 } window_flags;
 
 /* Window mask for Circulate and Direction functions */
+struct namelist
+{
+       char *name;
+       struct namelist *next;
+};
+
 typedef struct WindowConditionMask
 {
        struct
@@ -419,8 +425,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 +434,7 @@
        } my_flags;
        window_flags flags;
        window_flags flag_mask;
-       char *name;
+       struct namelist *namelist;
        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