/*
 * $Id: Awindow.c 3.00 1998/09/21 19:17:47 NielsF Exp NielsF $
 */
/*
 * (c) Copyright 1993, Silicon Graphics, Inc.
 * ALL RIGHTS RESERVED
 * Permission to use, copy, modify, and distribute this software for
 * any purpose and without fee is hereby granted, provided that the above
 * copyright notice appear in all copies and that both the copyright notice
 * and this permission notice appear in supporting documentation, and that
 * the name of Silicon Graphics, Inc. not be used in advertising
 * or publicity pertaining to distribution of the software without specific,
 * written prior permission.
 *
 * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
 * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
 * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
 * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
 * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
 * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
 * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
 * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
 * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
 * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
 */

/*
 * $Log: Awindow.c $
 * Revision 3.0  1998/09/21  19:17:47  NielsF
 * bumped to mesa 3.0
 * 
 * $Log: Awindow.c $
 * Revision 1.8  1997/06/25  19:17:47  StefanZ
 * bumped to mesa 2.2
 * 
 * Revision 1.5  1996/10/07  00:18:11  StefanZ
 * Mesa 2.0 Fixed
 * 
 * Revision 1.4  1996/08/14  22:53:16  StefanZ
 * rev 1.3 tk fixes was from George 'Wulf' Krämer
 * 
 * Revision 1.3  1996/08/14  22:23:31  StefanZ
 * Modified due to api change in amigaMesa
 * Implemented div. Input modifier and changed windowhandling
 * 
 * Revision 1.2  1996/06/02  00:03:03  StefanZ
 * Started to use RCS to keep track of code.
 * 
 */
/*
 * History:
 * 
 * 1.0 960315 Now almost evetything is implemented
 * 1.1 960425 Fixed problem with double closeclicks (Thanx to Daniel Jönsson)
 * 1.2 960731 Modified due to api change in amigaMesa
 * 1.3 Implemented div. Input modifier and changed windowhandling (Georg 'Wulf' Krämer)
 * 
 * TODO:
 * Exposefunc
 * 
 * 
 */

//#define USE_CLIP_LAYER
#undef USE_CLIP_LAYER

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#include <intuition/intuition.h>
#include <devices/inputevent.h>
#include <inline/exec.h>
#include <inline/intuition.h>
#include <inline/graphics.h>

#ifdef USE_CLIP_LAYER
#include <inline/layers.h>
#endif
extern struct ExecBase *SysBase;

#include <gl/gltk.h>
#include <gl/amigamesa.h>

#define static

#if defined(__cplusplus) || defined(c_plusplus)
#define class c_class
#endif

#if DBG
#define TKASSERT(x)                                     \
if ( !(x) ) {                                           \
	PrintMessage("%s(%d) Assertion failed %s\n",        \
		__FILE__, __LINE__, #x);                        \
}
#else
#define TKASSERT(x)
#endif									       /*
									        * * DBG 
									        */

/*
 * Some Bitmasks for amigaevents 
 */
#define ControlMask         (IEQUALIFIER_CONTROL)
#define ShiftMask           (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)
#define MousePressedMask    (SELECTDOWN | MENUDOWN | MIDDLEDOWN)

/**********************************************************************/

struct wnd {
  int x, y, width, height;
  GLenum type, dmPolicy;
  GLint ID;

  struct amigamesa_context *context;
  struct Screen *screen;
  struct Window *window;
#ifdef USE_CLIP_LAYER
  struct Region *clipreg;
#endif
};

struct wnd win =
{0, 0, 100, 100, TK_INDEX, 0, 0, NULL, NULL, NULL
#ifdef USE_CLIP_LAYER
,NULL
#endif
};

/*
 * Local prototypes 
 */
struct Region *clipWindow(struct Window *win,
			  LONG minX, LONG minY, LONG maxX, LONG maxY);
struct Region *clipWindowToBorders(struct Window *win);

GLboolean tkPopupEnable = TRUE;

/*
 * Fixed palette support.  
 */
// #define BLACK   PALETTERGB(0,0,0)
// #define WHITE   PALETTERGB(255,255,255)
// #define NUM_STATIC_COLORS   (COLOR_BTNHIGHLIGHT - COLOR_SCROLLBAR + 1)
static void (*ExposeFunc) (int, int) = NULL;
static void (*ReshapeFunc) (GLsizei, GLsizei) = NULL;
static void (*DisplayFunc) (void) = NULL;
static GLenum(*KeyDownFunc) (int, GLenum) = NULL;
static GLenum(*MouseDownFunc) (int, int, GLenum) = NULL;
static GLenum(*MouseUpFunc) (int, int, GLenum) = NULL;
static GLenum(*MouseMoveFunc) (int, int, GLenum) = NULL;
static void (*IdleFunc) (void) = NULL;

#ifdef USE_CLIP_LAYER
/*
 * Get from clipping example of the RKM 
 */
/*
 * clipWindow()
 * Clip a window to a specified rectangle (given by upper left and
 * lower right corner.)  the removed region is returned so that it
 * may be re-installed later.
 */
struct Region *clipWindow(struct Window *win,
			  LONG minX, LONG minY, LONG maxX, LONG maxY)
{
  struct Region *new_region;
  struct Rectangle my_rectangle;

  /*
   * set up the limits for the clip 
   */
  my_rectangle.MinX = minX;
  my_rectangle.MinY = minY;
  my_rectangle.MaxX = maxX;
  my_rectangle.MaxY = maxY;

  /*
   * get a new region and OR in the limits. 
   */
  if (NULL != (new_region = NewRegion())) {
    if (FALSE == OrRectRegion(new_region, &my_rectangle)) {
      DisposeRegion(new_region);
      new_region = NULL;
    }
  }

  /*
   * Install the new region, and return any existing region.
   * If the above allocation and region processing failed, then
   * new_region will be NULL and no clip region will be installed.
   */
  return (InstallClipRegion(win->WLayer, new_region));
}

/*
 * clipWindowToBorders()
 * clip a window to its borders.
 * The removed region is returned so that it may be re-installed later.
 */
struct Region *clipWindowToBorders(struct Window *win)
{
  return (clipWindow(win, win->BorderLeft, win->BorderTop,
     win->Width - win->BorderRight - 1, win->Height - win->BorderBottom - 1));
}
#endif

float colorMaps[] = {
    0.000000, 1.000000, 0.000000, 1.000000, 0.000000, 1.000000, 
    0.000000, 1.000000, 0.333333, 0.776471, 0.443137, 0.556863, 
    0.443137, 0.556863, 0.219608, 0.666667, 0.666667, 0.333333, 
    0.666667, 0.333333, 0.666667, 0.333333, 0.666667, 0.333333, 
    0.666667, 0.333333, 0.666667, 0.333333, 0.666667, 0.333333, 
    0.666667, 0.333333, 0.039216, 0.078431, 0.117647, 0.156863, 
    0.200000, 0.239216, 0.278431, 0.317647, 0.356863, 0.400000, 
    0.439216, 0.478431, 0.517647, 0.556863, 0.600000, 0.639216, 
    0.678431, 0.717647, 0.756863, 0.800000, 0.839216, 0.878431, 
    0.917647, 0.956863, 0.000000, 0.000000, 0.000000, 0.000000, 
    0.000000, 0.000000, 0.000000, 0.000000, 0.247059, 0.247059, 
    0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 
    0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 
    0.498039, 0.498039, 0.749020, 0.749020, 0.749020, 0.749020, 
    0.749020, 0.749020, 0.749020, 0.749020, 1.000000, 1.000000, 
    1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 
    0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 
    0.000000, 0.000000, 0.247059, 0.247059, 0.247059, 0.247059, 
    0.247059, 0.247059, 0.247059, 0.247059, 0.498039, 0.498039, 
    0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 
    0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 
    0.749020, 0.749020, 1.000000, 1.000000, 1.000000, 1.000000, 
    1.000000, 1.000000, 1.000000, 1.000000, 0.000000, 0.000000, 
    0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 
    0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 
    0.247059, 0.247059, 0.498039, 0.498039, 0.498039, 0.498039, 
    0.498039, 0.498039, 0.498039, 0.498039, 0.749020, 0.749020, 
    0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 
    1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 
    1.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 
    0.000000, 0.000000, 0.000000, 0.000000, 0.247059, 0.247059, 
    0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 
    0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 
    0.498039, 0.498039, 0.749020, 0.749020, 0.749020, 0.749020, 
    0.749020, 0.749020, 0.749020, 0.749020, 1.000000, 1.000000, 
    1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 
    0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 
    0.000000, 0.000000, 0.247059, 0.247059, 0.247059, 0.247059, 
    0.247059, 0.247059, 0.247059, 0.247059, 0.498039, 0.498039, 
    0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 
    0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 
    0.749020, 0.749020, 1.000000, 1.000000, 1.000000, 1.000000, 
    1.000000, 1.000000, 1.000000, 1.000000, 0.000000, 0.000000, 
    1.000000, 1.000000, 0.000000, 0.000000, 1.000000, 1.000000, 
    0.333333, 0.443137, 0.776471, 0.556863, 0.443137, 0.219608, 
    0.556863, 0.666667, 0.666667, 0.333333, 0.666667, 0.333333, 
    0.666667, 0.333333, 0.666667, 0.333333, 0.666667, 0.333333, 
    0.666667, 0.333333, 0.666667, 0.333333, 0.666667, 0.333333, 
    0.039216, 0.078431, 0.117647, 0.156863, 0.200000, 0.239216, 
    0.278431, 0.317647, 0.356863, 0.400000, 0.439216, 0.478431, 
    0.517647, 0.556863, 0.600000, 0.639216, 0.678431, 0.717647, 
    0.756863, 0.800000, 0.839216, 0.878431, 0.917647, 0.956863, 
    0.000000, 0.141176, 0.282353, 0.427451, 0.568627, 0.713726, 
    0.854902, 1.000000, 0.000000, 0.141176, 0.282353, 0.427451, 
    0.568627, 0.713726, 0.854902, 1.000000, 0.000000, 0.141176, 
    0.282353, 0.427451, 0.568627, 0.713726, 0.854902, 1.000000, 
    0.000000, 0.141176, 0.282353, 0.427451, 0.568627, 0.713726, 
    0.854902, 1.000000, 0.000000, 0.141176, 0.282353, 0.427451, 
    0.568627, 0.713726, 0.854902, 1.000000, 0.000000, 0.141176, 
    0.282353, 0.427451, 0.568627, 0.713726, 0.854902, 1.000000, 
    0.000000, 0.141176, 0.282353, 0.427451, 0.568627, 0.713726, 
    0.854902, 1.000000, 0.000000, 0.141176, 0.282353, 0.427451, 
    0.568627, 0.713726, 0.854902, 1.000000, 0.000000, 0.141176, 
    0.282353, 0.427451, 0.568627, 0.713726, 0.854902, 1.000000, 
    0.000000, 0.141176, 0.282353, 0.427451, 0.568627, 0.713726, 
    0.854902, 1.000000, 0.000000, 0.141176, 0.282353, 0.427451, 
    0.568627, 0.713726, 0.854902, 1.000000, 0.000000, 0.141176, 
    0.282353, 0.427451, 0.568627, 0.713726, 0.854902, 1.000000, 
    0.000000, 0.141176, 0.282353, 0.427451, 0.568627, 0.713726, 
    0.854902, 1.000000, 0.000000, 0.141176, 0.282353, 0.427451, 
    0.568627, 0.713726, 0.854902, 1.000000, 0.000000, 0.141176, 
    0.282353, 0.427451, 0.568627, 0.713726, 0.854902, 1.000000, 
    0.000000, 0.141176, 0.282353, 0.427451, 0.568627, 0.713726, 
    0.854902, 1.000000, 0.000000, 0.141176, 0.282353, 0.427451, 
    0.568627, 0.713726, 0.854902, 1.000000, 0.000000, 0.141176, 
    0.282353, 0.427451, 0.568627, 0.713726, 0.854902, 1.000000, 
    0.000000, 0.141176, 0.282353, 0.427451, 0.568627, 0.713726, 
    0.854902, 1.000000, 0.000000, 0.141176, 0.282353, 0.427451, 
    0.568627, 0.713726, 0.854902, 1.000000, 0.000000, 0.141176, 
    0.282353, 0.427451, 0.568627, 0.713726, 0.854902, 1.000000, 
    0.000000, 0.141176, 0.282353, 0.427451, 0.568627, 0.713726, 
    0.854902, 1.000000, 0.000000, 0.141176, 0.282353, 0.427451, 
    0.568627, 0.713726, 0.854902, 1.000000, 0.000000, 0.141176, 
    0.282353, 0.427451, 0.568627, 0.713726, 0.854902, 1.000000, 
    0.000000, 0.141176, 0.282353, 0.427451, 0.568627, 0.713726, 
    0.854902, 1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 
    1.000000, 1.000000, 1.000000, 1.000000, 0.333333, 0.443137, 
    0.443137, 0.219608, 0.776471, 0.556863, 0.556863, 0.666667, 
    0.666667, 0.333333, 0.666667, 0.333333, 0.666667, 0.333333, 
    0.666667, 0.333333, 0.666667, 0.333333, 0.666667, 0.333333, 
    0.666667, 0.333333, 0.666667, 0.333333, 0.039216, 0.078431, 
    0.117647, 0.156863, 0.200000, 0.239216, 0.278431, 0.317647, 
    0.356863, 0.400000, 0.439216, 0.478431, 0.517647, 0.556863, 
    0.600000, 0.639216, 0.678431, 0.717647, 0.756863, 0.800000, 
    0.839216, 0.878431, 0.917647, 0.956863, 0.000000, 0.000000, 
    0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 
    0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 
    0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 
    0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 
    0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 
    0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 
    0.000000, 0.000000, 0.247059, 0.247059, 0.247059, 0.247059, 
    0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 
    0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 
    0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 
    0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 
    0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 
    0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 0.247059, 
    0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 
    0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 
    0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 
    0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 
    0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 
    0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 0.498039, 
    0.498039, 0.498039, 0.498039, 0.498039, 0.749020, 0.749020, 
    0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 
    0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 
    0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 
    0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 
    0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 
    0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 0.749020, 
    0.749020, 0.749020, 1.000000, 1.000000, 1.000000, 1.000000, 
    1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 
    1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 
    1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 
    1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 
    1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 
    1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 
};

float tkRGBMap[8][3] =
{
  {0, 0, 0},
  {1, 0, 0},
  {0, 1, 0},
  {1, 1, 0},
  {0, 0, 1},
  {1, 0, 1},
  {0, 1, 1},
  {1, 1, 1}
};

/**********************************************************************/

struct Library *GfxBase = NULL;
struct Library *IntuitionBase = NULL;
struct Library *LayersBase = NULL;

void tkShutDown(int code) {
  tkCloseWindow();
  exit(0);
}

void tkConstructor(void) {
  if(!(IntuitionBase = OpenLibrary("intuition.library", 39))) {
    printf("Can't open intuition.library version 39\n");
    exit(10);
  }
  if(!(GfxBase = OpenLibrary("graphics.library", 39))) {
    printf("Can't open graphics.library version 39\n");
    exit(10);
  }
  if(!(LayersBase = OpenLibrary("layers.library", 39))) {
    printf("Can't open layers.library version 39\n");
    exit(10);
  }
  signal(SIGINT, tkShutDown);
  signal(SIGTERM, tkShutDown);
}

void tkDestructor(void) {
  if(IntuitionBase) {
    CloseLibrary(IntuitionBase);
    IntuitionBase = 0;
  }
  if(GfxBase) {
    CloseLibrary(GfxBase);
    GfxBase = 0;
  }
  if(LayersBase) {
    CloseLibrary(LayersBase);
    LayersBase = 0;
  }
}

#if 0
asm ("	.text; 	.stabs \"___CTOR_LIST__\",22,0,0,_constructor");
asm ("	.text; 	.stabs \"___DTOR_LIST__\",22,0,0,_destructor");
#endif

/******************************************************************************/
int atk_setIDCMPs(void)
{
  int mask;

  mask = IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE;
  if (ReshapeFunc)
    mask |= IDCMP_NEWSIZE;
  if (KeyDownFunc)
    mask |= (IDCMP_RAWKEY | IDCMP_VANILLAKEY);
  if (MouseDownFunc || MouseUpFunc)
    mask |= IDCMP_MOUSEBUTTONS;
  if (MouseMoveFunc)
    mask |= IDCMP_MOUSEMOVE;

  return (mask);
}

/*
 * TODO (*ExposeFunc)(int, int)   
 */

void atk_modifyIDCMP(void)
{
  if (win.window) {
    ModifyIDCMP(win.window, atk_setIDCMPs());
  }
}

int atk_FixKeyRAW(char c)
{
  int key;

  switch (c) {
    // case XK_Return:   key = TK_RETURN;    break;
    // case XK_Escape:   key = TK_ESCAPE;    break;
    case CURSORLEFT:
      key = TK_LEFT;
      break;
    case CURSORUP:
      key = TK_UP;
      break;
    case CURSORRIGHT:
      key = TK_RIGHT;
      break;
    case CURSORDOWN:
      key = TK_DOWN;
      break;
    default:
      key = GL_FALSE;
      break;
  }
  return (key);
}

/***************************************************************
 *                                                             *
 *  Exported Functions go here                                 *
 *                                                             *
 ***************************************************************/

/******************************************************************************/
/* cursor.c								      */
/******************************************************************************/

void tkNewCursor(GLint id, GLubyte * shapeBuf, GLubyte * maskBuf, GLenum fgColor,
		 GLenum bgColor, GLint hotX, GLint hotY) {}
void tkSetCursor(GLint id) {}

/******************************************************************************/
/*									      */
/******************************************************************************/

void tkErrorPopups(GLboolean bEnable)
{
  tkPopupEnable = bEnable;
}

/******************************************************************************/
/* window.c								      */
/******************************************************************************/

void tkCloseWindow(void)
{
  if (win.context) {
    amigaMesaDestroyContext(win.context);
    win.context = NULL;
  }
#ifdef USE_CLIP_LAYER
  if (win.clipreg) {
    win.clipreg = InstallClipRegion(win.window->WLayer, win.clipreg);
    DisposeRegion(win.clipreg);
    win.clipreg = NULL;
  }
#endif
  if (win.window) {
    CloseWindow(win.window);
    win.window = NULL;
  }
}

void tkInitDisplayModePolicy(GLenum type)
{
  win.dmPolicy = type;
}

GLenum tkInitDisplay(void)
{
  return GL_TRUE;
}

void tkInitDisplayMode(GLenum type)
{
  win.type = type;
}

GLenum tkInitDisplayModeID(GLint ID)
{
  if(!win.window)
    return GL_FALSE;
  else {
    win.ID = ID;
    return GL_TRUE;
  }
}

void tkInitPosition(int x, int y, int width, int height)
{
  win.x = x;
  win.y = y;
  win.width = width;
  win.height = height;
}

GLenum tkInitWindow(char *title)
{
  GLenum Result = GL_FALSE, RGB_Flag = GL_TRUE, DB_Flag = GL_FALSE;

  if (!(win.screen = LockPubScreen("Mesa")))
    win.screen = LockPubScreen(NULL);
  if (win.screen) {
    /*
     * open the window on the public win.screen 
     */

    win.window = OpenWindowTags(NULL,
			    WA_Left, win.x, WA_Top, win.x,
			    WA_InnerWidth, win.width,
			    WA_InnerHeight, win.height,
			    WA_ReportMouse, TRUE,
			    WA_RMBTrap, TRUE,				       /*
									        * Detect right mouse events, no Menus 
									        */
			    WA_MinWidth, 100, WA_MinHeight, 30,
			    WA_MaxWidth, -1, WA_MaxHeight, -1,
			    WA_IDCMP, (unsigned long)atk_setIDCMPs(),
			    WA_Flags, (unsigned long)WFLG_GIMMEZEROZERO | WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_NOCAREREFRESH | WFLG_REPORTMOUSE | WFLG_CLOSEGADGET | WFLG_DEPTHGADGET | WFLG_SIZEBBOTTOM,
			    WA_Title, title,
			    WA_PubScreen, win.screen,
			    TAG_END);
    /*
     * Unlock the win.screen.  The window now acts as a lock on
     * ** the win.screen, and we do not need the win.screen after the
     * ** window has been closed.  
     */
    UnlockPubScreen(NULL, win.screen);

    if (win.window) {
#ifdef USE_CLIP_LAYER
      win.clipreg = clipWindowToBorders(win.window);
#endif
      if (win.type & TK_INDEX) {
	RGB_Flag = GL_FALSE;
      }
      if (win.type & TK_DOUBLE) {
	DB_Flag = GL_TRUE;
      }

      win.context = amigaMesaCreateContextTags(AMA_DrawMode, AMESA_CYBERGFX,
					       AMA_Window, (unsigned long)win.window,
				               AMA_RastPort, (unsigned long)win.window->RPort,
				               AMA_Screen, (unsigned long)win.window->WScreen,
					       AMA_DoubleBuf, DB_Flag,
					       AMA_RGBMode, RGB_Flag,
/*					       AMA_Left, win.window->BorderLeft, */
/*					       AMA_Bottom, win.window->BorderBottom, */
					       AMA_Width, win.width,
					       AMA_Height, win.height,
					       TAG_DONE, 0);
      amigaMesaMakeCurrent(win.context, win.context->buffer);
      tkSetRGBMap(256, colorMaps);
      Result = GL_TRUE;
    }
    else {
      printf("Failed to open window.\n");
    }
  }
  return Result;
}

/*
 * You cannot just call DestroyWindow() here.  The programs do not expect
 * tkQuit() to return;  DestroyWindow() just sends a WM_DESTROY message
 */

void tkQuit(void)
{
  tkCloseWindow();
  exit(0);
}

void tkSwapBuffers(void)
{
  amigaMesaSwapBuffers(win.context);
}

/******************************************************************************/
/* events.c								      */
/******************************************************************************/

//#define PL printf("%d\n",__LINE__);

void tkExec(void)
{
  struct IntuiMessage *msg;
  BOOL done = FALSE;
  BOOL press = FALSE;
  int key, id;

  /*
   * Redraw handling changed by Wulf 11. Aug. 96 to ensure the
   * same handling under all systems 
   */
  GLenum Redraw = GL_FALSE;

  // printf("tkExec\n");

  if (ReshapeFunc) {
    (*ReshapeFunc) (win.window->GZZWidth, win.window->GZZHeight);
  }

  if (DisplayFunc) {
    //printf("DisplayFunk\n");
    (*DisplayFunc) ();
  }

  while (!done) {
    if ((msg = (struct IntuiMessage *)GetMsg(win.window->UserPort))) {
      id = msg->Class;
      // printf("msg->Class=0x%x\n",id);
      /*
       * after ReplyMsg, you are nolonger allowed to use msg !
       */
      switch (id) {
	case IDCMP_NEWSIZE:
	  /*
	   * Sizes should be adjusted by border, but painting isn't adjusted :-( 
	   */
	  win.width = win.window->GZZWidth;
	  win.height = win.window->GZZHeight;
#ifdef USE_CLIP_LAYER
	  if (win.clipreg)						       // Get rid of last clipping region
	    DisposeRegion(InstallClipRegion(msg->IDCMPWindow->WLayer, NULL));
	  clipWindowToBorders(msg->IDCMPWindow);
#endif
	  ReplyMsg((struct Message *)msg);
	  if (ReshapeFunc)
	    (*ReshapeFunc) (win.width, win.height);
	  Redraw = GL_TRUE;
	  break;
	case IDCMP_RAWKEY:
	  key = atk_FixKeyRAW(msg->Code);
	  if (key && KeyDownFunc) {
	    GLenum mask;

	    mask = 0;
	    if (msg->Qualifier & ControlMask)
	      mask |= TK_CONTROL;
	    if (msg->Qualifier & ShiftMask)
	      mask |= TK_SHIFT;
	    ReplyMsg((struct Message *)msg);
	    Redraw = (*KeyDownFunc) (key, mask);
	  }
	  else
	    ReplyMsg((struct Message *)msg);
	  break;
	case IDCMP_VANILLAKEY:
	  if (KeyDownFunc) {
	    GLenum mask;

	    mask = 0;
	    if (msg->Qualifier & ControlMask)
	      mask |= TK_CONTROL;
	    if (msg->Qualifier & ShiftMask)
	      mask |= TK_SHIFT;
	    key = msg->Code;
	    ReplyMsg((struct Message *)msg);
	    Redraw = (*KeyDownFunc) (key, mask);
	  }
	  else
	    ReplyMsg((struct Message *)msg);
	  break;
	case IDCMP_MOUSEMOVE:
	  if (MouseMoveFunc) {
	    int x = msg->MouseX, y = msg->MouseY;

	    ReplyMsg((struct Message *)msg);
	    Redraw = (*MouseMoveFunc) (x, y, press);
	  }
	  else
	    ReplyMsg((struct Message *)msg);
	  break;
	case IDCMP_MOUSEBUTTONS:
	  /*
	   * Buttonhandling changed Wulf 11.08.96 
	   */
	  // printf("code=%x\n",(WORD)msg->Code); 
	  {
	    GLenum mask = 0;
	    int x = msg->MouseX, y = msg->MouseY;

	    switch (msg->Code) {
	      case SELECTDOWN:
	      case SELECTUP:
		mask |= TK_LEFTBUTTON;
		break;
	      case MIDDLEDOWN:
	      case MIDDLEUP:
		mask |= TK_MIDDLEBUTTON;
		break;
	      case MENUDOWN:
	      case MENUUP:
		mask |= TK_RIGHTBUTTON;
		break;
	    }
	    if (msg->Qualifier & ControlMask)
	      mask |= TK_CONTROL;
	    if (msg->Qualifier & ShiftMask)
	      mask |= TK_SHIFT;
	    if ((msg->Code & MousePressedMask)) {
	      press = mask;
	      if (MouseDownFunc) {
		ReplyMsg((struct Message *)msg);
		Redraw = (*MouseDownFunc) (x, y, mask);
	      }
	      else
		ReplyMsg((struct Message *)msg);
	    }
	    else {
	      if (MouseUpFunc) {
		ReplyMsg((struct Message *)msg);
		Redraw = (*MouseUpFunc) (x, y, mask);
	      }
	      else
		ReplyMsg((struct Message *)msg);
	      press = 0;
	    }
	  }
	  break;
	case IDCMP_REFRESHWINDOW:					       /*
									        * Not entierly tested! Wulf 11.08.96 
									        */
	  BeginRefresh(msg->IDCMPWindow);				       /*
									        * Refresh Gadgets 
									        */
	  EndRefresh(msg->IDCMPWindow, TRUE);
	  ReplyMsg((struct Message *)msg);
	  if (ExposeFunc)
	    (*ExposeFunc) (win.width, win.height);
	  Redraw = GL_TRUE;
	  break;
	case IDCMP_CLOSEWINDOW:
	  ReplyMsg((struct Message *)msg);
	  done = TRUE;
	  break;
	default:
	  ReplyMsg((struct Message *)msg);
	  break;
      }
    }
    /*
     * TODO Fill this with tests and call apropriate functions 
     */
    if (IdleFunc) {
      (*IdleFunc) ();
      Redraw = GL_TRUE;
    }
    if ((Redraw == GL_TRUE) && DisplayFunc) {				       /*
									        * Redraw handling changed by Wulf 11. Aug. 96 
									        */
      (*DisplayFunc) ();
      Redraw = GL_FALSE;
    }
    if (!done && !IdleFunc) {
      WaitPort(win.window->UserPort);
    }
  }
  tkQuit();								       /*
									        * do not return after quit 
									        */
}

void tkExposeFunc(void (*Func) (int, int))
{
  ExposeFunc = Func;
  atk_modifyIDCMP();
}

void tkReshapeFunc(void (*Func) (GLsizei, GLsizei))
{
  ReshapeFunc = Func;
  atk_modifyIDCMP();
}

void tkDisplayFunc(void (*Func) (void))
{
  DisplayFunc = Func;
}

void tkKeyDownFunc(GLenum(*Func) (int, GLenum))
{
  KeyDownFunc = Func;
  atk_modifyIDCMP();
}

void tkMouseDownFunc(GLenum(*Func) (int, int, GLenum))
{
  MouseDownFunc = Func;
  atk_modifyIDCMP();
}

void tkMouseUpFunc(GLenum(*Func) (int, int, GLenum))
{
  MouseUpFunc = Func;
  atk_modifyIDCMP();
}

void tkMouseMoveFunc(GLenum(*Func) (int, int, GLenum))
{
  MouseMoveFunc = Func;
  atk_modifyIDCMP();
}

void tkIdleFunc(void (*Func) (void))
{
  IdleFunc = Func;
}

/******************************************************************************/
/* getset.c 								      */
/******************************************************************************/

GLint tkGetColorMapSize(void)
{
  /*
   * AmigaMesa simulates 8bit-Index in any case,
   * so we have 256 colors ever
   */
  return (256);
}

void tkGetMouseLoc(int *x, int *y)
{
  *x = win.window->MouseX;
  *y = win.window->MouseY;
}

void tkGetSystem(TKenum type, void *ptr)
{
  switch (type) {
    case TK_AOS_SCREEN:
      *((struct Screen **)ptr) = win.screen;
      break;
    case TK_AOS_WINDOW:
      *((struct Window **)ptr) = win.window;
      break;
    case TK_AOS_CONTEXT:
      *((struct amigamesa_context **)ptr) = win.context;
      break;
    default:
      *((int **)ptr) = 0;
      break;
  }
}

void tkSetFogRamp(int density, int startIndex)
{
  int fogValues, colorValues;
  int i, j, k;
  float intensity;

  fogValues = 1 << density;
  colorValues = 1 << startIndex;
  for (i = 0; i < colorValues; i++) {
    for (j = 0; j < fogValues; j++) {
      k = i * fogValues + j;
      intensity = (i * fogValues + j * colorValues) / 255.0;
      tkSetOneColor(k, intensity, intensity, intensity);
    }
  }
}

void tkSetGreyRamp(void)
{
  int i;
  float intensity;

  for (i = 0; i < 255; i++) {
    intensity = i / 255.0;
    tkSetOneColor(i, intensity, intensity, intensity);
  }
}

void tkSetOneColor(int index, float r, float g, float b)
{
  amigaMesaSetOneColor(win.context, index, r, g, b);
}

void tkSetOverlayMap(int size, float *rgb)
{
  printf("tkSetOverlayMap(%d,%f) TODO\n", size, *rgb);
}

void tkSetRGBMap(int Size, float *Values)
{
  int i;

  if (Size > 256)
    Size = 256;

  for (i = 0; i < Size; i++) {
    tkSetOneColor(i, Values[           i],
		     Values[Size     + i],
		     Values[Size * 2 + i]);
  }
}

GLenum tkSetWindowLevel(GLenum level)
{
  printf("tkSetWindowLevel(%d) TODO\n", level);
  return GL_FALSE;
}

/******************************************************************************/
/*									      */
/******************************************************************************/

GLint tkGetDisplayModeID(void)
{
  return win.ID;
}

GLint tkGetDisplayModePolicy(void)
{
  return win.dmPolicy;
}

GLenum tkGetDisplayMode(void)
{
  return win.type;
}

#undef USE_CLIP_LAYER
