/*
 * Copyright (c) 1997 Guylhem Aznar <guylhem@oeil.qc.ca>
 * Copyright (c) 1994 Nobutaka Suzuki <nobuta-s@is.aist-nara.ac.jp>
 * Copyright (c) 1994 Robert 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 0

#define YES "Yes"
#define NO  "No"

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

#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/time.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>
#include <X11/cursorfont.h>
#include <X11/Xmu/WinUtil.h>

#include "../../include/module.h"
#include "Scroll.h"

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

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

char *BackColor = "black";
char *ForeColor = "grey";

Window app_win;

#define MW_EVENTS   (ExposureMask | ButtonReleaseMask | KeyReleaseMask)

void ParseOptions (const char *);

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

  /* Save the program name for error messages and config parsing */
  temp = argv[0];
  s = strrchr (argv[0], '/');
  if (s != NULL)
    temp = s + 1;

  MyName = temp;

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

  if (argc == 7)
    {
      char *cptr;
      extern int Reduction_H, Reduction_V;

      cptr = argv[6];
      while (isspace (*cptr))
	cptr++;
      Reduction_H = atoi (cptr);
      while (!(isspace (*cptr)) && (*cptr != 0))
	cptr++;
      while (isspace (*cptr))
	cptr++;
      Reduction_V = atoi (cptr);
    }
  /* Dead pipe == dead AfterStep! */
  signal (SIGPIPE, DeadPipe);

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

  /* An application window may have already been selected - look for it */
  sscanf (argv[4], "%x", (unsigned int *) &app_win);

  /* Open the Display */
  if (!(dpy = XOpenDisplay (display_name)))
    {
      fprintf (stderr, "%s: can't open display %s", MyName,
	       XDisplayName (display_name));
      exit (1);
    }
  x_fd = XConnectionNumber (dpy);
  screen = DefaultScreen (dpy);
  Root = RootWindow (dpy, screen);
  d_depth = DefaultDepth (dpy, screen);

  ScreenHeight = DisplayHeight (dpy, screen);
  ScreenWidth = DisplayWidth (dpy, screen);

  /* scan config file for set-up parameters */
  /* Colors and fonts */
  if (strstr (argv[3], "steprc") != NULL)
    ParseOptions (argv[3]);
  else
    {
      sprintf (configfile, "%s/scroll", AFTER_DIR);

      realconfigfile = PutHome (configfile);

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

  if (app_win == 0)
    GetTargetWindow (&app_win);

  if (app_win == 0)
    return 1;

  fd_width = GetFdWidth ();

  GrabWindow (app_win);
  Loop (app_win);

  return 0;
}


void 
ParseOptions (const char *filename)
{
  FILE *file;
  char *line, *tline;
  int len;

  if ((file = fopen (filename, "r")) != (FILE *) NULL)
    {
      line = (char *) safemalloc (MAXLINELENGTH);
      len = strlen (MyName);
      while ((tline = fgets (line, MAXLINELENGTH, file)) == NULL)
	{
	  while (isspace (*tline))
	    tline++;
	  if ((*tline == '*') && (!mystrncasecmp (tline + 1, MyName, len)))
	    {
	      tline += len + 1;
	      if (!mystrncasecmp (tline, "Fore", 4))
		CopyString (&ForeColor, tline + 4);
	      else if (!mystrncasecmp (tline, "Back", 4))
		CopyString (&BackColor, tline + 4);
	    }
	}
      free (line);
      fclose (file);
    }
}

/***********************************************************************
 *
 * Detected a broken pipe - time to exit 
 *
 **********************************************************************/
void
DeadPipe (int nonsense)
{
  extern Atom wm_del_win;

  XReparentWindow (dpy, app_win, Root, 0, 0);
  send_clientmessage (app_win, wm_del_win, CurrentTime);
  XSync (dpy, 0);
  exit (0);
}


/**********************************************************************
 *
 * If no application window was indicated on the command line, prompt
 * the user to select one 
 *
 *********************************************************************/
void
GetTargetWindow (Window * app_win)
{
  XEvent eventp;
  int val = -10, trials;
  Window target_win;

  trials = 0;
  while ((trials < 100) && (val != GrabSuccess))
    {
      val = XGrabPointer (dpy, Root, True,
			  ButtonReleaseMask,
			  GrabModeAsync, GrabModeAsync, Root,
			  XCreateFontCursor (dpy, XC_crosshair),
			  CurrentTime);
      if (val != GrabSuccess)
	{
	  sleep_a_little (1000);
	}
      trials++;
    }
  if (val != GrabSuccess)
    {
      fprintf (stderr, "%s: Couldn't grab the cursor!\n", MyName);
      exit (1);
    }
  XMaskEvent (dpy, ButtonReleaseMask, &eventp);
  XUngrabPointer (dpy, CurrentTime);
  XSync (dpy, 0);
  *app_win = eventp.xany.window;
  if (eventp.xbutton.subwindow != None)
    *app_win = eventp.xbutton.subwindow;

  target_win = ClientWindow (*app_win);
  if (target_win != None)
    *app_win = target_win;
}


void
nocolor (char *a, char *b)
{
  fprintf (stderr, "InitBanner: can't %s %s\n", a, b);
}



/****************************************************************************
 *
 * Find the actual application 
 * 
 ***************************************************************************/
Window
ClientWindow (Window input)
{
  Atom _XA_WM_STATE;
  unsigned int nchildren;
  Window root, parent, *children, target;
  unsigned long nitems, bytesafter;
  unsigned char *prop;
  Atom atype;
  int aformat;
  int i;

  _XA_WM_STATE = XInternAtom (dpy, "WM_STATE", False);

  if (XGetWindowProperty (dpy, input, _XA_WM_STATE, 0L,
			  3L, False, _XA_WM_STATE, &atype,
			  &aformat, &nitems, &bytesafter,
			  &prop) == Success)
    {
      if (prop != NULL)
	{
	  XFree (prop);
	  return input;
	}
    }

  if (!XQueryTree (dpy, input, &root, &parent, &children, &nchildren))
    return None;

  for (i = 0; i < nchildren; i++)
    {
      target = ClientWindow (children[i]);
      if (target != None)
	{
	  XFree ((char *) children);
	  return target;
	}
    }
  XFree ((char *) children);
  return None;
}
