Subject: FvwmBacker changes

From: Michael Han <[email-masked]>
Date: Sat, 13 Nov 1999 08:54:11 -0800

Hi, as promised, I've completed some patches to FvwmBacker. The
primary change I made is to replace the config command FvwmBackerDesk
with FvwmBackerCommand (Desk x y). In the process of changing things,
I also discovered and fixed a bug involving negative desk numbers, and
converted FvwmBacker from using an action table to a linked list of
commands. Here's the changelog:

1999-11-13  Michael Han  <[email-masked]>

        * FvwmBacker/FvwmBacker.c: Added page-awareness; converted to
        linked list of commands instead of table (to fix bugs caused
        if DesktopSize changes or if desktop is negative).
        * FvwmBacker/FvwmBacker.1: Documented page-awareness

And the patch is attached.
-- 
[email-masked]                         http://www.best.com/~mikehan/
coffee achiever                              San Francisco, California
The life uncaffeinated is not worth living.

Index: FvwmBacker.1
===================================================================
RCS file: /home/cvs/fvwm/fvwm/modules/FvwmBacker/FvwmBacker.1,v
retrieving revision 1.3
diff -u -r1.3 FvwmBacker.1
--- FvwmBacker.1	1999/09/09 01:01:12	1.3
+++ FvwmBacker.1	1999/11/13 07:42:48
@@ -38,21 +38,31 @@
 .SH CONFIGURATION OPTIONS
 The following is the only supported option at present:
 
-.IP "*FvwmBackerDesk \fIDeskNumber command | -solid color | colorset n\fP"
-Specifies the \fIcommand\fP to execute when the specified
-\fIDeskNumber\fP becomes active.
+.IP "*FvwmBackerCommand \fI(Desk PageX PageY) command\fP"
+Specifies the \fIcommand\fP to execute when the viewport matches the
+arguments for the desk, x coordinate and y coordinate. Any or all of
+these arguments can be replaced with an asterisk (*) to indicate that
+any value matches.
 
-If the next word is \fI-solid\fP FvwmBacker uses the next
+If the \fIcommand\fP is \fI-solid\fP FvwmBacker uses the next
 argument as a color in the X database and sets the background to that
 color without generating a system call to xsetroot (only single word
 color names may be used).
 
-If the next word is \fIcolorset\fP FvwmBacker uses the background
+If the \fIcommand\fP is \fIcolorset\fP FvwmBacker uses the background
 specified in colorset \fIn\fP for the given desk.  Please refer to
 the man page of the FvwmTheme module for details about colorsets.
 
 Otherwise the command is sent to fvwm to execute.
 
+.SH OLD-STYLE OPTIONS
+There is continued support for the now deprecated option:
+
+.IP "*FvwmBackerDesk \fIDesk command\fP"
+
+It is functionally equivalent to using an asterisk for both page
+coordinates with \fI*FvwmBackerCommand\fP.
+
 .SH SAMPLE CONFIGURATION
 The following are excepts from an .fvwm2rc file which describe
 FvwmBacker initialization commands:
@@ -62,10 +72,10 @@
 ####
 # Set Up Backgrounds for different desktops.
 ####
-*FvwmBackerDesk 0 -solid steelblue
-*FvwmBackerDesk 1 -solid midnightblue
-*FvwmBackerDesk 2 -solid yellow
-*FvwmBackerDesk 3 Exec xpmroot /usr/include/X11/pixmaps/background2.xpm
+*FvwmBackerCommand (0 * *) -solid steelblue
+*FvwmBackerCommand (1 0 0) -solid midnightblue
+*FvwmBackerCommand (1 0 1) -solid yellow
+*FvwmBackerCommand (1 1 *) Exec xpmroot /usr/include/X11/pixmaps/background2.xpm
 .sp
 .fi
 
@@ -75,3 +85,5 @@
             (doodman on IRC, check the #linux channel)
 .SH Modified by
 Andrew Davison ([email-masked])
+
+Michael Han ([email-masked])
Index: FvwmBacker.c
===================================================================
RCS file: /home/cvs/fvwm/fvwm/modules/FvwmBacker/FvwmBacker.c,v
retrieving revision 1.20
diff -u -r1.20 FvwmBacker.c
--- FvwmBacker.c	1999/10/20 15:50:36	1.20
+++ FvwmBacker.c	1999/11/13 07:42:50
@@ -55,12 +55,17 @@
 
 #include "libs/Module.h"
 #include "libs/Colorset.h"
+#include "libs/Parse.h"
 #include "FvwmBacker.h"
 
 unsigned long BackerGetColor(char *color);
 
-typedef struct
+struct Command
 {
+  int desk;
+  int deskglob; /* Set in case desk is globbed */
+  int x;	/* Page X coordinate; -1 for glob */
+  int y;	/* Page Y coordinate; -1 for glob */
   int type; /* The command type.
 	     * -1 = no command.
 	     *  0 = command to be spawned
@@ -69,11 +74,24 @@
   char*	cmdStr; /* The command string (Type 0)   */
   unsigned long solidColor; /* A solid color after X parsing (Type 1) */
   int colorset; /* the colorset to be used */
-} Command;
+  struct Command *next;
+};
+
+typedef struct Command Command;
+
+typedef struct
+{
+  Command *first;
+  Command *last;
+  Command *current;
+} CommandChain;
 
-Command *commands;
-int DeskCount=0;
+CommandChain *commands;
+
+/* int DeskCount=0; */
 int current_desk = 0;
+int current_x = 0;
+int current_y = 0;
 
 int Fvwm_fd[2];
 int fd_width;
@@ -85,12 +103,14 @@
 Display* 	dpy;
 Window		root;
 int			screen;
+int MyDisplayHeight;
+int MyDisplayWidth;
 
 FILE*	logFile;
 
 /* Comment this out if you don't want a logfile. */
 
-/* #define LOGFILE "/tmp/FvwmBacker.log"*/
+/* #define LOGFILE "/tmp/FvwmBacker.log" */

 int main(int argc, char **argv)
@@ -98,7 +118,9 @@
   char *temp, *s;
   char* displayName = NULL;
 
-  commands=NULL;
+  commands = (CommandChain*)safemalloc(sizeof(CommandChain));
+  commands->first = NULL;
+  commands->current = NULL;
 
   /* Save the program name for error messages and config parsing */
   temp = argv[0];
@@ -129,6 +151,8 @@
   }
   screen = DefaultScreen(dpy);
   root = RootWindow(dpy, screen);
+  MyDisplayHeight = DisplayHeight(dpy, screen);
+  MyDisplayWidth = DisplayWidth(dpy, screen);
 
   /* allocate default colorset */
   AllocColorset(0);
@@ -146,8 +170,8 @@
 
   fd_width = GetFdWidth();
 
-  SetMessageMask(Fvwm_fd,
-		 M_NEW_DESK|M_CONFIG_INFO|M_END_CONFIG_INFO|M_SENDCONFIG);
+  SetMessageMask(Fvwm_fd, M_NEW_DESK|M_NEW_PAGE|
+                 M_CONFIG_INFO|M_END_CONFIG_INFO|M_SENDCONFIG);
 
   /*
   ** we really only want the current desk, and window list sends it
@@ -190,13 +214,13 @@
 }

-void set_desk_background(int desk)
+void set_desk_background(Command *c)
 {
-  switch (commands[desk].type)
+  switch (c->type)
   {
   case 1:
     /* Process a solid color request */
-    XSetWindowBackground(dpy, root, commands[desk].solidColor);
+    XSetWindowBackground(dpy, root, c->solidColor);
     XClearWindow(dpy, root);
     XFlush(dpy);
 #ifdef LOGFILE
@@ -206,22 +230,33 @@
     break;
   case 2:
     SetWindowBackground(
-      dpy, root, DisplayWidth(dpy, screen), DisplayHeight(dpy, screen),
-      &Colorset[commands[desk].colorset],
+      dpy, root, MyDisplayWidth, MyDisplayHeight, &Colorset[c->colorset],
       DefaultDepth(dpy, screen), DefaultGC(dpy, screen), True);
     XFlush(dpy);
     break;
   case 0:
   case -1:
   default:
-    if(commands[desk].cmdStr != NULL)
+    if(c->cmdStr != NULL)
     {
-      SendFvwmPipe(commands[desk].cmdStr, (unsigned long)0);
+      SendFvwmPipe(c->cmdStr, (unsigned long)0);
     }
     break;
   } /* switch */
 }
 
+/* MatchDeskPage - matches the current desk & page coordinates to a command
+ * entry. This is real messy. MMH, 11/99 */
+int MatchDeskPage(Command *c)
+{
+  if ( (c->deskglob || c->desk == current_desk ) &&
+       (c->x < 0 || c->x == current_x ) &&
+       (c->y < 0 || c->y == current_y ) )
+    return 1;
+  else
+    return 0;
+}
+
 /******************************************************************************
   ProcessMessage - Process the message coming from Fvwm
     Skeleton based on processmessage() from FvwmIdent:
@@ -239,39 +274,50 @@
     if (strncasecmp(tline, "colorset", 8) == 0)
     {
       colorset = LoadColorset(tline + 8);
-      if (commands[current_desk].colorset == colorset)
+      commands->current=commands->first;
+      while (commands->current != NULL)
       {
-	set_desk_background(current_desk);
+	if ((MatchDeskPage(commands->current)) &&
+	    (commands->current->colorset == colorset))
+	  set_desk_background(commands->current);
+	if (commands->current->next != NULL)
+	  commands->current = commands->current->next;
+	else
+	  break;
       }
     }
     break;
 
   case M_NEW_DESK:
-    if (body[0]>DeskCount || commands[body[0]].type == -1)
+    commands->current=commands->first;
+    current_desk = body[0];
+    while (commands->current != NULL)
     {
-      return;
+      if (MatchDeskPage(commands->current))
+	set_desk_background(commands->current);
+      if (commands->current->next != NULL)
+	commands->current = commands->current->next;
+      else
+	break;
     }
-#ifdef LOGFILE
-    fprintf(logFile,"Desk: %d\n",body[0]);
-    fprintf(logFile,"Command type: %d\n",commands[body[0]].type);
-    if (commands[body[0]].type == 0)
-      fprintf(logFile,"Command String: %s\n",commands[body[0]].cmdStr);
-    else if (commands[body[0]].type == 1)
-      fprintf(logFile,"Color Number: %d\n",commands[body[0]].solidColor);
-    else if (commands[body[0]].type == -1)
-      fprintf(logFile,"No Command\n");
-    else if (commands[body[0]].type == 2)
-      fprintf(logFile,"Use Colorset %d\n",commands[body[0]].colorset);
-    else
+    break;
+
+  case M_NEW_PAGE:
+    commands->current=commands->first;
+    current_desk = body[2];
+    current_x = body[0]/MyDisplayWidth;
+    current_y = body[1]/MyDisplayHeight;
+    while (commands->current != NULL)
     {
-      fprintf(logFile,"Illegal command type !\n");
-      exit(1);
+      if (MatchDeskPage(commands->current))
+	set_desk_background(commands->current);
+      if (commands->current->next != NULL)
+	commands->current = commands->current->next;
+      else
+	break;
     }
-    fflush(logFile);
-#endif
-    set_desk_background(body[0]);
-    current_desk = body[0];
     break;
+
   default:
     break;
   } /* switch */
@@ -331,25 +377,28 @@
 ******************************************************************************/
 void ParseConfig()
 {
-  char line2[40];
+  char *line_start;
   char *tline;
 
-  sprintf(line2,"*%sDesk",Module);
+  line_start=safemalloc(strlen(Module)+1);
+  strcpy(line_start,"*");
+  strcat(line_start, Module);
 
-  InitGetConfigLine(Fvwm_fd,line2);
+  InitGetConfigLine(Fvwm_fd,line_start);
   GetConfigLine(Fvwm_fd,&tline);
 
   while(tline != (char *)0)
   {
     if(strlen(tline)>1)
     {
-      if(strncasecmp(tline,line2,strlen(line2))==0)
-	AddCommand(&tline[strlen(line2)]);
+      if(strncasecmp(tline,line_start,strlen(line_start))==0)
+	AddCommand(&tline[strlen(line_start)]);
       else if (strncasecmp(tline, "colorset", 8) == 0)
 	LoadColorset(tline + 8);
     }
     GetConfigLine(Fvwm_fd,&tline);
   }
+  free(line_start);
 }
 
 /******************************************************************************
@@ -358,75 +407,117 @@
 void AddCommand(char *string)
 {
   char *temp;
+  char *token;
+  Command *this;
+  int deskflag;	/* Flag for handling old-style commands */
   int num = 0;
 
   temp=string;
-  while(isspace((unsigned char)*temp))
-    temp++;
-  num=atoi(temp);
-  while(!isspace((unsigned char)*temp))
+  this=(Command*)safemalloc(sizeof(Command));
+  this->desk=0;
+  this->deskglob=0;
+  this->x=0;
+  this->y=0;
+  this->type=-1;
+  this->cmdStr=NULL;
+  this->next = NULL;
+
+  if (strncasecmp(temp,"Desk",4)==0)
+  {
+    /* Old command style */
+    deskflag++;
+    temp=GetNextToken(temp,&token);
+    if (strcasecmp(token,"*")==0)
+    {
+      this->deskglob++;
+      this->x--;
+      this->y--;
+    }
+    else
+    {
+      this->desk=atoi(token);
+      this->x--;
+      this->y--;
+    }
+    free(token);
+  }
+  else if (strncasecmp(temp,"Command",7)==0)
+  {
+    char *parens;
+
+    /* New command style */
+    while (*temp != '(') temp++;
     temp++;
-  while(isspace((unsigned char)*temp))
+    parens=temp;
+    temp=strchr(parens,')');
+    *temp='\0';
     temp++;
-  if (DeskCount<1)
-  {
-    commands=(Command*)safemalloc((num+1)*sizeof(Command));
-    while(DeskCount<num+1) commands[DeskCount++].type= -1;
+
+    parens=GetNextToken(parens,&token);
+    if (strcasecmp(token,"*")==0)
+      this->deskglob++;
+    else
+      this->desk=atoi(token);
+    free(token);
+    parens=GetNextToken(parens,&token);
+    if (strcasecmp(token,"*")==0)
+      this->x--;
+    else
+      this->x=atoi(token);
+    free(token);
+    parens=GetNextToken(parens,&token);
+    if (strcasecmp(token,"*")==0)
+      this->y--;
+    else
+      this->y=atoi(token);
+    free(token);
   }
   else
-  {
-    if (num+1>DeskCount)
-    {
-      commands=(Command*)realloc(commands,(num+1)*sizeof(Command));
-      while(DeskCount<num+1) commands[DeskCount++].type= -1;
-    }
-  }
-/*  commands[num]=(Command*)safemalloc(sizeof(Command));
-*/
+    return;
 
   /* Now check the type of command... */
-  /* strcpy(commands[num],temp);*/
 
+  while (isspace(*temp)) temp++;
   if (strncasecmp(temp,"-solid",6)==0)
   {
-    char* color;
-    char* tmp;
     /* Process a solid color request */
 
-    color = &temp[7];
-    while (isspace((unsigned char)*color))
-      color++;
-    tmp= color;
-    while (!isspace((unsigned char)*tmp))
-      tmp++;
-    *tmp = 0;
-    commands[num].type = 1;
-    commands[num].solidColor = (!color || !*color) ?
+    temp+=6;
+    temp=GetNextToken(temp,&token);
+    this->type = 1;
+    this->solidColor = (!token || !*token) ?
       BlackPixel(dpy, screen) :
-      BackerGetColor(color);
+      BackerGetColor(token);
 #ifdef LOGFILE
-    fprintf(logFile,"Adding color: %s as number %d to desk %d\n",
-	    color,commands[num].solidColor, num);
+    fprintf(logFile,"Adding color: %s as number %d\n",
+	    token,this->solidColor);
     fflush(logFile);
 #endif
+    free(token);
   }
-  else if (strncasecmp(temp, "colorset", 8) == 0)
+  else if (strncasecmp(temp, "colorset",8) == 0)
   {
-    if (sscanf(temp + 8, "%d", &commands[num].colorset) < 1)
+    if (sscanf(temp, "%d", this->colorset) < 1)
     {
-      commands[num].colorset = 0;
+      this->colorset = 0;
     }
-    AllocColorset(commands[num].colorset);
-    commands[num].type = 2;
+    AllocColorset(this->colorset);
+    this->type = 2;
   }
   else
   {
 #ifdef LOGFILE
-    fprintf(logFile,"Adding command: %s to desk %d\n",temp, num);
+    fprintf(logFile,"Adding command: %s\n",temp);
     fflush(logFile);
 #endif
-    commands[num].type = 0;
-    commands[num].cmdStr = (char *)safemalloc(strlen(temp)+1);
-    strcpy(commands[num].cmdStr,temp);
+    this->type = 0;
+    this->cmdStr = (char *)safemalloc(strlen(temp)+1);
+    strcpy(this->cmdStr,temp);
   }
+  if (commands->last != NULL)
+    commands->last->next = this;
+  if (commands->first == NULL)
+    commands->first = this;
+  commands->current = this;
+  commands->last = this;
 }

---

From: Mikhael Goikhman <[email-masked]>
Date: Sat, 13 Nov 1999 22:57:21 +0200

On 13 Nov 1999 08:54:11 -0800, Michael Han wrote:
> commands.

I have problems with this patch. Old syntax actually is not emulated.

  *FvwmBackerDesk 0 Colorset 15

gives

  [FVWM][ExecuteFunction]: <<ERROR>> No such command '0'

I didn't manage to get a new syntax working well too:

  *FvwmBackerCommand (0 * 0) Colorset 1
  *FvwmBackerCommand (0 * 1) Colorset 3

always sets Colorset 1 for me (-solid instead of Colorset works well).

And the new syntax is still fixed. I would like more an extendable
syntax, also using 3 integers seems a bit cryptic to me, the tokens
Desk & Page would clarify them, i.e.:

  *FvwmBackerCommand ()         colorset 0
  *FvwmBackerCommand (Desk 1)   colorset 1
  *FvwmBackerCommand (Page 0 1) colorset 2

instead of:

  *FvwmBackerCommand (* * *) colorset 0
  *FvwmBackerCommand (1 * *) colorset 1
  *FvwmBackerCommand (* 0 1) colorset 2

I can do this syntax change myself if you agree.

Regards,
Mikhael.
--
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-masked].
To report problems, send mail to [email-masked]

---

From: Michael Han <[email-masked]>
Date: Sat, 13 Nov 1999 14:08:24 -0800

Previously from Mikhael Goikhman
>  [FVWM][ExecuteFunction]: <<ERROR>> No such command '0'

Oops. I think I forgot to adjust the Desk case when I redid the
Command case...

>always sets Colorset 1 for me (-solid instead of Colorset works well).

It appears I didn't test things comprehensively... Sorry all.

>I can do this syntax change myself if you agree.

Sounds fine to me if you want to make the changes... I actually wanted
to get this out, because I've got to be out of town next week and
wouldn't have time/opportunity to work on it further until next
weekend. So if you want to fix things up and make things more robust,
please go ahead.
-- 
[email-masked]                         http://www.best.com/~mikehan/
coffee achiever                              San Francisco, California
"I'm not paid to care." -ASR
--
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-masked].
To report problems, send mail to [email-masked]