/*
 * File:      wx_gdi.cc
 * Purpose:     GDI (Graphics Device Interface) objects and functions (X version)
 * Author:      Julian Smart
 * Created:     1993
 * Updated:	August 1994
 * RCS_ID:      $Id: wx_gdi.cc,v 1.3 1994/08/14 21:28:43 edz Exp $
 * Copyright:   (c) 1993, AIAI, University of Edinburgh
 */

static const char sccsid[] = "@(#)wx_gdi.cc	1.2 5/9/94";

#ifdef __GNUG__
#pragma implementation
#endif

#include <iostream.h>
#include "common.h"
#include "wx_utils.h"
#include "wx_main.h"
#include "wx_gdi.h"

#if USE_XPM_IN_X
#include "wx_item.h"
#ifdef VMS
#include "[--.contrib.wxxpm.libxpm.34b.lib]xpm34.h"
#else
extern "C" {
#include "../../contrib/wxxpm/libxpm.34b/lib/xpm34.h"
}
#endif
#endif
#if USE_IMAGE_LOADING_IN_X
#ifdef VMS
#include "[--.utils.image.src]wx_image.h"
#else
#include "../../utils/image/src/wx_image.h"
#endif
#endif

const DISPLAY_DPI = 100;

#ifdef wx_x
XFontPool *wxFontPool = NULL;
#include <X11/cursorfont.h>
#endif

#ifdef wx_motif
#include "wx_frame.h"
#endif

#ifdef wx_xview
#include <xview/screen.h>
#include <xview/cursor.h>
#include <xview/svrimage.h>
extern Xv_Server xview_server;

/* These cursors courtesy of xfig
 */

static const unsigned short bull_cursor_array[16] =
{
  0x0F00, 0x30C0, 0x4020, 0x4020, 0x8010, 0x8610, 0x8610, 0x8010,
  0x4020, 0x4020, 0x30C0, 0x0F00, 0x0000, 0x0000, 0x0000, 0x0000
};

static const unsigned short char_cursor_data[16] =
{
  0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00,
  0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00, 0xFF00,
};

static const unsigned short crosshair_cursor_data[16] =
{
  0x1000, 0x1000, 0x1000, 0xFE00, 0x1000, 0x1000, 0x1000, 0x0000,
  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
};

static const unsigned short magnifier_cursor_array[16] =
{
  0x0F80, 0x3060, 0x4010, 0x4010, 0x8008, 0x8008, 0x8008, 0x8008,
  0x8008, 0x4010, 0x4010, 0x3078, 0x0F9C, 0x000E, 0x0007, 0x0003,
};

static const unsigned short pencil_cursor_array[16] =
{
  0x0000, 0x0018, 0x0024, 0x0075, 0x009B, 0x0117, 0x022E, 0x045C,
  0x08B8, 0x1170, 0x22E0, 0x25C0, 0x7B80, 0x6700, 0x8600, 0x0800,
};

static const unsigned short vbar_cursor_array[16] =
{
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
};

static const unsigned short hand_cursor_array[16] =
{
  0x0C00, 0x1200, 0x1200, 0x1380, 0x1240, 0x7270, 0x9248, 0x924E,
  0x9249, 0x9249, 0x9009, 0x8001, 0x4002, 0x4002, 0x2004, 0x2004
};
#endif

#if !USE_IMAGE_PIXMAP_METHOD
#ifdef wx_motif
Pixmap
XCreateInsensitivePixmap( Display *display, Pixmap pixmap );
#endif
#endif

char *wxDecorativeFontName = copystring("helvetica");
char *wxRomanFontName = copystring("times");
char *wxModernFontName = copystring("courier");
char *wxSwissFontName = copystring("lucida");
char *wxScriptFontName = copystring("zapfchancery");
char *wxTeletypeFontName = copystring("lucidatypewriter");
char *wxDefaultFontName = copystring("*");

IMPLEMENT_DYNAMIC_CLASS(wxFont, wxObject)

wxFont::wxFont (void)
{
  point_size = 0;
  temporary = TRUE;
#ifdef wx_motif
  xFont = NULL;
  mFont = NULL;
#endif
#ifdef wx_xview
  x_font = 0;
#endif
  wxTheFontList->Append (this);
}

/* Constructor for a font. Note that the real construction is done
 * in wxDC::SetFont, when information is available about scaling etc.
 */
wxFont::wxFont (int PointSize, int Family, int Style, int Weight, Bool Underlined):
wxbFont (PointSize, Family, Style, Weight, Underlined)
{
  family = Family;
  style = Style;
  weight = Weight;
  point_size = PointSize;
  underlined = Underlined;
#ifdef wx_motif
  xFont = 0;
  mFont = NULL;
#endif
#ifdef wx_xview
  temporary = TRUE;
  x_font = 0;
#endif

  wxTheFontList->Append (this);
}

wxFont::~wxFont ()
{
#ifdef wx_motif
  if (mFont)
    XmFontListFree (mFont);
  mFont = NULL;
#endif
  wxTheFontList->DeleteObject (this);
}

#ifdef wx_motif
XmFontList wxFont::GetInternalFont (void)
{
  if (mFont == 0)
    {
      int res_x = DISPLAY_DPI;
      int res_y = DISPLAY_DPI;
      int scaled_size = (int) (10 * point_size);

      XFontStruct *fontStruct = wxFontPool->FindNearestFont (
							      family, style,
							weight, scaled_size,
						  underlined, res_x, res_y);
      mFont = XmFontListCreate (fontStruct, XmSTRING_DEFAULT_CHARSET);
    }
  return mFont;
}
#endif

#ifdef wx_xview
Xv_Font wxFont::GetInternalFont (void)
{
  if (x_font == 0)
    {
      int res_x = DISPLAY_DPI;
      int res_y = DISPLAY_DPI;
      int scaled_size = (int) (10 * point_size);

      x_font = wxFontPool->FindNearestFont (family, style,
					    weight, scaled_size,
					    underlined, res_x, res_y);
    }
  return x_font;
}
#endif

#ifdef wx_x
// Pseudo-scaleable Font management under XView - a nightmare!
// - but it works o.k.
XFontInfo::XFontInfo (int the_family, int the_style, int the_weight, int the_point_size,
	   Bool is_underlined,
#ifdef wx_xview
	   Xv_Font the_font)
#else
	   XFontStruct * the_font)
#endif
{
  family = the_family;
  style = the_style;
  weight = the_weight;
  point_size = the_point_size;
  font = the_font;
  underlined = is_underlined;
}

XFontPool::XFontPool (void)
{
  cache = NULL;
}

void XFontPool::
AddFont (int family, int style, int weight, int point_size,
	 Bool is_underlined,
#ifdef wx_xview
	 Xv_Font font)
#else
	 XFontStruct * font)
#endif
{
  XFontInfo *info = new XFontInfo (family, style, weight, point_size, is_underlined, font);
  Append (info);
}

#ifdef wx_xview
Xv_Font
#else
XFontStruct *
#endif
  XFontPool::
FindFont (int family, int style, int weight, int point_size, Bool is_underlined)
{
  if (cache && cache->family == family && cache->style == style && cache->weight == weight
   && cache->point_size == point_size && cache->underlined == is_underlined)
    return cache->font;

  wxNode *node = First ();
#ifdef wx_xview
  Xv_Font
#else
  XFontStruct *
#endif
    found = 0;
  while (node && !found)
    {
      XFontInfo *info = (XFontInfo *) node->Data ();
      if (info->family == family && info->style == style && info->weight == weight
      && info->point_size == point_size && info->underlined == is_underlined)
	{
	  found = info->font;
	  cache = info;
	}
      node = node->Next ();
    }
  return found;
}

// NEW FONT FINDING CODE
#ifdef wx_motif
XFontStruct *
#else
Xv_Font
#endif
XFontPool::
FindOrCreateFont (int family, int style, int weight,
		  int point_size, Bool is_underlined, 
		  int point_size_to_store, int xres, int yres)
{
#ifdef wx_xview
#define POINT_SCALE 10
  Xv_Font font;
#else
#define POINT_SCALE 1
  XFontStruct *font;
#endif

  font = FindFont (family, style, weight, point_size, is_underlined);

  if (!font)
    {
      char *xset;
      char *xfamily;
      char *xstyle;
      char *xweight;

      switch (family)
	{
	case wxDECORATIVE:
	  xfamily = wxDecorativeFontName;
	  break;
	case wxROMAN:
	  xfamily = wxRomanFontName;
	  break;
	case wxMODERN:
	  xfamily = wxModernFontName;
	  break;
	case wxSWISS:
	  xfamily = wxSwissFontName;
	  break;
	case wxSCRIPT:
	  xfamily = wxScriptFontName;
	  break;
	case wxTELETYPE:
	  xfamily = wxTeletypeFontName;
	  break;
	case wxDEFAULT:
	default:
	  xfamily = wxDefaultFontName;
	  break;
	}

      switch (style)
	{
	case wxITALIC:
	  xstyle = "i";
	  break;
	case wxSLANT:
	  xstyle = "o";
	  break;
	case wxNORMAL:
	  xstyle = "r";
	  break;
	default:
	  xstyle = "*";
	  break;
	}

      switch (weight)
	{
	case wxBOLD:
	  xweight = "bold";
	  break;
	case wxLIGHT:
	  xweight = "light";
	  break;
	case wxNORMAL:
	  xweight = "medium";
	  break;
	default:
	  xweight = "*";
	  break;
	}

      if (strchr(xfamily, '-'))
	xset = "";
      else
	xset = "*-";

      sprintf (wxBuffer, "-%s%s-%s-%s-normal-*-*-%d-*-*-*-*-*-*",
	       xset, xfamily, xweight, xstyle, point_size * POINT_SCALE);
      
#ifdef wx_xview
      font = (Xv_Font) xv_find (XV_NULL, FONT,
				FONT_NAME, wxBuffer,
				NULL);
#else
      Display *dpy = XtDisplay (wxTheApp->topLevel);
      font = XLoadQueryFont (dpy, wxBuffer);
#endif

      if (font)
	AddFont (family, style, weight, point_size_to_store, is_underlined, font);
    }

#ifdef wx_xview
  if (!font)
    font = (Xv_Font) xv_find (XV_NULL, FONT,
			      FONT_FAMILY, FONT_FAMILY_DEFAULT,
			      FONT_SIZE, point_size,
			      NULL);
#else
  if (!font) {
    Display *dpy = XtDisplay (wxTheApp->topLevel);
    /* last-ditch efforts to find a font */
    sprintf (wxBuffer, "-*-*--*--*-*-*-*-%d-*-*-*-*-*-*", point_size);
    font = XLoadQueryFont (dpy, wxBuffer);
  }
#endif

  return font;
}

// OLD CODE
#if 0

#ifdef wx_xview
Xv_Font XFontPool::
FindOrCreateFont (int family, int style, int weight, int point_size,
	    Bool is_underlined, int point_size_to_store, int xres, int yres)
{
  Xv_Font font = FindFont (family, style, weight, point_size, is_underlined);

  if (!font)
    {
      char *xfamily;
      char *xstyle;
      char *xname   = NULL;

      /* Determine which font to use */
      switch (family)
	{
	case wxDECORATIVE:
	  xfamily = FONT_FAMILY_HELVETICA;
	  break;
	case wxROMAN:
	  xfamily = FONT_FAMILY_ROMAN;
	  break;
	case wxMODERN:
	  xfamily = FONT_FAMILY_COUR;
	  break;
	case wxSWISS:
	  xfamily = FONT_FAMILY_LUCIDA;
	  break;
	case wxTELETYPE:
	  xfamily = FONT_FAMILY_LUCIDA_FIXEDWIDTH;
	  break;
	case wxSCRIPT:
	  xname = "ZapfChancery-MediumItalic";
	  break;
//    case wxDEFAULT:
	default:
	  xfamily = FONT_FAMILY_DEFAULT;
	  break;
	}

      /* Determine the font style */
      if (style == wxNORMAL && weight == wxNORMAL)
	xstyle = FONT_STYLE_NORMAL;
      else if (style == wxNORMAL && weight == wxBOLD)
	xstyle = FONT_STYLE_BOLD;
      else if (style == wxNORMAL && weight == wxLIGHT)
	xstyle = FONT_STYLE_NORMAL;

      else if (style == wxITALIC && weight == wxNORMAL)
	xstyle = FONT_STYLE_ITALIC;
      else if (style == wxITALIC && weight == wxBOLD)
	xstyle = FONT_STYLE_BOLD_ITALIC;
      else if (style == wxITALIC && weight == wxLIGHT)
	xstyle = FONT_STYLE_ITALIC;

      else if (style == wxSLANT && weight == wxNORMAL)
	xstyle = FONT_STYLE_OBLIQUE;
      else if (style == wxSLANT && weight == wxBOLD)
	xstyle = FONT_STYLE_BOLD_OBLIQUE;
      else if (style == wxSLANT && weight == wxLIGHT)
	xstyle = FONT_STYLE_OBLIQUE;

      else
	xstyle = FONT_STYLE_DEFAULT;

      /* Now search for the font */
      /* Now search for the font */
      if (xname)
        font = (Xv_Font) xv_find (XV_NULL, FONT,
				FONT_NAME, xname,
				FONT_SIZE, point_size,
				NULL);
      else 
        font = (Xv_Font) xv_find (XV_NULL, FONT,
				FONT_FAMILY, xfamily,
				FONT_STYLE, xstyle,
				FONT_SIZE, point_size,
				NULL);

      if (font)
	AddFont (family, style, weight, point_size_to_store, is_underlined, font);
    }
  return font;
}
#endif

#ifdef wx_motif
XFontStruct *XFontPool::
FindOrCreateFont (int family, int style, int weight,
		  int point_size, Bool is_underlined, int point_size_to_store, int xres, int yres)
{
  XFontStruct *font = FindFont (family, style, weight, point_size, is_underlined);

  if (!font)
    {
      char *xfamily;
      char *xstyle;
      char *xweight;

      switch (family)
	{
	case wxDECORATIVE:
	  xfamily = "helvetica";
	  break;
	case wxROMAN:
	  xfamily = "times";
	  break;
	case wxMODERN:
	  xfamily = "courier";
	  break;
	case wxSWISS:
//	  xfamily = "lucida sans";
	  xfamily = "lucida";
	  break;
	case wxSCRIPT:
	  xfamily = "zapfchancery";
	  break;
	case wxTELETYPE:
	  xfamily = "lucidatypewriter";
	  break;
	case wxDEFAULT:
	default:
	  xfamily = "*";
	  break;
	}

      switch (style)
	{
	case wxITALIC:
	  xstyle = "i";
	  break;
	case wxSLANT:
	  xstyle = "o";
	  break;
	case wxNORMAL:
	  xstyle = "r";
	  break;
	default:
	  xstyle = "*";
	  break;
	}

      switch (weight)
	{
	case wxBOLD:
	  xweight = "bold";
	  break;
	case wxLIGHT:
	  xweight = "light";
	  break;
	case wxNORMAL:
	  xweight = "medium";
	  break;
	default:
	  xweight = "*";
	  break;
	}

      sprintf (wxBuffer, "-*-%s-%s-%s-normal-*-*-%d-*-*-*-*-*-*",
	       xfamily, xweight, xstyle, point_size);

      Display *dpy = XtDisplay (wxTheApp->topLevel);
      font = XLoadQueryFont (dpy, wxBuffer);

      if (font)
	AddFont (family, style, weight, point_size_to_store, is_underlined, font);

    }
  return font;
}
#endif
#endif
 // OLD CODE

#ifdef wx_xview
Xv_Font
#else
XFontStruct *
#endif
  XFontPool::
FindNearestFont (int family, int style, int weight, int point_size,
		 Bool is_underlined, int xres, int yres)
{
#ifdef wx_xview
  Xv_Font
#else
  XFontStruct *
#endif
    font = FindOrCreateFont (family, style, weight, point_size, is_underlined, point_size, xres, yres);

  if (!font)
    {
#ifdef wx_xview
#define DELTA 1
#elif defined(wx_motif)
#define DELTA 10
#endif
      const int delta = DELTA;
      /* The weights below might need to be "tuned" @@@@ */
      const int max_size = point_size + 2 * delta * (1 + (point_size / (18 * delta)));
      const int min_size = point_size - 2 * delta * (1 + (point_size / (18 * delta)));
      int i;

      /* Search for another size (approx.) */
      /* Smaller */
      for (i = point_size - delta; !font && i >= delta && i >= min_size; i -= delta)
	font = FindOrCreateFont (family, style, weight, i, is_underlined, point_size, xres, yres);

      /* Larger */
      for (i = point_size + delta; !font && i <= max_size; i += delta)
	font = FindOrCreateFont (family, style, weight, i, is_underlined, point_size, xres, yres);

      /* Try Default family */
      if (!font && family != wxDEFAULT)
	font = FindOrCreateFont (wxDEFAULT, style, weight, point_size, is_underlined, point_size, xres, yres);

      /* Bogus font */
      if (!font)
	{
#ifdef wx_xview
	  int bog_standard = 12;
#elif defined(wx_motif)
	  int bog_standard = 120;
#endif
	  // For next time this happens, remember we just use a bog standard one
	  font = FindOrCreateFont (wxDEFAULT, wxNORMAL, wxNORMAL, bog_standard,
		       is_underlined, point_size, DISPLAY_DPI, DISPLAY_DPI);
	}

      // Remember which font to use for next time
      if (font)
	AddFont (family, style, weight, point_size, is_underlined, font);
    }

  return font;
}

#endif


/*
 * Colour map
 *
 * When constructed with the default constructor, we start from
 * the wxMainColormap, allocating additional read-only cells
 * in Create().  The cells are freed on the next call to Create()
 * or when the destructor is called.
 */
 
/* Wolfram Gloger <u7y22ab@sunmail.lrz-muenchen.de>
I have implemented basic colormap support for the X11 versions of
wxWindows, notably wxColourMap::Create().  The way I did it is to
allocate additional read-only color cells in the default colormap.  In
general you will get arbitrary pixel values assigned to these new
cells and therefore I added a method wxColourMap::TransferBitmap()
which maps the pixel values 0..n to the real ones obtained with
Create().  This is only implemented for the popular case of 8-bit
depth.

Allocating read-write color cells would involve installing a private
X11 colormap for a particular window, and AFAIK this is not
recommended; only the window manager should do this...  Also, it is
not the functionality that wxColourMap::Create() aims to provide.
 */

extern Colormap wxMainColormap;

IMPLEMENT_DYNAMIC_CLASS(wxColourMap, wxObject)

wxColourMap::wxColourMap (void)
{
  cmap = wxMainColormap;
  destroyable = FALSE;
  pix_array = 0;
  pix_array_n = 0;
}

wxColourMap::~wxColourMap (void)
{
  Display *dpy = wxGetDisplay();
  if(pix_array_n > 0)
  {
    XFreeColors(dpy, cmap, pix_array, pix_array_n, 0);
    delete [] pix_array;
    pix_array_n = 0;
  }
  if (destroyable) XFreeColormap(dpy, cmap);
}

Bool
wxColourMap::Create(const int n,
		const unsigned char *red,
		const unsigned char *green,
		const unsigned char *blue)
{
  Display *dpy = wxGetDisplay();
  XColor xcol;

  if(pix_array_n > 0) {
	XFreeColors(dpy, cmap, pix_array, pix_array_n, 0);
	delete [] pix_array;
	pix_array_n = 0;
  }
  pix_array = new unsigned long [n];
  if(!pix_array) return FALSE;
  pix_array_n = n;
  xcol.flags = DoRed | DoGreen | DoBlue;
  for(int i=0; i<n; i++) {
	xcol.red = (unsigned short)red[i] << 8;
	xcol.green = (unsigned short)green[i] << 8;
	xcol.blue = (unsigned short)blue[i] << 8;
	pix_array[i] = (XAllocColor(dpy, cmap, &xcol) == 0) ? 0 : xcol.pixel;
  }
  return TRUE;
}

Bool
wxColourMap::TransferBitmap(void *data, int depth, int size)
{
  switch(depth) {
  case 8:
    {
	unsigned char *uptr = (unsigned char *)data;
	while(size-- > 0) {
		if((int)*uptr < pix_array_n)
		 *uptr = (unsigned char)pix_array[*uptr];
		uptr++;
	}
	return TRUE;
     }
  default:
	return FALSE;
}
}

int wxColourMap::GetPixel(const unsigned char red, const unsigned char green, const unsigned char blue)
{
  return 0;
}

Bool wxColourMap::GetRGB(const int pixel, unsigned char *red, unsigned char *green, unsigned char *blue)
{
  return FALSE;
}

// Pens

IMPLEMENT_DYNAMIC_CLASS(wxPen, wxObject)

wxPen::wxPen (void)
{
  stipple = NULL;
  style = wxSOLID;
  join = wxJOIN_ROUND;
  cap = wxCAP_ROUND;
  nb_dash = 0;
  dash = NULL;
  width = 1;

#if !WXGARBAGE_COLLECTION_ON
  wxThePenList->AddPen (this);
#endif
}

wxPen::~wxPen ()
{
//  if (colour)
//    delete colour;

#if !WXGARBAGE_COLLECTION_ON
  wxThePenList->RemovePen (this);
#endif
}

wxPen::wxPen (wxColour & col, int Width, int Style):
wxbPen (col, Width, Style)
{
  colour = col;

  stipple = NULL;
  width = Width;
  style = Style;
  join = wxJOIN_ROUND;
  cap = wxCAP_ROUND;
  nb_dash = 0;
  dash = NULL;
#if !WXGARBAGE_COLLECTION_ON
  wxThePenList->AddPen (this);
#endif
}

wxPen::wxPen (char *col, int Width, int Style):
wxbPen (col, Width, Style)
{
  colour = col;
  stipple = NULL;
  width = Width;
  style = Style;
  join = wxJOIN_ROUND;
  cap = wxCAP_ROUND;
  nb_dash = 0;
  dash = NULL;

#if !WXGARBAGE_COLLECTION_ON
  wxThePenList->AddPen (this);
#endif
}

// Brushes

IMPLEMENT_DYNAMIC_CLASS(wxBrush, wxObject)

wxBrush::wxBrush (void)
{
  style = wxSOLID;
  stipple = NULL;
#if !WXGARBAGE_COLLECTION_ON
  wxTheBrushList->AddBrush (this);
#endif
}

wxBrush::~wxBrush ()
{
//  if (colour)
//    delete colour;
#if !WXGARBAGE_COLLECTION_ON
  wxTheBrushList->RemoveBrush (this);
#endif
}

wxBrush::wxBrush (wxColour & col, int Style):
wxbBrush (col, Style)
{
  colour = col;
  style = Style;
  stipple = NULL;
#if !WXGARBAGE_COLLECTION_ON
  wxTheBrushList->AddBrush (this);
#endif
}

wxBrush::wxBrush (char *col, int Style):
wxbBrush (col, Style)
{
  colour = col;
  style = Style;
  stipple = NULL;
#if !WXGARBAGE_COLLECTION_ON
  wxTheBrushList->AddBrush (this);
#endif
}

// Icons
IMPLEMENT_DYNAMIC_CLASS(wxIcon, wxBitmap)

wxIcon::wxIcon (char bits[], int Width, int Height)
{
  __type = wxTYPE_ICON;
  ok = FALSE;
  width = Width;
  height = Height;
  numColors = 0;
  x_pixmap = 0;
#ifdef wx_motif
  image = 0;
//  iconWidth = width;
//  iconHeight = height;
  Display *dpy = XtDisplay (wxTheApp->topLevel);
  x_pixmap = XCreateBitmapFromData (dpy, RootWindow (dpy, DefaultScreen (dpy)), bits, width, height);
  if (x_pixmap)
    ok = TRUE;
  else
    ok = FALSE;
#elif defined(wx_xview)
  x_image = (Server_image) xv_create (XV_NULL,
				      SERVER_IMAGE,
				      XV_WIDTH, width,
				      XV_HEIGHT, height,
				      SERVER_IMAGE_X_BITS, bits,
				      NULL);
  x_icon = (Icon) xv_create (XV_NULL,
			     ICON,
                             XV_WIDTH, width,
                             XV_HEIGHT, height,
			     ICON_IMAGE, x_image,
			     NULL);
  if (x_image && x_icon)
    ok = TRUE;
  else
    ok = FALSE;
#endif
//  wxTheIconList->Append (this);
}

wxIcon::wxIcon (void)
{
  __type = wxTYPE_ICON;
  ok = FALSE;
  width = 0;
  height = 0;
  x_pixmap = 0;
#ifdef wx_motif
//  iconWidth = 0;
//  iconHeight = 0;
  image = 0;
#elif defined(wx_xview)
  x_image = 0;
  x_icon = 0;
#endif
//  wxTheIconList->Append (this);
}

wxIcon::wxIcon (const char *icon_file, long flags)
{
  __type = wxTYPE_ICON;
  ok = FALSE;
  width = 0;
  height = 0;
  numColors = 0;
  x_pixmap = 0;
#ifdef wx_motif
  image = 0;
  int hotX, hotY;
  unsigned int w, h;
  Display *dpy = XtDisplay (wxTheApp->topLevel);
  int value = XReadBitmapFile (dpy, RootWindow (dpy, DefaultScreen (dpy)), icon_file, &w, &h, &x_pixmap, &hotX, &hotY);
  width = w;
  height = h;
  if ((value == BitmapFileInvalid) || (value == BitmapOpenFailed) || (value == BitmapNoMemory))
  {
    x_pixmap = 0;
    ok = FALSE;
  }
  else
    ok = TRUE;
#elif defined(wx_xview)
//  x_image = (Server_image) xv_create (XV_NULL, SERVER_IMAGE,
//				      SERVER_IMAGE_BITMAP_FILE, icon_file,
//				      NULL);
   x_icon = 0;
  (void)LoadFile((char *)icon_file, flags);

  if (x_image)
  {
    x_icon = (Icon) xv_create (XV_NULL, ICON,
  			     ICON_IMAGE, x_image,
			     NULL);
    width = (int) xv_get (x_icon, XV_WIDTH);
    height = (int) xv_get (x_icon, XV_HEIGHT);
  }
  if (x_image && x_icon)
    ok = TRUE;
  else
    ok = FALSE;
#endif
//  wxTheIconList->Append (this);
}

#if USE_XPM_IN_X
wxIcon::wxIcon(char **data):wxBitmap(data)
{
  __type = wxTYPE_ICON;

#ifdef wx_motif
#elif defined(wx_xview)
  if (ok)
  {
    x_icon = (Icon) xv_create (XV_NULL, ICON,
                             XV_WIDTH, width,
                             XV_HEIGHT, height,
			     ICON_IMAGE, x_image,
			     NULL);
    if (x_icon)
      ok = TRUE;
    else
      ok = FALSE;
  }
#endif
}
#endif

wxIcon::~wxIcon (void)
{
#ifdef wx_motif
  Display *dpy = XtDisplay (wxTheApp->topLevel);
  if (x_pixmap)
    XFreePixmap (dpy, x_pixmap);
#elif defined(wx_xview)
  xv_destroy_safe (x_icon);
#endif
//  wxTheIconList->DeleteObject (this);
}

// Cursors
IMPLEMENT_DYNAMIC_CLASS(wxCursor, wxBitmap)

wxCursor::wxCursor (void)
{
  __type = wxTYPE_CURSOR;
  x_cursor = 0;
  width = 0;
  height = 0;
  numColors = 0;
  x_pixmap = 0;
  ok = FALSE;
#ifdef wx_motif
  image = 0;
#endif
#ifdef wx_xview
  x_image = 0;
  use_raw_x_cursor = FALSE;
#endif
//  wxTheCursorList->Append (this);
}

wxCursor::wxCursor (char bits[], int w, int h)
{
  __type = wxTYPE_CURSOR;
  x_cursor = 0;
  width = 0;
  height = 0;
  numColors = 0;
  x_pixmap = 0;
#ifdef wx_motif
  ok = FALSE;
  image = 0;
#elif defined(wx_xview)
  x_image = (Server_image) xv_create (XV_NULL, SERVER_IMAGE,
				    XV_WIDTH, w,
				    XV_HEIGHT, h,
				    SERVER_IMAGE_X_BITS, bits,
				    NULL);
  x_cursor = xv_create (XV_NULL, CURSOR, CURSOR_IMAGE, x_image, NULL);
  use_raw_x_cursor = FALSE;
  if (x_cursor && x_image)
    ok = TRUE;
  else
    ok = FALSE;
#endif
//  wxTheCursorList->Append (this);
}


wxCursor::wxCursor (const char *cursor_file, long flags, int hotSpotX, int hotSpotY)
{
  __type = wxTYPE_CURSOR;
  x_cursor = 0;
  width = 0;
  height = 0;
  numColors = 0;
  x_pixmap = 0;
#ifdef wx_motif
  image = 0;
#elif defined(wx_xview)
  x_image = (Server_image) xv_create (XV_NULL, SERVER_IMAGE,
				    SERVER_IMAGE_BITMAP_FILE, cursor_file,
				    NULL);
  x_cursor = xv_create (XV_NULL, CURSOR, CURSOR_IMAGE, x_image, NULL);
  use_raw_x_cursor = FALSE;
#endif
//  wxTheCursorList->Append (this);
}

// Cursors by stock number
wxCursor::wxCursor (int cursor_type)
{
  __type = wxTYPE_CURSOR;
  width = 0;
  height = 0;
  ok = TRUE;
  x_cursor = 0;
  Display *dpy = wxGetDisplay();

  use_raw_x_cursor = FALSE;

#ifdef wx_motif
  image = 0;
  x_pixmap = 0;
#endif
#ifdef wx_xview
  x_image = 0;
#endif

  switch (cursor_type)
    {
    case wxCURSOR_WAIT:
      {
#ifdef wx_xview
	x_cursor = xv_create (XV_NULL, CURSOR, CURSOR_SRC_CHAR, OLC_BUSY_PTR, NULL);
#elif defined(wx_motif)
	x_cursor = XCreateFontCursor (dpy, XC_watch);
#endif
	break;
      }
    case wxCURSOR_CROSS:
      {
#ifdef wx_xview
	Server_image svr_image = (Server_image) xv_create (XV_NULL, SERVER_IMAGE,
							   XV_WIDTH, 16, XV_HEIGHT, 16, SERVER_IMAGE_BITS, crosshair_cursor_data, NULL);
	x_cursor = xv_create (XV_NULL, CURSOR, CURSOR_IMAGE, svr_image,
			      CURSOR_XHOT, 3, CURSOR_YHOT, 3, NULL);
#elif defined(wx_motif)
	x_cursor = XCreateFontCursor (dpy, XC_crosshair);
#endif
	break;
      }
    case wxCURSOR_CHAR:
      {
#ifdef wx_xview
	Server_image svr_image = (Server_image) xv_create (XV_NULL, SERVER_IMAGE,
							   XV_WIDTH, 16, XV_HEIGHT, 16, SERVER_IMAGE_BITS, char_cursor_data, NULL);
	x_cursor = xv_create (XV_NULL, CURSOR, CURSOR_IMAGE, svr_image,
			      CURSOR_XHOT, 0, CURSOR_YHOT, 13, NULL);
#elif defined(wx_motif)
	// Nothing
#endif
	break;
      }
    case wxCURSOR_HAND:
      {
#ifdef wx_xview
	Server_image svr_image = (Server_image) xv_create (XV_NULL, SERVER_IMAGE,
							   XV_WIDTH, 16, XV_HEIGHT, 16, SERVER_IMAGE_BITS, hand_cursor_array, NULL);
	x_cursor = xv_create (XV_NULL, CURSOR, CURSOR_IMAGE, svr_image,
			      CURSOR_XHOT, 5, CURSOR_YHOT, 0, NULL);
#elif defined(wx_motif)
	x_cursor = XCreateFontCursor (dpy, XC_hand1);
#endif
	break;
      }
    case wxCURSOR_BULLSEYE:
      {
#ifdef wx_xview
	Server_image svr_image = (Server_image) xv_create (XV_NULL, SERVER_IMAGE,
							   XV_WIDTH, 16, XV_HEIGHT, 16, SERVER_IMAGE_BITS, bull_cursor_array, NULL);
	x_cursor = xv_create (XV_NULL, CURSOR, CURSOR_IMAGE, svr_image,
			      CURSOR_XHOT, 5, CURSOR_YHOT, 5, NULL);
#elif defined(wx_motif)
	x_cursor = XCreateFontCursor (dpy, XC_target);
#endif
	break;
      }
    case wxCURSOR_PENCIL:
      {
#ifdef wx_xview
	Server_image svr_image = (Server_image) xv_create (XV_NULL, SERVER_IMAGE,
	XV_WIDTH, 16, XV_HEIGHT, 16, SERVER_IMAGE_BITS, pencil_cursor_array,
							   NULL);
	x_cursor = xv_create (XV_NULL, CURSOR, CURSOR_IMAGE, svr_image,
			      CURSOR_XHOT, 0, CURSOR_YHOT, 14, NULL);
#elif defined(wx_motif)
	x_cursor = XCreateFontCursor (dpy, XC_pencil);
#endif
	break;
      }
    case wxCURSOR_MAGNIFIER:
      {
#ifdef wx_xview
	Server_image svr_image = (Server_image) xv_create (XV_NULL, SERVER_IMAGE,
							   XV_WIDTH, 16, XV_HEIGHT, 16, SERVER_IMAGE_BITS, magnifier_cursor_array, NULL);
	x_cursor = xv_create (XV_NULL, CURSOR, CURSOR_IMAGE, svr_image,
			      CURSOR_XHOT, 6, CURSOR_YHOT, 6, NULL);
#elif defined(wx_motif)
	x_cursor = XCreateFontCursor (dpy, XC_sizing);
#endif
	break;
      }
    case wxCURSOR_IBEAM:
      {
#ifdef wx_xview
	Server_image svr_image = (Server_image) xv_create (XV_NULL, SERVER_IMAGE,
							   XV_WIDTH, 16, XV_HEIGHT, 16, SERVER_IMAGE_BITS, vbar_cursor_array, NULL);
	x_cursor = xv_create (XV_NULL, CURSOR, CURSOR_IMAGE, svr_image,
			      CURSOR_XHOT, 0, CURSOR_YHOT, 13, NULL);
#elif defined(wx_motif)
#endif
	break;
      }
    case wxCURSOR_NO_ENTRY:
      {
	use_raw_x_cursor = TRUE;
	x_cursor = XCreateFontCursor (dpy, XC_pirate);
	break;
      }

    case wxCURSOR_LEFT_BUTTON:
      {
	use_raw_x_cursor = TRUE;
	x_cursor = XCreateFontCursor (dpy, XC_leftbutton);
	break;
      }
    case wxCURSOR_RIGHT_BUTTON:
      {
	use_raw_x_cursor = TRUE;
	x_cursor = XCreateFontCursor (dpy, XC_rightbutton);
	break;
      }
    case wxCURSOR_MIDDLE_BUTTON:
      {
	use_raw_x_cursor = TRUE;
	x_cursor = XCreateFontCursor (dpy, XC_middlebutton);
	break;
      }
    case wxCURSOR_QUESTION_ARROW:
      {
	use_raw_x_cursor = TRUE;
	x_cursor = XCreateFontCursor (dpy, XC_question_arrow);
	break;
      }
    case wxCURSOR_SIZING:
      {
	use_raw_x_cursor = TRUE;
	x_cursor = XCreateFontCursor (dpy, XC_sizing);
	break;
      }
    case wxCURSOR_WATCH:
      {
	use_raw_x_cursor = TRUE;
	x_cursor = XCreateFontCursor (dpy, XC_watch);
	break;
      }
    case wxCURSOR_SPRAYCAN:
      {
	use_raw_x_cursor = TRUE;
	x_cursor = XCreateFontCursor (dpy, XC_spraycan);
	break;
      }
    case wxCURSOR_PAINT_BRUSH:
      {
	use_raw_x_cursor = TRUE;
	x_cursor = XCreateFontCursor (dpy, XC_spraycan);
	break;
      }
    case wxCURSOR_SIZENWSE:
    case wxCURSOR_SIZENESW:
      {
	use_raw_x_cursor = TRUE;
	x_cursor = XCreateFontCursor (dpy, XC_circle);
	break;
      }
    case wxCURSOR_SIZEWE:
      {
	use_raw_x_cursor = TRUE;
	x_cursor = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
	break;
      }
    case wxCURSOR_SIZENS:
      {
	use_raw_x_cursor = TRUE;
	x_cursor = XCreateFontCursor (dpy, XC_sb_v_double_arrow);
	break;
      }
    case wxCURSOR_POINT_LEFT:
      {
	use_raw_x_cursor = TRUE;
	x_cursor = XCreateFontCursor (dpy, XC_sb_left_arrow);
	break;
      }
    case wxCURSOR_POINT_RIGHT:
      {
	use_raw_x_cursor = TRUE;
	x_cursor = XCreateFontCursor (dpy, XC_sb_right_arrow);
	break;
      }
    // (JD Huggins) added more stock cursors for X
    // X-only cursors BEGIN
    case wxCURSOR_CROSS_REVERSE:
    {
      use_raw_x_cursor = TRUE;
      x_cursor = XCreateFontCursor(dpy, XC_cross_reverse);
      break;
    }
    case wxCURSOR_DOUBLE_ARROW:
    {
      use_raw_x_cursor = TRUE;
      x_cursor = XCreateFontCursor(dpy, XC_double_arrow);
      break;
    }
    case wxCURSOR_BASED_ARROW_UP:
    {
      use_raw_x_cursor = TRUE;
      x_cursor = XCreateFontCursor(dpy, XC_based_arrow_up);
      break;
    }
    case wxCURSOR_BASED_ARROW_DOWN:
    {
      use_raw_x_cursor = TRUE;
      x_cursor = XCreateFontCursor(dpy, XC_based_arrow_down);
      break;
    }
    // X-only cursors END
    default:
    case wxCURSOR_ARROW:
      {
#ifdef wx_xview
	x_cursor = xv_create (XV_NULL, CURSOR, CURSOR_SRC_CHAR, OLC_BASIC_PTR, NULL);
#elif defined(wx_motif)
	x_cursor = XCreateFontCursor (dpy, XC_top_left_arrow);
#endif
	break;
      }
    case wxCURSOR_BLANK:
      {
	GC gc;
	XGCValues gcv;
	Pixmap empty_pixmap;
	XColor blank_color;

	use_raw_x_cursor = TRUE;
	empty_pixmap = XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)),
				      16, 16, 1);
	gcv.function = GXxor;
	gc = XCreateGC (dpy,
			empty_pixmap,
			GCFunction,
			&gcv);
	XCopyArea (dpy,
		   empty_pixmap,
		   empty_pixmap,
		   gc,
		   0, 0,
		   16, 16,
		   0, 0);
	XFreeGC (dpy, gc);
	x_cursor = XCreatePixmapCursor (dpy,
					empty_pixmap,
					empty_pixmap,
					&blank_color,
					&blank_color,
					8, 8);

	break;
      }
    }
//  wxTheCursorList->Append (this);
}

wxCursor::~wxCursor (void)
{
#ifdef wx_motif
#endif
#ifdef wx_xview
  if (!use_raw_x_cursor && x_cursor)
    xv_destroy_safe (x_cursor);
#endif
//  wxTheCursorList->DeleteObject (this);
}

// Global cursor setting
void 
wxSetCursor (wxCursor * cursor)
{
#ifdef wx_motif
#endif
#ifdef wx_xview
  Xv_Screen screen = xv_get (xview_server, SERVER_NTH_SCREEN, 0);
  Xv_Window root_window = xv_get (screen, XV_ROOT);
  if (cursor && cursor->x_cursor)
    {
      if (cursor->use_raw_x_cursor)
	{
	  Display *dpy = (Display *) xv_get (root_window, XV_DISPLAY);
	  Window win2 = xv_get (root_window, XV_XID);

	  XDefineCursor (dpy, win2, cursor->x_cursor);
	}
      else
	xv_set (root_window, WIN_CURSOR, cursor->x_cursor, NULL);
    }

#endif

  wxFlushEvents ();
}

// Misc. functions

// Return TRUE if we have a colour display
Bool 
wxColourDisplay (void)
{
  Display *dpy = wxGetDisplay();

  if (DefaultDepth (dpy, DefaultScreen (dpy)) < 2)
    return FALSE;
  else
    return TRUE;
}

// Returns depth of screen
int 
wxDisplayDepth (void)
{
  Display *dpy = wxGetDisplay();
  return DefaultDepth (dpy, DefaultScreen (dpy));
}

// Get size of display
void 
wxDisplaySize (int *width, int *height)
{
  Display *dpy = wxGetDisplay();
  
#ifdef wx_motif
  if (wxTheApp->topLevel)
    {
      *width = DisplayWidth (dpy, DefaultScreen (dpy));
      *height = DisplayHeight (dpy, DefaultScreen (dpy));
    }
  else
    {
      // A good bet!
      *width = 1024;
      *height = 768;
    }
#endif
#ifdef wx_xview
  *width = DisplayWidth (dpy, DefaultScreen(dpy));
  *height = DisplayHeight (dpy, DefaultScreen(dpy));
#endif
}

IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxObject)

wxBitmap::wxBitmap (void)
{
  __type = wxTYPE_BITMAP;
  ok = FALSE;
  width = 0;
  height = 0;
  depth = 0;
  numColors = 0;
  bitmapColourMap = NULL;
  x_pixmap = 0;
  freePixmap = FALSE;

  free_colors = NULL;
  free_colors_num = 0;

#ifdef wx_motif
  insensPixmap = 0;
  labelPixmap = 0;
  armPixmap = 0;
  insensImage = 0;
  image = 0;
#endif
#ifdef wx_xview
  x_image = 0;
#endif

#if !WXGARBAGE_COLLECTION_ON
  wxTheBitmapList->Append (this);
#endif
}

wxBitmap::wxBitmap (char bits[], int the_width, int the_height, int no_bits)
{
  __type = wxTYPE_BITMAP;
  depth = no_bits;
  width = the_width;
  height = the_height;
  numColors = 0;
  bitmapColourMap = NULL;
  free_colors = NULL;
  free_colors_num = 0;

#ifdef wx_motif
  insensPixmap = 0;
  labelPixmap = 0;
  armPixmap = 0;
  insensImage = 0;
  image = 0;

  freePixmap = TRUE;
  Display *dpy = XtDisplay (wxTheApp->topLevel);
  x_pixmap = XCreateBitmapFromData (dpy, RootWindow (dpy, DefaultScreen (dpy)), bits, width, height);
  if (x_pixmap)
    ok = TRUE;
  else
    ok = FALSE;

  // code for wxItem
  image = (XImage *) XtMalloc (sizeof (XImage));
  image->width = the_width;
  image->height = the_height;
  image->data = bits;
  image->depth = 1;
  image->xoffset = 0;
  image->format = XYBitmap;
  image->byte_order = LSBFirst;
  image->bitmap_unit = 8;
  image->bitmap_bit_order = LSBFirst;
  image->bitmap_pad = 8;
  image->bytes_per_line = (the_width + 7) >> 3;

  char tmp[128];
  sprintf (tmp, "Im%x", (unsigned int)image);
  XmInstallImage (image, tmp);

  // Build our manually stipped pixmap.

  int bpl = (the_width + 7) / 8;
  char *data = new char[the_height * bpl];
  for (int i = 0; i < the_height; i++)
    {
      int mask = i % 2 ? 0x55 : 0xaa;
      for (int j = 0; j < bpl; j++)
	data[i * bpl + j] = bits[i * bpl + j] & mask;
    }
  insensImage = (XImage *) XtMalloc (sizeof (XImage));
  insensImage->width = the_width;
  insensImage->height = the_height;
  insensImage->data = data;
  insensImage->depth = 1;
  insensImage->xoffset = 0;
  insensImage->format = XYBitmap;
  insensImage->byte_order = LSBFirst;
  insensImage->bitmap_unit = 8;
  insensImage->bitmap_bit_order = LSBFirst;
  insensImage->bitmap_pad = 8;
  insensImage->bytes_per_line = bpl;

  sprintf (tmp, "Not%x", (unsigned int)insensImage);
  XmInstallImage (insensImage, tmp);
#endif
#ifdef wx_xview
  freePixmap = FALSE;
  // Use the class variable, used by wxItem!
  x_image = (Server_image) xv_create (XV_NULL, SERVER_IMAGE,
				      XV_WIDTH, width,
				      XV_HEIGHT, height,
				      SERVER_IMAGE_X_BITS, bits,
				      NULL);

  if (x_image)
    {
      ok = TRUE;
      x_pixmap = (Pixmap) xv_get (x_image, SERVER_IMAGE_PIXMAP);
    }
  else
    ok = FALSE;
#endif
#if !WXGARBAGE_COLLECTION_ON
  wxTheBitmapList->Append (this);
#endif
}

wxBitmap::wxBitmap (char *bitmap_file, long flags)
{
  __type = wxTYPE_BITMAP;
  free_colors = NULL;
  free_colors_num = 0;
  numColors = 0;
  bitmapColourMap = NULL;
#ifdef wx_motif
  insensPixmap = 0;
  labelPixmap = 0;
  armPixmap = 0;
  insensImage = 0;
  image = 0;
  bitmapColourMap = NULL;
#endif
  width = 0;
  height = 0;
  depth = 0;
  freePixmap = FALSE;

  (void)LoadFile(bitmap_file, (int)flags);

#if !WXGARBAGE_COLLECTION_ON
  wxTheBitmapList->Append (this);
#endif
}

#if USE_XPM_IN_X
wxBitmap::wxBitmap(char **data, wxItem *anItem)
{
  __type = wxTYPE_BITMAP;
  free_colors = NULL;
  free_colors_num = 0;
  numColors = 0;
  bitmapColourMap = NULL;
#ifdef wx_motif
  insensPixmap = 0;
  labelPixmap = 0;
  armPixmap = 0;
  insensImage = 0;
  image = 0;
#endif
  width = 0;
  height = 0;
  depth = 0;
  freePixmap = FALSE;

  XpmAttributes xpmAttr;

  ok = FALSE;

  xpmAttr.valuemask = XpmReturnInfos;	/* nothing yet, but get infos back */
  Display *dpy = wxGetDisplay();
#ifdef wx_motif
  XpmColorSymbol symbolicColors[4];
  if (anItem && anItem->handle) {
		symbolicColors[0].name = "foreground";
		symbolicColors[0].value = NULL;
		symbolicColors[1].name = "background";
		symbolicColors[1].value = NULL;
		XtVaGetValues((Widget)anItem->handle,
			XmNforeground,  &symbolicColors[0].pixel,
			XmNbackground,  &symbolicColors[1].pixel,NULL);
		xpmAttr.numsymbols = 2;
		xpmAttr.colorsymbols = symbolicColors;
		xpmAttr.valuemask |= XpmColorSymbols;	// add flag
	}
#endif

  Pixmap  pixmap;
  int ErrorStatus = XpmCreatePixmapFromData(dpy, RootWindow(dpy, DefaultScreen(dpy)),
               data, &pixmap, (Pixmap *) NULL, &xpmAttr);
  if (ErrorStatus == XpmSuccess)
  {
    // Set attributes
    width=xpmAttr.width;
    height = xpmAttr.height;
    if ( xpmAttr.npixels > 2 )
    {
	depth = 8;	// next time not just a guess :-) ...
    } else
    {
	depth = 1;	// mono	
    }
    numColors = xpmAttr.npixels;
    XpmFreeAttributes(&xpmAttr);
    ok = TRUE;
    x_pixmap = pixmap;
  }
  else
  {
//		XpmDebugError(ErrorStatus, NULL);
		ok = False;
  }
// ADDED JACS
#ifdef wx_xview
  freePixmap = TRUE;
  x_image = (Server_image) xv_create (XV_NULL, SERVER_IMAGE,
 				      SERVER_IMAGE_SAVE_PIXMAP, TRUE,
				      SERVER_IMAGE_PIXMAP, pixmap,
                                      SERVER_IMAGE_DEPTH, GetDepth(),
						   NULL);
  if (x_image)
    ok = TRUE;
  else
    ok = FALSE;

#endif
}
#endif

/*
 * Create a new bitmap of a given size and depth
 *
 */

wxBitmap::wxBitmap (int w, int h, int d)
{
  __type = wxTYPE_BITMAP;
  numColors = 0;
  bitmapColourMap = NULL;
  free_colors = NULL;
  free_colors_num = 0;
  bitmapColourMap = NULL;
  (void)Create(w, h, d);
#if !WXGARBAGE_COLLECTION_ON
  wxTheBitmapList->Append (this);
#endif
}

wxBitmap::~wxBitmap (void)
{
  Display *dpy = wxGetDisplay();
#ifdef wx_motif
  if (labelPixmap)
    XmDestroyPixmap (DefaultScreenOfDisplay (dpy), labelPixmap);

  if (armPixmap)
    XmDestroyPixmap (DefaultScreenOfDisplay (dpy), armPixmap);

  if (insensPixmap)
    XmDestroyPixmap (DefaultScreenOfDisplay (dpy), insensPixmap);

  if (image)
    {
      XmUninstallImage (image);
      XtFree ((char *) image);
    }

  if (insensImage)
    {
      XmUninstallImage (insensImage);
      delete[]insensImage->data;
      XtFree ((char *) insensImage);
    }
#endif
#ifdef wx_xview
  // Should we be destroying the Server_image or not?
//  xv_destroy_safe(x_image);
#endif
  if (x_pixmap && freePixmap)
    XFreePixmap (dpy, x_pixmap);

  if (free_colors)
     {
       int screen = DefaultScreen(dpy);
       Colormap cmp = DefaultColormap(dpy,screen);
       long llp;
       for(llp = 0;llp < free_colors_num;llp++)
          XFreeColors(dpy, cmp, &free_colors[llp], 1, 0L);
       delete free_colors;
     };

  if (bitmapColourMap)
    delete bitmapColourMap;

  free_colors = NULL;
  free_colors_num = 0;

#if !WXGARBAGE_COLLECTION_ON
  wxTheBitmapList->DeleteObject (this);
#endif
}

Bool wxBitmap::Create(int w, int h, int d)
{
  width = w;
  height = h;
  depth = d;
  if (d < 1)
    depth = wxDisplayDepth ();

  freePixmap = TRUE;

#ifdef wx_motif
  insensPixmap = 0;
  labelPixmap = 0;
  armPixmap = 0;
  insensImage = 0;
  image = 0;
#endif
  Display *dpy = wxGetDisplay();

  x_pixmap = XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)),
			    width, height, depth);
  if (x_pixmap)
    ok = TRUE;
  else
    ok = FALSE;
  return ok;
}

#ifdef wx_xview
void wxBitmap::CreateServerImage(Bool savePixmap)
{
  if (ok)
  {
    x_image = (Server_image) xv_create (XV_NULL, SERVER_IMAGE,
 				      SERVER_IMAGE_SAVE_PIXMAP, savePixmap,
				      SERVER_IMAGE_PIXMAP, x_pixmap,
                                      SERVER_IMAGE_DEPTH, GetDepth(),
						   NULL);
    freePixmap = savePixmap;

    if (x_image)
      ok = TRUE;
    else
      ok = FALSE;
  }
}
#endif

Bool wxBitmap::LoadFile(char *filename, long flags)
{
  if (flags & wxBITMAP_TYPE_XBM)
  {
#ifdef wx_motif
    insensPixmap = 0;
    labelPixmap = 0;
    armPixmap = 0;
    insensImage = 0;
    image = 0;
    width = 0;
    height = 0;
    
    freePixmap = TRUE;
    int hotX, hotY;
    unsigned int w, h;
    Display *dpy = XtDisplay (wxTheApp->topLevel);
    int value = XReadBitmapFile (dpy, RootWindow (dpy, DefaultScreen (dpy)),
                        filename, &w, &h, &x_pixmap, &hotX, &hotY);
    width = w;
    height = h;
    depth = 1;
    if ((value == BitmapFileInvalid) ||
        (value == BitmapOpenFailed) ||
        (value == BitmapNoMemory))
      {
        ok = FALSE;
        x_pixmap = 0;
      }
    else
      ok = TRUE;
#endif
#ifdef wx_xview
    freePixmap = FALSE;
    x_image = (Server_image) xv_create (XV_NULL, SERVER_IMAGE,
				      SERVER_IMAGE_BITMAP_FILE, filename,
						   NULL);
    if (x_image)
      {
        x_pixmap = (Pixmap) xv_get (x_image, SERVER_IMAGE_PIXMAP);
        depth = (int) xv_get (x_image, SERVER_IMAGE_DEPTH);
        width = (int) xv_get (x_image, XV_WIDTH);
        height = (int) xv_get (x_image, XV_HEIGHT);
        ok = TRUE;
        return TRUE;
      }
    else
    {
      ok = FALSE;
      return FALSE;
    }
#endif
  }
#if USE_XPM_IN_X
  else if (flags & wxBITMAP_TYPE_XPM)
  {
    Display *dpy = wxGetDisplay();
    XpmAttributes xpmAttr;
    Pixmap  pixmap;

    ok = FALSE;
    xpmAttr.valuemask = XpmReturnInfos | XpmCloseness;
    xpmAttr.closeness = 40000;
    int errorStatus = XpmReadFileToPixmap(dpy,
        RootWindow(dpy, DefaultScreen(dpy)), filename,
        &pixmap, (Pixmap *) NULL, &xpmAttr);
    if (errorStatus == XpmSuccess)
    {
        x_pixmap = pixmap;

	width=xpmAttr.width;
	height = xpmAttr.height;
	if ( xpmAttr.npixels > 2 ) {
		depth = 8;	// next time not just a guess :-) ...
	} else {
		depth = 1;	// mono	
	}

	numColors = xpmAttr.npixels;

	XpmFreeAttributes(&xpmAttr);

        ok = TRUE;
    } else
    {
//      XpmDebugError(errorStatus, filename);
      ok = FALSE;
      return FALSE;
    }
// ADDED JACS
#ifdef wx_xview
    CreateServerImage(TRUE);
#endif
    return ok;
  }
#endif
#if USE_IMAGE_LOADING_IN_X
  else if ((flags & wxBITMAP_TYPE_ANY) || (flags & wxBITMAP_TYPE_BMP) ||
           (flags & wxBITMAP_TYPE_GIF))
  {
    // BUGBUG: no depth information returned!!!
    wxColourMap *cmap = NULL;
    Bool success = FALSE;
    if (flags & wxBITMAP_DISCARD_COLOURMAP)
      success = wxLoadIntoBitmap(filename, this);
    else
      success = wxLoadIntoBitmap(filename, this, &cmap);
    if (!success && cmap)
    {
      delete cmap;
      cmap = NULL;
    }
    if (cmap)
      bitmapColourMap = cmap;
#ifdef wx_xview
    CreateServerImage(TRUE);
#endif
    return success;
  }
#endif
  return FALSE;
}

Bool wxBitmap::SaveFile(char *filename, int typ, wxColourMap *cmap)
{
  switch (typ)
  {
#if USE_IMAGE_LOADING_IN_X
/* IMAGE SAVING NOT IN X YET
    case wxBITMAP_TYPE_BMP:
    {
      wxColourMap *actualCmap = cmap;
      if (!actualCmap)
        actualCmap = bitmapColourMap;
      return wxSaveBitmap(filename, this, actualCmap);
      break;
    }
 */
#endif
#if defined(USE_XPM_IN_MSW) && defined(wx_msw)
    case wxBITMAP_TYPE_XPM:
    {
      if (ok && x_pixmap)
      {
        Display *dpy = wxGetDisplay();
        int errorStatus = XpmWriteFileFromPixmap(dpy, filename,
          x_pixmap, (Pixmap) NULL, (XpmAttributes *) NULL);
        if (errorStatus == XpmSuccess)
          return TRUE;
        else
          return FALSE;
      }
      else
        return FALSE;
      break;
    }
#endif
    default:
      break;
  }
  return FALSE;
}

#ifdef wx_motif
Pixmap wxBitmap::GetLabelPixmap (Widget w)
{
  if (image == 0)
    return x_pixmap;

  Display *dpy = XtDisplay (wxTheApp->topLevel);

#ifdef FOO
/*
   If we do:
   if (labelPixmap) return labelPixmap;
   things can be wrong, because colors can have been changed.

   If we do:
   if (labelPixmap)
   XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
   we got BadDrawable if the pixmap is referenced by multiples widgets

   this is a catch22!!

   So, before doing thing really clean, I just do nothing; if the pixmap is
   referenced by many widgets, Motif performs caching functions.
   And if pixmap is referenced with multiples colors, we just have some
   memory leaks... I hope we can deal with them...
 */
  // Must be destroyed, because colours can have been changed!
  if (labelPixmap)
    XmDestroyPixmap (DefaultScreenOfDisplay (dpy), labelPixmap);
#endif

  char tmp[128];
  sprintf (tmp, "Im%x", (unsigned int)image);

  Pixel fg, bg;

  while (XmIsGadget (w))
    w = XtParent (w);
  XtVaGetValues (w, XmNbackground, &bg, XmNforeground, &fg, NULL);

  labelPixmap = XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);

  return (labelPixmap);
}

Pixmap wxBitmap::GetArmPixmap (Widget w)
{
  if (image == 0)
    return x_pixmap;

  Display *dpy = XtDisplay (wxTheApp->topLevel);
#ifdef FOO
  See GetLabelPixmap () comment
  // Must be destroyed, because colours can have been changed!
  if (armPixmap)
      XmDestroyPixmap (DefaultScreenOfDisplay (dpy), armPixmap);
#endif

  char tmp[128];
  sprintf (tmp, "Im%x", (unsigned int)image);

  Pixel fg, bg;

  XtVaGetValues (w, XmNarmColor, &bg, NULL);
  while (XmIsGadget (w))
    w = XtParent (w);
  XtVaGetValues (w, XmNforeground, &fg, NULL);

  armPixmap = XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);

  return (armPixmap);
}

Pixmap wxBitmap::GetInsensPixmap (Widget w)
{
  Display *dpy = XtDisplay (wxTheApp->topLevel);

  if (insensImage == 0)
    return x_pixmap;

#ifdef FOO
  See GetLabelPixmap () comment
  // Must be destroyed, because colours can have been changed!
  if (insensPixmap)
      XmDestroyPixmap (DefaultScreenOfDisplay (dpy), insensPixmap);
#endif

  char tmp[128];
  sprintf (tmp, "Not%x", (unsigned int)insensImage);

  Pixel fg, bg;

  while (XmIsGadget (w))
    w = XtParent (w);
  XtVaGetValues (w, XmNbackground, &bg, XmNforeground, &fg, NULL);

  insensPixmap = XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);

  return (insensPixmap);
}

#endif

// We may need this sometime...
#if 0
#ifdef wx_motif
/****************************************************************************

NAME
	XCreateInsensitivePixmap - create a grayed-out copy of a pixmap

SYNOPSIS
	Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )

DESCRIPTION
	This function creates a grayed-out copy of the argument pixmap, suitable
	for use as a XmLabel's XmNlabelInsensitivePixmap resource.

RETURN VALUES
	The return value is the new Pixmap id or zero on error.  Errors include
	a NULL display argument or an invalid Pixmap argument.

ERRORS
	If one of the XLib functions fail, it will produce a X error.  The
	default X error handler prints a diagnostic and calls exit().

SEE ALSO
	XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
	XFillRectangle(3), exit(2)

AUTHOR
	John R Veregge - john@puente.jpl.nasa.gov
	Advanced Engineering and Prototyping Group (AEG)
	Information Systems Technology Section (395)
	Jet Propulsion Lab - Calif Institute of Technology

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

Pixmap
XCreateInsensitivePixmap( Display *display, Pixmap pixmap )

{
static
	char	stipple_data[] = 
		{
			0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
			0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
			0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
			0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA 
		};
    GC		gc;
    Pixmap	ipixmap, stipple;
    unsigned	width, height, depth;

    Window	window;	/* These return values */
    unsigned	border;	/* from XGetGeometry() */
    int		x, y;	/* are not needed.     */

    ipixmap = 0;

    if ( NULL == display || 0 == pixmap )
	return ipixmap;

    if ( 0 == XGetGeometry( display, pixmap, &window, &x, &y,
			    &width, &height, &border, &depth )
       )
	return ipixmap; /* BadDrawable: probably an invalid pixmap */

    /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
    */
    stipple = XCreateBitmapFromData( display, pixmap, stipple_data, 16, 16 );
    if ( 0 != stipple )
    {
	gc = XCreateGC( display, pixmap, (XtGCMask)0, (XGCValues*)NULL );
	if ( NULL != gc )
	{
	    /* Create an identical copy of the argument pixmap.
	    */
	    ipixmap = XCreatePixmap( display, pixmap, width, height, depth );
	    if ( 0 != ipixmap )
	    {
		/* Copy the argument pixmap into the new pixmap.
		*/
		XCopyArea( display, pixmap, ipixmap,
			   gc, 0, 0, width, height, 0, 0 );

		/* Refill the new pixmap using the stipple algorithm/pixmap.
		*/
		XSetStipple( display, gc, stipple );
		XSetFillStyle( display, gc, FillStippled );
		XFillRectangle( display, ipixmap, gc, 0, 0, width, height );
	    }
	    XFreeGC( display, gc );
	}
	XFreePixmap( display, stipple );
    }
    return ipixmap;
}
#endif
#endif
