/* Copyright (C) 2004 Damir Zucic */

/*=============================================================================

				makepixmap2.c

Purpose:
	Make pixmap from  an array of strings.  Array is obtained  from the
	file which is included in calling  function;  MakePixmap_  receives
	pointer to char pointer. Xpm library is not used here. Xpm is quite
	good,  but raw Xlib was chosen to make  the whole garlic package as
	portable as possible.  Though many systems have  Xpm library, there
	are still some which don't. Pixmap should be  hard-coded (included)
	in calling function.  This function should be used to create pixmap
	which is  not bound to any window.  Pixmaps bound to windows should
	be created using the function MakePixmap_ (make_pixmap.c).

Input:
	(1) Pointer to the pixmap identifier.
	(2) Pointer to the pixmap width.
	(3) Pointer to the pixmap height.
	(4) Pointer to GUIS structure.
	(5) Pointer to char pointer, with pixmap data. There are no special
	    checks: if pixmap file is bad, core dump may be expected. Check
	    each pixmap with a program like cxpm.  Up to 256 color allowed.
	    pixmap  data.  It has file scope.  This file is not checked; if
	    it is bad, core dump may be expected. If icon pixmap is changed
	    it may be checked with cxpm program.  Up to 256 colors allowed.

Output:
	(1) Pixmap created.
	(2) Pixmap identifier.
	(3) Pixmap width.
	(4) Pixmap height.
	(5) Return value.

Return value:
	(1) Positive on success.
	(2) Negative on failure.

========includes:============================================================*/

#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>

#include "defines.h"
#include "typedefs.h"

/*======function prototypes:=================================================*/

void		ErrorMessage_ (char *, char *, char *,
			       char *, char *, char *, char *);
void		RGBSFromXColor_ (RGBS *, XColor *);
unsigned long	PixelFromRGBS_ (RGBS *, GUIS *);

/*======make pixmap from an array of strings, version 2:=====================*/

int MakePixmap2_ (Pixmap *pixmapIDP,
		  unsigned int *pixmap_widthP, unsigned int *pixmap_heightP,
		  GUIS *guiSP, char **dataPP)
{
unsigned int	width, height, colorsN;
Status		status;
XColor		colorS;
RGBS		rgbS;
unsigned long	black_colorID;
Pixmap		pixmapID;
int		i, j;
char		line_copyA[STRINGSIZE];
int		n;
char		*P, *P1;
unsigned long	pixel;
unsigned long	colorIDA[256];
int		offset;

/* Extract pixmap dimensions and number of colors: */
if (sscanf (*dataPP, "%u %u %u", &width, &height, &colorsN) != 3)
	{
	ErrorMessage_ ("garlic", "MakePixmap_", "",
		"Failed to extract data from pixmap header!\n", "", "", "");
	return -1;
	}

/* Check the number of colors: */
if (colorsN > 256)
	{
	ErrorMessage_ ("garlic", "MakePixmap_", "",
		"Number of colors in pixmap limited to 256!\n", "", "", "");
	return -2;
	}

/* Store pixmap width and height: */
*pixmap_widthP  = width;
*pixmap_heightP = height;

/* Prepare the black color (replacement for unrecognized colors): */
status = XParseColor (guiSP->displaySP, guiSP->colormapID, "black", &colorS);
if (status)
	{
	RGBSFromXColor_ (&rgbS, &colorS);
	black_colorID = PixelFromRGBS_ (&rgbS, guiSP);
	}
else
	{
	ErrorMessage_ ("garlic", "MakePixmap_", "",
		       "Unable to parse black color!\n", "", "", "");
	return -3;
	}

/* Create pixmap: */
pixmapID = XCreatePixmap (guiSP->displaySP,
			  DefaultRootWindow (guiSP->displaySP),
			  width, height, guiSP->depth);
*pixmapIDP = pixmapID;

/* Parse colors: */
/* (Note: be sure that pixmap is good, no check is done here!) */
for (i = 1; i < (int) colorsN + 1; i++)
	{
	/** Copy the i-th line: **/
	strncpy (line_copyA, *(dataPP + i), STRINGSIZE - 1);
	line_copyA[STRINGSIZE - 1] = '\0';

	/** The first token is the color array index: **/
	n = line_copyA[0];

	/** Skip the first character and take one token; **/
	/** it should be letter  'c' or 's' - ignore it: **/
	P1 = line_copyA + 1;
	P = strtok (P1, " \t");

	/** The next token is color specification; **/
	P = strtok (NULL, " \t\"");

	/** This token is expected to specify some color; parse it: **/
	status = XParseColor (guiSP->displaySP, guiSP->colormapID, P, &colorS);
	if (status)
		{
		RGBSFromXColor_ (&rgbS, &colorS);
		pixel = PixelFromRGBS_ (&rgbS, guiSP);
		}
	else pixel = black_colorID;
	colorIDA[n] = pixel;
	}

/* Parse pixels and draw pixmap using default graphics context: */
offset = colorsN + 1;
for (j = 0; j < (int) height; j++)
	{
	offset = j + colorsN + 1;
	for (i = 0; i < (int) width; i++)
		{
		P = *(dataPP + offset) + i;
		n = *P;
		XSetForeground (guiSP->displaySP,
				guiSP->theGCA[0],
				colorIDA[n]);
		XDrawPoint (guiSP->displaySP, pixmapID,
			    guiSP->theGCA[0],
			    i, j);
		}
	}

return 1;
}

/*===========================================================================*/


