Blame src/RdBitF.c

Packit Service 2b1f13
/*
Packit Service 2b1f13
Packit Service 2b1f13
Copyright 1988, 1998  The Open Group
Packit Service 2b1f13
Packit Service 2b1f13
Permission to use, copy, modify, distribute, and sell this software and its
Packit Service 2b1f13
documentation for any purpose is hereby granted without fee, provided that
Packit Service 2b1f13
the above copyright notice appear in all copies and that both that
Packit Service 2b1f13
copyright notice and this permission notice appear in supporting
Packit Service 2b1f13
documentation.
Packit Service 2b1f13
Packit Service 2b1f13
The above copyright notice and this permission notice shall be included in
Packit Service 2b1f13
all copies or substantial portions of the Software.
Packit Service 2b1f13
Packit Service 2b1f13
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit Service 2b1f13
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit Service 2b1f13
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
Packit Service 2b1f13
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
Packit Service 2b1f13
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit Service 2b1f13
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit Service 2b1f13
Packit Service 2b1f13
Except as contained in this notice, the name of The Open Group shall not be
Packit Service 2b1f13
used in advertising or otherwise to promote the sale, use or other dealings
Packit Service 2b1f13
in this Software without prior written authorization from The Open Group.
Packit Service 2b1f13
Packit Service 2b1f13
*/
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 * This file contains miscellaneous utility routines and is not part of the
Packit Service 2b1f13
 * Xlib standard.
Packit Service 2b1f13
 *
Packit Service 2b1f13
 * Public entry points:
Packit Service 2b1f13
 *
Packit Service 2b1f13
 *     XmuReadBitmapData		read data from FILE descriptor
Packit Service 2b1f13
 *     XmuReadBitmapDataFromFile	read X10 or X11 format bitmap files
Packit Service 2b1f13
 *					and return data
Packit Service 2b1f13
 *
Packit Service 2b1f13
 * Note that this file and ../X/XRdBitF.c look very similar....  Keep them
Packit Service 2b1f13
 * that way (but don't use common source code so that people can have one
Packit Service 2b1f13
 * without the other).
Packit Service 2b1f13
 */
Packit Service 2b1f13
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 * Based on an optimized version provided by Jim Becker, Auguest 5, 1988.
Packit Service 2b1f13
 */
Packit Service 2b1f13
Packit Service 2b1f13
#ifdef HAVE_CONFIG_H
Packit Service 2b1f13
#include <config.h>
Packit Service 2b1f13
#endif
Packit Service 2b1f13
#include <X11/Xos.h>
Packit Service 2b1f13
#include <X11/Xlib.h>
Packit Service 2b1f13
#include <X11/Xutil.h>
Packit Service 2b1f13
#include <X11/Xlibint.h>
Packit Service 2b1f13
#include <stdio.h>
Packit Service 2b1f13
#include <ctype.h>
Packit Service 2b1f13
#include <X11/Xmu/Drawing.h>
Packit Service 2b1f13
#ifdef WIN32
Packit Service 2b1f13
#include <X11/Xwindows.h>
Packit Service 2b1f13
#include <direct.h>            /* for _getdrives() */
Packit Service 2b1f13
#endif
Packit Service 2b1f13
Packit Service 2b1f13
#define MAX_SIZE 255
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 * Prototypes
Packit Service 2b1f13
 */
Packit Service 2b1f13
static void initHexTable(void);
Packit Service 2b1f13
static int NextInt(FILE*);
Packit Service 2b1f13
Packit Service 2b1f13
/* shared data for the image read/parse logic */
Packit Service 2b1f13
static short hexTable[256];		/* conversion value */
Packit Service 2b1f13
static Bool initialized = False;	/* easier to fill in at run time */
Packit Service 2b1f13
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 *	Table index for the hex values. Initialized once, first time.
Packit Service 2b1f13
 *	Used for translation value or delimiter significance lookup.
Packit Service 2b1f13
 */
Packit Service 2b1f13
static void
Packit Service 2b1f13
initHexTable(void)
Packit Service 2b1f13
{
Packit Service 2b1f13
    /*
Packit Service 2b1f13
     * We build the table at run time for several reasons:
Packit Service 2b1f13
     *
Packit Service 2b1f13
     *     1.  portable to non-ASCII machines.
Packit Service 2b1f13
     *     2.  still reentrant since we set the init flag after setting table.
Packit Service 2b1f13
     *     3.  easier to extend.
Packit Service 2b1f13
     *     4.  less prone to bugs.
Packit Service 2b1f13
     */
Packit Service 2b1f13
    hexTable['0'] = 0;	hexTable['1'] = 1;
Packit Service 2b1f13
    hexTable['2'] = 2;	hexTable['3'] = 3;
Packit Service 2b1f13
    hexTable['4'] = 4;	hexTable['5'] = 5;
Packit Service 2b1f13
    hexTable['6'] = 6;	hexTable['7'] = 7;
Packit Service 2b1f13
    hexTable['8'] = 8;	hexTable['9'] = 9;
Packit Service 2b1f13
    hexTable['A'] = 10;	hexTable['B'] = 11;
Packit Service 2b1f13
    hexTable['C'] = 12;	hexTable['D'] = 13;
Packit Service 2b1f13
    hexTable['E'] = 14;	hexTable['F'] = 15;
Packit Service 2b1f13
    hexTable['a'] = 10;	hexTable['b'] = 11;
Packit Service 2b1f13
    hexTable['c'] = 12;	hexTable['d'] = 13;
Packit Service 2b1f13
    hexTable['e'] = 14;	hexTable['f'] = 15;
Packit Service 2b1f13
Packit Service 2b1f13
    /* delimiters of significance are flagged w/ negative value */
Packit Service 2b1f13
    hexTable[' '] = -1;	hexTable[','] = -1;
Packit Service 2b1f13
    hexTable['}'] = -1;	hexTable['\n'] = -1;
Packit Service 2b1f13
    hexTable['\t'] = -1;
Packit Service 2b1f13
Packit Service 2b1f13
    initialized = True;
Packit Service 2b1f13
}
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 *	read next hex value in the input stream, return -1 if EOF
Packit Service 2b1f13
 */
Packit Service 2b1f13
static int
Packit Service 2b1f13
NextInt(FILE *fstream)
Packit Service 2b1f13
{
Packit Service 2b1f13
    int	ch;
Packit Service 2b1f13
    int	value = 0;
Packit Service 2b1f13
    int gotone = 0;
Packit Service 2b1f13
    int done = 0;
Packit Service 2b1f13
Packit Service 2b1f13
    /* loop, accumulate hex value until find delimiter  */
Packit Service 2b1f13
    /* skip any initial delimiters found in read stream */
Packit Service 2b1f13
Packit Service 2b1f13
    while (!done) {
Packit Service 2b1f13
	ch = getc(fstream);
Packit Service 2b1f13
	if (ch == EOF) {
Packit Service 2b1f13
	    value	= -1;
Packit Service 2b1f13
	    done++;
Packit Service 2b1f13
	} else {
Packit Service 2b1f13
	    /* trim high bits, check type and accumulate */
Packit Service 2b1f13
	    ch &= 0xff;
Packit Service 2b1f13
	    if (isascii(ch) && isxdigit(ch)) {
Packit Service 2b1f13
		value = (value << 4) + hexTable[ch];
Packit Service 2b1f13
		gotone++;
Packit Service 2b1f13
	    } else if ((hexTable[ch]) < 0 && gotone)
Packit Service 2b1f13
	      done++;
Packit Service 2b1f13
	}
Packit Service 2b1f13
    }
Packit Service 2b1f13
    return value;
Packit Service 2b1f13
}
Packit Service 2b1f13
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 * The data returned by the following routine is always in left-most byte
Packit Service 2b1f13
 * first and left-most bit first.  If it doesn't return BitmapSuccess then
Packit Service 2b1f13
 * its arguments won't have been touched.  This routine should look as much
Packit Service 2b1f13
 * like the Xlib routine XReadBitmapfile as possible.
Packit Service 2b1f13
 */
Packit Service 2b1f13
int
Packit Service 2b1f13
XmuReadBitmapData(FILE *fstream, unsigned int *width, unsigned int *height,
Packit Service 2b1f13
		  unsigned char **datap, int *x_hot, int *y_hot)
Packit Service 2b1f13
{
Packit Service 2b1f13
    unsigned char *data = NULL;		/* working variable */
Packit Service 2b1f13
    char line[MAX_SIZE];		/* input line from file */
Packit Service 2b1f13
    int size;				/* number of bytes of data */
Packit Service 2b1f13
    char name_and_type[MAX_SIZE];	/* an input line */
Packit Service 2b1f13
    char *type;				/* for parsing */
Packit Service 2b1f13
    int value;				/* from an input line */
Packit Service 2b1f13
    int version10p;			/* boolean, old format */
Packit Service 2b1f13
    int padding;			/* to handle alignment */
Packit Service 2b1f13
    int bytes_per_line;			/* per scanline of data */
Packit Service 2b1f13
    unsigned int ww = 0;		/* width */
Packit Service 2b1f13
    unsigned int hh = 0;		/* height */
Packit Service 2b1f13
    int hx = -1;			/* x hotspot */
Packit Service 2b1f13
    int hy = -1;			/* y hotspot */
Packit Service 2b1f13
Packit Service 2b1f13
#undef  Xmalloc /* see MALLOC_0_RETURNS_NULL in Xlibint.h */
Packit Service 2b1f13
#define Xmalloc(size) malloc(size)
Packit Service 2b1f13
Packit Service 2b1f13
    /* first time initialization */
Packit Service 2b1f13
    if (initialized == False) initHexTable();
Packit Service 2b1f13
Packit Service 2b1f13
    /* error cleanup and return macro	*/
Packit Service 2b1f13
#define	RETURN(code) { if (data) free (data); return code; }
Packit Service 2b1f13
Packit Service 2b1f13
    while (fgets(line, MAX_SIZE, fstream)) {
Packit Service 2b1f13
	if (strlen(line) == MAX_SIZE-1) {
Packit Service 2b1f13
	    RETURN (BitmapFileInvalid);
Packit Service 2b1f13
	}
Packit Service 2b1f13
	if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
Packit Service 2b1f13
	    if (!(type = strrchr(name_and_type, '_')))
Packit Service 2b1f13
	      type = name_and_type;
Packit Service 2b1f13
	    else
Packit Service 2b1f13
	      type++;
Packit Service 2b1f13
Packit Service 2b1f13
	    if (!strcmp("width", type))
Packit Service 2b1f13
	      ww = (unsigned int) value;
Packit Service 2b1f13
	    if (!strcmp("height", type))
Packit Service 2b1f13
	      hh = (unsigned int) value;
Packit Service 2b1f13
	    if (!strcmp("hot", type)) {
Packit Service 2b1f13
		if (type-- == name_and_type || type-- == name_and_type)
Packit Service 2b1f13
		  continue;
Packit Service 2b1f13
		if (!strcmp("x_hot", type))
Packit Service 2b1f13
		  hx = value;
Packit Service 2b1f13
		if (!strcmp("y_hot", type))
Packit Service 2b1f13
		  hy = value;
Packit Service 2b1f13
	    }
Packit Service 2b1f13
	    continue;
Packit Service 2b1f13
	}
Packit Service 2b1f13
Packit Service 2b1f13
	if (sscanf(line, "static short %s = {", name_and_type) == 1)
Packit Service 2b1f13
	  version10p = 1;
Packit Service 2b1f13
	else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
Packit Service 2b1f13
	  version10p = 0;
Packit Service 2b1f13
	else if (sscanf(line, "static char %s = {", name_and_type) == 1)
Packit Service 2b1f13
	  version10p = 0;
Packit Service 2b1f13
	else
Packit Service 2b1f13
	  continue;
Packit Service 2b1f13
Packit Service 2b1f13
	if (!(type = strrchr(name_and_type, '_')))
Packit Service 2b1f13
	  type = name_and_type;
Packit Service 2b1f13
	else
Packit Service 2b1f13
	  type++;
Packit Service 2b1f13
Packit Service 2b1f13
	if (strcmp("bits[]", type))
Packit Service 2b1f13
	  continue;
Packit Service 2b1f13
Packit Service 2b1f13
	if (!ww || !hh)
Packit Service 2b1f13
	  RETURN (BitmapFileInvalid);
Packit Service 2b1f13
Packit Service 2b1f13
	if ((ww % 16) && ((ww % 16) < 9) && version10p)
Packit Service 2b1f13
	  padding = 1;
Packit Service 2b1f13
	else
Packit Service 2b1f13
	  padding = 0;
Packit Service 2b1f13
Packit Service 2b1f13
	bytes_per_line = (ww+7)/8 + padding;
Packit Service 2b1f13
Packit Service 2b1f13
	size = bytes_per_line * hh;
Packit Service 2b1f13
	data = (unsigned char *) Xmalloc ((unsigned int) size);
Packit Service 2b1f13
	if (!data)
Packit Service 2b1f13
	  RETURN (BitmapNoMemory);
Packit Service 2b1f13
Packit Service 2b1f13
	if (version10p) {
Packit Service 2b1f13
	    unsigned char *ptr;
Packit Service 2b1f13
	    int bytes;
Packit Service 2b1f13
Packit Service 2b1f13
	    for (bytes=0, ptr=data; bytes
Packit Service 2b1f13
		if ((value = NextInt(fstream)) < 0)
Packit Service 2b1f13
		  RETURN (BitmapFileInvalid);
Packit Service 2b1f13
		*(ptr++) = value;
Packit Service 2b1f13
		if (!padding || ((bytes+2) % bytes_per_line))
Packit Service 2b1f13
		  *(ptr++) = value >> 8;
Packit Service 2b1f13
	    }
Packit Service 2b1f13
	} else {
Packit Service 2b1f13
	    unsigned char *ptr;
Packit Service 2b1f13
	    int bytes;
Packit Service 2b1f13
Packit Service 2b1f13
	    for (bytes=0, ptr=data; bytes
Packit Service 2b1f13
		if ((value = NextInt(fstream)) < 0)
Packit Service 2b1f13
		  RETURN (BitmapFileInvalid);
Packit Service 2b1f13
		*ptr=value;
Packit Service 2b1f13
	    }
Packit Service 2b1f13
	}
Packit Service 2b1f13
	break;
Packit Service 2b1f13
    }					/* end while */
Packit Service 2b1f13
Packit Service 2b1f13
    if (data == NULL) {
Packit Service 2b1f13
	RETURN (BitmapFileInvalid);
Packit Service 2b1f13
    }
Packit Service 2b1f13
Packit Service 2b1f13
    *datap = data;
Packit Service 2b1f13
    data = NULL;
Packit Service 2b1f13
    *width = ww;
Packit Service 2b1f13
    *height = hh;
Packit Service 2b1f13
    if (x_hot) *x_hot = hx;
Packit Service 2b1f13
    if (y_hot) *y_hot = hy;
Packit Service 2b1f13
Packit Service 2b1f13
    RETURN (BitmapSuccess);
Packit Service 2b1f13
}
Packit Service 2b1f13
Packit Service 2b1f13
#if defined(WIN32)
Packit Service 2b1f13
static int
Packit Service 2b1f13
access_file(char *path, char *pathbuf, int len_pathbuf, char **pathret)
Packit Service 2b1f13
{
Packit Service 2b1f13
    if (access (path, F_OK) == 0) {
Packit Service 2b1f13
	if (strlen (path) < len_pathbuf)
Packit Service 2b1f13
	    *pathret = pathbuf;
Packit Service 2b1f13
	else
Packit Service 2b1f13
	    *pathret = malloc (strlen (path) + 1);
Packit Service 2b1f13
	if (*pathret) {
Packit Service 2b1f13
	    strcpy (*pathret, path);
Packit Service 2b1f13
	    return 1;
Packit Service 2b1f13
	}
Packit Service 2b1f13
    }
Packit Service 2b1f13
    return 0;
Packit Service 2b1f13
}
Packit Service 2b1f13
Packit Service 2b1f13
static int
Packit Service 2b1f13
AccessFile(char *path, char *pathbuf, int len_pathbuf, char **pathret)
Packit Service 2b1f13
{
Packit Service 2b1f13
#ifndef MAX_PATH
Packit Service 2b1f13
#define MAX_PATH 512
Packit Service 2b1f13
#endif
Packit Service 2b1f13
Packit Service 2b1f13
    unsigned long drives;
Packit Service 2b1f13
    int i, len;
Packit Service 2b1f13
    char* drive;
Packit Service 2b1f13
    char buf[MAX_PATH];
Packit Service 2b1f13
    char* bufp;
Packit Service 2b1f13
Packit Service 2b1f13
    /* just try the "raw" name first and see if it works */
Packit Service 2b1f13
    if (access_file (path, pathbuf, len_pathbuf, pathret))
Packit Service 2b1f13
	return 1;
Packit Service 2b1f13
Packit Service 2b1f13
    /* try the places set in the environment */
Packit Service 2b1f13
    drive = getenv ("_XBASEDRIVE");
Packit Service 2b1f13
    if (!drive)
Packit Service 2b1f13
	drive = "C:";
Packit Service 2b1f13
    len = strlen (drive) + strlen (path);
Packit Service 2b1f13
    if (len < MAX_PATH) bufp = buf;
Packit Service 2b1f13
    else bufp = malloc (len + 1);
Packit Service 2b1f13
    strcpy (bufp, drive);
Packit Service 2b1f13
    strcat (bufp, path);
Packit Service 2b1f13
    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
Packit Service 2b1f13
	if (bufp != buf) free (bufp);
Packit Service 2b1f13
	return 1;
Packit Service 2b1f13
    }
Packit Service 2b1f13
Packit Service 2b1f13
    /* one last place to look */
Packit Service 2b1f13
    drive = getenv ("HOMEDRIVE");
Packit Service 2b1f13
    if (drive) {
Packit Service 2b1f13
	len = strlen (drive) + strlen (path);
Packit Service 2b1f13
	if (len < MAX_PATH) bufp = buf;
Packit Service 2b1f13
	else bufp = malloc (len + 1);
Packit Service 2b1f13
	strcpy (bufp, drive);
Packit Service 2b1f13
	strcat (bufp, path);
Packit Service 2b1f13
	if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
Packit Service 2b1f13
	    if (bufp != buf) free (bufp);
Packit Service 2b1f13
	    return 1;
Packit Service 2b1f13
	}
Packit Service 2b1f13
    }
Packit Service 2b1f13
Packit Service 2b1f13
    /* does OS/2 (with or with gcc-emx) have getdrives? */
Packit Service 2b1f13
    /* tried everywhere else, go fishing */
Packit Service 2b1f13
#define C_DRIVE ('C' - 'A')
Packit Service 2b1f13
#define Z_DRIVE ('Z' - 'A')
Packit Service 2b1f13
    drives = _getdrives ();
Packit Service 2b1f13
    for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
Packit Service 2b1f13
	if ((1 << i) & drives) {
Packit Service 2b1f13
	    len = 2 + strlen (path);
Packit Service 2b1f13
	    if (len < MAX_PATH) bufp = buf;
Packit Service 2b1f13
	    else bufp = malloc (len + 1);
Packit Service 2b1f13
	    *bufp = 'A' + i;
Packit Service 2b1f13
	    *(bufp + 1) = ':';
Packit Service 2b1f13
	    *(bufp + 2) = '\0';
Packit Service 2b1f13
	    strcat (bufp, path);
Packit Service 2b1f13
	    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
Packit Service 2b1f13
		if (bufp != buf) free (bufp);
Packit Service 2b1f13
		return 1;
Packit Service 2b1f13
	    }
Packit Service 2b1f13
	}
Packit Service 2b1f13
    }
Packit Service 2b1f13
    return 0;
Packit Service 2b1f13
}
Packit Service 2b1f13
Packit Service 2b1f13
FILE *
Packit Service 2b1f13
fopen_file(char *path, char *mode)
Packit Service 2b1f13
{
Packit Service 2b1f13
    char buf[MAX_PATH];
Packit Service 2b1f13
    char* bufp;
Packit Service 2b1f13
    void* ret = NULL;
Packit Service 2b1f13
    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
Packit Service 2b1f13
Packit Service 2b1f13
    if (AccessFile (path, buf, MAX_PATH, &bufp))
Packit Service 2b1f13
	ret = fopen (bufp, mode);
Packit Service 2b1f13
Packit Service 2b1f13
    (void) SetErrorMode (olderror);
Packit Service 2b1f13
Packit Service 2b1f13
    if (bufp != buf) free (bufp);
Packit Service 2b1f13
Packit Service 2b1f13
    return ret;
Packit Service 2b1f13
}
Packit Service 2b1f13
Packit Service 2b1f13
#else
Packit Service 2b1f13
#define fopen_file fopen
Packit Service 2b1f13
#endif
Packit Service 2b1f13
Packit Service 2b1f13
Packit Service 2b1f13
int
Packit Service 2b1f13
XmuReadBitmapDataFromFile(_Xconst char *filename, unsigned int *width,
Packit Service 2b1f13
			       unsigned int *height, unsigned char **datap,
Packit Service 2b1f13
			       int *x_hot, int *y_hot)
Packit Service 2b1f13
{
Packit Service 2b1f13
    FILE *fstream;
Packit Service 2b1f13
    int status;
Packit Service 2b1f13
Packit Service 2b1f13
    if ((fstream = fopen_file (filename, "r")) == NULL) {
Packit Service 2b1f13
	return BitmapOpenFailed;
Packit Service 2b1f13
    }
Packit Service 2b1f13
    status = XmuReadBitmapData(fstream, width, height, datap, x_hot, y_hot);
Packit Service 2b1f13
    fclose (fstream);
Packit Service 2b1f13
    return status;
Packit Service 2b1f13
}