FVWM: FvwmSaveDesk bugs

From: Rob McElrath <mcelrath_at_nwu.edu>
Date: Sun, 24 Mar 1996 16:35:51 -0600 (CST)

I just downloaded and compiled fvwm 2.0.41, and discovered a rather nasty
bug in FvwmSaveDesk. You see, I have it set up so that novice users can
simply click on a menu to save their current window configuration (via
FvwmSaveDesk) into .fvwmdesk, which is automagically read on startup.
Now, as FvwmSaveDesk is distributed, if you have windows on desktops
other than the current desk, it would insert something similar to this:

AddToFunc InitFunction "I" Desk 3 0
+ xterm ....
        Wait "I" xterm
        "I" Desk 2 0
+ xterm ....
etc...

The problem is that first, there needs to be a plus in front of the Wait
and Desk commands, and second, the syntax of the Wait command is wrong:
the "I" should be first. I've hacked out a fix for it, and have attached
the new source to FvwmSaveDesk.c. This fix is a hack, and not very
pretty (I had to add the CurCmd global variable -- yuk.) but it works.
Do with it as you will. Please include this fix in the next release of
fvwm. :)

Also, I think this method of starting things on separate desktops is
rather clunky. Has anyone invested any thought in a superior method?
(that will always work...)

-- Rob

=<##########################################################################>=
  | "The meek shall inherit the Earth. The rest of us |
  | will go to the stars." -- Heinlein? _/_/_/_/_/_/ |
  | Regnant populi. (The people rule.) _/ _/ |
  | Pregnant robuli. (The snake will soon lay eggs.) _/ 0 0 _/ |
  | _/ / _/ |
  | Rob McElrath (wraith_at_nwu.edu) _/ \________/ _/ |
  | Northwestern University _/ U _/ |
  | Sophomore: ISP, Physics, Math, Computer Science _/_/_/_/_/_/ |
  | 76% nerd, 65% weird, 56% pure, Meyers-Briggs: ENTP |
  \________________________________________________________________________/
                                     |
                                     |
                                     O

/* This module, and the entire FvwmSaveDesktop program, and the concept for
 * interfacing this module to the Window Manager, are all original work
 * by Robert Nation and Mr. Per Persson <pp_at_solace.mh.se>
 *
 * The concept to write an function definition instead of an new.xinitrc
 * is from Carsten Paeth <calle_at_calle.in-berlin.de>
 *
 * Copyright 1994, Robert Nation and Mr. Per Persson.
 * No guarantees or warantees or anything
 * are provided or implied in any way whatsoever. Use this program at your
 * own risk. Permission to use this program for any purpose is given,
 * as long as the copyright is kept intact.
 *
 * Copyright 1995, Carsten Paeth.
 * No guarantees or warantees or anything
 * are provided or implied in any way whatsoever. Use this program at your
 * own risk. Permission to use this program for any purpose is given,
 * as long as the copyright is kept intact.
 *
 */

#define TRUE 1
#define FALSE 0

#include "../../configure.h"

#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <unistd.h>
#include <ctype.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xproto.h>
#include <X11/Xatom.h>
#include <X11/Intrinsic.h>

#include "../../fvwm/module.h"

#include "FvwmSaveDesk.h"
#include "../../version.h"

char *MyName;
int fd[2];

struct list *list_root = NULL;

Display *dpy; /* which display are we talking to */
int ScreenWidth, ScreenHeight;
int screen;

long Vx, Vy;

long CurDesk = 1; /* actual Desktop while being called */
long CurCmd = 0; /* is incremented for each command written to file */

/***********************************************************************
 *
 * Procedure:
 * main - start of module
 *
 ***********************************************************************/
void main(int argc, char **argv)
{
  char *temp, *s;
  char *display_name = NULL;

  /* Record the program name for error messages */
  temp = argv[0];

  s=strrchr(argv[0], '/');
  if (s != NULL)
    temp = s + 1;

  MyName = safemalloc(strlen(temp)+2);
  strcpy(MyName,"*");
  strcat(MyName, temp);

  if((argc != 6)&&(argc != 7))
    {
      fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",MyName,
              VERSION);
      exit(1);
    }

  /* Open the X display */
  if (!(dpy = XOpenDisplay(display_name)))
    {
      fprintf(stderr,"%s: can't open display %s", MyName,
              XDisplayName(display_name));
      exit (1);
    }
  screen= DefaultScreen(dpy);
  ScreenHeight = DisplayHeight(dpy,screen);
  ScreenWidth = DisplayWidth(dpy,screen);

  /* We should exit if our fvwm pipes die */
  signal (SIGPIPE, DeadPipe);
  
  fd[0] = atoi(argv[1]);
  fd[1] = atoi(argv[2]);

  /* Create a list of all windows */
  /* Request a list of all windows,
   * wait for ConfigureWindow packets */
  SendInfo(fd,"Send_WindowList",0);

  Loop(fd);
}


/***********************************************************************
 *
 * Procedure:
 * Loop - wait for data to process
 *
 ***********************************************************************/
void Loop(int *fd)
{
  unsigned long header[HEADER_SIZE], *body;
  char *cbody;
  int body_length,count,count2=0,total;

  while(1)
    {
      /* read a packet */
      if(count = ReadFvwmPacket(fd[1],header,&body) > 0)
        {
          /* dispense with the new packet */
          process_message(header[1],body);
          free(body);
        }
    }
}
 

/***********************************************************************
 *
 * Procedure:
 * Process message - examines packet types, and takes appropriate action
 *
 ***********************************************************************/
void process_message(unsigned long type,unsigned long *body)
{
  switch(type)
    {
    case M_CONFIGURE_WINDOW:
      if(!find_window(body[0]))
        add_window(body[0],body);
      break;
    case M_NEW_PAGE:
      list_new_page(body);
      break;
    case M_NEW_DESK:
      CurDesk = (long)body[0];
      break;
    case M_END_WINDOWLIST:
      do_save();
      break;
    default:
      break;
    }
}



/***********************************************************************
 *
 * Procedure:
 * find_window - find a window in the current window list
 *
 ***********************************************************************/
struct list *find_window(unsigned long id)
{
  struct list *l;

  if(list_root == NULL)
    return NULL;

  for(l = list_root; l!= NULL; l= l->next)
    {
      if(l->id == id)
        return l;
    }
  return NULL;
}



/***********************************************************************
 *
 * Procedure:
 * add_window - add a new window in the current window list
 *
 ***********************************************************************/
void add_window(unsigned long new_win, unsigned long *body)
{
  struct list *t;
  
  if(new_win == 0)
    return;

  t = (struct list *)safemalloc(sizeof(struct list));
  t->id = new_win;
  t->next = list_root;
  t->frame_height = (int)body[6];
  t->frame_width = (int)body[5];
  t->base_width = (int)body[11];
  t->base_height = (int)body[12];
  t->width_inc = (int)body[13];
  t->height_inc = (int)body[14];
  t->frame_x = (int)body[3];
  t->frame_y = (int)body[4];;
  t->title_height = (int)body[9];;
  t->boundary_width = (int)body[10];
  t->flags = (unsigned long)body[8];
  t->gravity = body[21];
  t->desk = body[7];
  list_root = t;
}

                

/***********************************************************************
 *
 * Procedure:
 * list_new_page - capture new-page info
 *
 ***********************************************************************/
void list_new_page(unsigned long *body)
{
  Vx = (long)body[0];
  Vy = (long)body[1];
}
/***********************************************************************
 *
 * Procedure:
 * SIGPIPE handler - SIGPIPE means fvwm is dying
 *
 ***********************************************************************/
void DeadPipe(int nonsense)
{
  exit(0);
}


/***********************************************************************
 *
 * Procedure:
 * writes a command line argument to file "out"
 * checks for qoutes and stuff
 *
 ***********************************************************************/
void write_string(FILE *out, char *line)
{
  int len,space = 0, qoute = 0,i;
  
  len = strlen(line);
  
  for(i=0;i<len;i++)
    {
      if(isspace(line[i]))
        space = 1;
      if(line[i]=='\"')
        qoute = 1;
    }
  if(space == 1)
    fprintf(out,"\"");
  if(qoute == 0)
    fprintf(out,"%s",line);
  else
    {
      for(i=0;i<len;i++)
        {
          if(line[i]=='\"')
            fprintf(out,"\\\"");
          else
            fprintf(out,"%c",line[i]);
        }
    }
  if(space == 1)
    fprintf(out,"\"");
  fprintf(out," ");

}

void do_save_command(FILE *out, struct list *t, int *curdesk, int emit_wait)
{
   char tname[200],loc[30];
   char **command_list;
   int dwidth,dheight,xtermline = 0;
   int x1,x2,y1,y2,i,command_count;
   long tVx, tVy;

   tname[0]=0;
   
   x1 = t->frame_x;
   x2 = ScreenWidth - x1 - t->frame_width - 2;
   if(x2 < 0)
     x2 = 0;
   y1 = t->frame_y;
   y2 = ScreenHeight - y1 - t->frame_height - 2;
   if(y2 < 0)
     y2 = 0;
   dheight = t->frame_height - t->title_height - 2*t->boundary_width;
   dwidth = t->frame_width - 2*t->boundary_width;
   dwidth -= t->base_width ;
   dheight -= t->base_height ;
   dwidth /= t->width_inc;
   dheight /= t->height_inc;

   if ( t->flags & STICKY )
     {
       tVx = 0;
       tVy = 0;
     }
   else
     {
       tVx = Vx;
       tVy = Vy;
     }
   sprintf(tname,"%dx%d",dwidth,dheight);
   if ((t->gravity == EastGravity) ||
       (t->gravity == NorthEastGravity) ||
       (t->gravity == SouthEastGravity))
     sprintf(loc,"-%d",x2);
   else
     sprintf(loc,"+%d",x1+(int)tVx);
   strcat(tname, loc);
   
   if((t->gravity == SouthGravity)||
      (t->gravity == SouthEastGravity)||
      (t->gravity == SouthWestGravity))
     sprintf(loc,"-%d",y2);
   else
     sprintf(loc,"+%d",y1+(int)tVy);
   strcat(tname, loc);

   if ( XGetCommand( dpy, t->id, &command_list, &command_count ) )
     {
       if (*curdesk != t->desk)
         {
            if(CurCmd == 0)
              fprintf( out, "\t\"I\" Desk %ld 0\n", t->desk);
            else
              fprintf( out, "+\t\t\"I\" Desk %ld 0\n", t->desk);
            fflush ( out );
            *curdesk = t->desk;
            CurCmd++;
         }

       fprintf( out, "+\t\t\t\"I\" Exec ");
       fflush ( out );
       for (i=0; i < command_count; i++)
         {
           if ( strncmp( "-geo", command_list[i], 4) == 0)
             {
               i++;
               continue;
             }
           if ( strncmp( "-ic", command_list[i], 3) == 0)
             continue;
           if ( strncmp( "-display", command_list[i], 8) == 0)
             {
               i++;
               continue;
             }
           write_string(out,command_list[i]);
           fflush ( out );
           if(strstr(command_list[i], "xterm"))
             {
               fprintf( out, "-geometry %s ", tname );
               if ( t->flags & ICONIFIED )
                 fprintf(out, "-ic ");
               xtermline = 1;
               fflush ( out );
             }
         }
       if ( command_count > 0 )
         {
           if ( xtermline == 0 )
             {
               if ( t->flags & ICONIFIED )
                 fprintf(out, "-ic ");
               fprintf( out, "-geometry %s &\n", tname);
             }
           else
             {
               fprintf( out, "&\n");
             }
           if (emit_wait) {
              fprintf( out, "+\t\t\t\"I\" Wait %s\n", command_list[0]);
              fflush( out );
           }
         }
       XFreeStringList( command_list );
       xtermline = 0;
     }
}


/***********************************************************************
 *
 * Procedure:
 * checks to see if we are supposed to take some action now,
 * finds time for next action to be performed.
 *
 ***********************************************************************/
void do_save(void)
{
  struct list *t;
  char fnbuf[200];
  FILE *out;
  int maxdesk = 0;
  int actdesk = -1;
  int curdesk;

  for (t = list_root; t != NULL; t = t->next)
     if (t->desk > maxdesk)
        maxdesk = t->desk;

  sprintf(fnbuf, "%s/.fvwmdesk", getenv( "HOME" ) );
  out = fopen( fnbuf, "w" );

  fprintf( out, "AddToFunc InitFunction");
  fflush ( out );

  /*
   * Generate all Desks except 'CurDesk'
   */
  for (curdesk = 0; curdesk <= maxdesk; curdesk++)
    {
        for (t = list_root; t != NULL; t = t->next)
           {
               if (t->desk != CurDesk && curdesk == t->desk)
                  do_save_command(out, t, &actdesk, 1);
           }
    }
  /*
   * Generate 'CurDesk'
   */
  for (t = list_root; t != NULL; t = t->next)
     {
         if (t->desk == CurDesk)
            do_save_command(out, t, &actdesk, 0);
     }

  if (actdesk != CurDesk)
     fprintf( out, "+\t\t\"I\" Desk %ld 0\n", CurDesk);

  fflush( out );
  fclose( out );
  exit(0);

}

--
Visit the official FVWM web page at <URL:http://www.hpc.uh.edu/fvwm/>.
To unsubscribe from the list, send "unsubscribe fvwm" in the body of a
message to majordomo_at_hpc.uh.edu.
To report problems, send mail to fvwm-owner_at_hpc.uh.edu.
Received on Sun Mar 24 1996 - 16:36:04 GMT

This archive was generated by hypermail 2.3.0 : Mon Aug 29 2016 - 19:37:58 BST