Subject: FVWM: Multiple window names in condition lists

From: Norman Yarvin <[email-masked]>
Date: Sun, 19 Aug 2001 23:45:59 -0400

Looking at FVWM 2.4.0, I see that the user can specify only one window
name in each condition list.  In particular, you can't have:

Key F1		A  N	Next (CurrentPage xterm1) goto-window
Key F2		A  N	Next (CurrentPage xterm2) goto-window
Key F3		A  N	Next (CurrentPage console) goto-window
Key F4		A  N	Next (CurrentPage emacs) goto-window
Key F5		A  N	Next (CurrentPage Netscape konqueror) goto-window
Key F6		A  N	Next (CurrentPage xdvi xpdf gv acroread) goto-window
Key F7		A  N	Next (CurrentPage xv ee gimp) goto-window
Key F8          A  N	Next (CurrentPage !XTerm !emacs !Netscape !konqueror \
					  !xdvi !xpdf !gv !acroread !xv !ee \
					  !gimp) goto-window

which is what I have now in my .fvwm2rc, after making the changes in the
patch at the end of this message.  The patch is short and simple; it uses
a fixed-size array rather than a linked list, and demands that each list
of windows either be all of windows to use, or all of windows to not use;
there is no attempt to introduce any kind of boolean algebra.  (Boolean
algebra would not only be more complicated to program, but also more
complicated for the user, and, I think, usually needlessly so.)

I wonder if this patch, or something to the same effect, could be added
to the mainstream version, so that I wouldn't have to keep it around and
keep adding it to new versions.  I'm willing to revise the man page to
describe the new behavior.

--- fvwm.h.orig	Sun Aug 19 16:27:49 2001
+++ fvwm.h	Sun Aug 19 17:51:11 2001
@@ -320,7 +320,9 @@
   } my_flags;
   window_flags flags;
   window_flags flag_mask;
-  char *name;
+#define WCMASK_NNAME	40
+  char *name[WCMASK_NNAME];
+  int nname;
   int layer;
 } WindowConditionMask;
 
--- conditional.c.orig	Sun Aug 19 16:27:32 2001
+++ conditional.c	Sun Aug 19 17:51:11 2001
@@ -103,10 +103,13 @@
  **********************************************************************/
 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);
+  int i;
+
+  for(i=0; i<mask->nname; i++)
+    if (mask->my_flags.needs_name)
+      free(mask->name[i]);
+    else if (mask->my_flags.needs_not_name)
+      free(mask->name[i] - 1);
 }
 
 /* Assign the default values for the window mask
@@ -128,6 +131,7 @@
   char *condition;
   char *prev_condition = NULL;
   char *tmp;
+  int i;
 
   if (flags == NULL)
     return;
@@ -245,20 +249,29 @@
           mask->layer = -1; /* needs current layer */
        }
     }
-    else if(!mask->my_flags.needs_name && !mask->my_flags.needs_not_name)
+    else if (mask->nname < WCMASK_NNAME)
     {
-      /* only 1st name to avoid mem leak */
-      mask->name = condition;
-      condition = NULL;
-      if (mask->name[0] == '!')
-      {
-	mask->my_flags.needs_not_name = 1;
-	mask->name++;
+      if (mask->nname==0) {
+	if (condition[0] == '!')
+	  mask->my_flags.needs_not_name = 1;
+	else
+	  mask->my_flags.needs_name = 1;
+      }
+      if (condition[0] == '!' && mask->my_flags.needs_not_name != 1 ||
+	  condition[0] != '!' && mask->my_flags.needs_name != 1) {
+	fvwm_msg(ERR,"CreateConditionMask","\"%s\": window names in condition"
+		" lists must be either all asserted or all negated; no mixes",
+		condition);
+	goto error;
       }
-      else
-	mask->my_flags.needs_name = 1;
+      i=mask->nname++;
+      mask->name[i] = condition;
+      condition = NULL;
+      if (mask->name[i][0] == '!')
+	mask->name[i]++;
     }
 
+error:
     if (prev_condition)
       free(prev_condition);
 
@@ -283,6 +296,7 @@
   Bool fMatchesResource;
   Bool fMatches;
   FvwmWindow *sf = get_focus_window();
+  int i;
 
   if (!blockcmpmask((char *)&(fw->flags), (char *)&(mask->flags),
                     (char *)&(mask->flag_mask), sizeof(fw->flags)))
@@ -320,14 +334,17 @@
     return 0;
 
   /* Yes, I know this could be shorter, but it's hard to understand then */
-  fMatchesName = matchWildcards(mask->name, fw->name);
-  fMatchesIconName = matchWildcards(mask->name, fw->icon_name);
-  fMatchesClass = (fw->class.res_class &&
-		   matchWildcards(mask->name,fw->class.res_class));
-  fMatchesResource = (fw->class.res_name &&
-		      matchWildcards(mask->name, fw->class.res_name));
-  fMatches = (fMatchesName || fMatchesIconName || fMatchesClass ||
-	      fMatchesResource);
+  fMatches = 0;
+  for(i=0; i<mask->nname; i++) {
+    fMatchesName = matchWildcards(mask->name[i], fw->name);
+    fMatchesIconName = matchWildcards(mask->name[i], fw->icon_name);
+    fMatchesClass = (fw->class.res_class &&
+		     matchWildcards(mask->name[i],fw->class.res_class));
+    fMatchesResource = (fw->class.res_name &&
+		        matchWildcards(mask->name[i], fw->class.res_name));
+    fMatches |= (fMatchesName || fMatchesIconName || fMatchesClass ||
+	        fMatchesResource);
+  }
 
   if (mask->my_flags.needs_name && !fMatches)
     return 0;
--
Visit the official FVWM web page at <URL: http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm" in the body of a
message to [email-masked].
To report problems, send mail to [email-masked].