/**
 *
 * ChoX11: XLib replacement for RISC OS
 *
 * ChoX11 declarations
 *
 * Copyright 2003 by Peter Naulls
 * Written by Peter Naulls
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation. No representations are made about the suitability of this
 * software for any purpose.  It is provided "as is" without express or
 * implied warranty.
 *
 */


#include <X11/X.h>
#include <X11/Xutil.h>

#ifndef DEBUG
  #define printf(args...)
  #define puts(x) 
#endif

#include "Desklib:Window.h"
#include "Desklib:Wimp.h"
#include "Desklib:SWI.h"
#include "Desklib:Sprite.h"
#include "Desklib:Event.h"
#include "Desklib:Error.h"
#include "Desklib:Handler.h"
#include "Desklib:GFX.h"
#include "Desklib:ColourTran.h"
#include "Desklib:Screen.h"
#include "Desklib:Font.h"

#define X_APP_NAME          "X Windows Program"
#define X_WIN_TITLE         "X Window"
#define X_SPRITE_NAME       "XSprite"
#define X_WIN_TITLE_BUFFER  100
#define CX_ERROR_BIT        1 << 31

#include "fortify.h"

typedef struct Chox_ClipRects {
  int ref_count;
  int xmin, xmax, ymin, ymax;
  int rect_count;
  XRectangle *rects;
} Chox_ClipRects;

typedef struct XDrawable {
  /* True if window, otherwise sprite */
  Bool isWindow;

  /* All drawables have a size */
  int width, height;

  /* Synchronisation information for Graphics contexts and queues */
  struct {
    XGCValues values;
    sprite_area clip_sprite;
    Chox_ClipRects *clip_rects;
  } gcinfo;

  union {
    struct {
      window_handle      handle;          /* WIMP Window handle       */
      int                isMapped    : 1; /* Has been mapped          */
      int                isOpen      : 1; /* If the window is showing */
      int                override    : 1; /* override_redirect        */
      int                visibility;      /* Visibility state         */

      int                x, y;            /* Position */

      int                event_mask;      /* Determine events to match */
      int                no_propagate;    /* Do not propogate events   */

      int                background;      /* ColourTrans background colour */
      int                border_width;    /* Border thickness */
      int                border;          /* ColourTrans border colour */

      Cursor             cursor;          /* Mouse pointer when over window */

      unsigned int       class;           /* window class - defines InputOnly,
                                           or InputOutput qualities */

      union {
        struct XDrawable *draw;
        Window            ref;
        Drawable          dref;
      } parent;                         /* Parent Window */

      int                 nchildren;

      union {
        struct XDrawable **draw;
        Window            *ref;
        Drawable          *dref;
      } children;                       /* Child Windows */
    } window;

    struct {
      sprite_areainfo pixmap; /* sprite data appears after this */
    } image;
  } data;

  /* Don't add any items after the pixmap field, or it will corrupt the sprite */

} XDrawable;


typedef struct Chox_Font {
  char *ro_name;
  unsigned int width, height;
  font_handle handle;
  int ref_count;
} Chox_Font;


typedef enum
{
  CXWindow    = 0,
  CXFont      = 1,
  CXPixmap    = 2,
  CXColourmap = 3,
  CXCursor    = 4,
  CXGContext  = 5,
  CXDeleted   = 6
} XResourceType;


typedef struct XContextEntry {
  XID rid;
  XContext context;
  XPointer data;
} XContextEntry;


typedef struct XResourceID {
  XID resourceid;
  void *internal_data;
  XResourceType type;
} XResourceID;


typedef struct XProperty {
  Window w;
  Atom property, type;
  int format, mode;
  unsigned char *data;
  int nelements;
} XProperty;


typedef struct XAtom {
  unsigned char *name;
} XAtom;


typedef struct XGContext {
  XGCValues values;
  Chox_ClipRects *clip_rects;
} XGContext;


typedef struct XEventList {
  struct XEventList *next;
  struct XEventList *prev;
  Bool      grabbed_event;
  XEvent            event;
} XEventList;


typedef struct XRegion {
  short x, y;
  unsigned short width, height;
  Bool set;
} XRegion;

typedef struct Chox11_Colormap
{
   int type;
} Chox11_Colormap;


/* Currently colour has to be a 32 bit colour number, in the internal
   format of 0x00bbggrr. ColourTrans wants 0xbbggrr00, hence the 8 bit
   left shift.
 */
#define ChoX11_InternalColourToColourTrans(intlcolour) \
   (((intlcolour) << 8) & 0xffffff00)
#define Chox11_SetGCOL(colour, action) \
   ColourTrans_SetGCOL(ChoX11_InternalColourToColourTrans(colour), 1 << 8, action)

/* chox11.c */
/**
 * Round given bpp value to suitable word width (in bytes).
 *
 * Used for the purposes of calling an allocation function.
 */
int Chox11_ConvertBppToBytes(int bpp);


/**
 * Find Drawable reference by window handle
 *
 * Return NULL if not found.  In many cases, that means return an
 * error to the client program.
 */
XDrawable *Chox11_FindWindow(window_handle window);


/**
 * Confirm that a drawable exists in our list of drawables
 *
 * Return False if not found, True if found.
 */
Bool Chox11_FindDrawable(XDrawable *entry);


/**
 * Remove a Drawable from the list of Drawables.
 *
 * Return true if it was found (and removed)
 */
Bool Chox11_RemoveDrawable(XDrawable *rdraw);


/**
 * Add a window or pixmap drawable to the list
 */
void Chox11_AddDrawable(XDrawable *drawable);


/* Reference to the single display.  X Supports multiple displays
   but we only implement display 0 */
extern Display *Chox11_display;

/* Amortised list of drawable objects (windows and images) */
extern XDrawable **Chox11_drawable_list;
/* Max size of list before increasing */
extern int Chox11_drawable_num;
/* Number of items in the list */
extern int Chox11_drawable_max;

/* The root window.  Effectively, the RISC OS Pinboard */
extern XDrawable Chox11_root_window;


/* Pixel translation table for plotting pixmaps to the screen */
extern void *Chox11_ScreenPixTrans;


/* choxevent.c */

/**
 * Create a MapNotify event
 */
XEvent *Chox11_CreateMapNotifyEvent(Display *display, XDrawable *window,
                                    int type);


/**
 * Create a Visibility event
 */
void Chox11_CreateVisibilityEvent(Display *display, Window window,
                                  int state);

/**
 * Create a ConfigureNotify event
 */
void Chox11_CreateConfigureNotifyEvent(Display *display, XDrawable *window);


/**
 * Update window co-ordinates
 */
void Chox11_UpdateWindowPos(XDrawable *window, window_openblock *openblock);

/**
 * Unset the window of the last event created.
 *
 * This ensures that serial numbers are generated correctly.
 */
void Chox11_EventWindowUnset(void);

void Chox11_EventInitialise(const char *application_name);
void Chox11_CheckPoll(void);
void Chox11_CallWimpPoll(void);

/* choxdb.c */


/**
 * Find a context in the list using the given XID and XContext.
 *
 * Return pointer to context in data_return. Note: this function returns a
 * pointer to the internal structure holding the context, not the actual
 * context data pointer.
 */
int Chox11DB_FindContext(XID rid, XContext context,
                         XContextEntry **data_return);


/**
 * Allocate memory for context database and other initialisations
 */
void Chox11DB_InitContexts(void);

/**
 * Find a described context in the database list
 */
int Chox11DB_FindContext(XID rid, XContext context,
                         XContextEntry **data_return);

/**
 * Store a new context to the list.
 *
 * If the context already exists, it is replaced and a new entry is not created. */
int Chox11DB_StoreContext(XID rid, XContext context, XPointer data);


/*
 * Remove a context from the list.
 *
 * Identify it using its XID and XContext values
 */
int Chox11DB_RemoveContext(XID rid, XContext context);


/**
 * Allocate memory for property and atom database and other initialisations
 */
void Chox11DB_InitProperties(void);



/**
 * Identify a property in the list and return pointer to its structure.
 *
 * property must match the given parameters. NULL is returned if no
 * matching property is found.
 */
XProperty *Chox11DB_PropertyFind(Window w, Atom property, Atom type);


/**
 * Add a property to the database.
 *
 * Return NULL for success or an appropiate error code. Note this adds a
 * totally new property to the database
 */
int Chox11DB_PropertyAdd(Window w, Atom property, Atom type, int format, int mode, _Xconst unsigned char *ata, int nelements);


/**
 * Remove property entry from list and free all associated memory.
 *
 * Return NULL for sucess or an appropiate X error code otherwise.
 */
int Chox11DB_PropertyRemove(XProperty *entry);


/**
 * Change the data for a given property
 *
 * The new data is pointed to by 'data'. Note: the given property pointer
 * must be valid.
 */
void Chox11DB_PropertyReplace(XProperty *entry, const unsigned char *data);


/**
 * Add an atom to the list and return pointer to atom entry.
 *
 * Return NULL for an error
 */
XAtom *Chox11DB_AtomAdd(const char *name);


/**
 * Returns atom value if the named atom has been defined, NULL if not
 */
XAtom *Chox11DB_AtomFind(const char *name);


/**
 * Returns atom name for a given atom ID
 */
unsigned char *Chox11DB_AtomGetName(XAtom *atom);


/**
 * Verifies if the given XID exists in the registered list of resources.
 * Returns pointer to internal resource structure if it exists, NULL if
 * the given XID does not exist
 */
XResourceID *Chox11DB_FindResource(XID id);


/**
 * Allocate an XID number for the X client to use to refer to an X11 resource.
 * data is a pointer to a public or internal structure associated with the
 * resource and the type currently is used for debugging
 */
XID Chox11DB_AllocateResource(void *data, XResourceType type);


/**
 * Mark a resource as deleted and release the memory used to hold its
 * internal data. Return True if the resource was found, False if it was
 * not.
 */
Bool Chox11DB_DeleteResource(XID id);


/**
 * Flush all queues
 *
 * Called regularly to ensure items don't stay too long in a queue
 * (and hence don't get drawn quickly.
 */
void Chox11Queue_EmptyAll(void);


/**
 * Flush queue allocated to drawable, if any
 *
 * Can be called when a drawable is deleted to ensure it doesn't have any
 * queued graphics.
 */
void Chox11Queue_EmptyFor(XDrawable *draw);


void Chox11Queue_DrawString(Display* display, Drawable d, GC gc,
                            int x, int y, _Xconst char* string,
                            int length, Bool background);


void Chox11Debug_Init(void);

Bool Chox11Debug_CheckWindow(Drawable draw);


Bool Chox11Debug_CheckImage(Drawable draw);


Bool Chox11Debug_CheckDrawable(Drawable draw);

void Chox11Debug_MemoryDump(const char *descript,
                            const void *base_address,
                            unsigned int size);

void Chox11Debug_CheckPointer(const void *ptr);

void Chox11Key_ConvertWimpKey(int key, XKeyEvent *xkey);
void Chox11Key_CheckKeyRelease();
void Chox11Key_AddKeyRelease(XKeyEvent *xkey);
void Chox11Key_FreeKeyRelease();
void Chox11_CreateKeyReleaseEvent(int keycode);

#define MOUSE_NULL_HANDLER 1
#define KEY_RELEASE_NULL_HANDLER 2
#define CHECK_EVENTS_NULL_HANDLER 4

void Chox11_AddNullHandler(int type);
void Chox11_RemoveNullHandler(int type);

sprite_area Chox11Image_CreateClipSprite(Pixmap clip_mask);
void Chox11Image_FreeImages(void);

void Chox11Font_AddRef(Chox_Font *font);
void Chox11Font_Release(Chox_Font *font);

/* ChoxCursor.c */
void Chox11Cursor_SetPointer(XDrawable *window);
void Chox11Cursor_UnsetPointer();

/* ChoxCurFnt.c */
#define CURSOR_FONT_SIZE 154
extern int Chox11_CursorFont[CURSOR_FONT_SIZE][17];

/* ChoxGC.c */
void Chox11ClipRects_AddRef(Chox_ClipRects *rects);
void Chox11ClipRects_Release(Chox_ClipRects *rects);
Chox_ClipRects *Chox11ClipRects_Create(int num_rects, XRectangle *rects);
int Chox11ClipRects_EqualRects(Chox_ClipRects *cr1, Chox_ClipRects **pcr2);
#define Chox11ClipRects_Equal(cr1, cr2)	((cr1 == cr2) ? 1 : Chox11ClipRects_EqualRects(cr1,&(cr2)))
