RdBitF.c

Go to the documentation of this file.
00001 /* $Xorg: RdBitF.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
00002 
00003 /*
00004 
00005 Copyright 1988, 1998  The Open Group
00006 
00007 Permission to use, copy, modify, distribute, and sell this software and its
00008 documentation for any purpose is hereby granted without fee, provided that
00009 the above copyright notice appear in all copies and that both that
00010 copyright notice and this permission notice appear in supporting
00011 documentation.
00012 
00013 The above copyright notice and this permission notice shall be included in
00014 all copies or substantial portions of the Software.
00015 
00016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00017 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00018 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00019 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00020 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00021 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00022 
00023 Except as contained in this notice, the name of The Open Group shall not be
00024 used in advertising or otherwise to promote the sale, use or other dealings
00025 in this Software without prior written authorization from The Open Group.
00026 
00027 */
00028 /* $XFree86: xc/lib/Xmu/RdBitF.c,v 3.12 2001/12/14 19:55:48 dawes Exp $ */
00029 
00030 /*
00031  * This file contains miscellaneous utility routines and is not part of the
00032  * Xlib standard.
00033  *
00034  * Public entry points:
00035  *
00036  *     XmuReadBitmapData                read data from FILE descriptor
00037  *     XmuReadBitmapDataFromFile        read X10 or X11 format bitmap files
00038  *                                      and return data
00039  *
00040  * Note that this file and ../X/XRdBitF.c look very similar....  Keep them
00041  * that way (but don't use common source code so that people can have one 
00042  * without the other).
00043  */
00044 
00045 
00046 /*
00047  * Based on an optimized version provided by Jim Becker, Auguest 5, 1988.
00048  */
00049 
00050 #include <X11/Xos.h>
00051 #include <X11/Xlib.h>
00052 #include <X11/Xutil.h>
00053 #include <X11/Xlibint.h>
00054 #include <stdio.h>
00055 #include <ctype.h>
00056 #include <X11/Xmu/Drawing.h>
00057 
00058 #define MAX_SIZE 255
00059 
00060 /*
00061  * Prototypes
00062  */
00063 static void initHexTable(void);
00064 static int NextInt(FILE*);
00065 
00066 /* shared data for the image read/parse logic */
00067 static short hexTable[256];             /* conversion value */
00068 static Bool initialized = False;        /* easier to fill in at run time */
00069 
00070 
00071 /*
00072  *      Table index for the hex values. Initialized once, first time.
00073  *      Used for translation value or delimiter significance lookup.
00074  */
00075 static void
00076 initHexTable(void)
00077 {
00078     /*
00079      * We build the table at run time for several reasons:
00080      *
00081      *     1.  portable to non-ASCII machines.
00082      *     2.  still reentrant since we set the init flag after setting table.
00083      *     3.  easier to extend.
00084      *     4.  less prone to bugs.
00085      */
00086     hexTable['0'] = 0;  hexTable['1'] = 1;
00087     hexTable['2'] = 2;  hexTable['3'] = 3;
00088     hexTable['4'] = 4;  hexTable['5'] = 5;
00089     hexTable['6'] = 6;  hexTable['7'] = 7;
00090     hexTable['8'] = 8;  hexTable['9'] = 9;
00091     hexTable['A'] = 10; hexTable['B'] = 11;
00092     hexTable['C'] = 12; hexTable['D'] = 13;
00093     hexTable['E'] = 14; hexTable['F'] = 15;
00094     hexTable['a'] = 10; hexTable['b'] = 11;
00095     hexTable['c'] = 12; hexTable['d'] = 13;
00096     hexTable['e'] = 14; hexTable['f'] = 15;
00097 
00098     /* delimiters of significance are flagged w/ negative value */
00099     hexTable[' '] = -1; hexTable[','] = -1;
00100     hexTable['}'] = -1; hexTable['\n'] = -1;
00101     hexTable['\t'] = -1;
00102         
00103     initialized = True;
00104 }
00105 
00106 /*
00107  *      read next hex value in the input stream, return -1 if EOF
00108  */
00109 static int
00110 NextInt(FILE *fstream)
00111 {
00112     int ch;
00113     int value = 0;
00114     int gotone = 0;
00115     int done = 0;
00116     
00117     /* loop, accumulate hex value until find delimiter  */
00118     /* skip any initial delimiters found in read stream */
00119 
00120     while (!done) {
00121         ch = getc(fstream);
00122         if (ch == EOF) {
00123             value       = -1;
00124             done++;
00125         } else {
00126             /* trim high bits, check type and accumulate */
00127             ch &= 0xff;
00128             if (isascii(ch) && isxdigit(ch)) {
00129                 value = (value << 4) + hexTable[ch];
00130                 gotone++;
00131             } else if ((hexTable[ch]) < 0 && gotone)
00132               done++;
00133         }
00134     }
00135     return value;
00136 }
00137 
00138 
00139 /*
00140  * The data returned by the following routine is always in left-most byte
00141  * first and left-most bit first.  If it doesn't return BitmapSuccess then
00142  * its arguments won't have been touched.  This routine should look as much
00143  * like the Xlib routine XReadBitmapfile as possible.
00144  */
00145 int
00146 XmuReadBitmapData(FILE *fstream, unsigned int *width, unsigned int *height,
00147                   unsigned char **datap, int *x_hot, int *y_hot)
00148 {
00149     unsigned char *data = NULL;         /* working variable */
00150     char line[MAX_SIZE];                /* input line from file */
00151     int size;                           /* number of bytes of data */
00152     char name_and_type[MAX_SIZE];       /* an input line */
00153     char *type;                         /* for parsing */
00154     int value;                          /* from an input line */
00155     int version10p;                     /* boolean, old format */
00156     int padding;                        /* to handle alignment */
00157     int bytes_per_line;                 /* per scanline of data */
00158     unsigned int ww = 0;                /* width */
00159     unsigned int hh = 0;                /* height */
00160     int hx = -1;                        /* x hotspot */
00161     int hy = -1;                        /* y hotspot */
00162 
00163 #undef  Xmalloc /* see MALLOC_0_RETURNS_NULL in Xlibint.h */
00164 #define Xmalloc(size) malloc(size)
00165 
00166     /* first time initialization */
00167     if (initialized == False) initHexTable();
00168 
00169     /* error cleanup and return macro   */
00170 #define RETURN(code) { if (data) free (data); return code; }
00171 
00172     while (fgets(line, MAX_SIZE, fstream)) {
00173         if (strlen(line) == MAX_SIZE-1) {
00174             RETURN (BitmapFileInvalid);
00175         }
00176         if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
00177             if (!(type = strrchr(name_and_type, '_')))
00178               type = name_and_type;
00179             else
00180               type++;
00181 
00182             if (!strcmp("width", type))
00183               ww = (unsigned int) value;
00184             if (!strcmp("height", type))
00185               hh = (unsigned int) value;
00186             if (!strcmp("hot", type)) {
00187                 if (type-- == name_and_type || type-- == name_and_type)
00188                   continue;
00189                 if (!strcmp("x_hot", type))
00190                   hx = value;
00191                 if (!strcmp("y_hot", type))
00192                   hy = value;
00193             }
00194             continue;
00195         }
00196     
00197         if (sscanf(line, "static short %s = {", name_and_type) == 1)
00198           version10p = 1;
00199         else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
00200           version10p = 0;
00201         else if (sscanf(line, "static char %s = {", name_and_type) == 1)
00202           version10p = 0;
00203         else
00204           continue;
00205 
00206         if (!(type = strrchr(name_and_type, '_')))
00207           type = name_and_type;
00208         else
00209           type++;
00210 
00211         if (strcmp("bits[]", type))
00212           continue;
00213     
00214         if (!ww || !hh)
00215           RETURN (BitmapFileInvalid);
00216 
00217         if ((ww % 16) && ((ww % 16) < 9) && version10p)
00218           padding = 1;
00219         else
00220           padding = 0;
00221 
00222         bytes_per_line = (ww+7)/8 + padding;
00223 
00224         size = bytes_per_line * hh;
00225         data = (unsigned char *) Xmalloc ((unsigned int) size);
00226         if (!data) 
00227           RETURN (BitmapNoMemory);
00228 
00229         if (version10p) {
00230             unsigned char *ptr;
00231             int bytes;
00232 
00233             for (bytes=0, ptr=data; bytes<size; (bytes += 2)) {
00234                 if ((value = NextInt(fstream)) < 0)
00235                   RETURN (BitmapFileInvalid);
00236                 *(ptr++) = value;
00237                 if (!padding || ((bytes+2) % bytes_per_line))
00238                   *(ptr++) = value >> 8;
00239             }
00240         } else {
00241             unsigned char *ptr;
00242             int bytes;
00243 
00244             for (bytes=0, ptr=data; bytes<size; bytes++, ptr++) {
00245                 if ((value = NextInt(fstream)) < 0) 
00246                   RETURN (BitmapFileInvalid);
00247                 *ptr=value;
00248             }
00249         }
00250         break;
00251     }                                   /* end while */
00252 
00253     if (data == NULL) {
00254         RETURN (BitmapFileInvalid);
00255     }
00256 
00257     *datap = data;
00258     data = NULL;
00259     *width = ww;
00260     *height = hh;
00261     if (x_hot) *x_hot = hx;
00262     if (y_hot) *y_hot = hy;
00263 
00264     RETURN (BitmapSuccess);
00265 }
00266 
00267 #if defined(WIN32)
00268 static int
00269 access_file(char *path, char *pathbuf, int len_pathbuf, char **pathret)
00270 {
00271     if (access (path, F_OK) == 0) {
00272         if (strlen (path) < len_pathbuf)
00273             *pathret = pathbuf;
00274         else
00275             *pathret = malloc (strlen (path) + 1);
00276         if (*pathret) {
00277             strcpy (*pathret, path);
00278             return 1;
00279         }
00280     }
00281     return 0;
00282 }
00283 
00284 static int
00285 AccessFile(char *path, char *pathbuf, int len_pathbuf, char **pathret)
00286 {
00287 #ifndef MAX_PATH
00288 #define MAX_PATH 512
00289 #endif
00290 
00291     unsigned long drives;
00292     int i, len;
00293     char* drive;
00294     char buf[MAX_PATH];
00295     char* bufp;
00296 
00297     /* just try the "raw" name first and see if it works */
00298     if (access_file (path, pathbuf, len_pathbuf, pathret))
00299         return 1;
00300 
00301     /* try the places set in the environment */
00302     drive = getenv ("_XBASEDRIVE");
00303 #ifdef __UNIXOS2__
00304     if (!drive)
00305         drive = getenv ("X11ROOT");
00306 #endif
00307     if (!drive)
00308         drive = "C:";
00309     len = strlen (drive) + strlen (path);
00310     if (len < MAX_PATH) bufp = buf;
00311     else bufp = malloc (len + 1);
00312     strcpy (bufp, drive);
00313     strcat (bufp, path);
00314     if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
00315         if (bufp != buf) free (bufp);
00316         return 1;
00317     }
00318 
00319 #ifndef __UNIXOS2__ 
00320     /* one last place to look */
00321     drive = getenv ("HOMEDRIVE");
00322     if (drive) {
00323         len = strlen (drive) + strlen (path);
00324         if (len < MAX_PATH) bufp = buf;
00325         else bufp = malloc (len + 1);
00326         strcpy (bufp, drive);
00327         strcat (bufp, path);
00328         if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
00329             if (bufp != buf) free (bufp);
00330             return 1;
00331         }
00332     }
00333 
00334     /* does OS/2 (with or with gcc-emx) have getdrives? */
00335     /* tried everywhere else, go fishing */
00336 #define C_DRIVE ('C' - 'A')
00337 #define Z_DRIVE ('Z' - 'A')
00338     drives = _getdrives ();
00339     for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
00340         if ((1 << i) & drives) {
00341             len = 2 + strlen (path);
00342             if (len < MAX_PATH) bufp = buf;
00343             else bufp = malloc (len + 1);
00344             *bufp = 'A' + i;
00345             *(bufp + 1) = ':';
00346             *(bufp + 2) = '\0';
00347             strcat (bufp, path);
00348             if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
00349                 if (bufp != buf) free (bufp);
00350                 return 1;
00351             }
00352         }
00353     }
00354 #endif
00355     return 0;
00356 }
00357 
00358 FILE *
00359 fopen_file(char *path, char *mode)
00360 {
00361     char buf[MAX_PATH];
00362     char* bufp;
00363     void* ret = NULL;
00364     UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
00365 
00366     if (AccessFile (path, buf, MAX_PATH, &bufp))
00367         ret = fopen (bufp, mode);
00368 
00369     (void) SetErrorMode (olderror);
00370 
00371     if (bufp != buf) free (bufp);
00372 
00373     return ret;
00374 }
00375 
00376 #else
00377 #define fopen_file fopen
00378 #endif
00379 
00380 
00381 int
00382 XmuReadBitmapDataFromFile(_Xconst char *filename, unsigned int *width, 
00383                                unsigned int *height, unsigned char **datap,
00384                                int *x_hot, int *y_hot)
00385 {
00386     FILE *fstream;
00387     int status;
00388 
00389 #ifdef __UNIXOS2__
00390     filename = __XOS2RedirRoot(filename);
00391 #endif
00392     if ((fstream = fopen_file (filename, "r")) == NULL) {
00393         return BitmapOpenFailed;
00394     }
00395     status = XmuReadBitmapData(fstream, width, height, datap, x_hot, y_hot);
00396     fclose (fstream);
00397     return status;
00398 }

Generated on Sun Mar 4 15:03:56 2007 for Scilab [trunk] by  doxygen 1.5.1