#include <stdio.h>
#include <malloc.h>
#include <unistd.h>
#include <asm/bitops.h>
#include <stdlib.h>
#include <string.h>
#include "loadim.h"


#ifdef XPM
#include "linux.xpm"
#include <X11/xpm.h>
#include <X11/xpmP.h>

/* 
 * This utils just loads a XPM format pixmap on the vga screen.
 * Colors are remapped to just 16 colors so an image may not look as it
 * actually was designed to be. See "loadim.h" for argument passing.
 */

void 
loadxpm (char *name, vga_bitmap *image)
{

  XpmImage xpmimage;
  XpmInfo xpminfo;
  int i,
    j;
  char pcmap16[16],
   *cmap16[24] =
  {
    "black",
    "blue",
    "green",
    "cyan",
    "red",
    "magenta",
    "brown",
    "lightgray",
    "darkgray",
    "lightblue",
    "lightgreen",
    "lightcyan",
    "lightred",
    "lightmagenta",
    "yellow",
    "white",
  };

  if (name && !access (name, F_OK | R_OK))
    XpmReadFileToXpmImage (name, &xpmimage, &xpminfo);
  else {
    image->data=NULL;
    image->wid=0;
    image->ht=0;
    return;
  }

  /* Remap colors in the xpm file to 16 colors */
  for (pcmap16[i=0]=0; i < xpmimage.ncolors; pcmap16[++i]=0) {
    for (j = 0; j < 16; j++)
      if (!strncasecmp (xpmimage.colorTable[i].c_color,
			cmap16[j], strlen (cmap16[j])))
	pcmap16[i] = j;
  }
  image->data=malloc(xpmimage.width*xpmimage.height);
  bzero(image->data,xpmimage.width*xpmimage.height);
  for (i = 0; i < xpmimage.width * xpmimage.height; i++) {
      image->data[i] =  pcmap16[xpmimage.data[i]];
  }
 image->wid=xpmimage.width;
 image->ht=xpmimage.height;
 XpmFreeXpmImage(&xpmimage);
}
#endif

/* Set the default bitmap background to BLACK and the foreground to WHITE */
static int xbmbg=0, xbmfg=15;

/* Thes allow us to change the bitmap colors */
inline void vga_xbmsetbg(int col) { xbmbg=col; };
inline void vga_xbmsetfg(int col) { xbmfg=col; };

void 
loadxbmfromdata (char *bitmap_data, int wid, int ht, vga_bitmap *image) {
int i;

 if (!bitmap_data) {
    image->data=NULL;
    image->wid=0;
    image->ht=0;
    return;
  }
   image->wid=wid;
   image->ht=ht;
   image->data = malloc (image->ht * image->wid);
    for (i = 0; i < image->wid*image->ht; i++)
	image->data[i] = test_bit (i, bitmap_data) ? xbmfg : xbmbg;

}

void 
loadxbm (char *name, vga_bitmap *image)
{
  int i = 0,
    j;
  FILE *fp;
  int maxlinelen = 1024;
  char str[1024],
    p[10],
   *q;
  int look_for_dimensions = 2;
  char *data = NULL;

  if (!name || !(fp = fopen (name, "r"))) {
    image->data=NULL;
    image->wid=0;
    image->ht=0;
    return;
  }

  fgets (str, maxlinelen, fp);
  while (!feof (fp)) {
    if (look_for_dimensions) {
      if (strstr (str, "_width ")) {
	--look_for_dimensions;
	sscanf (str, "%*s%*s%s", p);
	image->wid = atoi (p);
	image->wid = image->wid%8?(1+(image->wid/8))<<3:image->wid;
      } else if (strstr (str, "_height ")) {
	--look_for_dimensions;
	sscanf (str, "%*s%*s%s", p);
	image->ht = atoi (p);
      }
    } else {
      if (!data)
	data = malloc (image->ht * image->wid);
      for (q = strtok (str, ", \t\n};"); q; q = strtok (NULL, ", \t\n};"))
	if (*q && *q == '0' && *(q + 1) && *(q + 1) == 'x') {
	  data[i++]=strtol(q,0,16);
	}
    }
    fgets (str, maxlinelen, fp);
  }
  fclose (fp);

  image->data = malloc (image->ht * image->wid);
    for (j = 0; j < image->wid*image->ht; j++)
	image->data[j] = test_bit (j, data) ? xbmfg : xbmbg;
  free (data);
}

void
vga_tile(vga_bitmap *image, 
	 int x, int y, int wid, int ht) {
  char *scanline;
  int i,w;

  if (!image || !image->data || image->wid<=0 || image->ht<=0) return;

  scanline = malloc (wid * image->ht);
  for (i = 0; i < image->ht; i++) {
    for (w = 0; w < image->wid; w++)
      scanline[w + i * wid] = image->data[w + i * image->wid];

    if (image->wid < wid) {
      for (w = 1; w < wid / image->wid; w++)
	bcopy (scanline + i * wid,
	       scanline + i * wid + w * image->wid, image->wid);
      if (wid % image->wid)
	bcopy (scanline + i * wid,
	       scanline + i * wid + w * image->wid, wid % image->wid);
    }
  }
  for (i = 0; i < ht; i++)
    vga_drawscansegment (scanline + (i % image->ht) * wid, x, y + i, wid);

  free(scanline);
}
