/****************************************************************************
    Copyright (C) 1987-2005 by Jeffery P. Hansen

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    Last edit by hansen on Tue Dec  2 09:56:02 2003
****************************************************************************/
#include <stdlib.h>
#include "tkgate.h"
#include <X11/Xutil.h>

#define DEBUG_ICON 0

static SHash *icon_pixmaps = 0;
static NHash *zoomed_pixmaps = 0;

static Icon **icon_table = 0;
static int icon_table_len = 0;
static int icon_table_alloced = 16;

void icon_init()
{
  icon_pixmaps = new_SHash();
  zoomed_pixmaps = new_NHash();
  icon_table = (Icon**) ob_calloc(icon_table_alloced,sizeof(Icon*),"Icon*[]");
}

void Pixmap_initZoomSet(Pixmap p,int w,int h)
{
  int i;
  PixmapZoomSet *zset;

  zset = (PixmapZoomSet*)ob_malloc(sizeof(PixmapZoomSet),"PixmapZoomSet");
  for (i = 0;i < ZOOM_MAX+1;i++)
    zset->p[i] = 0;
  zset->p[1] = p;
  zset->width = w;
  zset->height = h;
  NHash_insert(zoomed_pixmaps,p,zset);
}

Pixmap Pixmap_register(char *name,unsigned char bits[],int w,int h)
{
  Pixmap *P;

  if (!XGate.tcl) return None;

  if (SHash_find(icon_pixmaps,name))
    return None;

  P = (Pixmap*) ob_malloc(sizeof(Pixmap),"Pixmap");
  *P = XCreatePixmapFromBitmapData(XGate.D,XGate.root,bits,w,h,1,0,1);
  SHash_insert(icon_pixmaps,name,P);
  Pixmap_initZoomSet(*P,w,h);

  return *P;
}

Pixmap Pixmap_registerFromFileWithParms(char *name,char *file,int *pw,int *ph,int *px,int *py)
{
  static const char *base_dir = 0;
  Pixmap *P;
  int w,h,x,y;
  char buf[STRMAX];

  if (!XGate.tcl) return None;


  if (!base_dir) {
    base_dir = Tcl_GetVar(XGate.tcl,"bd",TCL_GLOBAL_ONLY);
    if (!base_dir) base_dir = "bitmaps";
  }

  sprintf(buf,"%s/%s",base_dir,file);

  if (SHash_find(icon_pixmaps,name))
    return None;

  P = (Pixmap*) ob_malloc(sizeof(Pixmap),"Pixmap");

  if (XReadBitmapFile(XGate.D,XGate.root,buf,&w,&h,P,&x,&y) != BitmapSuccess) {
    fprintf(stderr,"Failed to find required bitmap '%s'\n",buf);
    exit(1);
    return None;
  }

  SHash_insert(icon_pixmaps,name,P);
  Pixmap_initZoomSet(*P,w,h);

  if (pw) *pw = w;
  if (ph) *ph = h;
  if (px) *px = x;
  if (py) *py = y;

  return *P;
}

Pixmap Pixmap_registerFromFile(char *name,char *file)
{
  return Pixmap_registerFromFileWithParms(name,file,0,0,0,0);
}


Pixmap Pixmap_find(char *name)
{
  Pixmap *P = (Pixmap*) SHash_find(icon_pixmaps,name);

  if (!P) return None;

  return *P;
}

/*
 * Create a copy of pixmap p magnified by scale factor zp
 */
Pixmap Pixmap_createZoomPixmap(Pixmap p,int w,int h,int zp)
{
  XImage *SI = XGetImage(XGate.D,p,0,0,w,h,0x1,XYPixmap);
  Pixmap DP = XCreatePixmap(XGate.D,XGate.root,zp*w,zp*h,1);
  XImage *DI = XGetImage(XGate.D,DP,0,0,zp*w,zp*h,0x1,XYPixmap);
  int x,y;

  for (x = 0;x < w;x++) {
    for (y = 0;y < h;y++) {
      int v = XGetPixel(SI,x,y);
      int a,b;

      for (a = 0;a < zp;a++)
	for (b = 0;b < zp;b++)
	  XPutPixel(DI,x*zp+a,y*zp+b,v);
    }
  }

  XPutImage(XGate.D,DP,XGate.bitGC,DI,0,0,0,0,zp*w,zp*h);


  XDestroyImage(DI);
  XDestroyImage(SI);

  return DP;
}


/*
 * Find and/or create zoomed pixmap
 */
Pixmap Pixmap_zoom(Pixmap p,int z)
{
  PixmapZoomSet *zset;
  if (z == 1) return p;

  zset = (PixmapZoomSet*)NHash_find(zoomed_pixmaps,p);
  if (!zset) return None;
  if (!zset->p[z]) {
    zset->p[z] = Pixmap_createZoomPixmap(p,zset->width,zset->height,z);
  }

  return zset->p[z];
}

Icon *new_Icon(Pixmap P,int x,int y,int w,int h,int ox,int oy)
{
  Icon *I = (Icon*) ob_malloc(sizeof(Icon),"Icon");

  I->pm = P;
  I->x = x;
  I->y = y;
  I->width = w;
  I->height = h;
  I->ox = ox;
  I->oy = oy;

#if DEBUG_ICON
  printf("create icon [%p p=(%d,%d) %dx%d o=(%d,%d) ]\n",
	 I->pm,I->x,I->y,I->width,I->height,I->ox,I->oy);
#endif
  return I;
}

int Icon_register(Pixmap P,int x,int y,int w,int h,int ox,int oy)
{
  Icon *I = new_Icon(P,x,y,w,h,ox,oy);

  if (icon_table_len >= icon_table_alloced) {
    Icon **newIT;
    int i;

    icon_table_alloced *= 2;
    newIT = ob_calloc(icon_table_alloced,sizeof(Icon*),"Icon*[]");
    for (i = 0;i < icon_table_len;i++)
      newIT[i] = icon_table[i];
    ob_free(icon_table);
    icon_table = newIT;
  }

  icon_table[icon_table_len] = I;

  return icon_table_len++;
}

int Icon_idimRegister(Pixmap P,iconDimensions *id,int yoffset)
{
  return Icon_register(P,id->x,id->y+yoffset,
		       id->w,id->h,
		       id->ox,id->oy);

}

Icon *Icon_find(int id)
{
  return icon_table[id];
}

void Icon_draw(Display *D,Window W,GC gc,int x,int y,int id)
{
  Icon *I = icon_table[id];

#if DEBUG_ICON
  printf("draw icon [%p p=(%d,%d) %dx%d o=(%d,%d) ] @(%d, %d) \n",
	 I->pm,I->x,I->y,I->width,I->height,I->ox,I->oy,x,y);
#endif
  ZCopyPlane(D,I->pm,W,gc,I->x,I->y,I->width,I->height,x-I->ox,y-I->oy,0x1);
}

