/*
 * Copyright (C) 1995 Bo Yang
 * Copyright (C) 1993 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.
 *
 */

/**********************************************************************
 *
 * code for parsing the afterstep style command
 *
 ***********************************************************************/
#include "../../configure.h"

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>

#include "../../include/afterstep.h"
#include "../../include/menus.h"
#include "../../include/parse.h"
#include "../../include/misc.h"
#include "../../include/screen.h"

/************************************************************************
 * ReapChildren - wait() for all dead child processes
 ************************************************************************/

#ifdef HAVE_SYS_WAIT_H
#define ReapChildren()  while ((waitpid(-1, NULL, WNOHANG)) > 0);
#elif defined (HAVE_WAIT3)
#define ReapChildren()  while ((wait3(NULL, WNOHANG, NULL)) > 0);
#endif


void
ParseStyle (char *text, FILE * fd, char **list, int *junk)
{
  extern char *orig_tline;
  char *name, *line;
  char *restofline;
  char *icon_name = NULL;
  char *forecolor = NULL;
  char *backcolor = NULL;
  unsigned long off_buttons = 0;
  unsigned long on_buttons = 0;
  int butt;

  int len, desknumber = 0, bw = 0, nobw = 0, viewport_x = 0, viewport_y = 0;
  unsigned long off_flags = 0;
  unsigned long on_flags = 0;

  name = stripcpy2 (text, 0);
  /* in case there was no argument! */
  if (name == NULL)
    return;

  restofline = stripcpy3 (text, FALSE);
  line = restofline;

  if (restofline == NULL)
    return;
  while ((*restofline != 0) && (*restofline != '\n'))
    {
      while (isspace ((unsigned char) *restofline))
	restofline++;
      if (mystrncasecmp (restofline, "Icon", 4) == 0)
	{
	  restofline = ReadFileName (restofline + 4, &icon_name, &len);
	  if (len > 0)
	    {
	      off_flags |= ICON_FLAG;
	      on_flags |= SUPPRESSICON_FLAG;
	    }
	  else
	    on_flags |= SUPPRESSICON_FLAG;
	}
      if (mystrncasecmp (restofline, "Color", 5) == 0)
	{
	  restofline = ReadColorValue (restofline + 5, &forecolor, &len);
	  if (len > 0)
	    off_flags |= FORE_COLOR_FLAG;

	  while (isspace ((unsigned char) *restofline))
	    restofline++;

	  if (*restofline == '/')
	    {
	      restofline = ReadColorValue (restofline + 1, &backcolor, &len);
	      if (len > 0)
		off_flags |= BACK_COLOR_FLAG;
	    }
	}
      if (mystrncasecmp (restofline, "ForeColor", 9) == 0)
	{
	  restofline = ReadColorValue (restofline + 9, &forecolor, &len);
	  if (len > 0)
	    off_flags |= FORE_COLOR_FLAG;
	}
      if (mystrncasecmp (restofline, "BackColor", 9) == 0)
	{
	  restofline = ReadColorValue (restofline + 9, &backcolor, &len);
	  if (len > 0)
	    off_flags |= BACK_COLOR_FLAG;
	}
#ifdef NO_ICON_BACKGROUND
      else if (mystrncasecmp (restofline, "NoIconTitle", 11) == 0)
	{
	  off_flags |= NOICON_TITLE_FLAG;
	  restofline += 11;
	}
      else if (mystrncasecmp (restofline, "IconTitle", 9) == 0)
	{
	  on_flags |= NOICON_TITLE_FLAG;
	  restofline += 9;
	}
#endif
      else if (mystrncasecmp (restofline, "NoIcon", 6) == 0)
	{
	  restofline += 6;
	  off_flags |= SUPPRESSICON_FLAG;
	}
      else if (mystrncasecmp (restofline, "NoFocus", 7) == 0)
	{
	  restofline += 7;
	  off_flags |= NOFOCUS_FLAG;
	}
      else if (mystrncasecmp (restofline, "NoTitle", 7) == 0)
	{
	  restofline += 7;
	  off_flags |= NOTITLE_FLAG;
	}
      else if (mystrncasecmp (restofline, "Title", 5) == 0)
	{
	  restofline += 5;
	  on_flags |= NOTITLE_FLAG;
	}
      else if (mystrncasecmp (restofline, "NoHandles", 9) == 0)
	{
	  restofline += 9;
	  off_flags |= NOBORDER_FLAG;
	}
      else if (mystrncasecmp (restofline, "Handles", 7) == 0)
	{
	  restofline += 7;
	  on_flags |= NOBORDER_FLAG;
	}
      else if (mystrncasecmp (restofline, "NoButton", 8) == 0)
	{
	  restofline = ReadIntValue (restofline + 8, &butt);
	  off_buttons |= (1 << (butt - 1));
	}
      else if (mystrncasecmp (restofline, "Button", 6) == 0)
	{
	  restofline = ReadIntValue (restofline + 6, &butt);
	  on_buttons |= (1 << (butt - 1));
	}
      else if (mystrncasecmp (restofline, "WindowListSkip", 14) == 0)
	{
	  restofline += 14;
	  off_flags |= LISTSKIP_FLAG;
	}
      else if (mystrncasecmp (restofline, "WindowListHit", 13) == 0)
	{
	  restofline += 13;
	  on_flags |= LISTSKIP_FLAG;
	}
      else if (mystrncasecmp (restofline, "CirculateSkip", 13) == 0)
	{
	  restofline += 13;
	  off_flags |= CIRCULATESKIP_FLAG;
	}
      else if (mystrncasecmp (restofline, "CirculateHit", 12) == 0)
	{
	  restofline += 12;
	  on_flags |= CIRCULATESKIP_FLAG;
	}
      else if (mystrncasecmp (restofline, "StartIconic", 11) == 0)
	{
	  restofline += 11;
	  off_flags |= START_ICONIC_FLAG;
	}
      else if (mystrncasecmp (restofline, "StartNormal", 11) == 0)
	{
	  restofline += 11;
	  on_flags |= START_ICONIC_FLAG;
	}
      else if (mystrncasecmp (restofline, "StaysOnTop", 10) == 0)
	{
	  restofline += 10;
	  off_flags |= STAYSONTOP_FLAG;
	}
      else if (mystrncasecmp (restofline, "StaysOnBack", 11) == 0)
	{
	  restofline += 11;
/* Will both ! */
	  off_flags |= STAYSONBACK_FLAG;
	  on_flags |= STAYSONTOP_FLAG;
	}
      else if (!mystrncasecmp (restofline, "AvoidCover", 10))
	{
	  restofline += 10;
	  off_flags |= AVOID_COVER_FLAG;
	}
      else if (!mystrncasecmp (restofline, "AllowCover", 10))
	{
	  restofline += 10;
	  on_flags |= AVOID_COVER_FLAG;
	}
      else if (mystrncasecmp (restofline, "Sticky", 6) == 0)
	{
	  off_flags |= STICKY_FLAG;
	  restofline += 6;
	}
      else if (mystrncasecmp (restofline, "Slippery", 8) == 0)
	{
	  on_flags |= STICKY_FLAG;
	  restofline += 8;
	}
      else if (mystrncasecmp (restofline, "BorderWidth", 11) == 0)
	{
	  off_flags |= BW_FLAG;
	  restofline = ReadIntValue (restofline + 11, &bw);
	}
      else if (mystrncasecmp (restofline, "HandleWidth", 11) == 0)
	{
	  restofline = ReadIntValue (restofline + 11, &nobw);
	  off_flags |= NOBW_FLAG;
	}
      else if (mystrncasecmp (restofline, "StartsOnDesk", 12) == 0)
	{
	  restofline = ReadIntValue (restofline + 12, &desknumber);
	  off_flags |= STAYSONDESK_FLAG;
	}
      else if (mystrncasecmp (restofline, "ViewportX", 9) == 0)
	{
	  restofline = ReadIntValue (restofline + 9, &viewport_x);
	  off_flags |= VIEWPORTX_FLAG;
	}
      else if (mystrncasecmp (restofline, "ViewportY", 9) == 0)
	{
	  restofline = ReadIntValue (restofline + 9, &viewport_y);
	  off_flags |= VIEWPORTY_FLAG;
	}
      else if (mystrncasecmp (restofline, "StartsAnywhere", 14) == 0)
	{
	  restofline += 14;
	  on_flags |= STAYSONDESK_FLAG;
	}
      while (isspace ((unsigned char) *restofline))
	restofline++;
      if (*restofline == ',')
	restofline++;
      else if ((*restofline != 0) && (*restofline != '\n'))
	{
	  afterstep_err ("bad style command in line %s at %s",
			 orig_tline, restofline, NULL);
	  return;
	}
    }
  /* capture default icons */
  if (strcmp (name, "*") == 0)
    {
      if (off_flags & ICON_FLAG)
	Scr.DefaultIcon = icon_name;
      off_flags &= ~ICON_FLAG;
      icon_name = NULL;
    }
#if 0
  /* this code does not work with the new QuickRestart(), and doesn't 
   * allocate memory properly -Ethan 10/15/98 */
  /* capture default colors */
  if (strcmp (name, "*") == 0)
    {
      extern char *Stdfore, *Stdback;

      if (off_flags & FORE_COLOR_FLAG)
	Stdfore = forecolor;
      off_flags &= ~FORE_COLOR_FLAG;
      forecolor = NULL;
      if (off_flags & BACK_COLOR_FLAG)
	Stdback = backcolor;
      off_flags &= ~BACK_COLOR_FLAG;
      backcolor = NULL;
    }
#endif
  free (line);
  AddToList (name, icon_name, off_flags, on_flags, desknumber, bw, nobw,
     forecolor, backcolor, off_buttons, on_buttons, viewport_x, viewport_y);
}


void
AddToList (char *name, char *icon_name, unsigned long off_flags,
	   unsigned long on_flags, int desk, int bw, int nobw,
	   char *forecolor, char *backcolor,
	   unsigned long off_buttons, unsigned long on_buttons,
	   int viewport_x, int viewport_y)
{
  name_list *nptr;

  if ((name == NULL) || ((off_flags == 0) && (on_flags == 0) && (on_buttons == 0) &&
			 (off_buttons == 0)))
    {
      if (name)
	free (name);
      if (icon_name)
	free (icon_name);
      if (forecolor)
	free (forecolor);
      if (backcolor)
	free (backcolor);
      return;
    }
  nptr = (name_list *) safemalloc (sizeof (name_list));
  nptr->next = NULL;
  nptr->name = name;
  nptr->on_flags = on_flags;
  nptr->off_flags = off_flags;
  nptr->value = icon_name;
  nptr->Desk = desk;
  nptr->border_width = bw;
  nptr->resize_width = nobw;
  nptr->ForeColor = forecolor;
  nptr->BackColor = backcolor;
  nptr->ViewportX = viewport_x;
  nptr->ViewportY = viewport_y;

  nptr->off_buttons = off_buttons;
  nptr->on_buttons = on_buttons;

  if (Scr.TheList != NULL)
    {
      /*  Scr.TheList->prev points to the last elements of the
         circular list TheList */
      Scr.TheList->prev->next = nptr;
      nptr->next = Scr.TheList;
      nptr->prev = Scr.TheList->prev;
      Scr.TheList->prev = nptr;
    }
  else
    {
      Scr.TheList = nptr;
      Scr.TheList->next = Scr.TheList->prev = Scr.TheList;
    }
}

void
RemoveFromList (name_list * name)
{
  name_list *p;

  if (Scr.TheList == NULL)
    return;

  /* find ourself from the style list */
  for (p = Scr.TheList; p->next != Scr.TheList; p = p->next)
    if (p == name)
      break;

  if (p != name)
    return;

  /* remove from list */
  if (p == Scr.TheList)
    {
      if (p->next == p)
	Scr.TheList = NULL;
      else
	Scr.TheList = p->next;
    }
  p->next->prev = p->prev;
  p->prev->next = p->next;
  if (p->name != NULL)
    free (p->name);
  if (p->value != NULL)
    free (p->value);
  if (p->ForeColor != NULL)
    free (p->ForeColor);
  if (p->BackColor != NULL)
    free (p->BackColor);

  free (p);
}
