#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "Xlibint.h"
#include <X11/Xos.h>
#include "Xutil.h"
#include <stdio.h>
#include <ctype.h>
#define MAX_SIZE 255
static const short hexTable[256] = {
['0'] = 0, ['1'] = 1,
['2'] = 2, ['3'] = 3,
['4'] = 4, ['5'] = 5,
['6'] = 6, ['7'] = 7,
['8'] = 8, ['9'] = 9,
['A'] = 10, ['B'] = 11,
['C'] = 12, ['D'] = 13,
['E'] = 14, ['F'] = 15,
['a'] = 10, ['b'] = 11,
['c'] = 12, ['d'] = 13,
['e'] = 14, ['f'] = 15,
[' '] = -1, [','] = -1,
['}'] = -1, ['\n'] = -1,
['\t'] = -1
};
static int
NextInt (
FILE *fstream)
{
int ch;
int value = 0;
int gotone = 0;
int done = 0;
while (!done) {
ch = getc(fstream);
if (ch == EOF) {
value = -1;
done++;
} else {
ch &= 0xff;
if (isascii(ch) && isxdigit(ch)) {
value = (value << 4) + hexTable[ch];
gotone++;
} else if ((hexTable[ch]) < 0 && gotone)
done++;
}
}
return value;
}
int
XReadBitmapFileData (
_Xconst char *filename,
unsigned int *width,
unsigned int *height,
unsigned char **data,
int *x_hot,
int *y_hot)
{
FILE *fstream;
unsigned char *bits = NULL;
char line[MAX_SIZE];
int size;
char name_and_type[MAX_SIZE];
char *type;
int value;
int version10p;
int padding;
int bytes_per_line;
unsigned int ww = 0;
unsigned int hh = 0;
int hx = -1;
int hy = -1;
#ifdef __UNIXOS2__
filename = __XOS2RedirRoot(filename);
#endif
if (!(fstream = fopen(filename, "r")))
return BitmapOpenFailed;
#define RETURN(code) \
{ if (bits) Xfree ((char *)bits); fclose (fstream); return code; }
while (fgets(line, MAX_SIZE, fstream)) {
if (strlen(line) == MAX_SIZE-1)
RETURN (BitmapFileInvalid);
if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
if (!(type = strrchr(name_and_type, '_')))
type = name_and_type;
else
type++;
if (!strcmp("width", type))
ww = (unsigned int) value;
if (!strcmp("height", type))
hh = (unsigned int) value;
if (!strcmp("hot", type)) {
if (type-- == name_and_type || type-- == name_and_type)
continue;
if (!strcmp("x_hot", type))
hx = value;
if (!strcmp("y_hot", type))
hy = value;
}
continue;
}
if (sscanf(line, "static short %s = {", name_and_type) == 1)
version10p = 1;
else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
version10p = 0;
else if (sscanf(line, "static char %s = {", name_and_type) == 1)
version10p = 0;
else
continue;
if (!(type = strrchr(name_and_type, '_')))
type = name_and_type;
else
type++;
if (strcmp("bits[]", type))
continue;
if (!ww || !hh)
RETURN (BitmapFileInvalid);
if ((ww % 16) && ((ww % 16) < 9) && version10p)
padding = 1;
else
padding = 0;
bytes_per_line = (ww+7)/8 + padding;
size = bytes_per_line * hh;
bits = (unsigned char *) Xmalloc ((unsigned int) size);
if (!bits)
RETURN (BitmapNoMemory);
if (version10p) {
unsigned char *ptr;
int bytes;
for (bytes=0, ptr=bits; bytes<size; (bytes += 2)) {
if ((value = NextInt(fstream)) < 0)
RETURN (BitmapFileInvalid);
*(ptr++) = value;
if (!padding || ((bytes+2) % bytes_per_line))
*(ptr++) = value >> 8;
}
} else {
unsigned char *ptr;
int bytes;
for (bytes=0, ptr=bits; bytes<size; bytes++, ptr++) {
if ((value = NextInt(fstream)) < 0)
RETURN (BitmapFileInvalid);
*ptr=value;
}
}
}
fclose(fstream);
if (!bits)
return (BitmapFileInvalid);
*data = bits;
*width = ww;
*height = hh;
if (x_hot) *x_hot = hx;
if (y_hot) *y_hot = hy;
return (BitmapSuccess);
}
int
XReadBitmapFile (
Display *display,
Drawable d,
_Xconst char *filename,
unsigned int *width,
unsigned int *height,
Pixmap *pixmap,
int *x_hot,
int *y_hot)
{
unsigned char *data;
int res;
res = XReadBitmapFileData(filename, width, height, &data, x_hot, y_hot);
if (res != BitmapSuccess)
return res;
*pixmap = XCreateBitmapFromData(display, d, (char *)data, *width, *height);
Xfree((char *)data);
if (*pixmap == None)
return (BitmapNoMemory);
return (BitmapSuccess);
}