#ifndef XCLASSES_INTERN
#define XCLASSES_INTERN

/*-----------------------------------------------------------------------
 * Xclasses code file
 * ($Id: intern.cxx,v 1.5 2001/09/13 16:07:07 schmitzj Exp $)
 * 
 * Copyright (C) 1998 Jürgen Schmitz
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 *-----------------------------------------------------------------------
 */

#include "types.h"
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/utsname.h>
#ifdef __AIX__
#include <sys/time.h>
#endif
#include <Xclasses/easy_dialog.h>
#include <Xclasses/gfx_xpm.h>
#include <Xclasses/appwindow.h>
#include "../include/version.h"
#include "pixmap/Xclasses_logo.xpm"

static int glob_match_after_star (char *pattern, char *text);
static int glob_pattern_p (char *pattern);
static int glob_match (char *pattern, char *text, int dot_special);

static short doanimlogo=0;
extern short NOKEY,BLACKBORDER;
extern short OBJDEBUGMODE;

void argvparser(int &argc, char *argv[])
{
	int i=1;
	while (i<argc)
	{
		if (!strcasecmp(argv[i],"-exportanim"))
		{
			doanimlogo=1;
			remarg(argc,argv,i);
			argc--;
		}
		else if (!strcasecmp(argv[i],"-blackborder"))
		{
			BLACKBORDER=1;
			remarg(argc,argv,i);
			argc--;
		}
		else if (!strcasecmp(argv[i],"-nokey"))
		{
			NOKEY=1;
			remarg(argc,argv,i);
			argc--;
		}
		else if (!strcasecmp(argv[i],"-objdebug"))
		{
			OBJDEBUGMODE=1;
			remarg(argc,argv,i);
			argc--;
		}
		else
		{
			i++;
		}
	}
	parseArgv(argc,argv);
}

#ifndef CCVERSION
#define CCVERSION ""
#endif

void about_Xclasses(class Xwindows *aw, class Xclasses *parent)
{
	easy_dialog info;
	gfx_xpm Xc_logo(Xclasses_logo);
	char buf[800];
	struct utsname nts;
	uname(&nts);

	sprintf(buf,"Xclasses %s (%s Lib %d.%d.%d) - compilation %d (%s) "CCVERSION"\n"
				"by Juergen Schmitz in 1996-2001 - published under LGPL\n\n"
				"EMail: {FONT_FIXED}schmitzj@js-home.org{/FONT}\n"
				"{FONT_FIXED}http://www.js-home.org/Xclasses/{/FONT}\n\n"
				"          Xclasses is a powerfull layout library to easily and fast\n"
				"          build fully font and context sensitiv graphical user\n"
				"          interfaces (GUIs). All this is available with a simple\n"
				"          C++ class interface (typically called API).\n\n"
				"  The final user may configure many optical parameters\n"
				"  to his wishes - Xclasses may always make the best GUI\n"
				"  possible with this settings!"
			,LibVersion(),nts.sysname,LibMajor(),LibMinor(),LibPatch(),LibCompile(),LibDate());
	info.ParentClass(parent);
	info.Text(buf);
	info.Options("Okay");
	if (strlen(aw->DisplayName())<5 || doanimlogo)
		info.Logo((gfx_object *)1);
	else
		info.Logo(Xc_logo);
	info.Start(aw);
}

#ifdef NOSTRCASECMP
int strcasecmp(char *s1,char *s2)
{
  register unsigned char *p1 = (unsigned char *) s1;
  register unsigned char *p2 = (unsigned char *) s2;
  register int ret;
  unsigned char c1;

  if (p1 == p2)
    return 0;

  for (; !(ret = (c1 = tolower(*p1)) - tolower(*p2)); p1++, p2++)
    if (c1 == '\0') break;
  return ret;
}
#endif

void go_sleep(int milli)
{
#ifndef NANOSLEEP
	usleep(milli);
#else
#ifdef __AIX__
#define nanosleep(a,b)	nsleep(a,b)
	struct timestruc_t	ts;
#else
	struct timespec ts;
#endif
	ts.tv_sec=0;
	ts.tv_nsec=milli*1000;
	nanosleep(&ts,NULL);
#endif
}
int glob_string(char *name,char *pattern,int hidden)
{
	return glob_match(pattern,name,hidden);
}

void remarg(int argc, char *argv[],int r)
{
	for(int i=r+1;i<argc;i++)
	{
		argv[i-1]=argv[i];
	}
}


// this bases on GNU glob.c

/* Return nonzero if PATTERN has any special globbing chars in it.  */
static int glob_pattern_p (char *pattern)
{
  register char *p = pattern;
  register char c;

  while ((c = *p++) != '\0')
    switch (c)
      {
      case '?':
      case '[':
      case '*':
	return 1;

      case '\\':
	if (*p++ == '\0')
	  return 0;
      }

  return 0;
}

/* Match the pattern PATTERN against the string TEXT;
   return 1 if it matches, 0 otherwise.

   A match means the entire string TEXT is used up in matching.

   In the pattern string, `*' matches any sequence of characters,
   `?' matches any character, [SET] matches any character in the specified set,
   [!SET] matches any character not in the specified set.

   A set is composed of characters or ranges; a range looks like
   character hyphen character (as in 0-9 or A-Z).
   [0-9a-zA-Z_] is the set of characters allowed in C identifiers.
   Any other character in the pattern must be matched exactly.

   To suppress the special syntactic significance of any of `[]*?!-\',
   and match the character exactly, precede it with a `\'.

   If DOT_SPECIAL is nonzero,
   `*' and `?' do not match `.' at the beginning of TEXT.  */

static int glob_match (char *pattern,char* text,int dot_special)
{
  register char *p = pattern, *t = text;
  register char c;

  while ((c = *p++) != '\0')
    switch (c)
      {
      case '?':
	if (*t == '\0' || (dot_special && t == text && *t == '.'))
	  return 0;
	else
	  ++t;
	break;

      case '\\':
	if (*p++ != *t++)
	  return 0;
	break;

      case '*':
	if (dot_special && t == text && *t == '.')
	  return 0;
	return glob_match_after_star (p, t);

      case '[':
	{
	  register char c1 = *t++;
	  int invert;

	  if (c1 == '\0')
	    return 0;

	  invert = (*p == '!');

	  if (invert)
	    p++;

	  c = *p++;
	  while (1)
	    {
	      register char cstart = c, cend = c;

	      if (c == '\\')
		{
		  cstart = *p++;
		  cend = cstart;
		}

	      if (cstart == '\0')
		return 0;	/* Missing ']'. */

	      c = *p++;

	      if (c == '-')
		{
		  cend = *p++;
		  if (cend == '\\')
		    cend = *p++;
		  if (cend == '\0')
		    return 0;
		  c = *p++;
		}
	      if (c1 >= cstart && c1 <= cend)
		goto match;
	      if (c == ']')
		break;
	    }
	  if (!invert)
	    return 0;
	  break;

	match:
	  /* Skip the rest of the [...] construct that already matched.  */
	  while (c != ']')
	    {
	      if (c == '\0')
		return 0;
	      c = *p++;
	      if (c == '\0')
		return 0;
	      if (c == '\\')
		p++;
	    }
	  if (invert)
	    return 0;
	  break;
	}

      default:
	if (c != *t++)
	  return 0;
      }

  return *t == '\0';
}

/* Like glob_match, but match PATTERN against any final segment of TEXT.  */

static int glob_match_after_star (char *pattern,char *text)
{
  register char *p = pattern, *t = text;
  register char c, c1;

  while ((c = *p++) == '?' || c == '*')
    if (c == '?' && *t++ == '\0')
      return 0;

  if (c == '\0')
    return 1;

  if (c == '\\')
    c1 = *p;
  else
    c1 = c;

  --p;
  while (1)
    {
      if ((c == '[' || *t == c1) && glob_match (p, t, 0))
	return 1;
      if (*t++ == '\0')
	return 0;
    }
}

char *xc_gethostname(void)
{
	static struct utsname nts;
	uname(&nts);
	return nts.nodename;
}

#endif
