BSD 4_3_Tahoe development
[unix-history] / usr / src / new / X / xwud / xwud.c
#include <X/mit-copyright.h>
/* Copyright 1985, 1986, Massachusetts Institute of Technology */
/*
* xwud.c - MIT Project Athena, X Window system window raster image
* undumper.
*
* This program will read a raster image of a window from stdin or a file
* and display it on an X display.
*
* Author: Tony Della Fera, DEC
*
* Modified 11/14/86 by William F. Wyatt,
* Smithsonian Astrophysical Observatory
* allows writing of monochrome XYFormat window dump files on a color
* display, using default WhitePixel for 1's and BlackPixel for 0's.
*
* Modified 11/20/86 WFW
* VERSION 6 - same as V5 for monochrome, but expects color map info
* in the file for color images. Checks to see if the requested
* colors are already in the display's map (e.g. if the window dump
* and undump are contemporaneous to the same display). If so,
* undump immediately. If not, request new colors, alter the
* pixels to the new values, then write the pixmap. Note that
* multi-plane XY format undumps don't work if the pixel values
* corresponding to the requested colors have to be changed.
*/
#ifndef lint
static char *rcsid_xwud_c = "$Header: xwud.c,v 10.10 86/11/25 08:44:25 jg Rel $";
#endif
#include <X/Xlib.h>
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
extern char *calloc();
#include <X/XWDFile.h>
typedef enum _bool {FALSE, TRUE} Bool;
#define MAX(a, b) (a) > (b) ? (a) : (b)
#define MIN(a, b) (a) < (b) ? (a) : (b)
#define ABS(a) (a) < 0 ? -(a) : (a)
#define FAILURE 0
extern int errno;
main(argc, argv)
int argc;
char **argv;
{
register int i;
register int *histbuffer;
register u_short *wbuffer;
register char *buffer;
int j, status;
int *cpixels, cplanes;
int onebufsize;
int planes;
int forepixel;
int backpixel;
unsigned buffer_size, total_buffer_size;
int win_name_size;
char *str_index;
char *file_name;
char display[256];
char *win_name;
Bool standard_in = TRUE;
Bool newcolors = FALSE, debug = FALSE, inverse = FALSE;
Color *pixcolors, *newpixcolors;
Display *dpy;
Window image_win;
Pixmap image_pixmap;
XEvent event;
register XExposeEvent *xevent = (XExposeEvent *)&event;
XWDFileHeader header;
FILE *in_file = stdin;
for (i = 1; i < argc; i++) {
str_index = (char *)index (argv[i], ':');
if(str_index != NULL) {
(void) strncpy(display,argv[i],sizeof(display));
continue;
}
str_index = (char *) index (argv [i], '-');
if (str_index == NULL) Syntax(argv[0]);
if (strncmp(argv[i], "-help", 5) == 0) {
Syntax(argv[0]);
}
if (strncmp(argv[i], "-in", 4) == 0) {
if (++i >= argc) Syntax(argv[0]);
file_name = argv[i];
standard_in = FALSE;
continue;
}
if(strcmp(argv[i], "-inverse") == 0) {
inverse = TRUE;
continue;
}
if(strcmp(argv[i], "-debug") == 0) {
debug = TRUE;
continue;
}
Syntax(argv[0]);
}
if (!standard_in) {
/*
* Open the output file.
*/
in_file = fopen(file_name, "r");
if (in_file == NULL) {
Error("Can't open output file as specified.");
}
}
/*
* Open the display.
*/
if ((dpy = XOpenDisplay(display)) == NULL) {
fprintf(stderr, "%s: Can't open display '%s'\n",
argv[0], XDisplayName(display));
exit(1);
}
/*
* Read in header information.
*/
if(fread((char *)&header, sizeof(header), 1, in_file) != 1)
Error("Unable to read dump file header.");
/*
* check to see if the dump file is in the proper format.
*/
if (header.file_version != XWD_FILE_VERSION) {
fprintf(stderr,"xwud: XWD file format version missmatch.");
if(header.file_version == 5 && header.display_planes == 1)
fprintf(stderr,"\n (monochrome works anyway)\n");
else Error("exiting.");
}
if(DisplayPlanes() < header.display_planes)
Error("Windump has more planes than display.");
/*
* Check to see if we are in the right pixmap format for the
* display type.
*/
if ((DisplayPlanes() == 1) && (header.pixmap_format != XYFormat)) {
Error(
"Windump is in ZFormat which is not valid on a monochrome display.");
}
/*
* Calloc window name.
*/
win_name_size = ABS(header.header_size - sizeof(header));
if((win_name = calloc((unsigned) win_name_size, sizeof(char))) == NULL)
Error("Can't calloc window name storage.");
/*
* Read in window name.
*/
if(fread(win_name, sizeof(char), win_name_size, in_file) != win_name_size)
Error("Unable to read window name from dump file.");
if(debug) fprintf(stderr,"win_name =%s\n", win_name);
/*
* Determine the pixmap size.
*/
if (header.pixmap_format == XYFormat) {
buffer_size =
XYPixmapSize(
header.pixmap_width,
header.pixmap_height,
header.display_planes);
total_buffer_size =
XYPixmapSize(
header.pixmap_width,
header.pixmap_height,
DisplayPlanes() );
}
else if (header.display_planes < 9) {
total_buffer_size = buffer_size = BZPixmapSize(
header.pixmap_width,
header.pixmap_height
);
}
else if(header.display_planes < 17) {
total_buffer_size = buffer_size = WZPixmapSize(
header.pixmap_width,
header.pixmap_height
);
}
else {
Error("Can't undump pixmaps more than 16 bits deep.\n");
}
/* Calloc the color map buffer.
* Read it in, copy it and use the copy to query for the
* existing colors at those pixel values.
*/
if(header.window_ncolors) {
pixcolors = (Color *)calloc(header.window_ncolors,sizeof(Color));
if(fread(pixcolors,sizeof(Color),header.window_ncolors, in_file)
!= header.window_ncolors)
Error("Unable to read color map from dump file.");
if(debug)
fprintf(stderr,"Read %d colors\n", header.window_ncolors);
newpixcolors = (Color *)calloc(header.window_ncolors,sizeof(Color));
bcopy(pixcolors, newpixcolors, sizeof(Color)*header.window_ncolors);
if(XQueryColors(newpixcolors,header.window_ncolors) == 0)
Error("Can't query the color map?");
for(i=0; i<header.window_ncolors; i++)
if(!ColorEqual(&pixcolors[i], &newpixcolors[i])) {
newcolors = TRUE;
break;
}
if(debug) {
if(newcolors) fprintf(stderr,"New colors needed\n");
else fprintf(stderr,"Old colors match!\n");
}
}
/*
* Calloc the pixel buffer.
*/
if((buffer = calloc(total_buffer_size, 1)) == NULL)
Error("Can't calloc data buffer.");
bzero(buffer,total_buffer_size);
/*
* Read in the pixmap buffer.
*/
if((status = fread(buffer, sizeof(char), (int)buffer_size, in_file))
!= buffer_size)
Error("Unable to read pixmap from dump file.");
/*
* Close the input file.
*/
(void) fclose(in_file);
/*
* If necessary, get and store the new colors, convert the pixels to the
* new colors appropriately.
*/
if(newcolors) {
cpixels = (int *)calloc(header.window_ncolors+1,sizeof(int));
if(XGetColorCells(0, header.window_ncolors, 0, &cplanes, cpixels)
== 0)
Error("Can't allocate colors.");
for(i=0; i<header.window_ncolors; i++) {
newpixcolors[i].pixel = cpixels[i];
newpixcolors[i].red = pixcolors[i].red;
newpixcolors[i].green = pixcolors[i].green;
newpixcolors[i].blue = pixcolors[i].blue;
if(debug)
fprintf(stderr,"Pixel %4d, r = %5d g = %5d b = %5d\n",
newpixcolors[i].pixel, newpixcolors[i].red,
newpixcolors[i].green, newpixcolors[i].blue);
}
XStoreColors(header.window_ncolors, newpixcolors);
/* now, make a lookup table to convert old pixels into the new ones*/
if(header.pixmap_format == ZFormat) {
if(header.display_planes < 9) {
histbuffer = (int *)calloc(256, sizeof(int));
bzero(histbuffer, 256*sizeof(int));
for(i=0; i<header.window_ncolors; i++)
histbuffer[pixcolors[i].pixel] = newpixcolors[i].pixel;
for(i=0; i<buffer_size; i++)
buffer[i] = histbuffer[buffer[i]];
}
else if(header.display_planes < 17) {
histbuffer = (int *)calloc(65536, sizeof(int));
bzero(histbuffer, 65536*sizeof(int));
for(i=0; i<header.window_ncolors; i++)
histbuffer[pixcolors[i].pixel] = newpixcolors[i].pixel;
wbuffer = (u_short *)buffer;
for(i=0; i<(buffer_size/sizeof(u_short)); i++)
wbuffer[i] = histbuffer[wbuffer[i]];
}
else if(header.display_planes > 16) {
Error("Unable to handle more than 16 planes at this time");
}
free(histbuffer);
}
free(cpixels);
bcopy(newpixcolors, pixcolors, sizeof(Color)*header.window_ncolors);
free(newpixcolors);
}
/*
* Create the image window.
*/
image_win = XCreateWindow(
RootWindow,
header.window_x, header.window_y,
header.pixmap_width, header.pixmap_height,
0, (Pixmap) 0,
(Pixmap) 0
);
if (image_win == FAILURE) Error("Can't create image window.");
/*
* Select mouse ButtonPressed on the window, this is how we determine
* when to stop displaying the window.
*/
XSelectInput(image_win, (ButtonPressed | ExposeWindow | ExposeRegion));
/*
* Store the window name string.
*/
XStoreName(image_win, win_name);
/*
* Map the image window.
*/
XMapWindow(image_win);
/*
* Set up a while loop to maintain the image.
*/
while (TRUE) {
int i, nbytes;
/*
* Wait on mouse input event to terminate.
*/
XNextEvent(&event);
if (event.type == ButtonPressed) break;
switch((int)event.type) {
case ExposeWindow: /* Copy the data into the window.*/
case ExposeRegion: /* simpler to copy from x=0 for full width */
if(header.pixmap_format == XYFormat) {
onebufsize = /* size of each bitmap */
XYPixmapSize(header.pixmap_width,
header.pixmap_height, 1);
nbytes = BitmapSize(header.pixmap_width,1);
if(header.display_planes > 1) {
forepixel = -1;
backpixel = 0;
planes = 1<<(DisplayPlanes()); /* MSB << 1 */
}
else {
forepixel = WhitePixel;
backpixel = BlackPixel;
planes = AllPlanes;
}
for(j=0; j<header.display_planes; j++) {
if(header.display_planes > 1)
planes >>= 1; /* shift down a bit */
for(i=0; i<xevent->height; i+=100)
if(inverse)
XBitmapBitsPut(image_win,
0, i + xevent->y,
header.pixmap_width,
MIN(100, xevent->height - i),
buffer+((i+xevent->y)*nbytes)
+ (onebufsize * j),
backpixel, forepixel,
0, GXcopy, planes);
else
XBitmapBitsPut(image_win,
0, i + xevent->y,
header.pixmap_width,
MIN(100, xevent->height - i),
buffer+((i+xevent->y)*nbytes)
+ (onebufsize * j),
forepixel, backpixel,
0, GXcopy, planes);
}
}
else if(DisplayPlanes() < 9) {
nbytes = BZPixmapSize(header.pixmap_width,1);
for(i=0; i<xevent->height; i+=100)
XPixmapBitsPutZ(image_win,
0, i + xevent->y,
header.pixmap_width,
MIN(100, xevent->height - i),
buffer+((i+xevent->y)*nbytes),
0, GXcopy, AllPlanes);
}
else { /* Display Planes > 8 */
nbytes = WZPixmapSize(header.pixmap_width, 1);
for(i=0; i<xevent->height; i+=100)
XPixmapBitsPutZ(image_win,
0, i + xevent->y,
header.pixmap_width,
MIN(50, xevent->height - i),
buffer+((i+xevent->y)*nbytes),
0, GXcopy, AllPlanes);
}
}
}
/*
* Destroy the image window.
*/
XDestroyWindow(image_win);
/*
* Free the pixmap buffer.
*/
free(buffer);
/*
* Free window name string.
*/
free(win_name);
exit(0);
}
/*
* test two color map entries for equality
*/
ColorEqual(color1, color2)
register Color *color1, *color2;
{
return(color1->pixel == color2->pixel &&
color1->red == color2->red &&
color1->green == color2->green &&
color1->blue == color2->blue);
}
/*
* Report the syntax for calling xwud.
*/
Syntax(call)
char *call;
{
fprintf( stderr,
"xwud: %s [-help][-debug][-inverse][-in <file>][[host]:vs]\n",
call
);
exit(1);
}
/*
* Error - Fatal xwud error.
*/
Error(string)
char *string; /* Error description string. */
{
fprintf(stderr, "xwud: Error => %s\n", string);
if (errno != 0) {
perror("xwud");
fprintf(stderr, "\n");
}
exit(1);
}
/* End of xwud.c */