/*
 * Copyright (C) 1998 Eric Tremblay <deltax@pragma.net>
 * Copyright (c) 1998 Michal Vitecek <fuf@fuf.sh.cvut.cz>
 * Copyright (c) 1998 Doug Alcorn <alcornd@earthlink.net>
 * Copyright (c) 1998 Sasha Vasko <sashav@sprintmail.com>
 * Copyright (c) 1997 ric@giccs.georgetown.edu
 * Copyright (C) 1998 Makoto Kato <m_kato@ga2.so-net.ne.jp>
 * Copyright (c) 1997 Guylhem Aznar <guylhem@oeil.qc.ca>
 * Copyright (C) 1996 Rainer M. Canavan (canavan@Zeus.cs.bonn.edu)
 * Copyright (C) 1996 Dan Weeks
 * Copyright (C) 1994 Rob Nation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */


#define TRUE 1
#define FALSE

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

#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/wait.h>
#include <sys/time.h>
#ifdef ISC			/* Saul */
#include <sys/bsdtypes.h>	/* Saul */
#endif /* Saul */

#include <stdlib.h>
#if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_
#include <sys/select.h>
#endif

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xproto.h>
#include <X11/Xatom.h>
#include <X11/Intrinsic.h>
#ifdef I18N
#include <X11/Xlocale.h>
#endif

#include "../../include/module.h"
#include "Pager.h"

/*
   #define LOG1(a)       fprintf( stderr, a ); 
   #define LOG2(a,b)    fprintf( stderr, a, b );
   #define LOG3(a,b,c)    fprintf( stderr, a, b, c );
   #define LOG4(a,b,c,d)    fprintf( stderr, a, b, c, d );
 */


#define LOG1(a)
#define LOG2(a,b)
#define LOG3(a,b,c)
#define LOG4(a,b,c,d)


char *MyName;
int fd_width;
int fd[2];

/*************************************************************************
 * 
 * Screen, font, etc info
 *
 **************************************************************************/
PagerInfo Pager;		/* global data holding object */
ScreenInfo Scr;			/* AS compatible screen information structure */

Display *dpy;			/* which display are we talking to */
int screen;
int x_fd, fd_width;

char *PagerFore = "black";
char *PagerGridColor = NULL;	/* don't change it - or Pager will crash */
char *PagerBack = "white";
char *font_string = "fixed";
char *smallFont = NULL;
char *HilightC = "black";

int different_grid_color = 0;
int hilight_borders = 0;

char *HiBack = "white";
char *HiFore = "black";

int window_w = 0, window_h = 0, window_x = 0, window_y = 0, window_x_negative = 0,
  window_y_negative = 0;
int icon_x = -10000, icon_y = -10000, icon_w = 0, icon_h = 0;
int usposition = 0, uselabel = 1;
int StartIconic = 0;
int TitleAlign = 1;
int RedrawBg = 1;
int FastStartup = 0;
int SetRootOnStartup = 0;

int StickyIcons = 0;
int LabelBelowDesk = 0;
int HideInactiveLabel = 0;
int DeskBorderWidth = 1;
int PageSeparatorOn = 1;
int FrameOn = 1;


extern unsigned long MaxBackgroundColors;

/***********************************************************************
 *
 *   Procedure:
 *   main - start of module
 *
 ***********************************************************************/
int
main (int argc, char **argv)
{
  char *temp, *s, *cptr;
  char *display_name = NULL;
  char configfile[255];
  char *realconfigfile;
  int itemp, i;
  char mask_mesg[50];

  /* explicitly initializing parameters before everything else */
  Pager.bStarted = 0;		/* not started yet */
  Pager.CurentRootBack = 0;	/* no root background yet */

  /* Save our program   name - for error messages */
  temp = argv[0];

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

  MyName = temp;

#ifdef I18N
  if (setlocale (LC_ALL, AFTER_LOCALE) == NULL)
    fprintf (stderr, "%s: cannot set locale.\n", MyName);
#endif

  if ((argc != 7) && (argc != 6))
    {
      fprintf (stderr, "%s Version %s should only be executed by afterstep!\n", MyName,
	       VERSION);
      exit (1);
    }
  if (argc != 7)
    {
      fprintf (stderr, "%s Version %s requires an argument: %s n m\n",
	       MyName, VERSION, MyName);
      fprintf (stderr, "      where desktops n through m are displayed\n");
      exit (1);
    }

  /* Dead pipe == AS died */
  signal (SIGPIPE, DeadPipe);

  fd[0] = atoi (argv[1]);
  fd[1] = atoi (argv[2]);

  fd_width = GetFdWidth ();

  cptr = argv[6];
  while (isspace (*cptr))
    cptr++;
  Pager.desk1 = atoi (cptr);
  while (!(isspace (*cptr)) && (*cptr))
    cptr++;
  while (isspace (*cptr))
    cptr++;
  Pager.desk2 = atoi (cptr);
  if (Pager.desk2 < Pager.desk1)
    {
      itemp = Pager.desk1;
      Pager.desk1 = Pager.desk2;
      Pager.desk2 = itemp;
    }
  Pager.ndesks = Pager.desk2 - Pager.desk1 + 1;

  Pager.Desks = (DeskInfo *) safemalloc (Pager.ndesks * sizeof (DeskInfo));

#ifdef PAGER_BACKGROUND
  Pager.Backgrounds = (FiledImage *) safemalloc (BACKS_NUM * sizeof (FiledImage));

  InitBackgrounds ();
#endif /* PAGER_BACKGROUND */

  for (i = 0; i < Pager.ndesks; i++)
    InitDesk (i);

#ifdef PAGER_BACKGROUND
  InitXImageLoader ();
#endif /* PAGER_BACKGROUND */

  /* Initialize X connection */
  if (!(dpy = XOpenDisplay (display_name)))
    {
      fprintf (stderr, "%s: can't open display %s", MyName,
	       XDisplayName (display_name));
      exit (1);
    }
  x_fd = XConnectionNumber (dpy);

  screen = Scr.screen = DefaultScreen (dpy);
  Scr.Root = RootWindow (dpy, Scr.screen);
  if (Scr.Root == None)
    {
      fprintf (stderr, "%s: Screen %d is not valid ", MyName, (int) Scr.screen);
      exit (1);
    }
  Scr.d_depth = DefaultDepth (dpy, Scr.screen);
  Scr.CurrentDesk = -1;

  sprintf (mask_mesg, "SET_MASK %lu\n", (unsigned long)
	   (M_ADD_WINDOW |
	    M_CONFIGURE_WINDOW |
	    M_DESTROY_WINDOW |
	    M_FOCUS_CHANGE |
	    M_NEW_PAGE |
	    M_NEW_DESK |
	    M_NEW_BACKGROUND |
	    M_RAISE_WINDOW |
	    M_LOWER_WINDOW |
	    M_ICONIFY |
	    M_ICON_LOCATION |
	    M_DEICONIFY |
	    M_ICON_NAME |
	    M_END_WINDOWLIST));
  SendInfo (fd, mask_mesg, 0);

  if (strstr (argv[3], "steprc") != NULL)
    ParseOptions (argv[3]);
  else
    {
      sprintf (configfile, "%s/pager", AFTER_DIR);
      realconfigfile = (char *) PutHome (configfile);

      if ((CheckFile (realconfigfile)) == -1)
	{
	  free (realconfigfile);
	  sprintf (configfile, "%s/pager", AFTER_SHAREDIR);
	  realconfigfile = PutHome (configfile);
	}

      ParseOptions (realconfigfile);
      free (realconfigfile);
    }

  ParseBaseOptions (argv[3]);

  /* finish initializing balloons */
  balloon_setup (dpy);

  /* open a pager window */
  initialize_pager ();

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

  Loop (fd);
  return 0;
}

/***********************************************************************
 *
 *   Procedure:
 *   Loop - wait for data to process
 *
 ***********************************************************************/
void 
Loop (int *fd)
{
  XEvent Event;

  while (1)
    {
      if (My_XNextEvent (dpy, &Event) && !balloon_handle_event (&Event))
	DispatchEvent (&Event);
    }
}


/***********************************************************************
 *
 *   Procedure:
 *   Process message - examines packet types, and takes appropriate action
 *
 ***********************************************************************/
void 
process_message (unsigned long type, unsigned long *body)
{
  switch (type)
    {
    case M_ADD_WINDOW:
      list_configure (body);
      break;
    case M_CONFIGURE_WINDOW:
      list_configure (body);
      break;
    case M_DESTROY_WINDOW:
      list_destroy (body);
      break;
    case M_FOCUS_CHANGE:
      list_focus (body);
      break;
    case M_NEW_PAGE:
      list_new_page (body);
      break;
    case M_NEW_DESK:
      list_new_desk (body);
      break;
    case M_NEW_BACKGROUND:
      list_new_background (body);
      break;
    case M_RAISE_WINDOW:
      list_raise (body);
      break;
    case M_LOWER_WINDOW:
      list_lower (body);
      break;
    case M_ICONIFY:
    case M_ICON_LOCATION:
      list_iconify (body);
      break;
    case M_DEICONIFY:
      list_deiconify (body);
      break;
    case M_ICON_NAME:
      list_icon_name (body);
      break;
    case M_END_WINDOWLIST:
      list_end ();
      break;
    default:
      list_unknown (body);
      break;
    }
}


/***********************************************************************
 *
 *   Procedure:
 *   SIGPIPE handler - SIGPIPE means afterstep is dying
 *
 ***********************************************************************/
void 
DeadPipe (int nonsense)
{
  SetERootPixmap (-1);
  XFlush (dpy);			/* need this for SetErootPixmap to take effect */
  XCloseDisplay (dpy);		/* need this for SetErootPixmap to take effect */
  exit (0);
}

PagerWindow *
FindWindow (Window w)
{
  PagerWindow *t;
  for (t = Pager.Start; t != NULL; t = t->next)
    if (t->w == w)
      return t;
  return NULL;
}

/***********************************************************************
 *
 *   Procedure:
 *   list_add - displays packet contents to stderr
 *
 ***********************************************************************/
void 
list_add (unsigned long *body)
{
  PagerWindow *t, **prev;
  int i = 0;

  t = Pager.Start;
  prev = &Pager.Start;
  while (t != NULL)
    {
      prev = &(t->next);
      t = t->next;
      i++;
    }
  *prev = (PagerWindow *) safemalloc (sizeof (PagerWindow));
  (*prev)->w = body[0];
  (*prev)->t = (char *) body[2];
  (*prev)->frame = body[1];
  (*prev)->x = body[3];
  (*prev)->y = body[4];
  (*prev)->width = body[5];
  (*prev)->height = body[6];
  (*prev)->desk = body[7];
  (*prev)->next = NULL;
  (*prev)->flags = body[8];
  (*prev)->icon_name = NULL;
  (*prev)->title_height = body[9];
  (*prev)->border_width = body[10];
  (*prev)->icon_w = body[19];
  (*prev)->icon_pixmap_w = body[20];
  (*prev)->text = body[22];
  (*prev)->back = body[23];
  AddNewWindow (*prev);
}

/***********************************************************************
 *
 *   Procedure:
 *   list_configure - displays packet contents to stderr
 *
 ***********************************************************************/
void
list_configure (unsigned long *body)
{
  PagerWindow *t;

  if ((t = FindWindow (body[0])) == NULL)
    list_add (body);
  else
    {
      t->t = (char *) body[2];
      t->frame = body[1];
      t->frame_x = body[3];
      t->frame_y = body[4];
      t->frame_width = body[5];
      t->frame_height = body[6];
      t->title_height = body[9];
      t->border_width = body[10];
      t->flags = body[8];
      t->icon_w = body[19];
      t->icon_pixmap_w = body[20];
      t->text = body[22];
      t->back = body[23];
      if (t->flags & ICONIFIED)
	{
	  t->x = t->icon_x;
	  t->y = t->icon_y;
	  t->width = t->icon_width;
	  t->height = t->icon_height;
	  if (t->flags & SUPPRESSICON)
	    {
	      t->x = -10000;
	      t->y = -10000;
	    }
	}
      else if (t->flags & SHADED)
	{
	  t->x = t->frame_x;
	  t->y = t->frame_y;
	  t->width = t->frame_width;
	  t->height = t->title_height;
	}
      else
	{
	  t->x = t->frame_x;
	  t->y = t->frame_y;
	  t->width = t->frame_width;
	  t->height = t->frame_height;
	}


      if (t->desk == body[7])
	{
	  LOG3 ("\nMoveResizePagerView of [%s] from list_configure: desk = %d", t->icon_name, t->desk)
	    MoveResizePagerView (t);
	}
      else
	{
	  LOG4 ("\nChangeDeskForWindow of [%s] from list_configure: from %d to %ld", t->icon_name, t->desk, body[7]);
	  ChangeDeskForWindow (t, body[7]);
	}

      if ((Pager.FocusWin == t) && !(t->flags & SHADED))
	Hilight (t, ON);
      else
	Hilight (t, OFF);
    }
}

/***********************************************************************
 *
 *   Procedure:
 *   list_destroy - displays packet contents to stderr
 *
 ***********************************************************************/
void 
list_destroy (unsigned long *body)
{
  PagerWindow *t, **prev;
  Window target_w;

  target_w = body[0];
  t = Pager.Start;
  prev = &Pager.Start;
  while ((t != NULL) && (t->w != target_w))
    {
      prev = &(t->next);
      t = t->next;
    }
  if (t != NULL)
    {
      if (prev != NULL)
	*prev = t->next;
      /* remove window from the chain */
      DestroyView (t);
      if (Pager.FocusWin == t)
	Pager.FocusWin = NULL;

      free (t->icon_name);
      free (t);
    }
}

/***********************************************************************
 *
 *   Procedure:
 *   list_focus - displays packet contents to stderr
 *
 ***********************************************************************/
void
list_focus (unsigned long *body)
{
  PagerWindow *t, *temp;

  if ((t = FindWindow (body[0])) != Pager.FocusWin)
    {
      temp = Pager.FocusWin;
      Pager.FocusWin = t;

      if (temp != NULL)
	Hilight (temp, OFF);
      if (Pager.FocusWin != NULL)
	Hilight (Pager.FocusWin, ON);
    }
}

/***********************************************************************
 *
 *   Procedure:
 *   list_new_page - displays packet contents to stderr
 *
 ***********************************************************************/
void 
list_new_page (unsigned long *body)
{
  Scr.Vx = (long) body[0];
  Scr.Vy = (long) body[1];
  Scr.CurrentDesk = (long) body[2];
  if (Scr.CurrentDesk != 10000)
    {
      MovePage ();
      LOG2 ("\nMoveStickyWindows from list_new_page: desk = %d", Scr.CurrentDesk)
	MoveStickyWindows ();
      Hilight (Pager.FocusWin, OFF);
      Hilight (Pager.FocusWin, ON);
    }
}

/***********************************************************************
 *
 *   Procedure:
 *   list_new_desk - displays packet contents to stderr
 *
 ***********************************************************************/
int oldoldDesk = -1;
int oldDesk = -1;
int firstTime = 1;

void 
list_new_desk (unsigned long *body)
{
  oldoldDesk = oldDesk;
  oldDesk = Scr.CurrentDesk;
  Scr.CurrentDesk = (long) body[0];

  if (Scr.CurrentDesk != 10000)
    MovePage ();

  if (oldDesk >= Pager.desk1 && oldDesk <= Pager.desk2)
    DrawGrid (oldDesk - Pager.desk1, 1);

#ifdef PAGER_BACKGROUND
  if (RedrawBg > 0)
    if (oldDesk != 10000 && Scr.CurrentDesk == 10000)
      {
	/* fprintf(stderr,"\nGrabRoot: oldoldDesk: %ld, oldDesk: %d, CurrentDesk: %d, ToGrab := %d \n",oldoldDesk, oldDesk, Scr.CurrentDesk, oldDesk-Pager.desk1); */
	CheckAndGrabRootPixmap (oldDesk - Pager.desk1);
      }
#endif
/*   fprintf(stderr,"\nChangeDesk: oldoldDesk: %ld, oldDesk: %d, CurrentDesk: %d, ToGrab := %d \n",oldoldDesk, oldDesk, Scr.CurrentDesk, oldDesk-Pager.desk1); */

  if (Scr.CurrentDesk >= Pager.desk1 && Scr.CurrentDesk <= Pager.desk2)
    DrawGrid (Scr.CurrentDesk - Pager.desk1, 1);

  LOG2 ("\nMoveStickyWindows from list_new_DESK: desk = %d", Scr.CurrentDesk)
    if (Scr.CurrentDesk != 10000)
    {
      MoveStickyWindows ();
      Hilight (Pager.FocusWin, OFF);
      Hilight (Pager.FocusWin, ON);
    }

#ifdef PAGER_BACKGROUND
  if (Scr.CurrentDesk >= Pager.desk1 && Scr.CurrentDesk <= Pager.desk2)
    {
      if (RedrawBg > 0)
	if ((oldDesk == 10000 && Scr.CurrentDesk != oldoldDesk) ||
	 (oldDesk != 10000 && Scr.CurrentDesk != oldDesk) || firstTime == 1)
	  DrawRoot (Scr.CurrentDesk - Pager.desk1);
    }
  else
    Pager.CurentRootBack = 0;	/* somebody else will probably change
				   background for this  desk */
#endif

  firstTime = 0;
}

/***********************************************************************
 *
 *   Procedure:
 *         list_new_background - reread config file & reconfigure on fly
 *
 ***********************************************************************/
void 
list_new_background (unsigned long *body)
{
/* need to add code here to reread config file */

#ifdef PAGER_BACKGROUND
  Pager.CurentRootBack = 0;	/* no longer valid - background has changed */
  BackgroundChanged (Scr.CurrentDesk);
  MakeBackgrounds (Scr.CurrentDesk);
  DrawRoot (Scr.CurrentDesk);
  SetPagerBackground (Scr.CurrentDesk);
#endif

  DrawGrid (Scr.CurrentDesk - Pager.desk1, 1);
}

/***********************************************************************
 *
 *   Procedure:
 *   list_raise - displays packet contents to stderr
 *
 ***********************************************************************/
void 
list_raise (unsigned long *body)
{
  PagerWindow *t;

  if ((t = FindWindow (body[0])) != NULL)
    {
      if (t->PagerView != None)
	XRaiseWindow (dpy, t->PagerView);
      if (t->IconView != None)
	XRaiseWindow (dpy, t->IconView);
    }
}

/***********************************************************************
 *
 *   Procedure:
 *   list_lower - displays packet contents to stderr
 *
 ***********************************************************************/
void 
list_lower (unsigned long *body)
{
  PagerWindow *t;

  if ((t = FindWindow (body[0])) != NULL)
    {
      if (t->PagerView != None)
	{
	  XLowerWindow (dpy, t->PagerView);
	  if (t->desk >= Pager.desk1 && t->desk <= Pager.desk2)
	    LowerFrame (t->desk - Pager.desk1);
	}
      if (t->IconView != None)
	XLowerWindow (dpy, t->IconView);
    }
}


/***********************************************************************
 *
 *   Procedure:
 *   list_unknow - handles an unrecognized packet.
 *
 ***********************************************************************/
void 
list_unknown (unsigned long *body)
{
  /*   fprintf(stderr,"Unknown packet type\n"); */
}

/***********************************************************************
 *
 *   Procedure:
 *   list_iconify - displays packet contents to stderr
 *
 ***********************************************************************/
void 
list_iconify (unsigned long *body)
{
  PagerWindow *t;
  if ((t = FindWindow (body[0])) == NULL)
    return;

  t->t = (char *) body[2];
  t->frame = body[1];
  t->icon_x = body[3];
  t->icon_y = body[4];
  t->icon_width = body[5];
  t->icon_height = body[6];
  t->flags |= ICONIFIED;
  if (t->flags & SUPPRESSICON)
    {
      t->x = -10000;
      t->y = -10000;
    }
  else
    {
      t->x = t->icon_x;
      t->y = t->icon_y;
    }
  t->width = t->icon_width;
  t->height = t->icon_height;
  MoveResizePagerView (t);
}


/***********************************************************************
 *
 *   Procedure:
 *   list_deiconify - displays packet contents to stderr
 *
 ***********************************************************************/

void 
list_deiconify (unsigned long *body)
{
  PagerWindow *t;
  if ((t = FindWindow (body[0])) != NULL)
    {
      t->flags &= ~ICONIFIED;
      t->x = t->frame_x;
      t->y = t->frame_y;
      t->width = t->frame_width;
      t->height = t->frame_height;
      MoveResizePagerView (t);
      if (Pager.FocusWin == t)
	Hilight (t, ON);
      else
	Hilight (t, OFF);
    }
}


/***********************************************************************
 *
 *   Procedure:
 *   list_icon_name - displays packet contents to stderr
 *
 ***********************************************************************/
void 
list_icon_name (unsigned long *body)
{
  PagerWindow *t;
  Balloon *balloon;

  if ((t = FindWindow (body[0])) != NULL)
    {
      if (t->icon_name != NULL)
	free (t->icon_name);
      CopyString (&t->icon_name, (char *) (&body[3]));
      LabelWindow (t);
      LabelIconWindow (t);
      if (t->PagerView != None)
	if ((balloon = balloon_find (t->PagerView)) != NULL)
	  balloon_set_text (balloon, t->icon_name);
      if (t->IconView != None)
	if ((balloon = balloon_find (t->IconView)) != NULL)
	  balloon_set_text (balloon, t->icon_name);
    }
}

/***********************************************************************
 *
 *   Procedure:
 *   list_end - displays packet contents to stderr
 *
 ***********************************************************************/
void 
list_end (void)
{
  unsigned int nchildren, i;
  Window root, parent, *children;
  PagerWindow *ptr;

  if (XQueryTree (dpy, Scr.Root, &root, &parent, &children, &nchildren))
    {
      for (i = 0; i < nchildren; i++)
	for (ptr = Pager.Start; ptr != NULL; ptr = ptr->next)
	  if ((ptr->frame == children[i]) || (ptr->icon_w == children[i]) ||
	      (ptr->icon_pixmap_w == children[i]))
	    {
	      if (ptr->PagerView != None)
		XRaiseWindow (dpy, ptr->PagerView);
	      if (ptr->IconView != None)
		XRaiseWindow (dpy, ptr->IconView);
	    }

      if (nchildren > 0 && children)
	XFree ((char *) children);
    }
}

/***************************************************************************
 *
 * Waits for next X event, or for an auto-raise timeout.
 *
 ****************************************************************************/
int 
My_XNextEvent (Display * dpy, XEvent * event)
{
  fd_set in_fdset;
  unsigned long header[3];
  int count;
  static int miss_counter = 0;
  unsigned long *body;
  struct timeval tv;
  struct timeval *t = NULL;

  if (XPending (dpy))
    {
      XNextEvent (dpy, event);
      return 1;
    }
  FD_ZERO (&in_fdset);
  FD_SET (x_fd, &in_fdset);
  FD_SET (fd[1], &in_fdset);

  if (timer_delay_till_next_alarm ((time_t *) & tv.tv_sec, (time_t *) & tv.tv_usec))
    t = &tv;

#ifdef __hpux
  while (select (fd_width, (int *) &in_fdset, 0, 0, t) == -1)
    if (errno != EINTR)
      break;
#else
  while (select (fd_width, &in_fdset, 0, 0, t) == -1)
    if (errno != EINTR)
      break;
#endif
  if (FD_ISSET (x_fd, &in_fdset))
    {
      if (XPending (dpy))
	{
	  XNextEvent (dpy, event);
	  miss_counter = 0;
	  return 1;
	}
      else
	miss_counter++;

      if (miss_counter > 100)
	DeadPipe (0);
    }
  if (FD_ISSET (fd[1], &in_fdset))
    {
      if ((count = ReadASPacket (fd[1], header, &body)) > 0)
	{
	  process_message (header[1], body);
	  free (body);
	}
    }
  /* handle timeout events */
  timer_handle ();

  return 0;
}

/*****************************************************************************
 * 
 * This routine is responsible for reading and parsing the config file
 *
 ****************************************************************************/
void 
ParseOptions (const char *filename)
{
  FILE *fd = NULL;
  char *line, *tline, *tmp;
  int n, desk;
  int g_x, g_y, flags;
  int len;
  unsigned width, height;

  Scr.Hilite = NULL;

  if ((fd = fopen (filename, "r")) == NULL)
    {
      fprintf (stderr, "%s: can't open config file %s", MyName, filename);
      exit (1);
    }

  line = (char *) safemalloc (MAXLINELENGTH);
  len = strlen (MyName);
  while ((tline = fgets (line, MAXLINELENGTH, fd)) != NULL)
    {
      while (isspace (*tline))
	tline++;
      if ((*tline == '*') && (!mystrncasecmp (tline + 1, MyName, len)))
	{
	  tline += len + 1;
	  if (!mystrncasecmp (tline, "Geometry", 8))
	    {
	      tmp = tline + 8;
	      while ((isspace (*tmp)) && (*tmp != '\n'))
		tmp++;
	      *(tmp + strlen (tmp) - 1) = 0;

	      flags = XParseGeometry (tmp, &g_x, &g_y, &width, &height);
	      if (flags & WidthValue)
		window_w = width;
	      if (flags & HeightValue)
		window_h = height;
	      if (flags & XValue)
		{
		  window_x = g_x;
		  usposition = 1;
		  if (flags & XNegative)
		    window_x_negative = 1;
		}
	      if (flags & YValue)
		{
		  window_y = g_y;
		  usposition = 1;
		  if (flags & YNegative)
		    window_y_negative = 1;
		}
	    }
	  else if (!mystrncasecmp (tline, "IconGeometry", 12))
	    {
	      tmp = tline + 12;
	      while ((isspace (*tmp)) && (*tmp != '\n'))
		tmp++;
	      *(tmp + strlen (tmp) - 1) = 0;

	      flags = XParseGeometry (tmp, &g_x, &g_y, &width, &height);
	      if (flags & WidthValue)
		icon_w = width;
	      if (flags & HeightValue)
		icon_h = height;
	      if (flags & XValue)
		icon_x = g_x;
	      if (flags & YValue)
		icon_y = g_y;
	    }
	  else if (!mystrncasecmp (tline, "LabelBelowDesk", 14))
	    LabelBelowDesk = 1;
#ifdef SHAPE
	  else if (!mystrncasecmp (tline, "HideInactiveLabels", 18))
	    HideInactiveLabel = 1;
#endif /* SHAPE */
	  else if (!mystrncasecmp (tline, "Label", 5))
	    {
	      desk = Pager.desk1;
	      n = 5;
	      sscanf (tline + n, "%d", &desk);
	      if ((desk >= Pager.desk1) && (desk <= Pager.desk2))
		{
		  while (isspace (*(tline + n)))
		    n++;
		  while (!isspace (*(tline + n)))
		    n++;
		  free (Pager.Desks[desk - Pager.desk1].label);
		  CopyString (&Pager.Desks[desk - Pager.desk1].label, tline + n);
		}
	    }
	  else if (!mystrncasecmp (tline, "Image", 5))
	    {
#ifdef PAGER_BACKGROUND
	      desk = Pager.desk1;
	      n = 5;
	      sscanf (tline + n, "%d", &desk);
	      if ((desk >= Pager.desk1) && (desk <= Pager.desk2))
		{
		  while (isspace (*(tline + n)))
		    n++;
		  while (!isspace (*(tline + n)))
		    n++;
		  CopyString (&tmp, tline + n);
		  SetPagerPixmap (desk - Pager.desk1, tmp);
		  free (tmp);
		}
#endif /* PAGER_BACKGROUND */
	    }
	  else if (!mystrncasecmp (tline, "XPM", 3))
	    {
	      /* unnofficialy supporting older PagerXPM setting */
#ifdef PAGER_BACKGROUND
	      desk = Pager.desk1;
	      n = 3;
	      sscanf (tline + n, "%d", &desk);
	      if ((desk >= Pager.desk1) && (desk <= Pager.desk2))
		{
		  while (isspace (*(tline + n)))
		    n++;
		  while (!isspace (*(tline + n)))
		    n++;
		  CopyString (&tmp, tline + n);
		  SetPagerPixmap (desk - Pager.desk1, tmp);
		  SetRootPixmap (desk - Pager.desk1, tmp);
		  free (tmp);
		}
#endif /* PAGER_BACKGROUND */
	    }
	  else if (!mystrncasecmp (tline, "Decoration", 10))
	    {
	      LOG2 ("\nEntering PagerDecoration:[%s]", tline + 10)

		for (tline += 10; *tline != '\0' && *tline != '\n';)
		{
		  LOG2 (">%s", tline)
		    for (; isspace (*tline); tline++);
		  LOG2 (">>%s", tline)
		    if (!mystrncasecmp (tline, "DeskBorderWidth", 15))
		    tline = ReadIntValue (tline + 15, &DeskBorderWidth);
		  else if (!mystrncasecmp (tline, "NoPageSeparator", 15))
		    {
		      PageSeparatorOn = 0;
		      tline += 15;
		    }
		  else if (!mystrncasecmp (tline, "GridColor", 9))
		    {
		      int colorlen;
		      tline = ReadColorValue (tline + 9, &PagerGridColor, &colorlen);
		      different_grid_color = 1;
		      LOG2 ("PagerGridColor = %s", PagerGridColor);
		    }
		  else if (!mystrncasecmp (tline, "NoSelection", 11))
		    {
		      FrameOn = 0;
		      tline += 10;
		    }
		  else
		    for (; !isspace (*tline) && *tline != '\0' && *tline != ','
			 && *tline != '\n'; tline++);
		  LOG2 (">>>%s", tline)
		    for (; *tline != '\0' && *tline != ',' && *tline != '\n'; tline++);
		  LOG2 (">>>>%s", tline)
		    if (*tline == ',')
		    tline++;
		}
	      LOG2 ("\n BorderWidth=%u", DeskBorderWidth)

	    }
	  else if (!mystrncasecmp (tline, "DesktopImage", 12))
	    {
#ifdef PAGER_BACKGROUND
	      desk = Pager.desk1;
	      n = 12;
	      sscanf (tline + n, "%d", &desk);
	      if ((desk >= Pager.desk1) && (desk <= Pager.desk2))
		{
		  while (isspace (*(tline + n)))
		    n++;
		  while (!isspace (*(tline + n)))
		    n++;
		  CopyString (&tmp, tline + n);
		  SetRootPixmap (desk - Pager.desk1, tmp);
		  free (tmp);
		}
#endif /* PAGER_BACKGROUND */
	    }
	  else if (!mystrncasecmp (tline, "FastBackground", 13))
	    {
#ifdef PAGER_BACKGROUND
	      desk = Pager.desk1;
	      n = 13;
	      sscanf (tline + n, "%d", &desk);
	      if ((desk >= Pager.desk1) && (desk <= Pager.desk2))
		{
		  while (isspace (*(tline + n)))
		    n++;
		  while (!isspace (*(tline + n)))
		    n++;
		  while (isspace (*(tline + n)))
		    n++;
		  CopyString (&tmp, tline + n);
		  SetFastBackground (desk - Pager.desk1, tmp);
		  free (tmp);
		}
#endif /* PAGER_BACKGROUND */
	    }
	  else if (!mystrncasecmp (tline, "XImageLoaderArgs", 15))
	    {
#ifdef PAGER_BACKGROUND
	      desk = Pager.desk1;
	      n = 15;
	      while (isspace (*(tline + n)))
		n++;
	      CopyString (&tmp, tline + n);
	      SetXImageLoaderArgs (tmp);
	      free (tmp);
#endif /* PAGER_BACKGROUND */
	    }
	  else if (!mystrncasecmp (tline, "Align", 5))
	    {
	      sscanf (tline + 5, "%d", &TitleAlign);
	    }
	  else if (!mystrncasecmp (tline, "RedrawBg", 8))
	    {
#ifdef PAGER_BACKGROUND
	      sscanf (tline + 8, "%d", &RedrawBg);
#endif /* PAGER_BACKGROUND */
	    }
	  else if (!mystrncasecmp (tline, "Font", 4))
	    {
	      CopyString (&font_string, tline + 4);
	      if (!mystrncasecmp (font_string, "none", 4))
		uselabel = 0;
	    }
	  else if (!mystrncasecmp (tline, "FastStartup", 4))
	    {
	      FastStartup = 1;
	    }
	  else if (!mystrncasecmp (tline, "SetRootOnStartup", 4))
	    {
	      SetRootOnStartup = 1;
	    }
	  else if (!mystrncasecmp (tline, "Fore", 4))
	    {
	      CopyString (&PagerFore, tline + 4);
	    }
	  else if (!mystrncasecmp (tline, "Back", 4))
	    {
	      CopyString (&PagerBack, tline + 4);
	    }
	  else if (!mystrncasecmp (tline, "HilightBorders", 14))
	    {
	      hilight_borders = 1;
	      LOG2 ("HilightBorders = %s", "yes")
	    }
	  else if (!mystrncasecmp (tline, "Hilight", 7))
	    {
	      if (Scr.d_depth > 1)
		CopyString (&HilightC, tline + 7);
	    }
	  else if (!mystrncasecmp (tline, "SmallFont", 9))
	    {
	      CopyString (&smallFont, tline + 9);
	    }
	  else if (!mystrncasecmp (tline, "StartIconic", 11))
	    {
	      StartIconic = 1;
	    }
	  else if (!mystrncasecmp (tline, "Rows", 4))
	    {
	      sscanf (tline + 4, "%d", &Pager.Rows);
	    }
	  else if (!mystrncasecmp (tline, "Columns", 7))
	    {
	      sscanf (tline + 7, "%d", &Pager.Columns);
	    }
	}
      else
	{
	  if (!mystrncasecmp (tline, "HiBackColor", 11))
	    {
	      if (Scr.d_depth > 1)
		CopyString (&HiBack, tline + 11);
	    }
	  else if (!mystrncasecmp (tline, "HiForeColor", 11))
	    {
	      if (Scr.d_depth > 1)
		CopyString (&HiFore, tline + 11);
	    }
	  else if (!mystrncasecmp (tline, "StickyPagerIcon", 15))
	    {
	      StickyIcons = 1;
	    }
	  else if (!mystrncasecmp (tline, "MaxBackgroundColors", 19))
	    {
#ifdef PAGER_BACKGROUND
	      sscanf (tline + 19, "%lu", &MaxBackgroundColors);
#endif /* PAGER_BACKGROUND */
	    }
	  else
	    balloon_parse (tline, fd);
	}
    }

  free (line);
  fclose (fd);
  return;
}


/*****************************************************************************
 *
 * This routine is responsible for reading and parsing the base file
 *
 ****************************************************************************/
void
ParseBaseOptions (const char *filename)
{
  FILE *fd;
  char line[MAXLINELENGTH * 2];
  char *tline;

  Scr.VScale = 32;

  Scr.MyDisplayWidth = DisplayWidth (dpy, Scr.screen);
  Scr.MyDisplayHeight = DisplayHeight (dpy, Scr.screen);

  Pager.PageRows = 2;
  Pager.PageColumns = 2;

  Scr.Vx = 0;
  Scr.Vy = 0;

  if ((fd = fopen (filename, "r")) == NULL)
    {
      fprintf (stderr, "%s: can't open config file %s", MyName, filename);
      exit (1);
    }
  tline = fgets (line, sizeof (line), fd);
  while (tline != NULL)
    {
      while (isspace (*tline))
	tline++;

      if (strlen (tline) > 1)
	if (*tline != '#')
	  {
	    if (!mystrncasecmp (tline, "DeskTopSize", 11))
	      {
		sscanf (tline + 11, "%dx%d", &Pager.PageColumns, &Pager.PageRows);
		if (Pager.PageRows < 1)
		  Pager.PageRows = 1;
		if (Pager.PageColumns < 1)
		  Pager.PageColumns = 1;
	      }
	    else if (!mystrncasecmp (tline, "DeskTopScale", 12))
	      {
		sscanf (tline + 12, "%d", &Scr.VScale);
		if (Scr.VScale < 1)
		  Scr.VScale = 1;
	      }
	  }
      tline = fgets (line, sizeof (line), fd);
    }

  Scr.VxMax = (Pager.PageColumns - 1) * Scr.MyDisplayWidth;
  Scr.VyMax = (Pager.PageRows - 1) * Scr.MyDisplayHeight;
  Pager.xSize = Scr.VxMax + Scr.MyDisplayWidth;
  Pager.ySize = Scr.VyMax + Scr.MyDisplayHeight;

  fclose (fd);
}
