#ifndef VGAGAMES4_H_
#define VGAGAMES4_H_

##VGAG_VERSION##
##VGAG_PREFIX##

# ifdef __cplusplus
extern "C" {
# endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdarg.h>


/* ++++++++++++++++++++++++++++++++++++ */
/* +++ definitions and enumerations +++ */
/* ++++++++++++++++++++++++++++++++++++ */

/* boolean */
typedef int VG_BOOL;
enum { VG_FALSE = 0, VG_TRUE = 1 };

/* window size enumeration */
typedef enum {
  VG_WINDOW_SIZE_LOW = 1,  /* 320x200x32 or 320x240x32 */
  VG_WINDOW_SIZE_HIGH,     /* 640x480x32 or 800x600x32 */
} VG_WINDOW_SIZES;

/* window scaling enumeration */
typedef enum {
  VG_WINDOW_SCALE_NONE = 0,  /* no scaling */
  VG_WINDOW_SCALE_BEST,      /* best integer scaling */
  VG_WINDOW_SCALE_MAX,       /* maximize window */
  VG_WINDOW_SCALE_FULL,      /* fullscreen */
} VG_WINDOW_SCALES;

/* axes */
typedef enum {
  VG_AXE_NONE = 0,    /* default */
  VG_AXE_HORIZONTAL,  /* horizontal axe */
  VG_AXE_VERTICAL,    /* vertical axe */
} VG_AXES;

/* color enumeration */
#define VG_COLOR_RGB(RED, GREEN, BLUE) (int)((((RED) & 0xff) << 16) | (((GREEN) & 0xff) << 8) | ((BLUE) & 0xff))
typedef enum {
  VG_COLOR_TRANSPARENT     = -1,
  VG_COLOR_BLACK           = 0x000000,
  VG_COLOR_WHITE           = 0xffffff,
  VG_COLOR_RED             = 0xff0000,
  VG_COLOR_REDORANGE       = 0xff8000,
  VG_COLOR_ORANGE          = 0xffa000,
  VG_COLOR_YELLOWORANGE    = 0xffc000,
  VG_COLOR_YELLOW          = 0xffff00,
  VG_COLOR_YELLOWGREEN     = 0xb0ff00,
  VG_COLOR_GREEN           = 0x00ff00,
  VG_COLOR_TURQUOISEGREEN  = 0x00ff90,
  VG_COLOR_TURQUOISE       = 0x00ffff,
  VG_COLOR_TURQUOISEBLUE   = 0x00a8ff,
  VG_COLOR_BLUE            = 0x0000ff,
  VG_COLOR_BLUEVIOLET      = 0xa000ff,
  VG_COLOR_VIOLET          = 0xff00ff,
  VG_COLOR_REDVIOLET       = 0xff00a0,
  VG_COLOR_PINK            = 0xff69b4,
  VG_COLOR_BROWN           = 0x8b4527,
} VG_COLORS;

/* position enumeration */
typedef enum {
  VG_POS_UPPER_LEFT = 1,  /* upper left corner */
  VG_POS_UPPER_RIGHT,     /* upper right corner */
  VG_POS_LOWER_LEFT,      /* lower left corner */
  VG_POS_LOWER_RIGHT,     /* lower right corner */
  VG_POS_CENTERED,        /* centered */
} VG_POSITIONS;

/* text orientation enumeration */
typedef enum {
  VG_ORI_LEFT = 1,  /* left orientated */
  VG_ORI_CENTER,    /* centered */
  VG_ORI_RIGHT,     /* right orientated */
  VG_ORI_BLOCK,     /* justified */
} VG_ORIENTATIONS;


/* keyboard and gamecontroller scancodes */

#define VG_INPUT_NOKEY            0
#define VG_INPUT_STARTKEY         0
#define VG_INPUT_STARTGCBUTTON    (VG_INPUT_STARTKEY + 256)
#define VG_INPUT_STARTGCAXIS      (VG_INPUT_STARTGCBUTTON + 32)

typedef enum {  /* keyboard key-codes */
  /* escape */
  VG_INPUT_KBDCODE_ESCAPE = VG_INPUT_STARTKEY + 1,
  /* main keyboard */
  VG_INPUT_KBDCODE_GRAVE,
  VG_INPUT_KBDCODE_1,
  VG_INPUT_KBDCODE_2,
  VG_INPUT_KBDCODE_3,
  VG_INPUT_KBDCODE_4,
  VG_INPUT_KBDCODE_5,
  VG_INPUT_KBDCODE_6,
  VG_INPUT_KBDCODE_7,
  VG_INPUT_KBDCODE_8,
  VG_INPUT_KBDCODE_9,
  VG_INPUT_KBDCODE_0,
  VG_INPUT_KBDCODE_MINUS,
  VG_INPUT_KBDCODE_EQUALS,
  VG_INPUT_KBDCODE_BACKSPACE,
  VG_INPUT_KBDCODE_TAB,
  VG_INPUT_KBDCODE_Q,
  VG_INPUT_KBDCODE_W,
  VG_INPUT_KBDCODE_E,
  VG_INPUT_KBDCODE_R,
  VG_INPUT_KBDCODE_T,
  VG_INPUT_KBDCODE_Y,
  VG_INPUT_KBDCODE_U,
  VG_INPUT_KBDCODE_I,
  VG_INPUT_KBDCODE_O,
  VG_INPUT_KBDCODE_P,
  VG_INPUT_KBDCODE_LEFTBRACKET,
  VG_INPUT_KBDCODE_RIGHTBRACKET,
  VG_INPUT_KBDCODE_BACKSLASH,
  VG_INPUT_KBDCODE_CAPSLOCK,
  VG_INPUT_KBDCODE_A,
  VG_INPUT_KBDCODE_S,
  VG_INPUT_KBDCODE_D,
  VG_INPUT_KBDCODE_F,
  VG_INPUT_KBDCODE_G,
  VG_INPUT_KBDCODE_H,
  VG_INPUT_KBDCODE_J,
  VG_INPUT_KBDCODE_K,
  VG_INPUT_KBDCODE_L,
  VG_INPUT_KBDCODE_SEMICOLON,
  VG_INPUT_KBDCODE_APOSTROPHE,
  VG_INPUT_KBDCODE_RETURN,
  VG_INPUT_KBDCODE_LSHIFT,
  VG_INPUT_KBDCODE_Z,
  VG_INPUT_KBDCODE_X,
  VG_INPUT_KBDCODE_C,
  VG_INPUT_KBDCODE_V,
  VG_INPUT_KBDCODE_B,
  VG_INPUT_KBDCODE_N,
  VG_INPUT_KBDCODE_M,
  VG_INPUT_KBDCODE_COMMA,
  VG_INPUT_KBDCODE_PERIOD,
  VG_INPUT_KBDCODE_SLASH,
  VG_INPUT_KBDCODE_RSHIFT,
  VG_INPUT_KBDCODE_LCTRL,
  VG_INPUT_KBDCODE_LGUI,
  VG_INPUT_KBDCODE_LALT,
  VG_INPUT_KBDCODE_SPACE,
  VG_INPUT_KBDCODE_RALT,
  VG_INPUT_KBDCODE_RGUI,
  VG_INPUT_KBDCODE_APPLICATION,
  VG_INPUT_KBDCODE_RCTRL,
  /* additional keys */
  VG_INPUT_KBDCODE_LCURS,
  VG_INPUT_KBDCODE_RCURS,
  VG_INPUT_KBDCODE_UCURS,
  VG_INPUT_KBDCODE_DCURS,
  VG_INPUT_KBDCODE_INSERT,
  VG_INPUT_KBDCODE_HOME,
  VG_INPUT_KBDCODE_PGUP,
  VG_INPUT_KBDCODE_DELETE,
  VG_INPUT_KBDCODE_END,
  VG_INPUT_KBDCODE_PGDOWN,
  /* keypad */
  VG_INPUT_KBDCODE_KP_0,
  VG_INPUT_KBDCODE_KP_1,
  VG_INPUT_KBDCODE_KP_2,
  VG_INPUT_KBDCODE_KP_3,
  VG_INPUT_KBDCODE_KP_4,
  VG_INPUT_KBDCODE_KP_5,
  VG_INPUT_KBDCODE_KP_6,
  VG_INPUT_KBDCODE_KP_7,
  VG_INPUT_KBDCODE_KP_8,
  VG_INPUT_KBDCODE_KP_9,
  VG_INPUT_KBDCODE_KP_ENTER,
  /* function keys */
  VG_INPUT_KBDCODE_F1,
  VG_INPUT_KBDCODE_F2,
  VG_INPUT_KBDCODE_F3,
  VG_INPUT_KBDCODE_F4,
  VG_INPUT_KBDCODE_F5,
  VG_INPUT_KBDCODE_F6,
  VG_INPUT_KBDCODE_F7,
  VG_INPUT_KBDCODE_F8,
  VG_INPUT_KBDCODE_F9,
  VG_INPUT_KBDCODE_F10,
  VG_INPUT_KBDCODE_F11,
  VG_INPUT_KBDCODE_F12,
  /* last entry */
  VG_INPUT_KBDCODE_MAXENUM
} VG_INPUT_KBDCODES;

typedef enum {  /* gamecontroller button key-codes */
  VG_INPUT_GCBUTTON_A = VG_INPUT_STARTGCBUTTON + 1,  /* A-Button: right button-cross: down */
  VG_INPUT_GCBUTTON_B,                               /* B-Button: right button-cross: right */
  VG_INPUT_GCBUTTON_X,                               /* X-Button: right button-cross: left */
  VG_INPUT_GCBUTTON_Y,                               /* Y-Button: right button-cross: up */
  VG_INPUT_GCBUTTON_BACK,                            /* Back-Button: middle left */
  VG_INPUT_GCBUTTON_GUIDE,                           /* Guide-Button: middle */
  VG_INPUT_GCBUTTON_START,                           /* Start-Button: middle right */
  VG_INPUT_GCBUTTON_LEFTSTICK,                       /* Leftstick-Button: click on left axis */
  VG_INPUT_GCBUTTON_RIGHTSTICK,                      /* Rightstick-Button: click on right axis */
  VG_INPUT_GCBUTTON_LEFTSHOULDER,                    /* Leftshoulder-Button: front left */
  VG_INPUT_GCBUTTON_RIGHTSHOULDER,                   /* Rightshoulder-Button: front right */
  VG_INPUT_GCBUTTON_DPAD_UP,                         /* DPAD-Up-Button: left button-cross: up */
  VG_INPUT_GCBUTTON_DPAD_DOWN,                       /* DPAD-Down-Button: left button-cross: down */
  VG_INPUT_GCBUTTON_DPAD_LEFT,                       /* DPAD-Left-Button: left button-cross: left */
  VG_INPUT_GCBUTTON_DPAD_RIGHT,                      /* DPAD-Right-Button: left button-cross: right */
  /* last entry */
  VG_INPUT_GCBUTTON_MAXENUM
} VG_INPUT_GCBUTTONS;

typedef enum {  /* gamecontroller axis key-codes */
  VG_INPUT_GCAXIS_LEFTX_LEFT = VG_INPUT_STARTGCAXIS + 1,  /* left axis: left */
  VG_INPUT_GCAXIS_LEFTX_RIGHT,                            /* left axis: right */
  VG_INPUT_GCAXIS_LEFTY_UP,                               /* left axis: up */
  VG_INPUT_GCAXIS_LEFTY_DOWN,                             /* left axis: down */
  VG_INPUT_GCAXIS_RIGHTX_LEFT,                            /* right axis: left */
  VG_INPUT_GCAXIS_RIGHTX_RIGHT,                           /* right axis: right */
  VG_INPUT_GCAXIS_RIGHTY_UP,                              /* right axis: up */
  VG_INPUT_GCAXIS_RIGHTY_DOWN,                            /* right axis: down */
  VG_INPUT_GCAXIS_TRIGGERLEFT,                            /* left front axis */
  VG_INPUT_GCAXIS_TRIGGERRIGHT,                           /* right front axis */
  /* last entry */
  VG_INPUT_GCAXIS_MAXENUM
} VG_INPUT_GCAXES;

/* audio frequencies */
typedef enum {
  VG_AUDIO_FREQ_LOW = 1,  /* frequency = 11025 */
  VG_AUDIO_FREQ_MEDIUM,   /* frequency = 22050 */
  VG_AUDIO_FREQ_HIGH,     /* frequency = 44100 */
} VG_AUDIO_FREQS;

/* audio bitsizes */
typedef enum {
  VG_AUDIO_BITSIZE_16 = 1,   /* 16bit integer */
  VG_AUDIO_BITSIZE_32,       /* 32bit integer */
  VG_AUDIO_BITSIZE_32FLOAT,  /* 32bit floating point */
} VG_AUDIO_BITSIZES;

/* audio volume enumeration */
typedef enum {
  VG_AUDIO_VOLUME_ALL = 0,
  VG_AUDIO_VOLUME_SOUND,
  VG_AUDIO_VOLUME_MUSIC,
  VG_AUDIO_VOLUME_SPEECH,
  /* last entry */
  VG_AUDIO_VOLUME_MAXENUM
} VG_AUDIO_VOLUMES;
#define VG_AUDIO_SYSTEM  0x100  /* system-sound or'ed */

/* collision types */
typedef enum {
  VG_COLL_TYPE_ENTRY = 1,  /* entry into collision */
  VG_COLL_TYPE_REPEAT,     /* collision repeated */
  VG_COLL_TYPE_LEAVE,      /* leaving collision */
} VG_COLL_TYPES;

/* collision sides (bitwise or'ed) */
typedef enum {
  VG_COLL_SIDE_RIGHT  = 1,
  VG_COLL_SIDE_LEFT   = 2,
  VG_COLL_SIDE_TOP    = 4,
  VG_COLL_SIDE_BOTTOM = 8
} VG_COLL_SIDES;

/* collision return values */
#define VG_COLL_RETURN_ADDING(PDEST, PSRC) ((PDEST) = \
  ((((PDEST) | (PSRC)) & VG_COLL_RETURN_DEAD) ? VG_COLL_RETURN_DEAD : \
  ((((PDEST) | (PSRC)) & VG_COLL_RETURN_BREAK) ? VG_COLL_RETURN_BREAK : \
  ((PDEST) | (PSRC))))
typedef enum {
  VG_COLL_RETURN_CONTINUE = 0,  /* no collision: continue moving */
  VG_COLL_RETURN_STOP_X = 1,    /* collision: stop x-moving, continue with y-moving */
  VG_COLL_RETURN_STOP_Y = 2,    /* collision: step y-moving, continue with x-moving */
  VG_COLL_RETURN_STOP = 3,      /* collision: stop moving and step one back */
  VG_COLL_RETURN_DEAD = 4,      /* collision: (destroy and) return immediately */
  VG_COLL_RETURN_BREAK = 5,     /* collision: stop moving and return immediately */
} VG_COLL_RETURNS;

/* settings for saving and loading (bitwise or'ed) */
typedef enum {
  VG_SETTING_WINDOWSCALE = 1,
  VG_SETTING_WINDOWBRIGHTNESS = 2,
  VG_SETTING_VOLUME = 4,
  VG_SETTING_KEYS = 8,
} VG_SETTINGS;


/* ++++++++++++++++++ */
/* +++ structures +++ */
/* ++++++++++++++++++ */

/* hash */
struct VG_Hash;

/* pixel-color */
struct VG_PixelColor {
  unsigned char r;  /* red value:   0 - 255 */
  unsigned char g;  /* green value: 0 - 255 */
  unsigned char b;  /* blue value:  0 - 255 */
  unsigned char a;  /* alpha value: 0 - 255 */
};

/* image */
struct VG_Image;

/* sprite */
struct VG_Sprite;

/* font */
struct VG_Font;
struct VG_Fontchar {  /* for a character of a font */
  int index;            /* index of character */
  char character[8];    /* UTF8-character */
  int width, height;    /* width and height of the character */
};

/* point struct */
struct VG_Point {
  int x, y;  /* position */
};

/* rectangle struct */
struct VG_Rect {
  int x, y;  /* position at left upper corner */
  int w, h;  /* width (for x) and height (for y) */
};

/* rectangle with hundredth of x- and y-position */
struct VG_RectCent {
  int centx, centy;     /* hundredth of x-position and y-position */
  struct VG_Rect rect;  /* rectangle */
};

/* position struct */
struct VG_Position {
  int pos;    /* one of VG_POSITIONS */
  int x, y;   /* position */
};

/* canvas struct */
struct VG_Canvas;

/* nodelink struct */
struct VG_Nodelink;


/* +++ image-copy attributes +++ */

enum { VG_PIXELCOLOR_NOP = 0, VG_PIXELCOLOR_GREY, VG_PIXELCOLOR_INVERT };

/* pixel-modifying part of image-copy attributes */
#define VG_MAX_BRIGHTNESS 255
struct VG_ImagecopyAttrPixel {
  int opaqueness;        /* opaqueness in percent: 0 = invisible, 100 = full visible, (default = 100) */
  int brightness;        /* brightness in percent: 0 = dark, 100 = bright, >100 up to VG_MAX_BRIGHTNESS = overdriving bright, (default = 100) */
  int colorize_color;    /* colorizing: one of VG_COLORS or from VG_COLOR_RGB(), (default = VG_COLOR_TRANSPARENT) */
  int colorize_percent;  /* colorizing: depth in percent: 0 = no, 100 = maximal, (default = 0) */
  int pixelcolor;        /* one of:
                          *  - VG_PIXELCOLOR_NOP = no change, (default)
                          *  - VG_PIXELCOLOR_GREY = convert to grey
                          *  - VG_PIXELCOLOR_INVERT = invert color
                          */
  /* cbf(): individual pixel-modifying function, (default = NULL)
   * will be called at last, if not NULL
   * parameter: pixel
   * return value: modified pixel
   */
  struct VG_PixelColor (*cbf)(struct VG_PixelColor);
};

/* image-modifying part of image-copy attributes */
struct VG_ImagecopyAttrImage {
  int zoom_width;        /* zooming: new width in pixels or in percent */
  int zoom_height;       /* zooming: new height in pixels or in percent */
  int zoom_ispercent;    /* zooming: whether values in zoom_width and zoom_height are in percent */
  int rotate;            /* rotating in degrees: 0 to 360, (default = 0) */
  int flip;              /* flipping axe: from VG_AXES, (default = VG_AXE_NONE) */
};

/* image-copy attributes */
struct VG_ImagecopyAttr {
  struct VG_ImagecopyAttrPixel pixel;  /* pixel-modifying attributes */
  struct VG_ImagecopyAttrImage image;  /* image-modifying attributes */
};

/* set image-copy attributes to default */
#define VG_IMAGECOPY_ATTR_DEFAULT(APTR) \
  do { \
    memset((APTR), 0, sizeof(*(APTR))); \
    (APTR)->pixel.opaqueness = (APTR)->pixel.brightness = 100; \
    (APTR)->pixel.colorize_color = VG_COLOR_TRANSPARENT; \
    (APTR)->pixel.pixelcolor = VG_PIXELCOLOR_NOP; \
    (APTR)->pixel.cbf = NULL; \
    (APTR)->image.zoom_width = (APTR)->image.zoom_height = 100; \
    (APTR)->image.zoom_ispercent = VG_TRUE; \
    (APTR)->image.flip = VG_AXE_NONE; \
  } while (0)

/* set pixel-modifying part of image-copy attributes to default */
#define VG_IMAGECOPY_ATTRPIXEL_DEFAULT(APTR) \
  do { \
    memset((APTR), 0, sizeof(*(APTR))); \
    (APTR)->opaqueness = (APTR)->brightness = 100; \
    (APTR)->colorize_color = VG_COLOR_TRANSPARENT; \
    (APTR)->pixelcolor = VG_PIXELCOLOR_NOP; \
    (APTR)->cbf = NULL; \
  } while (0)

/* set image-modifying part of image-copy attributes to default */
#define VG_IMAGECOPY_ATTRIMAGE_DEFAULT(APTR) \
  do { \
    memset((APTR), 0, sizeof(*(APTR))); \
    (APTR)->zoom_width = (APTR)->zoom_height = 100; \
    (APTR)->zoom_ispercent = VG_TRUE; \
    (APTR)->flip = VG_AXE_NONE; \
  } while (0)


/* +++ input structs +++ */

#define VG_MAX_GCS 4
#define VG_MAX_KEYENTRIES 64

/* list of gamecontrollers */
struct VG_GCList {
  int max;              /* number of gamecontrollers */
  struct {              /* each gamecontroller */
    int id;               /* ID */
    const char *name;     /* name */
  } gc[VG_MAX_GCS];
};

/* list of key-entrys */
struct VG_KeyList {
  int max;              /* number of entries */
  struct {              /* each key-entry */
    int keyref;             /* key-entry reference-number */
    char keyname[32];       /* short description */
    VG_BOOL is_changeable;  /* whether the key-code can be changed */
    VG_BOOL is_nwkey;       /* whether will be sent over network */
    int code;               /* key-code for the selected device */
    char codename[32];      /* name of key-code */
  } key[VG_MAX_KEYENTRIES];
};


/* +++ network structs +++ */

/* struct for additional-data and exchange-data for network */
#define VG_MAX_ZDATA 65535  /* data-header: max. size set in USHORT_*() */
struct VG_NwZdata {
  char data[VG_MAX_ZDATA];  /* data */
  size_t size;              /* number of bytes in data */
  int clnr;                 /* client-number, who has sent data */
};

/* struct for exchange-data list */
struct VG_NwXdataList {
  struct VG_NwXdataList *next;  /* pointer to next list-element */
  char *data;                   /* exchange-data */
  size_t size;                  /* number of bytes in data */
  int clnr;                     /* client-number */
};


/* +++ object structs +++ */

#define VG_OBJID_SIZE 64

/* object */
struct VG_Object {
  char objid[VG_OBJID_SIZE];        /* object-ID (e.g. name of object) */
  int subid;                        /* arbitrary sub-ID for object-ID, (default: 0 = no sub-ID) */
  int drawlevel;                    /* level-number for drawing order (begins with 1 = lowest level) */
  unsigned int instanceid;          /* instance-ID for the instance of this object (>0) */
  unsigned int parent_instanceid;   /* instance-ID for the parent-instance of this object (>0), or 0 = not relevant */
  void *opriv;                      /* private struct for object-instance */
  /* functions */
  void (*f_free)(void *, void *);                                       /* free()-function: destroy private struct for object-instance */
  VG_BOOL (*f_run)(void *, struct VG_Object *);                         /* run()-function: moving object-instance without drawing */
  void (*f_draw)(void *, struct VG_Object *);                           /* draw()-function: drawing object-instance */
  int (*f_data)(void *, struct VG_Object *, void *);                    /* data()-function: getting/setting data of object-instance */
  void (*f_childexit)(void *, struct VG_Object *, struct VG_Object *);  /* childexit()-function: a child of the object-instance is being destroyed */
  void (*f_signal)(void *, struct VG_Object *, int);                    /* signal()-function: a arbitray signal is sent to the object-instance */
};

/* object-management */
struct VG_ObjMgmt {
  char objid[VG_OBJID_SIZE];      /* object-ID */
  /* functions */
  void (*f_free)(void);           /* free()-function: for individual freeing */
  void (*f_run)(void *);          /* run()-function: managing object-instances */
  int (*f_data)(void *, void *);  /* data()-function: getting/setting data of object-management */
};


/* +++ collision struct +++ */

/* struct for returning collisions */
struct VG_Coll {
  int type;                  /* one from VG_COLL_TYPES */
  unsigned int tag;          /* collision-tag */
  unsigned int instanceid;   /* instance-ID */
  const char *objid;         /* object-ID of instance-ID, or empty if none */
  int side;                  /* hit side(s): VG_COLL_SIDES */
  int percent;               /* overlapping in percent (distance of both center-pixels) */
};


/* +++ main struct +++ */

/* sub-structs of main-struct */

struct VG_SubHash {
  struct VG_Hash * (*create)(void);
  struct VG_Hash * (*clone)(struct VG_Hash *);
  void (*destroy)(struct VG_Hash *);
  void (*destroyall)(void);
  const char * (*list)(struct VG_Hash *, void **);
  void (*clear)(struct VG_Hash *);
  VG_BOOL (*is_empty)(struct VG_Hash *);
  void (*set)(struct VG_Hash *, const char *, const void *, size_t);
  void (*setint)(struct VG_Hash *, const char *, int);
  void (*setstr)(struct VG_Hash *, const char *, const char *);
  VG_BOOL (*isset)(struct VG_Hash *, const char *);
  VG_BOOL (*isnum)(struct VG_Hash *, const char *);
  void * (*get)(struct VG_Hash *, const char *, size_t *);
  int (*getint)(struct VG_Hash *, const char *);
  void (*insert)(struct VG_Hash *, struct VG_Hash *, VG_BOOL);
  void * (*remove)(struct VG_Hash *, const char *);
  void (*dump)(FILE *);
};

struct VG_SubInput {
  VG_BOOL (*open)(void);
  void (*close)(void);
  void (*reopen)(void);
  int (*gclist)(struct VG_GCList *);
  VG_BOOL (*update)(VG_BOOL);
  VG_BOOL (*mouse_position)(int *, int *);
  VG_BOOL (*mouse_pressed)(VG_BOOL *, VG_BOOL *, VG_BOOL *);
  VG_BOOL (*mouse_newpressed)(VG_BOOL *, VG_BOOL *, VG_BOOL *);
  void (*mouse_warp)(int, int);
  VG_BOOL (*mouse_grabbing)(VG_BOOL);
  int (*key_insert)(const char *, VG_BOOL, VG_BOOL);
  VG_BOOL (*key_remove)(int);
  void (*key_setkbd)(int, int);
  void (*key_setgc)(int, int, int);
  VG_BOOL (*key_pressed)(int);
  VG_BOOL (*key_newpressed)(int);
  int (*key_uniqpressed)(int, const char **);
  int (*keylist)(struct VG_KeyList *, int);
  void (*textbuffer)(char *, size_t, const char *, const char *);
  void (*dump)(FILE *);
};

struct VG_SubWindow {
  VG_BOOL (*open)(int, int);
  void (*close)(void);
  VG_BOOL (*reopen)(int, int);
  void (*getparameters)(int *, int *);
  void (*getsize)(int *, int *);
  void (*setbrightness)(int);
  int (*getbrightness)(void);
  void (*setattr)(struct VG_ImagecopyAttrPixel *);
  struct VG_ImagecopyAttrPixel (*getattr)(void);
  void (*scale_params)(VG_BOOL, VG_BOOL *, VG_BOOL *);
  void (*shake)(int);
  void (*clear)(void);
  void (*fill)(int);
  void (*copy)(const struct VG_Image *, const struct VG_Position *, const struct VG_ImagecopyAttr *);
  struct VG_PixelColor (*getpoint)(int, int);
  void (*draw_point)(int, int, int);
  void (*draw_points)(const struct VG_Point *, size_t, int);
  void (*draw_line)(int, int, int, int, int);
  void (*draw_rect)(const struct VG_Rect *, int, VG_BOOL);
  void (*draw_circle)(int, int, int, int, VG_BOOL);
  void (*flush)(void);
  struct VG_Image * (*clone)(const struct VG_Rect *, const struct VG_ImagecopyAttr *);
  VG_BOOL (*screenshot)(const char *);
  VG_BOOL (*size_extend)(VG_BOOL *);
};

struct VG_SubAudio {
  VG_BOOL (*open)(int, VG_BOOL);
  VG_BOOL (*is_open)(void);
  void (*close)(void);
  int (*load)(const char *, int, int);
  void (*unload)(int);
  void (*unload_group)(int);
  const char * (*getname)(int);
  void (*play)(int, VG_BOOL, VG_BOOL);
  void (*play_after)(int, VG_BOOL, int);
  VG_BOOL (*is_playing)(int, VG_BOOL *);
  void (*stop)(int, VG_BOOL);
  void (*stop_group)(int, VG_BOOL);
  void (*pause)(int, VG_BOOL);
  void (*pause_group)(int, VG_BOOL);
  int (*volume)(int, int);
  VG_BOOL (*mute)(VG_BOOL);
  VG_BOOL (*is_mute)(void);
  VG_BOOL (*suspend)(VG_BOOL);
  void (*dump)(FILE *);
};

struct VG_SubImage {
  struct VG_Image * (*create)(int, int);
  struct VG_Image * (*load)(const char *);
  VG_BOOL (*save)(const struct VG_Image *, const char *, VG_BOOL);
  VG_BOOL (*tobase64)(const struct VG_Image *, VG_BOOL, char **, size_t *);
  void (*destroy)(struct VG_Image *);
  void (*destroyall)(void);
  void (*getsize)(const struct VG_Image *, const struct VG_ImagecopyAttrImage *, int *, int *);
  const char * (*getname)(const struct VG_Image *);
  void (*clear)(struct VG_Image *);
  void (*fill)(struct VG_Image *, int);
  void (*copy)(struct VG_Image *, const struct VG_Image *, const struct VG_Position *, const struct VG_ImagecopyAttr *);
  struct VG_Image * (*clone)(const struct VG_Image *, const struct VG_Rect *, const struct VG_ImagecopyAttr *);
  struct VG_PixelColor (*getpoint)(struct VG_Image *, int, int);
  void (*draw_point)(struct VG_Image *, int, int, int);
  void (*draw_points)(struct VG_Image *, const struct VG_Point *, size_t, int);
  void (*draw_line)(struct VG_Image *, int, int, int, int, int);
  void (*draw_rect)(struct VG_Image *, const struct VG_Rect *, int, VG_BOOL);
  void (*draw_circle)(struct VG_Image *, int, int, int, int, VG_BOOL);
  void (*attr_sum)(struct VG_ImagecopyAttr *, const struct VG_ImagecopyAttr *, const struct VG_ImagecopyAttr *);
  void (*dump)(FILE *);
};

struct VG_SubFont {
  void (*path)(const char *);
  struct VG_Font * (*load)(const char *);
  void (*destroy)(struct VG_Font *);
  void (*destroyall)(void);
  const char * (*getname)(const struct VG_Font *);
  void (*setdefault)(const char *);
  void (*getdefault)(char *, size_t);
  void (*maxsize)(const struct VG_Font *, int *, int *);
  void (*gaps)(const struct VG_Font *, int *, int *);
  struct VG_Image * (*loadtext)(const char *, const char *, struct VG_Hash *, struct VG_Hash **);
  struct VG_Image * (*totext)(const char *, const char *, const char *, struct VG_Hash *, struct VG_Hash **);
  int (*getchars)(const struct VG_Font *, struct VG_Fontchar **);
  void (*dump)(FILE *);
};

struct VG_SubMlang {
  void (*fb_locale)(const char *);
  void (*clear)(void);
  const char * (*getlocale)(VG_BOOL);
  VG_BOOL (*add)(const char *);
  const char * (*get)(const char *, const char *);
  void (*dump)(FILE *);
};

struct VG_SubRandom {
  unsigned int (*get)(const char *, unsigned int, unsigned int);
  void (*remove)(const char *);
};

struct VG_SubSprite {
  struct VG_Sprite * (*load)(const char *);
  void (*destroy)(struct VG_Sprite *);
  void (*destroyall)(void);
  const char * (*getname)(const struct VG_Sprite *);
  int (*get_blocks)(const struct VG_Sprite *);
  void (*go_block)(struct VG_Sprite *, int);
  void (*rewind)(struct VG_Sprite *);
  void (*imagesize)(const struct VG_Sprite *, const char *, int *, int *);
  VG_BOOL (*next)(struct VG_Sprite *, struct VG_Image **, struct VG_ImagecopyAttr *);
  void (*dump)(FILE *);
  VG_BOOL (*has_next)(struct VG_Sprite *);
  VG_BOOL (*current)(struct VG_Sprite *, struct VG_Image **, struct VG_ImagecopyAttr *);
};

struct VG_SubNW {
  void (*server)(const char *);
  void (*set_ports)(int, int);
  VG_BOOL (*check_server)(VG_BOOL *);
  char * (*get_ip)(char *, size_t);
  void (*close)(void);
  int (*connect)(const char *, int, int, const char *, void (*)(const char * const *, int, void *), void *); 
  VG_BOOL (*update)(VG_BOOL *, struct VG_NwZdata *);
  void (*pause)(void);
  VG_BOOL (*key_pressed)(int, int);
  VG_BOOL (*key_newpressed)(int, int);
  void (*mouse_position)(int, int *, int *);
  VG_BOOL (*mouse_pressed)(int, VG_BOOL *, VG_BOOL *, VG_BOOL *);
  VG_BOOL (*mouse_newpressed)(int, VG_BOOL *, VG_BOOL *, VG_BOOL *);
  int (*numberofclients)(int *);
  VG_BOOL (*is_connected)(int);
  int (*local_clnr)(void);
  const char * (*get_clientname)(int);
  void (*connected_clients)(void);
  void (*put_zdata)(const struct VG_NwZdata *);
  VG_BOOL (*xdata_recv)(char **, size_t *, int *);
  VG_BOOL (*xdata_send)(const char *, size_t);
  void (*xdata_retag)(void);
  VG_BOOL (*xdata_allclients_recv)(struct VG_NwXdataList **, VG_BOOL, const char *, size_t, VG_BOOL *);
  void (*xdata_allclients_free)(struct VG_NwXdataList *);
};

struct VG_SubMisc {
  long (*time_delta)(long *);
  int (*wait_time)(int);
  int (*angle_from_xy)(int, int, int *);
  int (*xy_from_angle)(int, int *, int *);
  int (*sin)(int);
  int (*cos)(int);
  VG_BOOL (*pause)(void);
  int (*moving_one_step)(const struct VG_RectCent *, int, int, struct VG_RectCent **);
  struct VG_Position * (*rect2position)(struct VG_Position *, const struct VG_Rect *);
  VG_BOOL (*move_and_check_collisions)(void *, unsigned int, struct VG_RectCent *, unsigned int, const struct VG_RectCent *, int);
  int (*line_positions)(const struct VG_Rect *, const struct VG_Rect *, int, struct VG_Rect **);
  VG_BOOL (*fadeout)(int);
  int (*colorbrightness)(int, int);
  const char * (*version)(int *, int *);
  size_t (*strcpy)(char *, size_t, const char *);
  size_t (*strscpy)(char *, size_t, const char *, size_t);
  size_t (*strccat)(char *, size_t, ...);
  void (*bgposition_init)(int, int, int, int);
  VG_BOOL (*bgposition_getbg)(const struct VG_Rect *, struct VG_Position *, VG_BOOL);
  struct VG_Position (*bgposition_getobj)(struct VG_Position);
  void (*settings_load)(const char *);
  char * (*settings_save)(int);
  void (*base64_encode)(char **, size_t *, const char *, size_t);
  void (*base64_decode)(char **, size_t *, const char *, size_t);
  int (*utf8_next)(const char *, size_t, int *);
  int (*utf8_from_codepoint)(int, char *);
  int (*utf8_toupper)(int);
  int (*utf8_tolower)(int);
  int (*moving_one_step_to_dst)(const struct VG_RectCent *, const struct VG_Point *, int, struct VG_RectCent **);
  VG_BOOL (*bgposition_reached)(const struct VG_Rect *);
  int (*points_on_line)(const struct VG_Point *, const struct VG_Point *, int, struct VG_Point **);
};

struct VG_SubCanvas {
  struct VG_Canvas * (*load)(const char *, struct VG_Hash *);
  VG_BOOL (*reload)(struct VG_Canvas *, struct VG_Hash *);
  void (*destroy)(struct VG_Canvas *);
  void (*destroyall)(void);
  const char * (*getname)(const struct VG_Canvas *);
  VG_BOOL (*exec)(struct VG_Canvas *, const struct VG_Position *, const char **);
  struct VG_Position (*subcanvas)(const struct VG_Canvas *, const struct VG_ImagecopyAttrPixel *);
  void (*set_mouse)(const char *, const char *, int);
  void (*set_activated)(struct VG_Canvas *, const char *);
  void (*disable)(struct VG_Canvas *, const char *, VG_BOOL);
  VG_BOOL (*is_disabled)(const struct VG_Canvas *, const char *);
  void (*switch_set)(struct VG_Canvas *, const char *, VG_BOOL);
  VG_BOOL (*switch_get)(struct VG_Canvas *, const char *);
  void (*list_clear)(struct VG_Canvas *, const char *);
  VG_BOOL (*list_add)(struct VG_Canvas *, const char *, const char *, const char *);
  void (*list_set_activated)(struct VG_Canvas *, const char *, const char *);
  const char * (*list_get_activated)(struct VG_Canvas *, const char *);
  void (*chain_clear)(struct VG_Canvas *, const char *);
  VG_BOOL (*chain_add)(struct VG_Canvas *, const char *, const char *, const char *, const char *);
  VG_BOOL (*chain_disable)(struct VG_Canvas *, const char *, const char *, VG_BOOL);
  void (*chain_set_activated)(struct VG_Canvas *, const char *, const char *);
  const char * (*chain_get_activated)(struct VG_Canvas *, const char *);
  void (*input_set_text)(struct VG_Canvas *, const char *, const char *);
  const char * (*input_get_text)(struct VG_Canvas *, const char *);
  void (*bar_set_percent)(struct VG_Canvas *, const char *, int);
  int (*bar_get_percent)(struct VG_Canvas *, const char *);
  VG_BOOL (*map_area_disable)(struct VG_Canvas *, const char *, const char *, VG_BOOL);
  const char * (*map_area_get_selected)(struct VG_Canvas *, const char *);
  void (*text_set)(struct VG_Canvas *, const char *, const char *);
  void (*uniqkey_set)(struct VG_Canvas *, const char *, int, int);
  int (*uniqkey_get)(struct VG_Canvas *, const char *);
  void (*dump)(FILE *);
  void (*image_setimage)(struct VG_Canvas *, const char *, struct VG_Image *);
  void (*image_setsprite)(struct VG_Canvas *, const char *, struct VG_Sprite *);
};

struct VG_SubDialog {
  VG_BOOL (*file_select)(char *, size_t, const char *, const struct VG_Position *, struct VG_Hash *, const char *, VG_BOOL, VG_BOOL);
  VG_BOOL (*exit)(const char *, const struct VG_Position *, struct VG_Hash *);
  VG_BOOL (*windowsize)(const char *, const struct VG_Position *, struct VG_Hash *);
  VG_BOOL (*volume)(const char *, const struct VG_Position *, struct VG_Hash *);
  VG_BOOL (*keydef)(const char *, const struct VG_Position *, struct VG_Hash *, int);
  VG_BOOL (*sysmenu)(const char *, const struct VG_Position *, struct VG_Hash *, void *, void (*)(const char *, void *), void (*)(const char *, void *), const char *);
  VG_BOOL (*nw_clientname)(char *, size_t, const char *, const struct VG_Position *, struct VG_Hash *);
  VG_BOOL (*nw_connect)(VG_BOOL *, char *, size_t, const char *, const struct VG_Position *, struct VG_Hash *);
  VG_BOOL (*nw_server)(const char *, const struct VG_Position *, struct VG_Hash *);
  VG_BOOL (*text)(const char *, const char *, const struct VG_Position *, struct VG_Hash *);
  VG_BOOL (*winbright)(const char *, const struct VG_Position *, struct VG_Hash *);
};

struct VG_SubObject {
  void (*instance_create)(struct VG_Object *);
  void (*instance_destroy)(unsigned int);
  struct VG_Object * (*instance_getobj)(unsigned int);
  struct VG_Object * (*create)(const char *, int, unsigned int, int, void *);
  void (*destroy)(void *, unsigned int);
  void (*destroy_objid)(void *, const char *, int);
  void (*destroyall)(void);
  int (*list)(const char *, int, unsigned int **);
  VG_BOOL (*has_instances)(const char *, int);
  struct VG_ObjMgmt * (*mgmt_create)(const char *);
  void (*mgmt_destroy)(const char *);
  void (*mgmt_destroyall)(void);
  VG_BOOL (*call_run)(void *);
  void (*call_draw)(void *);
  int (*call_data)(void *, unsigned int, void *);
  void (*call_mgmt_run)(void *);
  int (*call_mgmt_data)(void *, const char *, void *);
  void (*collision_add)(const char *, const char *, int (*)(void *, unsigned int, struct VG_Coll *));
  void (*collision_destroyall)(void);
  int (*collision_call)(void *, unsigned int, struct VG_Coll *, int);
  void (*dump)(FILE *);
  void (*destroy_except)(void *, ...);
  void (*call_signal)(void *, unsigned int, int);
  void (*call_signal_objid)(void *, const char *, int, int);
};

struct VG_SubCollision {
  unsigned int (*create)(const struct VG_Rect *, int, int);
  void (*destroy)(unsigned int);
  void (*destroyall)(void);
  void (*clear)(unsigned int);
  void (*insert)(unsigned int, unsigned int, const struct VG_Rect *, int);
  void (*remove)(unsigned int, unsigned int);
  int (*setpos)(unsigned int, unsigned int, const struct VG_Rect *, struct VG_Coll **);
  void (*mark)(unsigned int, struct VG_Image *, int, const char *);
  void (*dump)(FILE *);
};

struct VG_SubFilm {
  VG_BOOL (*play)(const char *, const struct VG_Rect *, VG_BOOL *, struct VG_Hash *);
};

struct VG_SubActionstack {
  void (*freefunction)(void (*)(unsigned int, void *));
  void (*push)(unsigned int, void *);
  void * (*get)(unsigned int *);
  void (*pop)(void);
  void * (*parent)(unsigned int *);
  void (*clear)(void);
};

struct VG_SubNodelink {
  struct VG_Nodelink * (*create)(void);
  void (*destroy)(struct VG_Nodelink *);
  void (*destroyall)(void);
  void (*clear)(struct VG_Nodelink *);
  VG_BOOL (*add)(struct VG_Nodelink *, const char *, const char *, int, VG_BOOL);
  void (*del)(struct VG_Nodelink *, const char *, const char *, VG_BOOL);
  VG_BOOL (*islink)(struct VG_Nodelink *, const char *, const char *, VG_BOOL);
  int (*get)(struct VG_Nodelink *, const char *, const char ***, VG_BOOL);
  void (*deactivate)(struct VG_Nodelink *, const char *, const char *, VG_BOOL);
  void (*activate)(struct VG_Nodelink *, const char *, const char *, VG_BOOL);
  void (*reactivate)(struct VG_Nodelink *);
  int (*moveto)(struct VG_Nodelink *, const char *, const char *, const char ***, VG_BOOL);
  void (*dump)(FILE *);
};

/* main-struct for functions */
struct vg4 {
  struct VG_SubHash *hash;
  struct VG_SubInput *input;
  struct VG_SubWindow *window;
  struct VG_SubAudio *audio;
  struct VG_SubImage *image;
  struct VG_SubFont *font;
  struct VG_SubMlang *mlang;
  struct VG_SubRandom *random;
  struct VG_SubSprite *sprite;
  struct VG_SubNW *nw;
  struct VG_SubMisc *misc;
  struct VG_SubCanvas *canvas;
  struct VG_SubDialog *dialog;
  struct VG_SubObject *object;
  struct VG_SubCollision *collision;
  struct VG_SubFilm *film;
  struct VG_SubActionstack *actionstack;
  struct VG_SubNodelink *nodelink;
};

extern struct vg4 *vg4;


/* +++++++++++++++++ */
/* +++ functions +++ */
/* +++++++++++++++++ */

/* vgi.c */
extern int VG_init(const char *);
extern void VG_dest(void);

# ifdef __cplusplus
}
# endif

#endif /* VGAGAMES4_H_ */
