/*
Copyright (c) 2000-2008, Dirk Krause
All rights reserved.

Redistribution and use in source and binary forms,
with or without modification, are permitted provided
that the following conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.
* Redistributions in binary form must reproduce the above 
  opyright notice, this list of conditions and the following
  disclaimer in the documentation and/or other materials
  provided with the distribution.
* Neither the name of the Dirk Krause nor the names of
  contributors may be used to endorse or promote
  products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/

/**	@file	dktypes.h
	Type definitions for dklibs library set.

	Define data types used by the dklibs library set.
*/

#ifndef DKTYPES_INC

/** Make sure to include the file only once. */
#define DKTYPES_INC 1

#ifndef DKCONFIG_INC
#include <dkconfig.h>
#endif

#include <stdio.h>

#if DK_HAVE_LIMITS_H
#include <limits.h>
#endif
#if DK_HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif

#if DK_HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif

#if DK_HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif

#if DK_HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#else
#if DK_HAVE_WINSOCK2_H
#ifndef WINSOCK2_INCLUDED
#include <winsock2.h>
#define WINSOCK2_INCLUDED 1
#endif
#endif
#endif

#if DK_TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else
#if DK_HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#if DK_HAVE_TIME_H
#include <time.h>
#endif
#endif
#endif
#if DK_HAVE_STDDEF_H
#include <stddef.h>
#endif
#if DK_HAVE_UNISTD_H
#include <unistd.h>
#endif
#if DK_HAVE_DIRECT_H
#include <direct.h>
#endif
#if DK_HAVE_DIRENT_H
#include <dirent.h>
#endif
#if DK_HAVE_DIR_H
#include <dir.h>
#endif
#if DK_HAVE_IO_H
#include <io.h>
#endif
#if DK_HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#if DK_HAVE_FCNTL_H
#include <fcntl.h>
#endif
#if DK_HAVE_TERMIOS_H
#include <termios.h>
#endif
#if DK_HAVE_SYS_TERMIOS_H
#include <sys/termios.h>
#endif
#if DK_HAVE_SYS_TTOLD_H
#include <sys/ttold.h>
#endif
#if DK_HAVE_WINCON_H
#include <wincon.h>
#endif
#if DK_HAVE_WCHAR_H
#include <wchar.h>
#endif
#if DK_HAVE_ZLIB_H
#include <zlib.h>
#endif

#include <dkwin.h>

#if defined(PATH_MAX)
/** Maximum number of characters in file path name. */
#define DK_MAX_PATH (PATH_MAX + 1)
#else
#if defined(MAXPATHLEN)
/** Maximum number of characters in file path name. */
#define DK_MAX_PATH (MAXPATHLEN + 1)
#else
/** Maximum number of characters in file path name. */
#define DK_MAX_PATH 1025
#endif
#endif

/** Maximum value for double variables. */
#define DK_MAX_DOUBLE 1.7e308

#if defined(__BORLANDC__)
/** Specify file access mode. */
typedef int mode_t;
#endif

#if !DK_HAVE_WCHAR_T
#if !DK_HAVE_WCHAR_H
#if !WCHAR_T_DEFINED
/** The wchar_t type is defined now. */
#define WCHAR_T_DEFINED 1
/** Wide character. */
typedef unsigned short wchar_t;
#endif
#endif
#endif

/*
	Simple data types, may be instantiated statically.
*/

/** String is defined as pointer to characters. */
typedef char		*dk_str;

/** Pointer to a string. */
typedef	dk_str		*dk_str_ptr;

/** Byte (signed or unsigned). */
typedef char		dk_byte;

/** Unsigned byte. */
typedef unsigned char	dk_ubyte;

/** Word (2 bytes, signed or unsigned). */
typedef short		dk_word;

/** Unsigned word. */
typedef unsigned short	dk_uword;

/** Double word (4 bytes, signed or unsigned). */
typedef long		dk_dword;

/** Unsigned double word. */
typedef unsigned long	dk_udword;

/* change the following void to int if necessary */

/** Return type of the signal function. */
typedef void		dk_signal_ret_t;

/** Prototype for signal handler function. */
typedef dk_signal_ret_t dk_signal_fct_t DK_PR((int));

/** Data type to establish signal hander. */
typedef dk_signal_fct_t *dk_signal_disp_t;



#if defined(__cplusplus)
extern "C" {
#endif
/** Signal handler function prototype for C++. */
typedef dk_signal_ret_t dk_extc_signal_fct_t DK_PR((int));
#if defined(__cplusplus)
}
#endif
/** Signal handler function data type for C++. */
typedef dk_extc_signal_fct_t *dk_extc_signal_disp_t;



/** String search function prototype. */
typedef	char * dk_fct_type_ss DK_PR((\
void *obj, char *table, char *key, char *def\
));



/** Log function prototype. */
typedef void dk_fct_type_log DK_PR((void *obj, int level, char **ptr, int num));



/**	8 or 4 byte integer (support for long long is required for 8 bytes). */
#if DK_HAVE_LONG_LONG_INT
typedef long long unsigned	dk_long_long_unsigned_t;
#else
typedef long unsigned		dk_long_long_unsigned_t;
#endif

/**	8 or 4 byte unsigned integer. */
#if DK_HAVE_LONG_LONG_INT
typedef long long		dk_long_long_int_t;
#else
typedef long			dk_long_long_int_t;
#endif


/**     Type to hold size of socket address. */
#if DK_HAVE_SOCKLEN_T
#define dk_socklen_t	socklen_t
#else
#if DK_HAVE_SIZE_T
#define dk_socklen_t	size_t
#else
#define dk_socklen_t	unsigned int
#endif
#endif


/**	Result from read() or write(). */
#ifdef _WIN32
#define dk_read_write_t	int
#else
#define dk_read_write_t	ssize_t
#endif


/**	Key/value pair.
	This structure can be used to provide defaults
	for preferences or localized texts.
*/
typedef struct {
  char *key;	/**< Key.	*/
  char *value;	/**< Value.	*/
} dk_key_value_t ;



/**	Retrieve size of key/value pair.
	Return the number of elements in an dk_key_value_t array.
*/
#define DK_KEY_VALUE_ARRAY_SIZE(x) (sizeof(x)/sizeof(dk_key_value_t))



/*
	More complex data types.
	Do not instatiate them statically.
	Use the ...open/new-functions to create them
	dynamically.
*/


/**	Font description.
	This structure can be used to find font names for a font
	in different languages.
*/
typedef struct _dk_font_ {
  char *texname;	/**< Font name in TeX.		*/
  char *psname;		/**< Font name in PostScript.	*/
  int  features;	/**< Font features. I.e. bold, italic... */
  char *svgFontFamily;	/**< Font family name for SVG.	*/
  char *gs_alias;	/**< Font alias name in GhostScript.	*/
  char *gs_actual;	/**< Font file name in GhostScript.	*/
  char *svgFontId;	/**< Font name to use in SVG output.	*/
  char *gs_new;		/**< New GhostScript font name. */
} dk_font_t;



/**	String finder.
	This structure can be used to search for localized strings.
*/
typedef struct {
  char  *key;			/**< Key to look up.		*/
  char **value_pointer;		/**< Pointer to result pointer.	*/
  char  *default_value;		/**< Default value.		*/
} dk_string_finder_t;



/**	Bit field.
	This structure stores an array of bits.
*/
typedef struct {
  unsigned char *data;	/**< Data buffer.		*/
  size_t        bits;	/**< Number of bits in array.	*/
} dk_bitfield_t ;



/**	Bit matrix.
	This structure stores a matrix of bits.
*/
typedef struct {
  unsigned char **data;	/**< Data buffer.			*/
  size_t	c;	/**< Number of columns in matrix.	*/
  size_t	r;	/**< Number of rows in matrix.		*/
} dk_bitmatrix_t;



/**	File status information.
	This structure can be used to obtain information
	about a file status.
*/
typedef struct {

#if VERSION_BEFORE_2009_01_27

#if DK_HAVE_SYS_STAT_H
#if DK_HAVE_STAT
  struct stat st;	/**< A struct stat.	*/
#else
#if DK_HAVE__STAT
  struct _stat st;	/**< A struct _stat. */
#endif
#endif
#if DK_HAVE_LSTAT
  struct stat lst;	/**< A struct stat for lstat(). */
#endif
#endif

#endif

  int permissions;	/**< File permissions. */
  int filetype;		/**< File type. */
  unsigned long inode_number;	/**< Inode number. */
  unsigned long device_number;	/**< Device number. */
  unsigned long rdevice_number;	/**< Relative device number. */
  unsigned long number_of_links;	/**< Number of links. */
  dk_long_long_unsigned_t   size;	/**< File size. */
  int      size_math_error;	/**< Math error in file size. */
  long     uid;		/**< Owner UID. */
  long     gid;		/**< Owner GID. */
  char ctime[24];	/**< Creation time as text. */
  char atime[24];	/**< Last access time. */
  char mtime[24];	/**< Modification time. */
  short	is_far_link;	/**< Flag to indicate link outside file system. */
  struct tm ori_ctime;	/**< ctime. */
  struct tm ori_atime;	/**< atime. */
  struct tm ori_mtime;	/**< mtime. */
  unsigned char ud;	/**< Flag: Link owner different from file owner. */
  unsigned char gd;	/**< Flag: Link owner group differs. */
} dk_stat_t;



/**	Directory traversal.
	This structure can be used to traverse a directory.
	You must not modify the directory while traversing it.
*/
typedef struct {
  char *dirname;	/**< Directory name. */
  char *shortname;	/**< Short file name of current file. */
  char *fullname;	/**< Full file name of current file found. */
  dk_stat_t stbuf;	/**< File status. */
  int  state;		/**< Current state of traversal. */
  long maxpathlen;	/**< Largest file name length. */
  int  error_code;	/**< Last error occured. */
#if defined(WIN32) || defined(_WIN32)
/* + Win32 */
#if DK_HAVE__FINDFIRST64
/* Win32, _findfirst64 */
  long			hFile64;	/**< 64 bit file handle. */
  struct __finddata64_t	fdt64;		/**< 64 bit find data structure. */
#else
#if DK_HAVE__FINDFIRST32
/* Win32, _findfirst32 */
  long			hFile32;	/**< 32 bit file handle. */
  struct __finddata32_t	fdt32;		/**< 32 bit find data structure. */
#else
#if DK_HAVE__FINDFIRST
/* Win32, _findfirst */
  long			hFile;		/**< File handle (16 bit?). */
  struct _finddata_t	fdt;		/**< Find data structure (16 bit?). */
#endif
#endif
#endif
/* - Win32 */
#else
#if DK_HAVE_FINDFIRST
/* DOS, findfirst */
  struct ffblk		ffblk;		/**< DOS find first block. */
#else
#if DK_HAVE_DIRENT_H
/* UNIX/Linux, dirent */
  DIR			*dir;		/**< UNIX/Linux directory. */
#else
/* any unknown directory listing mechanism */
#endif
#endif
#endif

} dk_dir_t;



/**	File name expander.
	This structure can be used on DOS/Windows to expand file
	names containing wildcards.
*/
typedef dk_dir_t dk_fne_t ;



/**	Logging structure (obsoleted). */
typedef struct {
	void	*obj;		/**< Handler object */
	dk_fct_type_log *fct;	/**< Handler function */
	int	level;		/**< Required priority of message */
	int	maxlevel;	/**< Maximum received priority */
} dk_log_t;



/**	String search structure (obsoleted). */
typedef struct {
	void	*obj;		/**< Handler object */
	dk_fct_type_ss	*fct;	/**< Handler function */
} dk_ss_t;



/**	Internal API for dk_stream_t.
	This structure is used internally by the dkstream module
	to provide data to the low-level functions.
*/
typedef struct {
  int cmd;		/**< Command type.	*/
  /** Command parameters. Passed to low-level function. */
  struct {
    char   *buffer;	/**< Buffer pointer. */
    size_t length;	/**< Buffer length. */
    int cmd;		/**< Sub-command. */
  } params;
  /** Command results. Filled by low-level function. */
  struct {
    char   *buffer;	/**< Buffer pointer. */
    size_t length;	/**< Buffer length. */
    size_t used;	/**< Number of bytes used in buffer. */
  } results;
  int return_value;	/**< Command result to return. */
  int error_code;	/**< Last error occured. */
  void *strm;		/**< Data for low-level function. I.e. FILE *... */
} dk_stream_api_t;



/**	Low-level function prototype.
*/
typedef void dk_stream_fct_t DK_PR((dk_stream_api_t *api));



/**	I/O stream.
	This structure provides a generic API for I/O operations.
*/
typedef struct {
  dk_stream_api_t api;		/**< Data exchange with low-level function */
  void            *data;	/**< Stream target. I.e. FILE *... */
  dk_stream_fct_t *fct;		/**< Low-level function. */
  unsigned long bytes;		/**< Number of bytes written to the stream. */
  int flags;			/**< Bit flags, used by Perl XS . */
  int opt;			/**< Options. */
} dk_stream_t;



/**	I/O stream wrapper for Perl XS.
	Perl XS needs additional information whether or not the stream
	must be closed by the DESTROY method.
*/
typedef struct {
  dk_stream_t	*s;	/**< The stream. */
  int		 flags;	/**< The state of the stream. */
} dk_stream_wrapper_t;



#if 0
/**	Encoder on top of stream (obsoleted).
*/
typedef struct {
  dk_stream_t *target;
  char *rlbuffer;
  char *flate_inbuffer;
  char *flate_outbuffer;
  int  flags;
  size_t rlb_size;
  size_t fib_size;
  size_t fob_size;
} dk_output_encoder_t;
#endif


/**	Prototype of function to open a stream.  */
typedef dk_stream_t *
dk_stream_open_fct_t DK_PR((char *name, char *mode, int ign, int *reason));



/**	File suffix table entry.
	This structure can be used to specify a stream opener function
	for a file name suffix.
*/
typedef struct {
  char *suffix;			/**< The file name suffix. I.e. ".gz". */
  dk_stream_open_fct_t *fct;	/**< The function to open a stream. */
} dk_stream_suffix_t;



/**	Internal node for dk_storage_t.
	This structure is used internally by the dksto module.
*/
struct _dk_storage_node {
  struct _dk_storage_node *p;	/**< Parent node in tree. */
  struct _dk_storage_node *l;	/**< Left son or preceeding node. */
  struct _dk_storage_node *r;	/**< Right son or following node. */
  short                    b;	/**< Balance flags in trees. */
  short                    w;	/**< Direction to walk. */
  void                    *o;	/**< Object to store. */
  /** Object evaluation. */
  union {
    char c;		/**< Character evaluation of object. */
    unsigned char uc;	/**< Unsigned character evaluation. */
    short s;		/**< Short evaluation. */
    unsigned short us;	/**< Unsigned short evaluation. */
    int i;		/**< Integer evaluation. */
    unsigned int ui;	/**< Unsigned integer evaluation. */
    long l;		/**< Long evaluation. */
    unsigned long ul;	/**< Unsigned long evaluation. */
    float f;		/**< Float evaluation. */
    double d;		/**< Double evaluation. */
  } v;
};

/** Internal node for dk_storage_t. */
typedef struct _dk_storage_node dk_storage_node_t;

/** Pointer to internal node for dk_storage_t. */
typedef dk_storage_node_t *dk_storage_node_p;



/**	Evaluation functions.
	These function type are used to evaluate and compare objects
	stored in a sorted dk_storage_t.
*/

/** Object evaluation function. */
typedef char dk_fct_eval_c_t(void *obj, int crit);

/** Object evaluation function. */
typedef unsigned char dk_fct_eval_uc_t(void *obj, int crit);

/** Object evaluation function. */
typedef short dk_fct_eval_s_t(void *obj, int crit);

/** Object evaluation function. */
typedef unsigned short dk_fct_eval_us_t(void *obj, int crit);

/** Object evaluation function. */
typedef int dk_fct_eval_i_t(void *obj, int crit);

/** Object evaluation function. */
typedef unsigned int dk_fct_eval_ui_t(void *obj, int crit);

/** Object evaluation function. */
typedef long dk_fct_eval_l_t(void *obj, int crit);

/** Object evaluation function. */
typedef unsigned long dk_fct_eval_ul_t(void *obj, int crit);

/** Object evaluation function. */
typedef float dk_fct_eval_f_t(void *obj, int crit);

/** Object evaluation function. */
typedef double dk_fct_eval_d_t(void *obj, int crit);

/** Object comparison function. */
typedef int dk_fct_comp_t(void *o1, void *o2, int crit);



/**	Object storage.
	A storage can be used to store pointers to objects.
*/
typedef struct {
  dk_storage_node_p *d;	/**< Critical path for delete operations. */
  short              l;	/**< Path length of critical path (buffer size). */
  dk_storage_node_t *r; /**< The trees root element, lists left. */
  int 		     h;	/**< Comparison/evaluation algorithm. */
  int                c;	/**< Comparison/evaluation criteria. */
  int		     t;	/**< Flag: tree or sorted list. */
  /** Comparison or evaluation function. */
  union {
    dk_fct_eval_c_t *c;
    dk_fct_eval_uc_t *uc;
    dk_fct_eval_s_t *s;
    dk_fct_eval_us_t *us;
    dk_fct_eval_i_t *i;
    dk_fct_eval_ui_t *ui;
    dk_fct_eval_l_t *l;
    dk_fct_eval_ul_t*ul;
    dk_fct_eval_f_t *f;
    dk_fct_eval_d_t *d;
    dk_fct_comp_t *comp;
  } e;
  void              *i;	/**< Double linked list of iterators. */
} dk_storage_t;



/**	Storage iterator.
	This structure can be used to iterate through a dk_storage_t.
*/
struct _dk_storage_iterator {
  struct _dk_storage_iterator *l;	/**< Preceeding iterator. */
  struct _dk_storage_iterator *r;	/**< Following iterator. */
  dk_storage_t                *s;	/**< Storage the iterator belongs to. */
  dk_storage_node_t           *c;	/**< Current storage node. */
};
/**	Storage iterator. Can be used to iterate through a dk_storage_t. */
typedef struct _dk_storage_iterator dk_storage_iterator_t;



/**	String table.
	This structure can be used to read a binary string table.
*/
typedef struct {
  dk_uword	  vers_major;	/**< Major version number. */
  dk_uword	  vers_minor;	/**< Minor version number. */
  dk_uword	  elems;	/**< Number of elements in table. */
  char		**keys;		/**< Array of keys. */
  char		**values;	/**< Array of values. */
} dk_stt_t;



/**	Preference.
	This structure stores a preference key/value pair.
*/
typedef struct {
  char *n;		/**< Name. */
  char *v;		/**< Value. */
  int   p;		/**< Priority: user=4, app=2, host=1 or combined. */
} dk_preference_t;




/**	Command line application.
	This structure stores data for applications.
*/
typedef struct {
  struct {
    struct {
      int    argc;	/**< Number of arguments. */
      char **argv;	/**< Pointer to first argument. */
    } o;	/**< Original command line arguments. */
    struct {
      int    argc;	/**< Number of arguments. */
      char **argv;	/**< Pointer to first argument. */
    } a;	/**< Command line arguments without preferences. */
  } a;	/**< Copy of command line arguments. */
  struct {
    char *u;            /**< User login name. */
    char *a;            /**< Application name. */
    char *h;            /**< Host name. */
    char *g;		/**< Program group or package name. */
  } n;	/**< Names often needed. */
  struct {
    char *h;            /**< Users home directory. */
    char *t;            /**< Temporary directory. */
    char *a;            /**< Application directory. */
    char *s;            /**< Shared directory. */
    char *pt;		/**< Processes temporary directory. */
    char *etc;		/**< etc directory. */
  } d;	/**< Directories often needed. */
  struct {
    /** Command line preferences. */
    dk_storage_t *c;
    dk_storage_iterator_t *ci;
    /** Applications self-set preferences. */
    dk_storage_t *a;
    dk_storage_iterator_t *ai;
#if DK_HAVE_WINREG_H
    /** Windows registry access. */
    int what;
    HKEY hklm_all;
    HKEY hklm_app;
    HKEY hkcu_all;
    HKEY hkcu_app;
#else
    /** Preferences set by system (storage). */
    dk_storage_t *s;
    /** Preferences set by system (storage iterator). */
    dk_storage_iterator_t *si;
    /** Preferences set by user (storage). */
    dk_storage_t *u;
    /** Preferences set by user (storage iterator). */
    dk_storage_iterator_t *ui;
#endif
    int unc;		/**< Flag: unconfigure application. */
    int prf;		/**< Flag: preferences were set. */
  } p;	/**< Preferences management */
  struct {
    char *f;		/**< Executable file name. */
    char *d;		/**< Executable directory. */
  } x;	/**< Information about the executable. */
  struct {
    int max;		/**< Maximum priority occured so far. */
    int nostdio;	/**< Flag: no logging to stdout/stderr. */
    struct {
      int m;		/**< Minimum priority required. */
      int f;		/**< Flag: 1=date+time, 2=split. */
      unsigned char *c;	/**< Codepage for output. */
      int ide_type;	/**< IDE type. */
    } o;	/**< Logging to stdout. */
    struct {
      int m;		/**< Minimum priority required. */
      int f;		/**< Flag: 1=date+time, 2=split. */
      unsigned char *c;	/**< Codepage for output. */
      int ide_type;	/**< IDE type. */
    } e;	/**< Logging to stderr. */
    struct {
      int m;		/**< Minimum priority required. */
      int k;		/**< Minimum priority required to keep log file */
      int f;		/**< Flag: 1=date+time, 2=split. */
      FILE *t;		/**< Output file. */
      char *n;		/**< Output file name. */
      unsigned char *c;	/**< Codepage for output. */
      int ide_type;	/**< IDE type. */
    } f;	/**< Logging to file. */
#if DK_HAVE_SYSLOG
    struct {
      int m;		/**< Minimum priority required. */
      char *i;		/**< Ident argument to openlog(). */
      int f;		/**< Log facility. */
      int o;		/**< Flag: 1=syslog opened, 0=not opened. */
    } s;	/**< Logging to syslog. */
#endif
    struct {
      char *n;			/**< Input file name. */
      unsigned long lineno;	/**< Line number of error. */
    } ef;	/**< Error reporting (error source). */
  } l;	/**< Logging. */
  struct {
    char *l;		/**< Language. */
    char *r;		/**< Region. */
    char *e;		/**< Encoding. */
    dk_storage_t *s;	/**< String tables storage */
    dk_storage_iterator_t *si;	/**< String tables storage iterator. */
    int   es;		/**< Encoding short. */
  } loc;	/**< Localization. */
  struct {
    unsigned long l;	/**< Number of next file. */
  } td;	/**< Data related to temporary file names. */
  struct {
    int prng_type;		/**< Type of PRNG found. */
    char *seed_file_name;	/**< File name to save seed. */
  } random;	/**< Random number generation. */
  int relaxed_fopen_check;	/**< Security checks. */
  int relaxed_fopen_reason;	/**< Failed security checks. */
  int keep_temp_dir;	/**< Message level required to keep temp dir. */
} dk_app_t;


/**	Tokenizer function.
	A function to split data into tokens.
*/
#if DK_HAVE_PROTOTYPES
typedef int dk_fct_tokenizer(void *data, void *tok, char *s, int *err);
#else
typedef int dk_fct_tokenizer();
#endif



/**	Tokenizer.
	This structure can be used to split input into a sequence
	of tokens.
*/
typedef struct {
  char *token_buffer;		/**< Buffer for token. */
  size_t buffer_size;		/**< Buffer size for token. */
  size_t buffer_used;		/**< Number of bytes used in token buffer. */
  char **quotes;		/**< Pairs of opening and closing quotes. */
  char  *sct;			/**< Single character tokens. */
  char  *whsp;			/**< Whitespaces. */
  char  *nl;			/**< Newlines. */
  char   comment;		/**< Comment introducer. */
  char  *endquote;		/**< This ends the current quote. */
  int    error_code;		/**< Last error occured. */
  dk_fct_tokenizer *fct;	/**< Function to process a token. */
  void  *user_data;		/**< Additional data for function. */
  int    state;			/**< Current state of the tokenizer. */
  unsigned long lineno;		/**< Line number in input file. */
} dk_tokenizer_t ;



/**	Output filter cell.
	Several cells can be combined.
*/
typedef struct {
  int what;		/**< Type of cell. */
  union {
    struct {
      char *buffer;		/**< Pointer to buffer. */
      size_t lgt;		/**< Size of buffer. */
      size_t used;		/**< Number of bytes used in buffer. */
    } b;		/**< Details for buffered output. */
    struct {
      unsigned long a85val;	/**< Current numeric value. */
      size_t used;		/**< Number of bytes stored in current value. */
      size_t linepos;		/**< Position in output line. */
      size_t maxlinepos;	/**< Maximum output line length. */
      int      fl;		/**< Flag: 1=append finalizer. */
    } a85;		/**< Details for ASCII-85-encoding. */
    struct {
      size_t linepos;		/**< Position in output line. */
      size_t maxlinepos;	/**< Maximum output line length. */
      int      fl;		/**< Flag:  1=append finalizer. */
    } ah;		/**< Details for ASCII-Hex-encoding. */
    struct {
      char *buffer;		/**< Output buffer. */
      char lc;			/**< Previous character. */
      size_t used;		/**< Characters in buffer. */
      int st;			/**< Current run-length compression state. */
    } rl;		/**< Details for run-length compression. */
#if DK_HAVE_ZLIB_H
    struct {
      z_stream *zs;		/**< GZIP output struct. */
      Bytef *ibuffer;		/**< Buffer to pass data to GZIP. */
      uLong i_length;		/**< Buffer length. */
      Bytef *obuffer;		/**< Buffer to get data from GZIP. */
      uLong o_length;		/**< Buffer length. */
      uLong used;		/**< Number of bytes used. */
      int   stillok;		/**< Flag: can continue. */
    } flate;		/**< Details for flate compression. */
#endif
  } c;			/**< Cell details. */
} dk_of_cell_t;



/**	Output filter.
	This structure is the data component of an output
	filtering stream.
*/
typedef struct {
  int flags;			/**< Flags. */
  dk_stream_t	*target;	/**< Stream for real output. */
  dk_of_cell_t	*cells;		/**< Pointer to array of filtering cells. */
  int		 n_of_cells;	/**< Number of filtering cells. */
  int		 have_data;	/**< Flag: Already have data. */
} dk_of_t;



/**	Bit shifter.
	This function can be used for bit-wise output.
*/
typedef struct {
  dk_stream_t	*t;		/**< Output stream. */
  unsigned char	c;		/**< Combination of previous bits. */
  unsigned short	b;	/**< Number of bits in c. */
} dk_bitshift_t;



/**	Perl XS wrapper for dk_bitshift_t.
	Perl XS needs to know whether or not to close the
	dk_bitshift_t during DESTROY.
*/
typedef struct {
  dk_bitshift_t	*t;		/**< Bit shifter. */
  int		flags;		/**< Flag for close operation. */
} dk_bitshift_wrapper_t;



/**	LaTeX representation of a character.
*/
typedef struct {
  char *t;	/**< Representation when in text mode. */
  char *m;	/**< Representation when in math mode. */
  char *a;	/**< Representation in all modes. */
} dk_le_ct_t;



/**	LaTeX encoding table.
*/
typedef struct {
  char *dirname;		/**< Directory containing converstion tables. */
  char *filename;		/**< Buffer to construct temporary file name. */
  int  flags;			/**< Flags. */
  int  error_code;		/**< Last error occured. */
  unsigned long error_line;	/**< Last error position (line number) */
  unsigned long cache_element;	/**< Number of element in cache. */
  dk_le_ct_t   *cache_ptr;	/**< Pointer to character representation. */
  void *data;			/**< Data pointer. */
} dk_le_t;



/**	Perl XS wrapper for dk_le_t.
	Perl XS needs to know, whether or not to close the dk_le_t
	during DESTROY.
*/
typedef struct {
  dk_le_t	*l;		/**< LaTeX encoding table. */
  int		 flags;		/**< Close flag. */
} dk_le_wrapper_t;

#if DK_HAVE_SYS_SOCKET_H || DK_HAVE_WINSOCK2_H



/**	IP address.
*/
typedef struct {
  int what;			/**< Type of address. */
  struct {
    struct sockaddr_in sin;	/**< IP of host. */
    unsigned short portmin;	/**< Minimum port number. */
    unsigned short portmax;	/**< Maximum port number. */
  } ip4;			/**< IP address data */
} dk_ip_addr_t;



/**	TCP end point.
*/
typedef struct {
  int state;		/**< Current state. */
  int flags;		/**< Flags. */
#if DK_HAVE_WINSOCK2_H
  SOCKET s;		/**< Low-level socket. */
#else
  int s;		/**< Low-level socket. */
#endif
  struct {
    struct {
      dk_ip_addr_t w;	/**< Wished. */
      dk_ip_addr_t f;	/**< Found. */
    } l;		/**< Local addresses. */
    struct {
      dk_ip_addr_t w;	/**< Wished. */
      dk_ip_addr_t f;	/**< Found. */
    } r;		/**< Remote addresses. */
  } a;			/**< Addresses. */
  struct {
    time_t seconds;	/**< Seconds in timeout. */
    long   usecs;	/**< Microseconds in timeout. */
  } to;			/**< Timeout. **/
  int error_code;	/**< Last error occured. */
} dk_tcpip_t;


/**	Terminal echo handling.
*/
typedef struct {
  int			is_tty;		/**< Flag, stdin is terminal*/
#if DK_HAVE_TCGETATTR
  struct termios	ori;		/**< Original behaviour. */
#else
#if defined(TCGETS)
  struct termios	ori;		/**< Original behaviour. */
#else
#if DK_HAVE_GETSTDHANDLE
  HANDLE		consoleHandle;	/**< Console handle. */
  DWORD			ori;		/**< Original behaviour. */
#else
  unsigned long		dummy;		/**< Dummy variable. */
#endif
#endif
#endif
} dk_echo_t;



/**	One replacement candidate for a font.
*/
typedef struct _font_replacement_ {
  char			*n;	/**< Font name. */
  char			*f;	/**< Font family. */
  char			*l;	/**< Font location. */
  char			*s;	/**< Font source name. */
  char			*ft;	/**< Font type. */
  char			*tn;	/**< Font name for TeX. */
  char			*pl;	/**< PFB location. */
  char			*ps;	/**< PFB source. */
  char			*tl;	/**< TTF location. */
  char			*ts;	/**< TTF source. */
  dk_storage_t		*d;	/**< Driver names storage. */
  dk_storage_iterator_t	*di;	/**< Driver names storage iterator. */
  int			 ff;	/**< Font features. */
  int			 t;	/**< Font type. */
  unsigned long		 num;	/**< Number in order of appearance in the file. */
} dk_font_replacement_t;



/**	All replacement candidates for one font.
*/
typedef struct _one_font_mapping {
  dk_storage_t		*r;		/**< Candidates storage by priority. */
  dk_storage_iterator_t	*ri;		/**< Candidates storage iterator */
  dk_storage_t		*byname;	/**< Candidates storage by name. */
  dk_storage_iterator_t	*bynamei;	/**< Candidates storage iterator. */
  unsigned char		 used;		/**< Flag: font is used. */
  size_t		 noe;		/**< Number of entries. */
} dk_one_font_mapping_t;



/**	Complete replacement set as obtained from file.
*/
typedef struct _font_mapping_ {
  dk_one_font_mapping_t	*m;		/**< Pointer to array of 35 elements. */
  dk_storage_t		*d;		/**< Driver names storage. */
  dk_storage_iterator_t	*di;		/**< Driver names storage iterator. */
  int			 error_code;	/**< Last error occured. */
  unsigned long		 err_lineno;	/**< Line number where error occured. */
} dk_font_mapping_t;



/*
 * For Perl XS
 */
/** Perl XS wrapper data type definition. */
typedef dk_bitfield_t		*DKrause__BitField;
/** Perl XS wrapper data type definition. */
typedef dk_bitmatrix_t		*DKrause__BitMatrix;
/** Perl XS wrapper data type definition. */
typedef dk_stream_wrapper_t	*DKrause__Stream;
/** Perl XS wrapper data type definition. */
typedef dk_bitshift_wrapper_t	*DKrause__BitStream;
/** Perl XS wrapper data type definition. */
typedef dk_stt_t		*DKrause__StringTable;
/** Perl XS wrapper data type definition. */
typedef dk_app_t		*DKrause__Application;
/** Perl XS wrapper data type definition. */
typedef dk_tokenizer_t		*DKrause__Tokenizer;
/** Perl XS wrapper data type definition. */
typedef dk_le_wrapper_t		*DKrause__LaTeXEncoder;

#endif

#if DK_HAVE_LONG_LONG_INT
/** Maximum value for long long unsigned. */
#define DK_MAX_LONG_LONG_UNSIGNED 0xFFFFFFFFFFFFFFFFULL
/** Maximum value for long long. */
#define DK_MAX_LONG_LONG_INT	  0x7FFFFFFFFFFFFFFFLL
/** (long long unsigned)0. */
#define DK_ZERO_LONG_LONG_UNSIGNED 0ULL
/** (long long)0. */
#define DK_ZERO_LONG_LONG_INT      0LL
/** (long long unsigned)1. */
#define DK_ONE_LONG_LONG_UNSIGNED  1ULL
/** (long long)1. */
#define DK_ONE_LONG_LONG_INT       1LL
#else
/** Maximum value for long long unsigned. */
#define DK_MAX_LONG_LONG_UNSIGNED 0xFFFFFFFFUL
/** Maximum value for long long. */
#define DK_MAX_LONG_LONG_INT	  0x7FFFFFFFL
/** (long long unsigne)0. */
#define DK_ZERO_LONG_LONG_UNSIGNED 0UL
/** (long long)0. */
#define DK_ZERO_LONG_LONG_INT      0L
/** (long long unsigned)1. */
#define DK_ONE_LONG_LONG_UNSIGNED  1UL
/** (long long)1. */
#define DK_ONE_LONG_LONG_INT       1L
#endif

#if SIZEOF_LONG == 8
/** Maximum value for unsigned long. */
#define DK_MAX_ULONG	(0xFFFFFFFFFFFFFFFFUL)
/** Maximum value for long. */
#define DK_MAX_LONG	(0x7FFFFFFFFFFFFFFFL)
#else
/** Maximum value for unsigned long. */
#define DK_MAX_ULONG	(0xFFFFFFFFUL)
/** Maximum value for long. */
#define DK_MAX_LONG	(0x7FFFFFFFL)
#endif

#if SIZEOF_INT == 4
/** Maximum value for unsigned. */
#define DK_MAX_UNSIGNED	(0xFFFFFFFFU)
/** Maximum value for int. */
#define DK_MAX_INT	(0x7FFFFFFF)
#else
/** Maximum value for unsigned. */
#define DK_MAX_UNSIGNED	(0xFFFFU)
/** Maximum value for int. */
#define DK_MAX_INT	(0x7FFF)
#endif

#if SIZEOF_SHORT == 4
/** Maximum number for unsigned short. */
#define DK_MAX_USHORT	(0xFFFFFFFFU)
/** Maximum number for short. */
#define DK_MAX_SHORT	(0x7FFFFFFF)
#else
/** Maximum number for unsigned short. */
#define DK_MAX_USHORT	(0xFFFFU)
/** Maximum number for short. */
#define DK_MAX_SHORT	(0x7FFF)
#endif

#if SIZEOF_SIZE_T == 2
/** Maximum value for size_t. */
#define DK_MAX_SIZE_T	0xFFFFU
#else
#if SIZEOF_SIZE_T == 4
/** Maximum value for size_t. */
#define DK_MAX_SIZE_T	0xFFFFFFFFUL
#else
#if SIZEOF_SIZE_T == 8
/** Maximum value for size_t. */
#define DK_MAX_SIZE_T	0xFFFFFFFFFFFFFFFFULL
#endif
#endif
#endif

/** Use default (non UTF-8) encoding. */
#define DK_APP_ENCODING_DEFAULT 0

/** Use UTF-8 encoding. */
#define DK_APP_ENCODING_UTF8	1

#endif

