/*
 * Copyright (C) 1998 Sasha Vasko <sashav@sprintmail.com>
 *
 * 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 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)



#include "../../configure.h"
#ifdef PAGER_BACKGROUND

#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xproto.h>
#include <X11/Xatom.h>
#include <X11/Intrinsic.h>
#include <X11/xpm.h>

#include "Pager.h"
#include "../../include/loadimg.h"

#ifdef HAVE_SYS_WAIT_H
#define WAIT_CHILDREN(pstatus)  waitpid(-1, pstatus, WNOHANG)
#elif defined (HAVE_WAIT3)
#define WAIT_CHILDREN(pstatus)  wait3(pstatus, WNOHANG, NULL)
#else
#define WAIT_CHILDREN(pstatus)  (-1)
#endif

extern Display *dpy;

extern int StickyIcons;

extern char *MyName;

extern int desk_w;
extern int desk_h;
extern int scr_w;
extern int scr_h;
extern int label_h;

long MaxBackgroundColors = 5000;

void 
InitXImageLoader ()
{
  char *tmp;
  int i, l;

  LOG1 ("\nEnter InitXImageLoader");
  bReportErrorIfTypeUnknown = 0;	/* telling asimagelib not to 
					   report errors if image type unknown */

  tmp = (char *) safemalloc (strlen (XIMAGELOADER) + 1);
  strcpy (tmp, XIMAGELOADER);

  for (i = 0; isspace (tmp[i]); i++);
  for (l = 0; !isspace (tmp[i + l]); l++);

  Pager.XImageLoaderApp = (char *) safemalloc (l + 1);
  strncpy (Pager.XImageLoaderApp, tmp + i, l);
  Pager.XImageLoaderApp[l] = '\0';
  for (i = i + l; isspace (tmp[i]); i++);

  Pager.XImageLoaderArgs = (char *) safemalloc (strlen (tmp + i) + 1);
  strcpy (Pager.XImageLoaderArgs, tmp + i);
  free (tmp);

  LOG1 ("\nExit InitXImageLoader");
}

void 
SetDeskLoaderArgs (long Desk, char *args)
{
  if (Pager.Desks[Desk].LoaderArgs)
    free (Pager.Desks[Desk].LoaderArgs);

  if (args == NULL)
    Pager.Desks[Desk].LoaderArgs = NULL;
  else
    {
      Pager.Desks[Desk].LoaderArgs = (char *) safemalloc (strlen (args) + 1);
      strcpy (Pager.Desks[Desk].LoaderArgs, args);
    }

}

void 
SetXImageLoaderArgs (char *args)
{
  int i;
  long Desk;

  LOG2 ("\nEnter SetXImageLoaderArgs:[%s]", args);

  if (args)
    {
      for (i = 0; isdigit (args[i]); i++);
      if (i > 0 && isspace (args[i]))
	{
	  sscanf (args, "%lu", &Desk);
	  if ((Desk >= Pager.desk1) && (Desk <= Pager.desk2))
	    {
	      while (isspace (args[i]))
		i++;
	      SetDeskLoaderArgs (Desk - Pager.desk1, args + i);
	      LOG2 ("Exit SetXImageLoaderArgs[%s]", args + i);
	      return;
	    }
	}
    }
  if (Pager.XImageLoaderArgs)
    free (Pager.XImageLoaderArgs);

  if (args == NULL)
    Pager.XImageLoaderArgs = NULL;
  else
    {
      Pager.XImageLoaderArgs = (char *) safemalloc (strlen (args) + 1);
      strcpy (Pager.XImageLoaderArgs, args);
    }
  LOG1 ("\nExit SetXImageLoaderArgs");
}

/* checks that file's format is XPM, and if so if pixmap has been loaded 
   from the file, if no - loads it.
   Returns :
   -1 - if file is not in XPM format ;
   0 - if failed to load pixmap ;
   1 - if pixmap loaded successfully.
 */

int 
CheckPixmapLoaded (int BackNum, Drawable w)
{
/* nowdays just a thunk to : */
/* Pixmap LoadImage( Display *dpy, Window w, unsigned long max_colors, char* realfilename ); */

  /* check that parameters are valid */
  if (Pager.Backgrounds[BackNum].filename == NULL || Pager.Backgrounds[BackNum].LoaderArgs != NULL)
    return 0;
  if (Pager.Backgrounds[BackNum].pixmap != 0)
    return 1;

  LOG3 ("\nPager{%lu}: CheckPixmapLoaded - loading file:[%s] ", time (NULL), Pager.Backgrounds[BackNum].filename);
  if (strlen (Pager.Backgrounds[BackNum].filename) == 0)
    return 0;

  Pager.Backgrounds[BackNum].pixmap = LoadImage (dpy, w, MaxBackgroundColors, Pager.Backgrounds[BackNum].filename);

  LOG3 ("\nPager time:{%lu}: CheckPixmapLoaded - %s.", time (NULL), ((Pager.Backgrounds[BackNum].pixmap == 0) ? "Failed" : "Success"));
  return (Pager.Backgrounds[BackNum].pixmap != 0) ? 1 : 0;
}

void
SetFastBackground (long Desk, char *params)
{
  unsigned int offset = 0;

  LOG2 ("\nSetFastBackgr: Input=[%s]", params);
  LOG2 ("\nSetFastBackgr: Desk=[%ld]", Desk);
  if (strncasecmp (params, "yes", 3) != 0)
    Pager.Desks[Desk].FastBackgroundOn = 0;
  else
    {
      Pager.Desks[Desk].FastBackgroundOn = 1;
      Pager.Desks[Desk].tile_hsize = 0;
      Pager.Desks[Desk].tile_vsize = 0;
      while (!isspace (params[offset]) && params[offset] != '\0')
	offset++;
      while (isspace (params[offset]) && params[offset] != '\0')
	offset++;
      if (params[offset] != '\0')
	{
	  sscanf (params + offset, "%u", &Pager.Desks[Desk].tile_hsize);
	  while (!isspace (params[offset]) && params[offset] != '\0')
	    offset++;
	  while (isspace (params[offset]) && params[offset] != '\0')
	    offset++;
	  if (params[offset] != '\0')
	    sscanf (params + offset, "%u", &Pager.Desks[Desk].tile_vsize);
	}
    }
  LOG2 ("\nExit SetFastBackgr: Desk=[%ld]", Desk);
}

int 
UnmapIfMapped (Window w)
{
  XWindowAttributes attr;
  LOG2 ("\nUnmapping Window %ld ... ", w);

  if (w != 0)
    if (XGetWindowAttributes (dpy, w, &attr) != 0)
      if (attr.map_state != IsUnmapped)
	{
	  XUnmapWindow (dpy, w);
	  LOG1 ("Done.");
	  return 1;
	}
  LOG1 ("Failed.");
  return 0;

}

int CheckForDrawChild (int kill_it_to_death);

void 
GrabRoot (Pixmap * pPixmap, int bUnmapSubwindows, long Desk)
{
  GC tmp_gc;
  Window *childs_to_map = NULL;
  unsigned int childs_num = 0, to_map_num = 0;
  register unsigned int i;
  PagerWindow *t;
  unsigned int h_size, v_size;

  if (CheckForDrawChild (0) != 0)
    return;

  h_size = (Pager.Desks[Desk].tile_hsize == 0) ? Scr.MyDisplayWidth : Pager.Desks[Desk].tile_hsize;
  v_size = (Pager.Desks[Desk].tile_vsize == 0) ? Scr.MyDisplayHeight : Pager.Desks[Desk].tile_vsize;

  LOG1 ("\nstarting grab");
  if ((*pPixmap = XCreatePixmap (dpy, Scr.Root, h_size, v_size, Scr.d_depth)) != 0)
    {
      if (bUnmapSubwindows > 0)
	{
	  XGrabServer (dpy);
	  LOG1 ("\ncounting windows ...");
	  t = Pager.Start;
	  while (t != NULL)
	    {
	      t = t->next;
	      childs_num++;
	    }
	  childs_num *= 2;

	  if (childs_num > 0)
	    {
	      LOG2 ("Done. Kids num = %u.", childs_num);
	      childs_to_map = (Window *) safemalloc (sizeof (Window) * childs_num);
	      LOG2 ("\nQuerying kids %d...", childs_num);
	      for (t = Pager.Start; t != NULL; t = t->next)
		{
		  if ((t->flags & ICONIFIED) != 0)
		    {
		      if (UnmapIfMapped (t->icon_w) == 1)
			childs_to_map[to_map_num++] = t->icon_w;
		      if (UnmapIfMapped (t->icon_pixmap_w) == 1)
			childs_to_map[to_map_num++] = t->icon_pixmap_w;
		    }
		  else if (UnmapIfMapped (t->frame) == 1)
		    childs_to_map[to_map_num++] = t->frame;

		}
	      LOG2 ("Done. Mapped kids = %u.\n Unmapping all ...", to_map_num);

	    }
	}

      LOG1 ("\ncreating GC");
      /*GC XCreateGC(display, d, valuemask, values) */
      if ((tmp_gc = XCreateGC (dpy, *pPixmap, 0, NULL)) != NULL)
	{
	  LOG1 ("\n Copying area");
	  /*XCopyArea(display, src, dest, gc, src_x, src_y, width, height,  dest_x, dest_y) */
	  XCopyArea (dpy, Scr.Root, *pPixmap, tmp_gc, 0, 0, h_size, v_size, 0, 0);
	  LOG1 ("\nfreeing GC");
	  XFreeGC (dpy, tmp_gc);
	}

      LOG1 ("\nMapping kids back ...");
      for (i = 0; i < to_map_num; i++)
	if (childs_to_map[i] != 0)
	  XMapWindow (dpy, childs_to_map[i]);

      LOG2 ("Done. %u kids mapped back.", to_map_num);

      if (childs_to_map)
	free (childs_to_map);
      if (bUnmapSubwindows > 0)
	XUngrabServer (dpy);

      LOG2 ("\nRoot Pixmap grabbed with id = %ld", *pPixmap);
    }
  else
    fprintf (stderr, "Insufficient Memory to grab root pixmap\n");
  LOG1 ("\ngrab completed");
}

int ScalePagerBackground (long Desk);

void 
CheckAndGrabRootPixmap (long Desk)
{
  if (Desk < 0 || Desk >= Pager.ndesks)
    return;

  if (CheckForDrawChild (0) == 0 && Pager.Desks[Desk].FastBackgroundOn != 0)
    if (ROOT_FILENAME != NULL && ROOT_PIXMAP == 0 && Pager.Desks[Desk].LoaderArgs == NULL)
      {
	GrabRoot (&(ROOT_PIXMAP), 1, Desk);
	if (ROOT_PIXMAP != 0)
	  if (ScalePagerBackground (Desk) == 1 || PAGER_PIXMAP == ROOT_PIXMAP)
	    SetPagerBackground (Desk);	/* updating the pager window */
      }
}

int DrawChildPID = 0;

void 
sigchild_handler (int signum)
{
  int pid;
  int status;
  signal (SIGCHLD, sigchild_handler);
  LOG2 ("\nEntering SigChild_handler(%lu)", time (NULL))
    while (1)
    {
      pid = WAIT_CHILDREN (&status);
      if (pid < 0 || pid == DrawChildPID)
	DrawChildPID = 0;
      if (pid == 0 || pid < 0)
	break;
    }
  LOG2 ("\nExiting SigChild_handler(%lu)", time (NULL))
}

/* 
   This should return 0 if process of running external app to draw background completed or killed.
   otherwise it returns > 0
 */
int 
CheckForDrawChild (int kill_it_to_death)
{
  int i;
  int status;

  LOG2 ("\nCheckingForDrawChild(%lu)....", time (NULL));
  if (DrawChildPID > 0)
    {
      LOG2 ("\n Child has been started with PID (%d).", DrawChildPID);
      if (kill_it_to_death > 0)
	{
	  kill (DrawChildPID, SIGTERM);
	  for (i = 0; i < 10; i++)	/* give it 10 sec to terminate */
	    {
	      sleep (1);
	      if (WAIT_CHILDREN (&status) <= 0)
		break;
	    }
	  if (i >= 10)
	    kill (DrawChildPID, SIGKILL);	/* no more mercy */
	  DrawChildPID = 0;
	}
    }
  else if (DrawChildPID < 0)
    DrawChildPID = 0;

  LOG3 ("Done(%lu). Child PID on exit = %d.", time (NULL), DrawChildPID);
  return DrawChildPID;
}

void 
DrawRootExt (long Desk, char *realfilename)
{
  char *action = NULL;
  int len = 0;

  if (Pager.XImageLoaderApp == NULL || strlen (Pager.XImageLoaderApp) == 0)
    len = strlen (XIMAGELOADER);
  else
    {
      len = strlen (Pager.XImageLoaderApp) + 1;
      if (Pager.Desks[Desk].LoaderArgs)
	len += strlen (Pager.Desks[Desk].LoaderArgs);
      else if (Pager.XImageLoaderArgs)
	len += strlen (Pager.XImageLoaderArgs);
    }

  action = (char *) safemalloc (len + 1 + strlen (realfilename) + 1);
  LOG1 ("\n constructing command...");

  if (Pager.XImageLoaderApp == NULL || strlen (Pager.XImageLoaderApp) == 0)
    sprintf (action, "%s %s", XIMAGELOADER, realfilename);
  else
    {
      if (Pager.Desks[Desk].LoaderArgs)
	sprintf (action, "%s %s %s", Pager.XImageLoaderApp, Pager.Desks[Desk].LoaderArgs, realfilename);
      else if (Pager.XImageLoaderArgs)
	sprintf (action, "%s %s %s", Pager.XImageLoaderApp, Pager.XImageLoaderArgs, realfilename);
      else
	sprintf (action, "%s %s", Pager.XImageLoaderApp, realfilename);
    }

  LOG1 ("\n running command...");

  execl ("/bin/sh", "/bin/sh", "-c", action, (char *) 0);

  /* if all is fine then the thread will   exit here */
  /* so displaying error if not                */

  fprintf (stderr, "\nPager%lu: failed to show root image %s.\n", Desk, realfilename);
  exit (0);			/*thread completed */
}

int 
IfRootPixmap (long Desk)
{
  if (ROOT_PIXMAP != None)
    return 1;
  return 0;
}

int 
SetERootPixmap (long Desk)
{
  Atom id = XInternAtom (dpy, "_XROOTPMAP_ID", True);
  if (Desk < 0)
    {
      if (id != None)
	{
	  static Pixmap nonepixmap = None;
	  XChangeProperty (dpy, Scr.Root, id, XA_PIXMAP, 32, PropModeReplace, (char *) &nonepixmap, 1);
	}
      return 1;
    }

  if (ROOT_PIXMAP != None)
    {
      if (id == None)
	id = XInternAtom (dpy, "_XROOTPMAP_ID", False);
      else
	{
	  Atom act_type;
	  int act_format;
	  unsigned long nitems, bytes_after;
	  unsigned char *prop = NULL;
	  Pixmap currentEPixmap = None;

	  /* this will prevent Eterm crashes on restarts etc */
	  /* but, will only work if we make sure to release all of our resources
	   * ourself - including windows, colormap entries, etc - see the Xlib 
	   * manual for more information; basically, this is not a good idea - 
	   * Eterm can be written to not crash if it loses the root pixmap, and 
	   * should be -Ethan */
	  /* XSetCloseDownMode (dpy, RetainPermanent); */
	  /* checking if it's already set, so not to disturb Eterm/aterm */
	  if (XGetWindowProperty (dpy, Scr.Root, id, 0, 1, False, XA_PIXMAP,
			      &act_type, &act_format, &nitems, &bytes_after,
				  &prop) == Success)
	    {
	      if (prop)
		{
		  currentEPixmap = *((Pixmap *) prop);
		  XFree (prop);
		}
	      if (currentEPixmap == ROOT_PIXMAP)
		return 1;
	    }
	}
      XChangeProperty (dpy, Scr.Root, id, XA_PIXMAP, 32, PropModeReplace, (char *) &(ROOT_PIXMAP), 1);
      return 1;
    }
  return 0;
}

/* This function actually displays root background, depending on what pixmap is loaded */
void 
DrawRoot (long Desk)
{
  /* See Switch to Page in x_pager.c */
  if (Desk == 10000)
    return;

  if (CheckForDrawChild (1) != 0)
    return;			/* previos drawing procces not finished */

  if (ROOT_PIXMAP != 0 && Pager.Desks[Desk].LoaderArgs == NULL)
    {
      if (Pager.CurentRootBack != ROOT_PIXMAP)
	{
	  XSetWindowBackgroundPixmap (dpy, Scr.Root, ROOT_PIXMAP);
	  XClearWindow (dpy, Scr.Root);
	  SetERootPixmap (Desk);
	  Pager.CurentRootBack = ROOT_PIXMAP;
	}
    }
  else if (ROOT_FILENAME != NULL)	/* using external PRG for all other formats */
    if (strlen (ROOT_FILENAME) > 0)
      {
	signal (SIGCHLD, sigchild_handler);

	LOG2 ("\nPager%ld: forking...", Desk);
	if (!(DrawChildPID = fork ()))	/* child process */
	  DrawRootExt (Desk, ROOT_FILENAME);

	/* don't want to clear root window if everything is Ok - child process will do that */
      }

}

/****************************************************************************
 *
 * Do all the background pixmap loading for specified desk in here
 * 
 ****************************************************************************/

 /*
    This two initialize values for backgrounds to 0
  */
void 
InitDeskBackgrounds (long Desk)
{
  Pager.Desks[Desk].RootBack = 0;
  Pager.Desks[Desk].PagerBack = 0;
}

void 
InitBackgrounds ()
{
  int i;
  for (i = 0; i < BACKS_NUM; i++)
    {
      Pager.Backgrounds[i].pixmap = 0;
      Pager.Backgrounds[i].filename = NULL;
      Pager.Backgrounds[i].LoaderArgs = NULL;
      Pager.Backgrounds[i].in_use = 0;
    }
}

/*
   This two deallocates all allocated resources and initialize background values to 0
 */
void 
FlushBackPixmap (int BackNum)
{
  if (BackNum > 0 && BackNum < BACKS_NUM)
    if (Pager.Backgrounds[BackNum].pixmap != 0)
      {
	XFreePixmap (dpy, Pager.Backgrounds[BackNum].pixmap);
	Pager.Backgrounds[BackNum].pixmap = 0;
      }
}

void 
DetachBackground (int BackNum)
{
  if (Pager.Backgrounds[BackNum].in_use > 0)
    {
      Pager.Backgrounds[BackNum].in_use--;
      if (Pager.Backgrounds[BackNum].in_use <= 0)
	{
	  FlushBackPixmap (BackNum);
	  if (Pager.Backgrounds[BackNum].filename)
	    {
	      free (Pager.Backgrounds[BackNum].filename);
	      Pager.Backgrounds[BackNum].filename = NULL;
	    }
	  if (Pager.Backgrounds[BackNum].LoaderArgs)
	    {
	      free (Pager.Backgrounds[BackNum].LoaderArgs);
	      Pager.Backgrounds[BackNum].LoaderArgs = NULL;
	    }
	}
    }
}

void 
SetBackLoaderArgs (int BackNum, char *LArgs)
{
  if (BackNum > 0 && BackNum < BACKS_NUM)
    {
      if (Pager.Backgrounds[BackNum].LoaderArgs != NULL)
	free (Pager.Backgrounds[BackNum].LoaderArgs);
      if (LArgs != NULL)
	Pager.Backgrounds[BackNum].LoaderArgs = (char *) safemalloc (strlen (LArgs) + 1);
      else
	Pager.Backgrounds[BackNum].LoaderArgs = NULL;
    }

}

int 
AttachBackground (int BackNum)
{

  if (BackNum > 0 && BackNum < BACKS_NUM)
    Pager.Backgrounds[BackNum].in_use++;

  return BackNum;
}

void 
FlushPixmaps (long Desk)
{
  FlushBackPixmap (Pager.Desks[Desk].RootBack);
  FlushBackPixmap (Pager.Desks[Desk].PagerBack);
}

void 
BackgroundChanged (long Desk)
{
  if (Desk >= 0 && Desk < Pager.ndesks)
    if (Pager.Desks[Desk].PagerBack > 0 && Pager.Desks[Desk].PagerBack < BACKS_NUM)
      if (Pager.Desks[Desk].PagerBackType == backgrScaleRoot)
	if (PAGER_FILENAME != NULL)
	  {
	    remove (PAGER_FILENAME);
	    free (PAGER_FILENAME);
	    PAGER_FILENAME = NULL;
	  }

  FlushPixmaps (Desk);
}

/* usefull to run before rereading config */
void 
FlushBackgrounds (long Desk)
{
  if (Desk >= 0 && Desk < Pager.ndesks)
    {
      DetachBackground (Pager.Desks[Desk].RootBack);
      DetachBackground (Pager.Desks[Desk].PagerBack);
      InitDeskBackgrounds (Desk);
    }
}

void 
FlushAllBackgrounds ()
{
  long i;
  for (i = 0; i < Pager.ndesks; i++)
    FlushBackgrounds (i);
}
/*
   Find empty entry in Backgrounds table 
 */
int 
GetEmptyBackgrEntry (long Desk, char *sameas)
{
  int i;
  /* looking for empty entry in the backgrounds table */
  if (sameas != NULL)
    for (i = 1; i < BACKS_NUM; i++)
      if (Pager.Backgrounds[i].filename)
	if (strcmp (Pager.Backgrounds[i].filename, sameas) == 0)
	  return i;

  for (i = 1; i < BACKS_NUM; i++)
    if (Pager.Backgrounds[i].filename == NULL)
      return i;

  return -1;
}


void 
SetBackgroundType (long Desk, char *params)
{

  LOG2 ("\nSetBackgrType: Input=[%s]", params);
  LOG2 ("\nSetBackgrType: Desk=[%ld]", Desk);
  if (strncasecmp (params, "Scale", 5) == 0)
    Pager.Desks[Desk].PagerBackType = backgrScaleRoot;
  else if (strncasecmp (params, "Same", 4) == 0)
    Pager.Desks[Desk].PagerBackType = backgrSameAsRoot;
  else
    {
      Pager.Desks[Desk].PagerBackType = backgrUseXPM;
      if (strncasecmp (params, "UseXPM", 6) != 0)
	fprintf (stderr, "Pager%lu: wrong pager background type specified [%s]. Assuming 'UseXPM'", Desk, params);
    }
}

/********
 set root backround to xpmFile XPM
 ********/
void
SetRootPixmap (long Desk, char *xpmFile)
{
  char *tmp;
  LOG3 ("\nEnter SetRootPixmap %ld, [%s]", Desk, xpmFile);

  if (xpmFile)
    if (strlen (xpmFile) > 0)
      {
	/* looking for empty entry in the backgrounds table */
	if ((tmp = PutHome (xpmFile)) == NULL)
	  fprintf (stderr, "Pager%ld: Not enough memory to store file name[%s].\n", Desk, xpmFile);
	else
	  {
	    Pager.Desks[Desk].RootBack = AttachBackground (GetEmptyBackgrEntry (Desk, tmp));

	    if (Pager.Desks[Desk].RootBack < 0)		/* empty entry not found */
	      fprintf (stderr, "Pager%ld: Redundant background filename : [%s].\n", Desk, xpmFile);
	    else
	      {
		if (ROOT_FILENAME == NULL)
		  ROOT_FILENAME = tmp;
		LOG3 ("\nExit SetRootPixmap %ld, [%d]", Desk, Pager.Desks[Desk].RootBack);
		return;
	      }
	  }
	Pager.Desks[Desk].RootBack = 0;		/* enabling usage of some other available background */
      }
  LOG3 ("\nBad Exit SetRootPixmap %ld, [%s]", Desk, xpmFile);
}

/****************************************************************************
 *
 * set Background for Desks in Pager window to xpmFile XPM
 *
 ****************************************************************************/
void
SetPagerPixmap (long Desk, char *xpmFile)
{
  char *tmp;

  LOG3 ("\nEnter SetPagerPixmap %ld, [%s]", Desk, xpmFile);
  if (xpmFile)
    if (strlen (xpmFile) > 0)
      {
	/* looking for empty entry in the backgrounds table */
	if ((tmp = PutHome (xpmFile)) == NULL)
	  fprintf (stderr, "Pager%ld: Not enough memory to store file name[%s].\n", Desk, xpmFile);
	else
	  {
	    LOG3 ("\nSetPagerPixmap %ld, [%s] GetEmptyBack...", Desk, xpmFile);
	    Pager.Desks[Desk].PagerBack = AttachBackground (GetEmptyBackgrEntry (Desk, tmp));
	    LOG2 ("Done.[%d]", Pager.Desks[Desk].PagerBack);

	    if (Pager.Desks[Desk].PagerBack < 0)	/* empty entry not found */
	      fprintf (stderr, "Pager%ld: Redundant background filename : [%s].\n", Desk, xpmFile);
	    else
	      {
		if (PAGER_FILENAME == NULL)
		  PAGER_FILENAME = tmp;
		LOG3 ("\nExit SetPagerPixmap %ld, [%d]", Desk, Pager.Desks[Desk].PagerBack);
		return;
	      }
	  }
	Pager.Desks[Desk].PagerBack = 0;	/* enabling usage of some other available background */
      }
  LOG3 ("\nBad Exit SetPagerPixmap %ld, [%s]", Desk, xpmFile);
}

/*
   This function sets background of pager's window for the specified Desk
 */
void 
SetPagerBackground (long Desk)
{
  if (PAGER_PIXMAP != 0)
    {
      XSetWindowBackgroundPixmap (dpy, Pager.Desks[Desk].w, PAGER_PIXMAP);
      XClearWindow (dpy, Pager.Desks[Desk].w);
    }
}

/*
   This function scales root background to pager size if user requested so, and
   saves it in small file for the future use, or loads it from there if it can
 */
int 
ScalePagerBackground (long Desk)
{
  int to_return = 0;

  LOG2 ("\nEnter ScalePagerBackground %ld", Desk);
  if (Pager.Desks[Desk].PagerBackType == backgrScaleRoot)
    {
      if (ROOT_PIXMAP != 0)	/* scale down image is faster then loading it from file - 
				   let's do that          */
	{
	  if ((PAGER_PIXMAP = ScalePixmapToWin (ROOT_PIXMAP, Pager.Desks[Desk].w, Scr.d_depth)) != 0)
	    {
#ifdef HAVE_XPM_WRITE
	      /* save newly created pixmap into .small. file if it is not there already */
	      if (access (PAGER_FILENAME, F_OK) != 0)
		XpmWriteFileFromPixmap (dpy, PAGER_FILENAME, PAGER_PIXMAP, 0, NULL);
#endif /* HAVE_XPM_WRITE */
	      to_return = 1;
	    }
	}			/* nothing to scale othervise, trying to load image saved before */
      else
	to_return = CheckPixmapLoaded (Pager.Desks[Desk].PagerBack, Pager.Desks[Desk].w);
    }
  LOG2 ("\nExit ScalePagerBackground %ld", Desk);
  return to_return;
}

/*
   This function will try to load background pixmaps or scale pager background from the root
 */

void 
MakeBackgrounds (long Desk)
{
  LOG2 ("\nEnter MakeBackgrounds %ld", Desk);

  /* checking that we have some backgrounds specified */
  if (ROOT_FILENAME == NULL)
    fprintf (stderr, "\nPager: Desk#%lu: Root background is not specified!", Desk);

  Pager.Desks[Desk].PagerBackType = backgrUseXPM;
  if (PAGER_FILENAME == NULL)
    {
      if (ROOT_FILENAME == NULL)
	return;			/*nothing to do here */
      else
	Pager.Desks[Desk].PagerBackType = backgrScaleRoot;
    }

  if (Pager.Desks[Desk].PagerBackType == backgrSameAsRoot)
    {
      DetachBackground (Pager.Desks[Desk].PagerBack);
      Pager.Desks[Desk].PagerBack = AttachBackground (Pager.Desks[Desk].RootBack);
    }
  else if (Pager.Desks[Desk].PagerBackType == backgrScaleRoot)
    {
      XWindowAttributes win_attr;
      char SmallExt[SMALL_FILE_NAME_EXT_MAX_LEN];
      char *fname;

      LOG1 ("\n Type = ScaleRoot.")
      /* here constructing the filename for the small image   */
	if (XGetWindowAttributes (dpy, Pager.Desks[Desk].w, &win_attr) == 0)
	{
	  win_attr.width = 0;
	  win_attr.height = 0;
	}

      sprintf (SmallExt, SMALL_FILE_NAME_EXT, win_attr.width, win_attr.height);
      LOG2 ("\n  Small File Extension = [%s]", SmallExt)
	fname = safemalloc (strlen (ROOT_FILENAME) + strlen (SmallExt) + 1);
      sprintf (fname, "%s%s", ROOT_FILENAME, SmallExt);
      LOG2 ("\n  Small File Name = [%s]", fname)
	if (Pager.Desks[Desk].PagerBack != 0)
	{
	  if (PAGER_FILENAME != NULL)
	    {
	      if (strcmp (PAGER_FILENAME, fname) != 0)
		{
		  DetachBackground (Pager.Desks[Desk].PagerBack);
		  Pager.Desks[Desk].PagerBack = 0;
		}
	    }
	  else if (Pager.Desks[Desk].PagerBack == Pager.Desks[Desk].RootBack)
	    {
	      DetachBackground (Pager.Desks[Desk].PagerBack);
	      Pager.Desks[Desk].PagerBack = 0;
	    }
	  LOG1 (" Done.")
	}

      if (Pager.Desks[Desk].PagerBack == 0)
	{
	  LOG1 ("\n   Attaching new pager background... ")
	    Pager.Desks[Desk].PagerBack = AttachBackground (GetEmptyBackgrEntry (Desk, fname));
	  LOG1 (" Done.")
	}

      if (PAGER_FILENAME)
	free (PAGER_FILENAME);
      LOG1 ("\n Setting Pager backgr filename... ")
	PAGER_FILENAME = fname;
      LOG1 (" Done.")

    }
  else
    {
      CheckPixmapLoaded (Pager.Desks[Desk].PagerBack,
	       (Pager.Desks[Desk].PagerBack == Pager.Desks[Desk].RootBack &&
		Pager.Desks[Desk].LoaderArgs == NULL) ? Scr.Root : Pager.Desks[Desk].w);

      /* let's check that pixmap was loaded ok. */
      if (PAGER_PIXMAP == 0)
	{
	  fprintf (stderr, "\nPager: Desk%lu: unable to load image [%s] for Pager's window background.", Desk, PAGER_FILENAME);

	  /* hmmm looks like we are going to use the one that is displayed on the root */
	  /* DetachBackground(Pager.Desks[Desk].PagerBack);                      */
	  /* Pager.Desks[Desk].PagerBack=AttachBackground(Pager.Desks[Desk].RootBack) ; */
	}
    }

  /* Loading Root Background */
  if (Pager.Desks[Desk].PagerBack > 0 &&
      Pager.Desks[Desk].LoaderArgs == NULL)
    CheckPixmapLoaded (Pager.Desks[Desk].RootBack, Scr.Root);

  /* now lets scale pager's background if we need to do so */
  ScalePagerBackground (Desk);
  LOG2 ("\nExit MakeBackgrounds %ld", Desk);
}

#endif /*PAGER_BACKGROUND */
