/* 
 * xtoxwd.c
 *
 * Copyright (C) 1997,98 Rasca, Berlin
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif                          // HAVE_CONFIG_H

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/XWDFile.h>
#include "job.h"

/* 
 * image size for ZPixmap 
 */
#define ZImageSize(i) (i->bytes_per_line * i->height)


// a couple of byte swap functions originally from util.c

/* 
 * swap the byte order of a 16 bit word;
 */
void swap_2byte(unsigned short *i)
{
    unsigned char t;
    unsigned char *p = (unsigned char *) i;
    t = p[0];
    p[0] = p[1];
    p[1] = t;
}

/* 
 * swap the byte order of a long integer (32 byte)
 */
void swap_4byte(unsigned long *i)
{
    unsigned char t;
    unsigned char *p = (unsigned char *) i;

    t = p[0];
    p[0] = p[3];
    p[3] = t;
    t = p[1];
    p[1] = p[2];
    p[2] = t;
}

/* 
 * swap the byte order of a 32 bit word;
 */
void swap_n_4byte(unsigned char *p, unsigned long n)
{
    register unsigned char t;
    register unsigned long i;
    for (i = 0; i < n; i++) {
        t = p[0];
        p[0] = p[3];
        p[3] = t;
        t = p[1];
        p[1] = p[2];
        p[2] = t;
        p += 4;
    }
}

/* 
 * swap n bytes in a char array
 */
void swap_n_bytes(unsigned char *p, unsigned long n)
{
    unsigned char t;
    unsigned int i, h;

    h = n-- / 2;
    for (i = 0; i < h; i++) {
        t = *(p + i);
        *(p + i) = *(p + (n - i));
        *(p + (n - i)) = t;
    }
}


/* 
 * global, we need this to check if we must swap some bytes
 */
static unsigned long little_endian = 1;

/* 
 * prepare the color table for the xwd file
 */
void *XWDcolorTable(XColor * colors, int ncolors)
{
    XWDColor *color_table;
    int i;
    color_table = (XWDColor *) malloc(sizeof(XWDColor) * ncolors);
    if (!color_table)
        return (NULL);
    for (i = 0; i < ncolors; i++) {
        color_table[i].pixel = colors[i].pixel;
        color_table[i].red = colors[i].red;
        color_table[i].green = colors[i].green;
        color_table[i].blue = colors[i].blue;
        color_table[i].flags = colors[i].flags;
    }
    if (*(char *) &little_endian) {
        for (i = 0; i < ncolors; i++) {
            swap_4byte(&color_table[i].pixel);
            swap_2byte(&color_table[i].red);
            swap_2byte(&color_table[i].green);
            swap_2byte(&color_table[i].blue);
        }
    }
    return (color_table);
}

/* 
 * write ximage as xwd file to 'fp'
 */
void XImageToXWD(FILE * fp, XImage * image, Job * job)
{
    static XWDFileHeader head;
    static int file_name_len;
    char *file = job->file;

    /* 
     * header must be prepared only once .. 
     */
    if (job->state & VC_START /* it's the first call */ ) {
        XWindowAttributes win_attr = job->win_attr;
#ifdef DEBUG
        printf("Preparing XWD header ... win_attr.x = %i\n",
               job->win_attr.x);
#endif
        file_name_len = strlen(file) + 1;
        head.header_size = (CARD32) (sizeof(head) + file_name_len);
        head.file_version = (CARD32) XWD_FILE_VERSION;
        head.pixmap_format = (CARD32) ZPixmap;
        head.pixmap_depth = (CARD32) image->depth;
        head.pixmap_width = (CARD32) image->width;
        head.pixmap_height = (CARD32) image->height;
        head.xoffset = (CARD32) image->xoffset;
        head.byte_order = (CARD32) image->byte_order;
        head.bitmap_unit = (CARD32) image->bitmap_unit;
        head.bitmap_bit_order = (CARD32) image->bitmap_bit_order;
        head.bitmap_pad = (CARD32) image->bitmap_pad;
        head.bits_per_pixel = (CARD32) image->bits_per_pixel;
        head.bytes_per_line = (CARD32) image->bytes_per_line;
        head.visual_class = (CARD32) win_attr.visual->class;
        head.red_mask = (CARD32) win_attr.visual->red_mask;
        head.green_mask = (CARD32) win_attr.visual->green_mask;
        head.blue_mask = (CARD32) win_attr.visual->blue_mask;
        head.bits_per_rgb = (CARD32) win_attr.visual->bits_per_rgb;
        head.colormap_entries = (CARD32) win_attr.visual->map_entries;
        head.ncolors = (CARD32) job->ncolors;
        head.window_width = (CARD32) win_attr.width;
        head.window_height = (CARD32) win_attr.height;
        head.window_x = (long) win_attr.x;
        head.window_y = (long) win_attr.y;
        head.window_bdrwidth = (CARD32) win_attr.border_width;

        if (*(char *) &little_endian)
            swap_n_4byte((unsigned char *) &head,
                         sizeof(head) / sizeof(long));
    }
    if (fwrite((char *) &head, sizeof(head), 1, fp) < 1)
        perror(file);
    if (fwrite(file, file_name_len, 1, fp) < 1)
        perror(file);
    if (fwrite(job->color_table, sizeof(XWDColor), job->ncolors, fp) < 1)
        perror(file);
    if (fwrite(image->data, ZImageSize(image), 1, fp) < 1)
        perror(file);

#ifdef DEBUG
    printf("XImageToXWD() header size = %d visual=%d\n",
           sizeof(XWDFileHeader), job->win_attr.visual->class);
#endif
}

/* 
 * XwdClean() is not needed 
 */


syntax highlighted by Code2HTML, v. 0.9.1