home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / xicon05.zip / readxbm.c < prev    next >
C/C++ Source or Header  |  1993-05-06  |  6KB  |  224 lines

  1. /* Copyright, 1987, Massachusetts Institute of Technology */
  2. /* Slightly modified by Norman Walsh for XIcon.  I believe */
  3. /* that this file is free within the context of the X11 */
  4. /* Consortium. */
  5.  
  6. #if 0
  7. #include "copyright.h"
  8. #endif
  9.  
  10. /*
  11.  *    Code to read bitmaps from disk files. Interprets 
  12.  *    data from X10 and X11 bitmap files and creates
  13.  *    Pixmap representations of files. Returns Pixmap
  14.  *    ID and specifics about image.
  15.  *
  16.  *    Modified for speedup by Jim Becker, changed image
  17.  *    data parsing logic (removed some fscanf()s). 
  18.  *    Aug 5, 1988
  19.  *
  20.  * Note that this file and ../Xmu/RdBitF.c look very similar....  Keep them
  21.  * that way (but don't use common source code so that people can have one 
  22.  * without the other).
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include "iconio.h"
  28.  
  29. typedef int    Bool;
  30. #define True 1
  31. #define False 0
  32. char *rindex();
  33.  
  34.  
  35. #define MAX_SIZE 255
  36.  
  37. /* shared data for the image read/parse logic */
  38. static short hexTable[256];        /* conversion value */
  39. static Bool initialized = False;    /* easier to fill in at run time */
  40.  
  41.  
  42. /*
  43.  *    Table index for the hex values. Initialized once, first time.
  44.  *    Used for translation value or delimiter significance lookup.
  45.  */
  46. static void initHexTable()
  47. {
  48.     /*
  49.      * We build the table at run time for several reasons:
  50.      *
  51.      *     1.  portable to non-ASCII machines.
  52.      *     2.  still reentrant since we set the init flag after setting table.
  53.      *     3.  easier to extend.
  54.      *     4.  less prone to bugs.
  55.      */
  56.     hexTable['0'] = 0;    hexTable['1'] = 1;
  57.     hexTable['2'] = 2;    hexTable['3'] = 3;
  58.     hexTable['4'] = 4;    hexTable['5'] = 5;
  59.     hexTable['6'] = 6;    hexTable['7'] = 7;
  60.     hexTable['8'] = 8;    hexTable['9'] = 9;
  61.     hexTable['A'] = 10;    hexTable['B'] = 11;
  62.     hexTable['C'] = 12;    hexTable['D'] = 13;
  63.     hexTable['E'] = 14;    hexTable['F'] = 15;
  64.     hexTable['a'] = 10;    hexTable['b'] = 11;
  65.     hexTable['c'] = 12;    hexTable['d'] = 13;
  66.     hexTable['e'] = 14;    hexTable['f'] = 15;
  67.  
  68.     /* delimiters of significance are flagged w/ negative value */
  69.     hexTable[' '] = -1;    hexTable[','] = -1;
  70.     hexTable['}'] = -1;    hexTable['\n'] = -1;
  71.     hexTable['\t'] = -1;
  72.     
  73.     initialized = True;
  74. }
  75.  
  76. /*
  77.  *    read next hex value in the input stream, return -1 if EOF
  78.  */
  79. static NextInt (fstream)
  80.     FILE *fstream;
  81. {
  82.     int    ch;
  83.     int    value = 0;
  84.     int gotone = 0;
  85.     int done = 0;
  86.     
  87.     /* loop, accumulate hex value until find delimiter  */
  88.     /* skip any initial delimiters found in read stream */
  89.  
  90.     while (!done) {
  91.     ch = getc(fstream);
  92.     if (ch == EOF) {
  93.         value    = -1;
  94.         done++;
  95.     } else {
  96.         /* trim high bits, check type and accumulate */
  97.         ch &= 0xff;
  98.         if (isascii(ch) && isxdigit(ch)) {
  99.         value = (value << 4) + hexTable[ch];
  100.         gotone++;
  101.         } else if ((hexTable[ch]) < 0 && gotone)
  102.           done++;
  103.     }
  104.     }
  105.     return value;
  106. }
  107.  
  108.  
  109. int ReadXBM (input, width, height, data)
  110.     FILE *input;
  111.     unsigned int *width, *height;       /* RETURNED */
  112.     char   *data[];                     /* RETURNED */
  113. {
  114.     char line[MAX_SIZE];        /* input line from file */
  115.     int size;                /* number of bytes of data */
  116.     char name_and_type[MAX_SIZE];    /* an input line */
  117.     char *type;                /* for parsing */
  118.     int value;                /* from an input line */
  119.     int version10p;            /* boolean, old format */
  120.     int padding;            /* to handle alignment */
  121.     int bytes_per_line;            /* per scanline of data */
  122.     unsigned int ww = 0;        /* width */
  123.     unsigned int hh = 0;        /* height */
  124.     int hx = -1;            /* x hotspot */
  125.     int hy = -1;            /* y hotspot */
  126.  
  127.     /* first time initialization */
  128.     if (initialized == False) initHexTable();
  129.  
  130.     /* error cleanup and return macro    */
  131. #define    RETURN(code) { if (*data) free (*data); return code; }
  132.  
  133.     while (fgets(line, MAX_SIZE, input)) {
  134.     if (strlen(line) == MAX_SIZE-1) {
  135.         RETURN (-1);
  136.     }
  137.     if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
  138.         if (!(type = rindex(name_and_type, '_')))
  139.           type = name_and_type;
  140.         else
  141.           type++;
  142.  
  143.         if (!strcmp("width", type))
  144.           ww = (unsigned int) value;
  145.         if (!strcmp("height", type))
  146.           hh = (unsigned int) value;
  147.         if (!strcmp("hot", type)) {
  148.         if (type-- == name_and_type || type-- == name_and_type)
  149.           continue;
  150.         if (!strcmp("x_hot", type))
  151.           hx = value;
  152.         if (!strcmp("y_hot", type))
  153.           hy = value;
  154.         }
  155.         continue;
  156.     }
  157.     
  158.     if (sscanf(line, "static short %s = {", name_and_type) == 1)
  159.       version10p = 1;
  160.     else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
  161.       version10p = 0;
  162.     else if (sscanf(line, "static char %s = {", name_and_type) == 1)
  163.       version10p = 0;
  164.     else
  165.       continue;
  166.  
  167.     if (!(type = rindex(name_and_type, '_')))
  168.       type = name_and_type;
  169.     else
  170.       type++;
  171.  
  172.     if (strcmp("bits[]", type))
  173.       continue;
  174.     
  175.     if (!ww || !hh)
  176.       RETURN (-1);
  177.  
  178.     if ((ww % 16) && ((ww % 16) < 9) && version10p)
  179.       padding = 1;
  180.     else
  181.       padding = 0;
  182.  
  183.     bytes_per_line = (ww+7)/8 + padding;
  184.  
  185.     size = bytes_per_line * hh;
  186.     *data = (char *) malloc ((unsigned int) size);
  187.     if (!*data) 
  188.       RETURN (-1);
  189.  
  190.     if (version10p) {
  191.         unsigned char *ptr;
  192.         int bytes;
  193.  
  194.         for (bytes=0, ptr= (unsigned char *) *data;
  195.          bytes<size; (bytes += 2)) {
  196.         if ((value = NextInt(input)) < 0)
  197.           RETURN (-1);
  198.         *(ptr++) = value;
  199.         if (!padding || ((bytes+2) % bytes_per_line))
  200.           *(ptr++) = value >> 8;
  201.         }
  202.     } else {
  203.         unsigned char *ptr;
  204.         int bytes;
  205.  
  206.         for (bytes=0, ptr= (unsigned char *) *data;
  207.          bytes<size; bytes++, ptr++) {
  208.         if ((value = NextInt(input)) < 0) 
  209.           RETURN (-1);
  210.         *ptr=value;
  211.         }
  212.     }
  213.     }                    /* end while */
  214.  
  215.     if (*data == NULL) {
  216.     RETURN (-1);
  217.     }
  218.  
  219.     *width = ww;
  220.     *height = hh;
  221.  
  222.     return 0;
  223. }
  224.