image.c
上传用户:zlh9724
上传日期:2007-01-04
资源大小:1991k
文件大小:46k
源码类别:

浏览器

开发平台:

Unix_Linux

  1. /* image.c - creates textured background and other pixmap stuff */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. #include <math.h>
  7. #include "www.h"
  8. #include "www.bm"
  9. extern Display *display;
  10. extern int screen;
  11. extern Window win;
  12. extern Visual *visual;
  13. extern unsigned long labelColor, textColor, statusColor, strikeColor,
  14.             transparent, windowColor, windowBottomShadow, windowShadow;
  15. extern int RPixelShift, GPixelShift, BPixelShift;
  16. extern int RPixelMask, GPixelMask, BPixelMask;
  17. extern int depth;
  18. extern int IsIndex;
  19. extern Doc *CurrentDoc;
  20. extern Context *context;
  21. extern BOOL OwnColorMap; /* howcome 10/8/95 */
  22. extern int tileWidth, tileHeight;
  23. extern unsigned char *tileData;
  24. extern Pixmap default_pixmap;
  25. extern int default_pixmap_width, default_pixmap_height;
  26. extern Colormap colormap;
  27. extern int Magic256[256];
  28. extern int Magic16[256];
  29. extern int Magic32[256];
  30. extern int Magic64[256];
  31. extern GC disp_gc;
  32. extern unsigned int win_width, win_height;
  33. extern int debug;
  34. extern double Gamma;
  35. extern HTAtom *text_atom;
  36. extern HTAtom *html_atom;
  37. extern HTAtom *html3_atom;
  38. extern HTAtom *html_level3_atom;
  39. extern HTAtom *gif_atom;
  40. extern HTAtom *jpeg_atom;
  41. extern HTAtom *png_atom;
  42. extern HTAtom *png_exp_atom;
  43. extern HTAtom *xpm_atom;
  44. extern HTAtom *xbm_atom;
  45. Pixmap smile, frown, note_pixmap, caution_pixmap, warning_pixmap;
  46. int imaging; /* set to COLOR888, COLOR232, GREY4 or MONO */
  47. Image *images;  /* linked list of images */
  48. Image *note_image, *caution_image, *warning_image;  /* standard icons */
  49. unsigned long stdcmap[128];  /* 2/3/2 color maps for gifs etc */
  50. unsigned long greymap[16];  /* for mixing with unsaturated colors */
  51. extern unsigned long mycmap[256]; 
  52. Image *default_image = NULL;
  53. #define smile_xbm_width 15
  54. #define smile_xbm_height 15
  55. /* janet 21/07/95: declared and defined but not used 
  56. static char smile_xbm_bits[] = {
  57.    0x1f, 0x7c, 0xe7, 0x73, 0xfb, 0x6f, 0xfd, 0x5f, 0xfd, 0x5f, 0xce, 0x39,
  58.    0xce, 0x39, 0xfe, 0x3f, 0xfe, 0x3f, 0xee, 0x3b, 0xdd, 0x5d, 0x3d, 0x5e,
  59.    0xfb, 0x6f, 0xe7, 0x73, 0x1f, 0x7c};
  60.    */
  61. #define frown_xbm_width 15
  62. #define frown_xbm_height 15
  63. /* janet 21/07/95: defined but not used
  64. static char frown_xbm_bits[] = {
  65.    0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f,
  66.    0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f,
  67.    0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f};
  68.    */
  69. #define note_width 26
  70. #define note_height 39
  71. static char note_bits[] = {
  72.    0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x38, 0xfc,
  73.    0x00, 0x00, 0x7c, 0xfc, 0x00, 0x00, 0x7c, 0xfc, 0x00, 0x00, 0x7c, 0xfc,
  74.    0x00, 0x00, 0x7c, 0xfc, 0x00, 0x00, 0x7c, 0xfc, 0x00, 0x00, 0x7c, 0xfc,
  75.    0x00, 0x00, 0x7c, 0xfc, 0x00, 0x00, 0x7c, 0xfc, 0x00, 0x00, 0x7c, 0xfc,
  76.    0x30, 0xc6, 0x7c, 0xfc, 0x78, 0xef, 0x7d, 0xfc, 0x78, 0xef, 0x7f, 0xfc,
  77.    0x78, 0xef, 0x7f, 0xfc, 0x7c, 0x2f, 0x00, 0xfc, 0x7c, 0xcf, 0xff, 0xfc,
  78.    0x7c, 0xcf, 0xff, 0xfc, 0x7c, 0xcf, 0xff, 0xfc, 0x7c, 0x2f, 0xff, 0xfc,
  79.    0x7c, 0xef, 0xf8, 0xfc, 0x7c, 0xef, 0xfd, 0xfc, 0x38, 0xef, 0xfd, 0xfc,
  80.    0xc0, 0xf9, 0xff, 0xfc, 0xe0, 0xff, 0xff, 0xfc, 0xe0, 0xff, 0xff, 0xfc,
  81.    0xe0, 0xff, 0xff, 0xfc, 0xe0, 0xff, 0xff, 0xfc, 0xc0, 0xff, 0xff, 0xfc,
  82.    0x80, 0xff, 0x3f, 0xfc, 0x00, 0xff, 0x1f, 0xfc, 0x00, 0xff, 0x0f, 0xfc,
  83.    0x00, 0xff, 0x0f, 0xfc, 0x00, 0xff, 0x0f, 0xfc, 0x00, 0xff, 0x0f, 0xfc,
  84.    0x00, 0xff, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc};
  85. #define caution_width 26
  86. #define caution_height 38
  87. static char caution_bits[] = {
  88.    0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xc0, 0x00, 0xfc,
  89.    0x00, 0xe0, 0x01, 0xfc, 0x00, 0xee, 0x19, 0xfc, 0x00, 0xef, 0x3d, 0xfc,
  90.    0x00, 0xef, 0x3d, 0xfc, 0x00, 0xef, 0x3d, 0xfc, 0x00, 0xef, 0x3d, 0xfc,
  91.    0x70, 0xef, 0x3d, 0xfc, 0x78, 0xef, 0x3d, 0xfc, 0x78, 0xef, 0x3d, 0xfc,
  92.    0x78, 0xef, 0x3d, 0xfc, 0x78, 0xef, 0x3d, 0xfc, 0x78, 0xef, 0xdd, 0xfc,
  93.    0x78, 0xef, 0xed, 0xfc, 0x78, 0xff, 0xef, 0xfc, 0xf8, 0xff, 0xf7, 0xfc,
  94.    0xf8, 0xff, 0xf7, 0xfc, 0xf8, 0xff, 0xf7, 0xfc, 0xf8, 0xff, 0xf7, 0xfc,
  95.    0xf8, 0xff, 0xf9, 0xfc, 0xf8, 0x7f, 0xfe, 0xfc, 0xf8, 0xbf, 0xff, 0xfc,
  96.    0xf8, 0xbf, 0xff, 0xfc, 0xf8, 0xdf, 0xff, 0xfc, 0xf8, 0xdf, 0xff, 0xfc,
  97.    0xf8, 0xdf, 0xff, 0xfc, 0xf0, 0xff, 0x7f, 0xfc, 0xe0, 0xff, 0x3f, 0xfc,
  98.    0x80, 0xff, 0x0f, 0xfc, 0x80, 0xff, 0x07, 0xfc, 0x80, 0xff, 0x07, 0xfc,
  99.    0x80, 0xff, 0x07, 0xfc, 0x80, 0xff, 0x07, 0xfc, 0x80, 0xff, 0x07, 0xfc,
  100.    0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfc};
  101. #define warning_width 26
  102. #define warning_height 38
  103. static char warning_bits[] = {
  104.  0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0xfc,0x00,0xc0,0x00,0xfc,0x00,0xe0,0x01,
  105.  0xfc,0x00,0xee,0x19,0xfc,0x00,0xef,0x3d,0xfc,0x00,0xef,0x3d,0xfc,0x00,0xef,
  106.  0x3d,0xfc,0x00,0xef,0x3d,0xfc,0x70,0xef,0x3d,0xfc,0x78,0xef,0x3d,0xfc,0x78,
  107.  0x2f,0x30,0xfc,0x78,0x0f,0x38,0xfc,0x78,0x0f,0x3c,0xfc,0x78,0x07,0xde,0xfc,
  108.  0x78,0x07,0xef,0xfc,0xf8,0x03,0xef,0xfc,0xf8,0x01,0xf6,0xfc,0xf8,0x0f,0xf7,
  109.  0xfc,0xf8,0x8f,0xf7,0xfc,0xf8,0xe7,0xf7,0xfc,0xf8,0xf3,0xf9,0xfc,0xf8,0x79,
  110.  0xfe,0xfc,0xf8,0xbe,0xff,0xfc,0xf8,0xbf,0xff,0xfc,0xf8,0xdf,0xff,0xfc,0xf8,
  111.  0xdf,0xff,0xfc,0xf8,0xdf,0xff,0xfc,0xf0,0xff,0x7f,0xfc,0xe0,0xff,0x3f,0xfc,
  112.  0x80,0xff,0x0f,0xfc,0x80,0xff,0x07,0xfc,0x80,0xff,0x07,0xfc,0x80,0xff,0x07,
  113.  0xfc,0x80,0xff,0x07,0xfc,0x80,0xff,0x07,0xfc,0x00,0x00,0x00,0xfc,0x00,0x00,
  114.  0x00,0xfc};
  115. Image *DefaultImage()
  116. {
  117.     if (default_image)
  118. return default_image;
  119.     default_pixmap = XCreatePixmapFromBitmapData(display, win, www_bits,
  120.                       www_width, www_height, textColor, transparent, depth);
  121.     default_image = (Image *)malloc(sizeof(Image));
  122.     default_image->pixmap =  XCreatePixmapFromBitmapData(display, win, www_bits,
  123.       www_width, www_height, textColor, transparent, depth);
  124.     default_image->width = www_width;
  125.     default_image->height = www_height;
  126.     return default_image;
  127. }
  128. int Brightness2Voltage(int brightness)
  129. {
  130.     double voltage;
  131.     static double log_a = 0; /* howcome added double */
  132.     if (brightness == 0)
  133.         return 0;
  134.     if (log_a == 0)
  135.         log_a = (Gamma - 1.0) * log((double)65535);      /* cast added by howcome 21/9/94 */
  136.     voltage = (log_a + log((double)brightness))/Gamma;   /* cast added by howcome 21/9/94 */
  137.     return (int)(0.5 + exp(voltage));
  138. }
  139. int Voltage2Brightness(int voltage)
  140. {
  141.     double brightness;
  142.     static double log_a;
  143.     if (voltage == 0)
  144.         return 0;
  145.     if (log_a == 0)
  146.         log_a = (Gamma - 1.0) * log((double)255);   /* cast added by howcome 21/9/94 */
  147.     brightness = Gamma * log((double)voltage) - log_a;    /* cast added by howcome 21/9/94 */
  148.     return (int)(0.5 + exp(brightness));
  149. }
  150. /* don't add this to images list to avoid trouble when freeing document images */
  151. Image *MakeIcon(unsigned int depth, char *name, int width, int height, char *bits)
  152. {
  153.     GC drawGC;
  154.     Pixmap pixmap;
  155.     XImage *ximage;
  156.     Image *image;
  157.     unsigned char *data, *p, *s;
  158.     int size, i, j, k;
  159.     unsigned int byte = 0;
  160.     size = width * height;
  161.     if (size == 0)
  162.         return NULL;
  163.     image = (Image *)malloc(sizeof(Image));
  164.     image->url = name;
  165.     image->npixels = 0;
  166.     image->pixels = 0;
  167.     image->next = NULL;
  168.     image->width = width;
  169.     image->height = height;
  170.     s = (unsigned char*)bits;
  171.     if (depth == 8)
  172.     {
  173.         p = data = (unsigned char *)malloc(size);
  174.         for (i = 0; i < height; ++i)
  175.             for (j = 0, k= 8; j < width; ++j)
  176.             {
  177.                 if (++k > 8)  /* need to read next 8 pixel values */
  178.                 {
  179.                     byte = *s++;
  180.                     k = 1;
  181.                 }
  182.                 if (byte & 0x01)
  183.                     *p++ = textColor;
  184.                 else
  185.                     p = Transparent(p, j, i);
  186.                 byte = byte >> 1;
  187.             }
  188.     }
  189.     else  if (depth == 16)
  190.     {
  191.         p = data = (unsigned char *)malloc(size * 2);
  192.         for (i = 0; i < height; ++i)
  193.             for (j = 0, k= 8; j < width; ++j)
  194.             {
  195.                 if (++k > 8)  /* need to read next 8 pixel values */
  196.                 {
  197.                     byte = *s++;
  198.                     k = 1;
  199.                 }
  200.                 if (byte & 1)
  201.                 {
  202.     *p++ = (textColor >>  8) & 0xFF;
  203.     *p++ = textColor & 0xFF;
  204. }
  205.                 else
  206.                     p = Transparent(p, j, i);
  207.                 byte = byte >> 1;
  208.             }
  209.     }
  210.     else  if (depth == 24)
  211.     {
  212.         p = data = (unsigned char *)malloc(size * 4);
  213.         for (i = 0; i < height; ++i)
  214.             for (j = 0, k= 8; j < width; ++j)
  215.             {
  216.                 if (++k > 8)  /* need to read next 8 pixel values */
  217.                 {
  218.                     byte = *s++;
  219.                     k = 1;
  220.                 }
  221.                 if (byte & 1)
  222.                 {
  223.                     *p++ = '';
  224.                     *p++ = (textColor >> 16) & 0xFF;
  225.                     *p++ = (textColor >>  8) & 0xFF;
  226.                     *p++ = textColor & 0xFF;
  227.                 }
  228.                 else
  229.                     p = Transparent(p, j, i);
  230.                 byte = byte >> 1;
  231.             }
  232.     }
  233.     else if (depth == 4 || depth == 2 || depth == 1)
  234.     {
  235. int             ppb, bpl, shift = 0;
  236. int newbyte;
  237. ppb = 8/depth; /* pixels per byte */
  238. bpl = width/ppb + (width%ppb ? 1 : 0); /* bytes per line */
  239.         p = data = (unsigned char *)malloc(bpl * height);
  240. newbyte = 1;
  241.         for (i = 0; i < height; ++i) {
  242.             for (j = 0, k= 8; j < width; ++j)
  243.             {
  244.         if (newbyte) {
  245.     *p = 0;
  246.             newbyte = 0;
  247.         }
  248.                 if (++k > 8)  /* need to read next 8 pixel values */
  249.                 {
  250.                     byte = *s++;
  251.                     k = 1;
  252.                 }
  253.                 if (byte & 0x01) {
  254.     shift = (((7 - (j % 8)) % ppb) * depth);
  255.     *p |= textColor << shift;
  256.     if (shift == 0) {
  257. p++;
  258. newbyte = 1;
  259.     }
  260. }
  261.                 else {
  262.     shift = (((7 - (j % 8)) % ppb) * depth);
  263.     *p |= transparent << shift;
  264.     if (shift == 0) {
  265. p++;
  266. newbyte = 1;
  267.     }
  268. }
  269.                 byte = byte >> 1;
  270.             }
  271.     
  272.     if (shift) {
  273. p++;   /* make sure we start on a new byte for the next line */
  274. newbyte = 1;
  275.     }
  276. }
  277.     }
  278.     else
  279.     {
  280. fprintf(stderr,"Icons for display depth %d unsupportedn", depth);
  281.         return NULL;
  282.     }
  283.     if ((ximage = XCreateImage(display, DefaultVisual(display, screen),
  284.              depth, ZPixmap, 0, (char *)data,
  285.              width, height, (depth == 24 ? 32 :(depth == 16 ? 16 : 8)), 0)) == 0)
  286.     {
  287.         Warn("Failed to create XImage: %s", image->url);
  288.         Free(data);
  289. Free(image);
  290.         return DefaultImage();
  291.     }
  292.     /* howcome 22/2/95: do we need to set these?? */
  293.     ximage->byte_order = MSBFirst;
  294.                        
  295.     ximage->bitmap_bit_order = BitmapBitOrder(display);
  296.     if ((pixmap = XCreatePixmap(display, win, width, height, depth)) == 0)
  297.     {
  298.         Warn("Failed to create Pixmap: %s", image->url);
  299.         XDestroyImage(ximage); /* also free's image data */
  300. Free(image);
  301.         return DefaultImage();
  302.     }
  303.     drawGC = XCreateGC(display, pixmap, 0, 0);
  304.     XSetFunction(display, drawGC, GXcopy);
  305.     XPutImage(display, pixmap, drawGC, ximage, 0, 0, 0, 0, width, height);
  306.     XFreeGC(display, drawGC);
  307.     XDestroyImage(ximage);  /* also free's image data */
  308.     /* janet 27/07/95: image not always freed! */
  309.     Free(image); 
  310.       
  311.     image = (Image *)malloc(sizeof(Image));
  312.     image->url = name;
  313.     image->npixels = 0;
  314.     image->pixels = 0;
  315.     image->next = NULL;
  316.     image->width = width;
  317.     image->height = height;
  318.     image->pixmap = pixmap;
  319.     return image;    
  320. }
  321. void MakeIcons(unsigned int depth)
  322. {
  323.     note_image = MakeIcon(depth, "note", note_width, note_height, note_bits);
  324.     caution_image = MakeIcon(depth, "caution", caution_width, caution_height, caution_bits);
  325.     warning_image = MakeIcon(depth, "warning", warning_width, warning_height, warning_bits);
  326. }
  327. unsigned char *gamma_table=NULL;
  328. static unsigned int
  329. range (unsigned int val, unsigned int max)
  330. {
  331.   return (val > max) ? max : val;
  332. }
  333. void
  334. build_gamma_table()
  335. {
  336.   if (!gamma_table) {
  337.     int i;
  338.     double file_gamma = 1.0/2.2;
  339.     double g = 1.0 / (file_gamma * Gamma);
  340.   
  341.     gamma_table = (unsigned char *) malloc(256 * sizeof(char));
  342.     for (i = 0; i < 256; i++)
  343. gamma_table[i] = (unsigned char)range((pow((double)i / 255.0, g) * 255.0), 255);
  344.   }
  345. }
  346. void
  347. free_gamma_table()
  348. {
  349.   if(gamma_table){
  350.     free(gamma_table);
  351.     gamma_table=NULL;
  352.   }
  353. }
  354. int AllocGreyScale(void)
  355. {
  356.     unsigned long g;
  357.     XColor color;
  358.     greymap[0] = BlackPixel(display, screen);
  359.     greymap[15] = WhitePixel(display, screen);
  360. /*    mycmap[128 & 0] = BlackPixel(display, screen);
  361.     mycmap[128 & 15] = WhitePixel(display, screen);
  362.     */
  363.     for (g = !OwnColorMap; g < 16+OwnColorMap; ++g)
  364.     {
  365.         color.red = color.green = color.blue = (g * 65535)/15;
  366.      /* map brightness values into voltages for Gamma correction */
  367.         color.red = Brightness2Voltage(color.red);
  368.         color.green = Brightness2Voltage(color.green);
  369.         color.blue = Brightness2Voltage(color.blue);
  370.         if (XAllocColor(display, colormap, &color) == 0)
  371.         {
  372.             fprintf(stderr, "Can't allocate standard grey paletten");
  373.             while (g > 1)
  374.                 XFreeColors(display, colormap, &(greymap[--g]), 1, 0);
  375.             return 0;
  376.         }
  377.         greymap[g] = color.pixel;
  378. /* mycmap[128 & g] = color.pixel;*/
  379.     }
  380.     return 1;
  381. }
  382. int AllocStandardColors(void)
  383. {
  384.     unsigned long i;
  385.     XColor colors[128];  /* howcome 5/10/94 */
  386.     int status[128];  /* howcome 5/10/94 */
  387.     XColor color;
  388.     int color_ok=1;
  389.     stdcmap[0] = BlackPixel(display, screen);
  390.     stdcmap[127] = WhitePixel(display, screen);
  391.     mycmap[0] = BlackPixel(display, screen);
  392.     mycmap[127] = WhitePixel(display, screen);
  393.     for (i = 0; i < 128; ++i)
  394.     {
  395. #if 0
  396. double gammaC = 0.7;
  397.         color.red = /*(i & 0x3) * 65535/3 ; */ pow((((double)(i & 0x3))/3.0), gammaC)*65535;
  398.         color.green = /*((i >> 2) & 0x7) * 65535/7 ;*/ pow((((double)((i >> 2) & 0x7))/7.0), gammaC)*65535;    
  399.         color.blue = /*((i >> 5) & 0x3) * 65535/3 ;*/ pow((((double)((i >> 5) & 0x3))/3.0), gammaC)*65535;
  400. #endif
  401. color.red = (i & 0x3) * 65535/3;
  402.         color.green = ((i >> 2) & 0x7) * 65535/7;
  403.         color.blue = ((i >> 5) & 0x3) * 65535/3;
  404. if (COLOR_TRACE)
  405.     fprintf(stderr,"AllocStandardColors exact %d %d %dn", (color.red >> 8), (color.green >> 8), (color.blue >> 8));
  406. /* howcome 5/10/94: added support for XAllocColors which will
  407.            speed things up. */
  408. /* map brightness values into voltages for Gamma correction */
  409. colors[i].red = Brightness2Voltage(color.red);
  410.         colors[i].green = Brightness2Voltage(color.green);
  411.         colors[i].blue = Brightness2Voltage(color.blue);
  412. #if 0
  413. colors[i].red = color.red;
  414.         colors[i].green = color.green;
  415.         colors[i].blue = color.blue; 
  416. #endif
  417. if (COLOR_TRACE)
  418.     fprintf(stderr,"AllocStandardColors %d %d %dn", (colors[i].red >> 8), (colors[i].green >> 8), (colors[i].blue >> 8));
  419.     }
  420.     /* howcome 5/10/94: here comes the one and only call to XAllocColors */
  421.     if (!OwnColorMap)
  422.     {
  423. if (XAllocColors(display, colormap, colors, i, status)) {
  424.     for (i = 1; i < 127; i++ ) {
  425. stdcmap[i] = colors[i].pixel;
  426. mycmap[i] = colors[i].pixel;
  427.     }
  428. } else {
  429.     int j;
  430.     for(j = 1; j < i ; j++)
  431. if (status[j])
  432.     XFreeColors( display, colormap, &colors[j].pixel, 1, 0L );
  433.     OwnColorMap = 1; /* --Spif 25-Oct-95 -cm flag now works */
  434.     color_ok=0;
  435. }
  436.     };
  437.   
  438.     /* howcome 10/8/05: added support for own colormap */
  439.     if (OwnColorMap) {
  440. int j;
  441. if(!color_ok) {
  442.     fprintf(stderr,"Can't alloc colors, creating new colormap..n");
  443.     for(i=1; i < 15 ; i++)
  444. XFreeColors(display, colormap, &(greymap[i]), 1, 0);
  445. };
  446. colormap = XCreateColormap(display, RootWindow(display, screen),
  447.    visual, AllocNone);
  448. AllocGreyScale();
  449. for(j=0;j<128;j++)
  450. {
  451.     if (XAllocColor(display, colormap, &colors[j]) == 0)
  452.     {
  453. int g;
  454. fprintf(stderr, "FATAL ERROR:Can't allocate my own palette!!n");
  455. g=j;
  456. while (g > 1)
  457.     XFreeColors(display, colormap, &(stdcmap[--g]), 1, 0);
  458. return 0;
  459.     };
  460.     stdcmap[j] = colors[j].pixel;
  461.     mycmap[j] = colors[j].pixel;
  462. }
  463. return 1; /* assume success, what could go wrong? */
  464.     }
  465.     return 1;
  466. }
  467. int SupportTrueColor(void)
  468. {
  469.     long visual_info_mask;
  470.     int number_visuals, i, flag;
  471.     XVisualInfo *visual_array, visual_info_template;
  472.     visual_info_template.screen = DefaultScreen(display);
  473.     visual_info_mask = VisualClassMask | VisualScreenMask;
  474.     visual_info_template.class = TrueColor;
  475.     visual_array = XGetVisualInfo(display, visual_info_mask,
  476.                         &visual_info_template,
  477.                         &number_visuals);
  478.     for (i = flag = 0; i < number_visuals; ++i)
  479.     {
  480. if (visual_array[i].depth == 16)
  481. {
  482.     long int maskval;
  483.     int j=0, k;
  484.     maskval = (*visual).blue_mask;
  485.     while ((maskval & 1) == 0) { j++; maskval = maskval >> 1; }
  486.     maskval = (*visual).blue_mask;
  487.     BPixelMask = 0;
  488.     for(k=0; k<16; k++)
  489.     {
  490. if(maskval & 1)
  491. {
  492.     if(!BPixelMask)
  493. BPixelMask = 1;
  494.     else
  495. BPixelMask += BPixelMask + 1;
  496. };
  497. maskval = maskval >> 1;
  498.     }
  499.     j=0;
  500.     maskval = (*visual).green_mask;
  501.     while ((maskval & 1) == 0) { j++; maskval = maskval >> 1; }
  502.     GPixelShift = j;
  503.     GPixelMask = 0;
  504.     for(k=0; k<16; k++)
  505.     {
  506. if(maskval & 1)
  507. {
  508.     if(!GPixelMask)
  509. GPixelMask = 1;
  510.     else
  511. GPixelMask += GPixelMask + 1;
  512. };
  513. maskval = maskval >> 1;
  514.     }
  515.     j=0;
  516.     maskval = (*visual).red_mask;
  517.     while ((maskval & 1) == 0) { j++; maskval = maskval >> 1; }
  518.     RPixelShift = j;
  519.     RPixelMask = 0;
  520.     for(k=0; k<16; k++)
  521.     {
  522. if(maskval & 1)
  523. {
  524.     if(!RPixelMask)
  525. RPixelMask = 1;
  526.     else
  527. RPixelMask += RPixelMask + 1;
  528. };
  529. maskval = maskval >> 1;
  530.     };
  531.             flag = 1;
  532. }
  533. if (visual_array[i].depth == 24)
  534.         {
  535.     long int maskval;
  536.     int j=0;
  537.     
  538.     maskval = (*visual).blue_mask;
  539.     while ((maskval & 1) == 0) { j++; maskval = maskval >> 1; }
  540.     BPixelShift = j;
  541.     j=0;
  542.     maskval = (*visual).green_mask;
  543.     while ((maskval & 1) == 0) { j++; maskval = maskval >> 1; }
  544.     GPixelShift = j;
  545.     j=0;
  546.     maskval = (*visual).red_mask;
  547.     while ((maskval & 1) == 0) { j++; maskval = maskval >> 1; }
  548.     RPixelShift = j;
  549.             flag = 1;
  550.             break;
  551. }
  552.     }
  553.     XFree((void *)visual_array);
  554.     return flag;
  555. }
  556. int InitImaging(int ColorStyle)
  557. {
  558.     imaging = MONO;
  559.     
  560.     build_gamma_table();
  561.     
  562.     greymap[0] = BlackPixel(display, screen);
  563.     greymap[15] = WhitePixel(display, screen);
  564.     if (ColorStyle == MONO)
  565.     {
  566.         imaging = ColorStyle;
  567.         return imaging;
  568.     }
  569.     if (ColorStyle == COLOR888 && SupportTrueColor())
  570.     {
  571.         imaging = ColorStyle;
  572.         return imaging;
  573.     }
  574.     if(OwnColorMap)
  575. if (AllocStandardColors())
  576. {
  577.     imaging = COLOR232;
  578.     return imaging;
  579. };
  580.     
  581.     if (AllocGreyScale())
  582.     {
  583.         imaging = GREY4;
  584.         if (ColorStyle == GREY4)
  585.             return imaging;
  586.         if (AllocStandardColors())
  587.             imaging = COLOR232;
  588.     } else 
  589. if(OwnColorMap)
  590.     if (AllocStandardColors())
  591. imaging = COLOR232;
  592.     return imaging;
  593. }
  594. void ReportVisuals(void)
  595. {
  596.     long visual_info_mask;
  597.     int number_visuals, i;
  598.     XVisualInfo *visual_array, visual_info_template;
  599.     visual_info_template.screen = DefaultScreen(display);
  600.     visual_info_mask = VisualClassMask | VisualScreenMask;
  601.     printf("TrueColor:n");
  602.     visual_info_template.class = TrueColor;
  603.     visual_array = XGetVisualInfo(display, visual_info_mask,
  604.                         &visual_info_template,
  605.                         &number_visuals);
  606.     for (i = 0; i < number_visuals; ++i)
  607.     {
  608.         printf("  visual Id 0x%xn", visual_array[i].visualid);
  609.         printf("  depth = %d, bits per rgb = %d, size = %dn", visual_array[i].depth,
  610.                     visual_array[i].bits_per_rgb, visual_array[i].colormap_size);
  611.         printf("   rgb masks %lx, %lx, %lxn", visual_array[i].red_mask,
  612.                     visual_array[i].green_mask, visual_array[i].blue_mask);
  613.     }
  614.     XFree((void *)visual_array);
  615.     printf("DirectColor:n");
  616.     visual_info_template.class = DirectColor;
  617.     visual_array = XGetVisualInfo(display, visual_info_mask,
  618.                         &visual_info_template,
  619.                         &number_visuals);
  620.     for (i = 0; i < number_visuals; ++i)
  621.     {
  622.         printf("  visual Id 0x%xn", visual_array[i].visualid);
  623.         printf("  depth = %d, bits per rgb = %d, size = %dn", visual_array[i].depth,
  624.                     visual_array[i].bits_per_rgb, visual_array[i].colormap_size);
  625.         printf("   rgb masks %lx, %lx, %lxn", visual_array[i].red_mask,
  626.                     visual_array[i].green_mask, visual_array[i].blue_mask);
  627.     }
  628.     XFree((void *)visual_array);
  629.     printf("PseudoColor:n");
  630.     visual_info_template.class = PseudoColor;
  631.     visual_array = XGetVisualInfo(display, visual_info_mask,
  632.                         &visual_info_template,
  633.                         &number_visuals);
  634.     for (i = 0; i < number_visuals; ++i)
  635.     {
  636.         printf("  visual Id 0x%xn", visual_array[i].visualid);
  637.         printf("  depth = %d, bits per rgb = %d, size = %dn", visual_array[i].depth,
  638.                     visual_array[i].bits_per_rgb, visual_array[i].colormap_size);
  639.         printf("   rgb masks %lx, %lx, %lxn", visual_array[i].red_mask,
  640.                     visual_array[i].green_mask, visual_array[i].blue_mask);
  641.     }
  642.     XFree((void *)visual_array);
  643. }
  644. void ReportStandardColorMaps(Atom which_map)
  645. {
  646.     XStandardColormap *std_colormaps;
  647.     int i, number_colormaps;
  648.     char *atom_name;
  649.     if (XGetRGBColormaps(display, RootWindow(display, screen),
  650.             &std_colormaps, &number_colormaps, which_map) != 0)
  651.     {
  652.         atom_name = XGetAtomName(display, which_map);
  653.         printf("nPrinting %d standard colormaps for %sn",
  654.                 number_colormaps, atom_name);
  655.         XFree(atom_name);
  656.         for  (i = 0; i < number_colormaps; ++i)
  657.         {
  658.             printf("tColormap: 0x%xn", std_colormaps[i].colormap);
  659.             printf("tMax cells (rgb): %d, %d, %dn",
  660.                 std_colormaps[i].red_max,
  661.                 std_colormaps[i].green_max,
  662.                 std_colormaps[i].blue_max);
  663.             printf("tMultipliers: %d, %d, %dn",
  664.                 std_colormaps[i].red_mult,
  665.                 std_colormaps[i].green_mult,
  666.                 std_colormaps[i].blue_mult);
  667.             printf("tBase pixel: %dn", std_colormaps[i].base_pixel);
  668.             printf("tVisual Id 0x%x, Kill Id 0x%xn",
  669.                 std_colormaps[i].visualid,
  670.                 std_colormaps[i].killid);
  671.         }
  672.         XFree((void *)std_colormaps);
  673.     }
  674. }
  675. XColor paperrgb[3];
  676. /* Init paperrgb */
  677. void InitPaperRGB ()
  678. {
  679.   int i;
  680.   
  681.   for (i=0; i<3; i++) {
  682.     int r=0, g=0, b=0;
  683.     switch(i) {
  684.       case 0:
  685. r=230; g=218; b=194;
  686. break;
  687.       case 1:
  688. r=220; g=209; b=186;
  689. break;
  690.       case 2:
  691. r=210; g=199; b=177;
  692. break;
  693.     }
  694.   
  695.     paperrgb[i].red=gamma_table[r];
  696.     paperrgb[i].green=gamma_table[g];
  697.     paperrgb[i].blue=gamma_table[b];
  698.   }
  699. }   
  700. /* Barely used colormap */
  701. XColor papercols[256];
  702. /* create a textured background as paper */
  703. unsigned char *CreateBackground(unsigned int width, unsigned int height, unsigned int depth)
  704. {
  705.     unsigned char *data, *p;
  706.     int size, i, j;
  707.     unsigned long cs[3]; /* howcome 21/9/94 */
  708.     unsigned long int ulp;
  709.     
  710.     if (depth == 8)
  711.     {
  712.       /* howcome 4/10/94: changed last arg to GetColor */
  713.       
  714.       int i;
  715.       for (i=0; i<3; i++) {
  716. int r, g, b;
  717. r=paperrgb[i].red;
  718. g=paperrgb[i].green;
  719. b=paperrgb[i].blue;
  720. if (!GetColor(r, g, b, &cs[i]))
  721.   return NULL;
  722. paperrgb[i].pixel=cs[i];
  723. papercols[cs[i]].red=r;
  724. papercols[cs[i]].green=g;
  725. papercols[cs[i]].blue=b;
  726.       }
  727.       size = width * height;
  728.     }
  729.     else if (depth == 24)
  730.         size = width * height * 4;
  731.     else if (depth == 16)
  732. size = width * height *2;
  733.     else
  734.         return NULL;
  735.     p = data = (unsigned char *)malloc(size);
  736.     if (data == NULL)
  737.         return NULL;
  738.     srand(0x6000);
  739.     if (depth == 8)
  740.     {
  741.         for (i = 0; i < height; ++i)
  742.             for (j = 0; j < width; ++j)
  743.             {
  744.                 /* howcome 21/9/94: rand returns different ranges on different platforms, therefore: */
  745.             
  746.       *p++ = paperrgb[rand() % 3].pixel;
  747.             }
  748.     }
  749.     else if (depth == 24)
  750.     {
  751.         for (i = 0; i < height; ++i)
  752.             for (j = 0; j < width; ++j)
  753.     {
  754. int col,r,g,b;
  755.                 
  756. col=rand() % 3;
  757. r=paperrgb[col].red;
  758. g=paperrgb[col].green;
  759. b=paperrgb[col].blue;
  760. GetColor(r, g, b, &ulp);
  761.                 
  762. *p++ = '';
  763. *p++ = (ulp >> 16) & 0xff; 
  764. *p++ = (ulp >> 8) & 0xff; 
  765. *p++ = ulp & 0xff; 
  766. #if 0
  767. *p++ = '';
  768. *p++ = paperrgb[col].red;
  769. *p++ = paperrgb[col].green;
  770. *p++ = paperrgb[col].blue;
  771. #endif
  772.             }
  773.     } else if (depth == 16) 
  774.     {
  775.  for (i = 0; i < height; ++i)
  776.             for (j = 0; j < width; ++j)
  777.     {
  778. int col,r,g,b;
  779.                 
  780. col=rand() % 3;
  781. r=paperrgb[col].red;
  782. g=paperrgb[col].green;
  783. b=paperrgb[col].blue;
  784. GetColor(r, g, b, &ulp);
  785.                 
  786. *p++ = ((char*)&ulp)[1]; 
  787. *p++ = ((char*)&ulp)[0]; 
  788.     }
  789.     }
  790.     return data;
  791. }
  792. #if 0  /* used to allow for nested comments */
  793. /* XPM */
  794. /********************************************************/
  795. /**   (c) Copyright Hewlett-Packard Company, 1992.     **/
  796. /********************************************************/
  797. static char ** arizona.l.px  = {
  798. /* width height ncolors cpp [x_hot y_hot] */
  799. "28 38 13 1",
  800. /* colors */
  801. "   s iconColor2    m white c white",
  802. ".  s iconGray2     m white c #c8c8c8c8c8c8",
  803. "X  s iconColor1    m black c black",
  804. "o  s iconGray6     m black c #646464646464",
  805. "O  s iconGray3     m white c #afafafafafaf",
  806. "+  s iconColor3    m black c red",
  807. "@  s iconColor8    m white c magenta",
  808. "#  s iconGray4     m white c #969696969696",
  809. "$  s iconGray5     m black c #7d7d7d7d7d7d",
  810. "%  s iconColor6    m white c yellow",
  811. "&  s iconGray1     m white c #e1e1e1e1e1e1",
  812. "*  s iconColor4    m black c green",
  813. "=  s bottomShadowColor     m black c #646464646464",
  814. /* pixels */
  815. "                            ",
  816. " ..........................X",
  817. " ..............oo..........X",
  818. " .........OOOoo+@@oooOOOOOOX",
  819. " .....OOOoooo@####@+ooooo..X",
  820. " ..ooo#oo+@###$$$$#####OOO.X",
  821. " ..OOOOOO###$$....$$#@+ooo.X",
  822. " .......+@#$.%%%%%%.$###OOOX",
  823. " ..o.ooo..$.%%%%%%%%%$#@+ooX",
  824. and so on, ending with:
  825. " XXXXXXXXXXXXXXXXXXXXXXXXXXX"};
  826. #endif
  827. #define NEXTCHAR(s) (*s ? *s++ : '')
  828. static char *FindCh(char *s, char ch)
  829. {
  830.     char c;
  831.     for (;;)
  832.     {
  833.         c = NEXTCHAR(s);
  834.         if (c == ch || c == '')
  835.             return s;
  836.     }
  837. }
  838. /* *c to first char and return last word */
  839. static char *ReadColor(char *s, char **name, int *ch)
  840. {
  841.     char *p;
  842.     int c;
  843.     static char line[256];
  844.     s = FindCh(s, '"');
  845.     *ch = NEXTCHAR(s);
  846.     p = line;
  847.     while ((c = NEXTCHAR(s)) != '"' && c != '' && p < line+255)
  848.         *p++ = c;
  849.     *p = '';
  850.     p = strrchr(line, ' ');
  851.     if (p)
  852.         ++p;
  853.     *name = p;
  854.     return s;
  855. }
  856. unsigned char *Transparent(unsigned char *p, int x, int y)
  857. {
  858.     unsigned int i;
  859.     unsigned char *s;
  860.     if (tileData)
  861.     {
  862.         x = x % tileWidth;
  863.         y = y % tileHeight;
  864.         i = y * tileWidth + x;
  865. if (depth == 24)
  866.         {
  867.             s = tileData + 4 * i;
  868.     
  869.             *p++ = *s++;
  870.             *p++ = *s++;
  871.             *p++ = *s++;
  872.             *p++ = *s++;
  873.     
  874.             return p;
  875.         }
  876. if (depth == 16)
  877. {
  878.     s = tileData + 2 * i;
  879.     
  880.     *p++ = *s++;
  881.     *p++ = *s++;
  882.     
  883.     return p;
  884. };
  885. *p++ = gamma_table[tileData[i]];
  886. return p;
  887.     }
  888.     if (depth == 24)
  889.     {
  890.         *p++ = '';
  891.         *p++ = (transparent  >> 16) & 0xFF;
  892.         *p++ = (transparent  >> 8) & 0xFF;
  893. *p++ = transparent & 0xFF;
  894.         return p;
  895.     }
  896.     if (depth == 16) 
  897.     {
  898. *p++ = (transparent  >> 8) & 0xFF;
  899. *p++ = transparent & 0xFF;
  900.         return p;
  901.     };
  902.     *p++ = transparent;
  903.     return p;
  904. }
  905. /* load data from an XPM file and allocate colors */
  906. char *LoadXpmImage(Image *image, Block *bp, unsigned int depth)
  907. {
  908.     int c, i, j, cr, cg, cb, r, g, b, ncolors, size, map[256];
  909.     unsigned int width, height;
  910.     /*    unsigned long pixel, *pixdata; */ /* janet 21/07/95: not used */
  911.     unsigned char *data = NULL, *p;
  912.     unsigned long ccolor;
  913.     char *name, *s;
  914.     Color *colors, color;
  915.     XColor xcolor;
  916.     s = bp->buffer + bp->next;
  917.     s = FindCh(s, '"');
  918.     sscanf(s, "%d %d %d", &width, &height, &ncolors);
  919.     s = FindCh(s, 'n');
  920.     size = width * height;
  921.     image->width = width;
  922.     image->height = height;
  923.     if (size == 0 || ncolors == 0)
  924.         return NULL;
  925.     if (depth != 8 && depth != 24 && depth != 4 && depth != 2 && depth != 1)
  926.     {
  927.         printf("Display depth %d unsupportedn", depth);
  928.         return NULL;
  929.     }
  930.     image->npixels = 0;
  931.     image->pixels = 0; /*(unsigned long *)malloc(ncolors * sizeof(unsigned long)); */
  932.     colors = (Color *)malloc(ncolors * sizeof(Color));
  933.     for (i = 0; i < 256; ++i)
  934.         map[i] = -1;
  935.     for (i = 0; i < ncolors; ++i)
  936.     {
  937.         s = ReadColor(s, &name, &c);
  938.         if (XParseColor(display, colormap, name, &xcolor) == 0)
  939.         {
  940.             map[c] = -1;
  941.             continue;
  942.         }
  943.         map[c] = i;
  944.         r = xcolor.red >> 8;
  945.         g = xcolor.green >> 8;
  946.         b = xcolor.blue >> 8;
  947.      /* apply Gamma correction to map voltages to brightness values */
  948.         if (imaging != COLOR888)
  949.         {
  950.     /*
  951.     r = gamma_table[r];
  952.             g = gamma_table[g];
  953.             b = gamma_table[b];*/
  954.     r = Voltage2Brightness(r);
  955.     g = Voltage2Brightness(g);
  956.     b = Voltage2Brightness(b);
  957.         }
  958.         colors[i].red = r;
  959.         colors[i].green = g;
  960.         colors[i].blue = b;
  961.         colors[i].grey = (3*r + 6*g + b)/10;
  962.     }
  963.     if (depth == 8)
  964.     {
  965.         p = data = malloc(size);
  966.         for (i = 0; i < height; ++i)
  967.         {
  968.             s = FindCh(s, '"');
  969.             for (j = 0; j < width; ++j)
  970.             {
  971.                 c = *s++;
  972.                 c = map[c];
  973.                 if (c < 0)
  974.                 {
  975.                     p = Transparent(p, j, i);
  976.                     continue;
  977.                 }
  978.                 color = colors[c];
  979.                 c = ((i % 16) << 4) + (j % 16);
  980.                 if (imaging == COLOR232)
  981.                 {
  982.                     cr = color.red;
  983.                     cg = color.green;
  984.                     cb = color.blue;
  985.                     if (cr == cg  && cg == cb)
  986.                     {
  987.                         cg  = color.grey;
  988.                         g = cg & 0xF0;
  989.                         if (cg - g > Magic16[c])
  990.                             g += 16;
  991.                         g = min(g, 0xF0);
  992.                         *p++ = greymap[g >> 4];
  993.                     }
  994.                     else
  995.                     {
  996.                         r = cr & 0xC0;
  997.                         g = cg & 0xE0;
  998.                         b = cb & 0xC0;
  999.                         if (cr - r > Magic64[c])
  1000.                             r += 64;
  1001.                         if (cg - g > Magic32[c])
  1002.                             g += 32;
  1003.                         if (cb - b > Magic64[c])
  1004.                             b += 64;
  1005.                         r = min(r, 255) & 0xC0;
  1006.                         g = min(g, 255) & 0xE0;
  1007.                         b = min(b, 255) & 0xC0;
  1008.                         *p++ = stdcmap[(r >> 6) | (g >> 3) | (b >> 1)];
  1009.                     }
  1010.                 }
  1011.                 else if (imaging == GREY4)
  1012.                 {
  1013.                     cg  = color.grey;
  1014.                     g = cg & 0xF0;
  1015.                     if (cg - g > Magic16[c])
  1016.                         g += 16;
  1017.                     g = min(g, 0xF0);
  1018.                     *p++ = greymap[g >> 4];
  1019.                 }
  1020.                 else /* MONO */
  1021.                 {
  1022.                     if (color.grey < Magic256[c])
  1023.                         *p++ = greymap[0];
  1024.                     else
  1025.                         *p++ = greymap[15];
  1026.                 }
  1027.             }
  1028.             s = FindCh(s, 'n');
  1029.         }
  1030.     }
  1031.     else if (depth == 24)
  1032.     {
  1033.         p = data = malloc(size * 4);
  1034.         for (i = 0; i < height; ++i)
  1035.         {
  1036.             s = FindCh(s, '"');
  1037.             for (j = 0; j < width; ++j)
  1038.             {
  1039.                 if ((c = map[*s++]) < 0)
  1040.                 {
  1041.                     p = Transparent(p, j, i);
  1042.                     continue;
  1043.                 };
  1044.                 color = colors[c];
  1045.                 *p++ = '';
  1046.                 *p++ = color.red;
  1047.                 *p++ = color.green;
  1048.                 *p++ = color.blue;
  1049.             }
  1050.             s = FindCh(s, 'n');
  1051.         }
  1052.     } 
  1053.     else if (depth == 16)
  1054.     {
  1055. p = data = malloc(size * 2);
  1056.         for (i = 0; i < height; ++i)
  1057.         {
  1058.             s = FindCh(s, '"');
  1059.     
  1060.             for (j = 0; j < width; ++j)
  1061.             {
  1062.                 if ((c = map[*s++]) < 0)
  1063.                 {
  1064.                     p = Transparent(p, j, i);
  1065.                     continue;
  1066.                 };
  1067.                 color = colors[c];
  1068. GetColor(color.red, color.green, color.blue, &ccolor);
  1069.                 *p++ = (ccolor >> 8 )& 0xff;
  1070.                 *p++ = (ccolor & 0xff);
  1071.     }
  1072.     s = FindCh(s, 'n');
  1073.         }
  1074.     }
  1075.     else if (depth == 1 || depth == 2 || depth == 4)  /* howcome added support for these */
  1076.     {
  1077. int             ppb, bpl, shift = 0;
  1078. int newbyte;
  1079. ppb = 8/depth; /* pixels per byte */
  1080. bpl = width/ppb + (width%ppb ? 1 : 0); /* bytes per line */
  1081.         p = data = (unsigned char *)malloc(bpl * height);
  1082. newbyte = 1;
  1083.         for (i = 0; i < height; ++i)
  1084. {
  1085.             s = FindCh(s, '"');
  1086.             for (j = 0; j < width; ++j)
  1087.             {
  1088. if (newbyte) {
  1089.     *p = 0;
  1090.     newbyte = 0;
  1091. }
  1092. c = *s++;
  1093.                 c = map[c];
  1094.                 if (c < 0)
  1095.                 {
  1096.     shift = (((7 - (j % 8)) % ppb) * depth);
  1097.     *p |= transparent << shift;
  1098.     if (shift == 0) {
  1099. p++;
  1100. *p = 0;
  1101.     }
  1102.                     continue;
  1103.                 }
  1104.                 color = colors[c];
  1105.                 c = ((i % 16) << 4) + (j % 16);
  1106.                 if (imaging == COLOR232)
  1107.                 {
  1108.                     cr = color.red;
  1109.                     cg = color.green;
  1110.                     cb = color.blue;
  1111.                     if (cr == cg  && cg == cb)
  1112.                     {
  1113.                         cg  = color.grey;
  1114.                         g = cg & 0xF0;
  1115.                         if (cg - g > Magic16[c])
  1116.                             g += 16;
  1117.                         g = min(g, 0xF0);
  1118. shift = (((7 - (j % 8)) % ppb) * depth);
  1119. *p |= greymap[g >> 4] << shift;
  1120. if (shift == 0) {
  1121.     p++;
  1122.     newbyte = 1;
  1123. }
  1124.                     }
  1125.                     else
  1126.     {
  1127.                         r = cr & 0xC0;
  1128.                         g = cg & 0xE0;
  1129.                         b = cb & 0xC0;
  1130.                         if (cr - r > Magic64[c])
  1131.                             r += 64;
  1132.                         if (cg - g > Magic32[c])
  1133.                             g += 32;
  1134.                         if (cb - b > Magic64[c])
  1135.                             b += 64;
  1136.                         r = min(r, 255) & 0xC0;
  1137.                         g = min(g, 255) & 0xE0;
  1138.                         b = min(b, 255) & 0xC0;
  1139. shift = (((7 - (j % 8)) % ppb) * depth);
  1140. *p |= stdcmap[(r >> 6) | (g >> 3) | (b >> 1)] << shift;
  1141. if (shift == 0) {
  1142.     p++;
  1143.     newbyte = 1;
  1144. }
  1145.                     }
  1146.                 }
  1147.                 else if (imaging == GREY4)
  1148.                 {
  1149.                     cg  = color.grey;
  1150.                     g = cg & 0xF0;
  1151.                     if (cg - g > Magic16[c])
  1152.                         g += 16;
  1153.                     g = min(g, 0xF0);
  1154.     shift = (((7 - (j % 8)) % ppb) * depth);
  1155.     *p |= greymap[g >> 4] << shift;
  1156.     if (shift == 0) {
  1157. p++;
  1158. newbyte = 1;
  1159.     }
  1160.                 }
  1161.                 else /* MONO */
  1162.                 {
  1163.                     if (color.grey < Magic256[c]) {
  1164. shift = (((7 - (j % 8)) % ppb) * depth);
  1165. *p |= greymap[0] << shift;
  1166. if (shift == 0) {
  1167.     p++;
  1168.     newbyte = 1;
  1169. }
  1170.     }
  1171.                     else {
  1172. shift = (((7 - (j % 8)) % ppb) * depth);
  1173. *p |= greymap[15] << shift;
  1174. if (shift == 0) {
  1175.     p++;
  1176.     newbyte = 1;
  1177. }
  1178.     }
  1179. }
  1180.     }
  1181.     s = FindCh(s, 'n');
  1182.     
  1183.     if (shift) {
  1184.         p++;   /* make sure we start on a new byte for the next line */
  1185.         newbyte = 1;
  1186.     }
  1187. }
  1188.     }
  1189.     Free(colors);
  1190.     return (char *)data;
  1191. }
  1192. /* 
  1193.     Load data from an XBM file
  1194. #define back_width 20
  1195. #define back_height 23
  1196. static char back_bits[] = {
  1197.    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f,
  1198.    0x00, 0x80, 0x0f, 0x00, 0x80, 0x0f, 0x00, 0x80, 0x0f, 0x00, 0x80, 0x0f,
  1199.    0x00, 0x80, 0x0f, 0x60, 0x80, 0x0f, 0x70, 0x80, 0x0f, 0x78, 0x00, 0x00,
  1200.    0xfc, 0xff, 0x0f, 0xfe, 0xff, 0x07, 0xff, 0xff, 0x03, 0xfe, 0xff, 0x01,
  1201.    0xfc, 0xff, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x00,
  1202.    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  1203. So find line start with #define and read last number as width.
  1204. Repeat to get height. Should really look at names to avoid problems
  1205. if order is swapped, but probably won't be necessary.
  1206. Number of bytes of data is:     ((height * width) + 7)/8
  1207. Then skip to '{' char and then start reading data:
  1208.     whitespace or ',' followed by hex number
  1209. */
  1210. char *LoadXbmImage(Image *image, Block *bp, unsigned int depth)
  1211. {
  1212.     char *s;
  1213.     int c, i, j, k, size;
  1214.     unsigned int width, height, byte;
  1215.     unsigned char *data, *p;
  1216.     s = (char *)bp->buffer + bp->next;
  1217.     s = FindCh(s, '#');         /* find #define */
  1218.     s = FindCh(s, ' ');         /* find 1st space char */
  1219.     s = FindCh(s, ' ');         /* find 2nd space char */
  1220.     sscanf(s, "%d", &width);    /* and read width */
  1221.     s = FindCh(s, '#');         /* find next #define */
  1222.     s = FindCh(s, ' ');         /* find 1st space char */
  1223.     s = FindCh(s, ' ');         /* find 2nd space char */
  1224.     sscanf(s, "%d", &height);   /* and read width */
  1225.     s = FindCh(s, '{');         /* find opening brace for data */
  1226.     size = width * height;
  1227.     image->width = width;
  1228.     image->height = height;
  1229.     if (size == 0)
  1230.         return NULL;
  1231.     image->npixels = 0;
  1232.     image->pixels = 0;
  1233.     if (depth == 8)
  1234.     {
  1235.         p = data = (unsigned char *)malloc(size);
  1236.         for (i = 0; i < height; ++i)
  1237.             for (j = 0, k= 8; j < width; ++j)
  1238.             {
  1239.                 if (++k > 8)  /* need to read next 8 pixel values */
  1240.                 {
  1241.                     s = FindCh(s, '0');
  1242.                     sscanf(s+1, "%x", &byte); /* howcome 5/11/94: '-1' changed to '+1' since some don't like 0x */
  1243.                     while ((c = NEXTCHAR(s)) != ',' && c != '}');
  1244.                     k = 1;
  1245.                 }
  1246.                 if (byte & 0x01)
  1247.                     *p++ = textColor;
  1248.                 else
  1249.                     p = Transparent(p, j, i);
  1250.                 byte = byte >> 1;
  1251.             }
  1252.     }
  1253.     else if (depth == 24)
  1254.     {
  1255.         p = data = (unsigned char *)malloc(size * 4);
  1256.         
  1257.         for (i = 0; i < height; ++i)
  1258.             for (j = 0, k= 8; j < width; ++j)
  1259.             {
  1260.                 if (++k > 8)  /* need to read next 8 pixel values */
  1261.                 {
  1262.                     s = FindCh(s, '0');
  1263.                     sscanf(s-1, "%x", &byte);
  1264.                     while ((c = NEXTCHAR(s)) != ',' && c != '}');
  1265.                     k = 1;
  1266.                 }
  1267.                 if (byte & 1)
  1268.                 {
  1269.                     *p++ = '';
  1270.                     *p++ = (textColor >> 16) & 0xFF;
  1271.                     *p++ = (textColor >>  8) & 0xFF;
  1272.                     *p++ = textColor & 0xFF;
  1273.                 }
  1274.                 else
  1275.                     p = Transparent(p, j, i);
  1276.                 byte = byte >> 1;
  1277.             }
  1278.     }
  1279.     else if (depth == 16)
  1280.     {
  1281.         p = data = (unsigned char *)malloc(size * 2);
  1282.         
  1283.         for (i = 0; i < height; ++i)
  1284.             for (j = 0, k= 8; j < width; ++j)
  1285.             {
  1286.                 if (++k > 8)  /* need to read next 8 pixel values */
  1287.                 {
  1288.                     s = FindCh(s, '0');
  1289.                     sscanf(s-1, "%x", &byte);
  1290.                     while ((c = NEXTCHAR(s)) != ',' && c != '}');
  1291.                     k = 1;
  1292.                 }
  1293.                 if (byte & 1)
  1294.                 {
  1295.     *p++ = (textColor >>  8) & 0xFF;
  1296.                     *p++ = textColor & 0xFF;
  1297.                 }
  1298.                 else
  1299.                     p = Transparent(p, j, i);
  1300.                 byte = byte >> 1;
  1301.             }
  1302.     }
  1303.     else if (depth == 1 || depth == 2 || depth == 4)  /* howcome added support for these */
  1304.     {
  1305. int             ppb, bpl, shift;
  1306. int newbyte;
  1307. ppb = 8/depth; /* pixels per byte */
  1308. bpl = width/ppb + (width%ppb ? 1 : 0); /* bytes per line */
  1309.         p = data = (unsigned char *)malloc(bpl * height);
  1310. newbyte = 1;
  1311.         for (i = 0; i < height; ++i) {
  1312.             for (j = 0, k= 8; j < width; ++j)
  1313.             {
  1314. if (newbyte) {
  1315.       *p = 0;
  1316.               newbyte = 0;
  1317.           }
  1318.                 if (++k > 8)  /* need to read next 8 pixel values */
  1319.                 {
  1320.                     s = FindCh(s, '0');
  1321.                     sscanf(s+1, "%x", &byte); /* howcome 5/11/94: '-1' changed to '+1' since some don't like 0x */
  1322.                     while ((c = NEXTCHAR(s)) != ',' && c != '}');
  1323.                     k = 1;
  1324.                 }
  1325.                 if (byte & 0x01) {
  1326.     shift = (((7 - (j % 8)) % ppb) * depth);
  1327.     *p |= textColor << shift;
  1328. }
  1329.                 else {
  1330.     shift = (((7 - (j % 8)) % ppb) * depth);
  1331.     *p |= transparent << shift;
  1332. }
  1333. if (shift == 0) {
  1334.     p++;
  1335.     newbyte = 1;
  1336. }
  1337.                 byte = byte >> 1;
  1338.             }
  1339.     if (shift) {
  1340. p++;
  1341. newbyte = 1;
  1342.     }
  1343. }
  1344.     }
  1345.     else
  1346.     {
  1347.         Warn("image/x-xbitmap unsupported for depth %d", depth);
  1348.         return NULL;
  1349.     }
  1350.     return (char *)data;
  1351. }
  1352. Image *ProcessLoadedImage(Doc *doc)
  1353. {
  1354.     char *data;
  1355.     Image *image;
  1356.     Block block;
  1357.     unsigned int width, height;
  1358.     XImage *ximage;
  1359.     Pixmap pixmap;
  1360.     GC drawGC;
  1361.     HTAtom *a = NULL;
  1362.     if (doc && doc->anchor)
  1363. a = HTAnchor_format(doc->anchor->parent);
  1364.     image = (Image *)malloc(sizeof(Image));
  1365.     image->npixels = 0;
  1366.     block.next = 0;  /*NewDoc.hdrlen; */
  1367.     block.size = doc->loaded_length; /* NewDoc.length; */
  1368.     block.buffer = doc->content_buffer;
  1369.     
  1370.     if (!doc->content_buffer) { /* probably externally viewed image */
  1371.         doc->state = DOC_EXTERNAL;
  1372. return NULL;
  1373. /* return DefaultImage(image); */
  1374.     }
  1375.     Announce("Processing image %s...", doc->url);
  1376.     
  1377.     if (a == gif_atom)
  1378. {
  1379.     if ((data = (char *)LoadGifImage(image, &block, depth)) == NULL)
  1380. {
  1381.     Warn("Failed to load GIF image: %s", doc->url);
  1382.     Free(block.buffer);
  1383. /*     return DefaultImage(image); */
  1384.     doc->state = DOC_REJECTED;
  1385.     return NULL;
  1386. }
  1387. }
  1388.     else if (a == xpm_atom)
  1389. {
  1390.     if ((data = LoadXpmImage(image, &block, depth)) == NULL)
  1391. {
  1392.     Warn("Failed to load XPM image: %s", doc->url);
  1393.     Free(block.buffer);
  1394.     doc->state = DOC_REJECTED;
  1395. /*     return DefaultImage(image); */
  1396.     return NULL;
  1397. }
  1398. }
  1399.     else if (a == xbm_atom)
  1400. {
  1401.     if ((data = LoadXbmImage(image, &block, depth)) == NULL)
  1402. {
  1403.     Warn("Failed to load XBM image: %s", doc->url);
  1404.     Free(block.buffer);
  1405.     doc->state = DOC_REJECTED;
  1406. /*     return DefaultImage(image); */
  1407.     return NULL;
  1408. }
  1409. }
  1410. #ifdef JPEG
  1411.       else if (a == jpeg_atom)
  1412. {
  1413.     if ((data = LoadJPEGImage(image, &block, depth)) == NULL)
  1414. {
  1415.     Warn("Failed to load JPEG image: %s", doc->url);
  1416.     Free(block.buffer);
  1417.     doc->state = DOC_REJECTED;
  1418.     return NULL;
  1419. }
  1420. }
  1421. #endif /* JPEG */
  1422. #ifdef PNG
  1423.       else if (a == png_atom || a == png_exp_atom)
  1424. {
  1425.     if ((data = LoadPNGImage(image, &block, depth)) == NULL)
  1426. {
  1427.     Warn("Failed to load PNG image: %s", doc->url);
  1428.     Free(block.buffer);
  1429.     doc->state = DOC_REJECTED;
  1430.     return NULL;
  1431. }
  1432. }
  1433. #endif /* PNG */
  1434.       else
  1435. {
  1436.     Warn("Failed to load unknown image format: %s", doc->url);
  1437.     Free(block.buffer);
  1438.     doc->state = DOC_REJECTED;
  1439. /*     return DefaultImage(image); */
  1440.     return NULL;
  1441. }
  1442.     
  1443.     Free(block.buffer);
  1444.     doc->state = DOC_PROCESSED;
  1445.     doc->content_buffer = NULL; /* howcome 4/12/94: no need to keep the gif source around */
  1446.     width = image->width;
  1447.     height = image->height;
  1448.     
  1449.     if ((ximage = XCreateImage(display, DefaultVisual(display, screen),
  1450.        depth, ZPixmap, 0, data, width, height,
  1451.        (depth == 24 ? 32 :(depth == 16 ? 16 : 8)), 0)) == 0)
  1452. {
  1453.     Warn("Failed to create XImage: %s", doc->url);
  1454.     doc->state = DOC_REJECTED;
  1455.     Free(data);
  1456. /*      return DefaultImage(image);*/
  1457.     return NULL;
  1458. }
  1459.     /* howcome 22/2/95: do we need to set these?? */
  1460.     ximage->byte_order = MSBFirst;
  1461.     ximage->bitmap_bit_order = BitmapBitOrder(display);
  1462.        
  1463.     if ((pixmap = XCreatePixmap(display, win, width, height, depth)) == 0)
  1464. {
  1465.     Warn("Failed to create Pixmap: %s", doc->url);
  1466.     XDestroyImage(ximage); /* also free's image data */
  1467.     doc->state = DOC_REJECTED;
  1468. /*     return DefaultImage(image); */
  1469.     return NULL;
  1470. }
  1471.     
  1472.     drawGC = XCreateGC(display, pixmap, 0, 0);
  1473.     XSetFunction(display, drawGC, GXcopy);
  1474.     XPutImage(display, pixmap, drawGC, ximage, 0, 0, 0, 0, width, height);
  1475.     XFreeGC(display, drawGC);
  1476.     XDestroyImage(ximage);  /* also free's image data */
  1477.   
  1478.     image->pixmap = pixmap;
  1479.     image->width = width;
  1480.     image->height = height;
  1481.     doc->image = image;
  1482.     return doc->image;
  1483. }
  1484. Image *GetImage(char *href, int hreflen, BOOL reload)
  1485. {
  1486.     Doc *doc = NULL;
  1487.     /* check for null name */
  1488.     if ((doc = GetInline(href, hreflen, reload))) {
  1489. if (doc->image)
  1490.     return (doc->image);
  1491. else
  1492.     return (ProcessLoadedImage(doc));
  1493.     }
  1494.     
  1495.     return NULL;
  1496. }
  1497. void FreeImages(int cloned)
  1498. {
  1499.     Image *im;
  1500.     while (images)
  1501.     {
  1502.         /* deallocate colors */
  1503.         if (!cloned && images->npixels > 0)
  1504.             XFreeColors(display, colormap, images->pixels, images->npixels, 0);
  1505.         /* free pixmap and image structure */
  1506.         if (!cloned && images->pixmap != default_pixmap)
  1507.             XFreePixmap(display, images->pixmap);
  1508.         im = images;
  1509.         images = im->next;
  1510.         Free(im->url);
  1511.         if (im->npixels > 0)
  1512.             Free(im->pixels);
  1513.         Free(im);
  1514.     }
  1515. }