v05i002: Yet ANOTHER xwps program, Part01/01

Dan Heller argv at island.uu.net
Wed Sep 20 18:37:19 AEST 1989


Submitted-by: cs.buffalo.edu!sigmast!planck!meyer
Posting-number: Volume 5, Issue 2
Archive-name: xwps3/part01

[ Here is yet another xwps program, kids! Actually, this one has some
  pretty neat features.  As you may have noticed, I am numbering these
  one by one as they come in.  If there are patches sent in later, be
  sure to apply them to the right version.  --argv ]

I got a copy of 'xwps' from the net some time ago.  I don't remember
who posted it but I had a great time modifying the heck out of it to
get it to support LUT driven X displays.  I also added code to do
automagic aspect ratio scaling to fit the entire image in as much of
the page as possible.

This program is a decendant of the 'xwd' program written by Bill Wyatt
at the Smithsonian Astrophysical Observatory, David Krikorian at MIT
Project Athena and Tony Della Fera at Digital Equipment Corp., MIT
Project Athena.

Somebody else got hold of it and modified it to generate Postscript
output.  That version of the code only supported truecolor displays.
It allowed manual selection of scale sizes and offsets.  If I hadn't
lost the header from the shar file, I could give credit to that
person.

I took that version and generated this one.  I have thoroughly tested
this program on a SUN 4/260 with SunOS 4.0.3 and a CG2 framebuffer.
It should work for most other machines (we've heard this before,
haven't we? :-), your mileage may vary.

It works more or less like 'xwd' (which is where the original code
comes from) with the addition of a few options:

-scale X Y    make the picture size X by Y inches.  As a special
              case, using the value 0.0 for X and Y will cause the
              code to generate a page containing the image in true
              aspect ratio and filling as much of the 7.5 X 10 inch
              drawing area as possible.

-off X Y      Shift the image on the page by X and Y inches (does
              nothing if scale is zeroes

An example of how to use 'xwps' to print an X screen in true aspect
is:

xwps -scale 0 0 | lpr [printer options to print Postscript]

In fact, the entry in my '.awmrc' file for a menu option is:

Print Window:	!"xwps -scale 0 0 | lpr"&

I have also included a hacked up version of the 'XWD' manual describing
all of the new features.

If you have any questions on this version of the program, send Email to

planck!meyer at cs.buffalo.edu
or
...!rutgers!sunybcs!planck!meyer

or

US Snail Mail to:
P.O. Box 400
Buffalo, NY 14225

or

Call me at (716) 632-7500 X5542

Enjoy!!!!

---------------------->8 cut here 8<----------------------------
# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# Makefile dsimple.c dsimple.h extern.h psfile.c xwps.c xwps.man

echo x - Makefile
sed -e 's/^X//' > "Makefile" << '//E*O*F Makefile//'
X#
X# 	Makefile for XWD -> XWPS: Xwindow Dump to a Postscript  format
X#
X
XXLIBS =  -lX11
XCFLAGS = -g
Xsrc = xwps.c dsimple.c psfile.c 
Xobj = xwps.o dsimple.o psfile.o 
Xheaders = dsimple.h extern.h
XDEST = ./xwps
X
Xxwps: $(obj)
X	$(CC) $(obj) $(XLIBS) -o $(DEST)
X
X$(obj): $(headers)
X
Xall: xwps clean
X	
Xclean:
X	rm -f $(obj)
//E*O*F Makefile//

echo x - dsimple.c
sed -e 's/^X//' > "dsimple.c" << '//E*O*F dsimple.c//'
X/* $Header: dsimple.c,v 1.5 88/02/09 11:28:35 jim Exp $ */
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/cursorfont.h>
X#include <stdio.h>
X/*
X * Other_stuff.h: Definitions of routines in other_stuff.
X *
X * Written by Mark Lillibridge.   Last updated 7/1/87
X *
X * Send bugs, etc. to chariot at athena.mit.edu.
X */
X
Xunsigned long Resolve_Color();
XPixmap Bitmap_To_Pixmap();
XWindow Select_Window();
Xvoid out();
Xvoid blip();
XWindow Window_With_Name();
X/*
X * Just_display: A group of routines designed to make the writting of simple
X *               X11 applications which open a display but do not open
X *               any windows much faster and easier.  Unless a routine says
X *               otherwise, it may be assumed to require program_name, dpy,
X *               and screen already defined on entry.
X *
X * Written by Mark Lillibridge.   Last updated 7/1/87
X *
X * Send bugs, etc. to chariot at athena.mit.edu.
X */
X
X
X/* This stuff is defined in the calling program by just_display.h */
Xextern char *program_name;
Xextern Display *dpy;
Xextern int screen;
X
X
X/*
X * Standard fatal error routine - call like printf but maximum of 7 arguments.
X * Does not require dpy or screen defined.
X */
Xvoid Fatal_Error(msg, arg0,arg1,arg2,arg3,arg4,arg5,arg6)
Xchar *msg;
Xchar *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
X{
X	fflush(stdout);
X	fflush(stderr);
X	fprintf(stderr, "%s: error: ", program_name);
X	fprintf(stderr, msg, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
X	fprintf(stderr, "\n");
X	exit(1);
X}
X
X
X/*
X * Malloc: like malloc but handles out of memory using Fatal_Error.
X */
Xchar *Malloc(size)
X     unsigned size;
X{
X	char *data, *malloc();
X
X	if (!(data = malloc(size)))
X	  Fatal_Error("Out of memory!");
X
X	return(data);
X}
X	
X
X/*
X * Realloc: like Malloc except for realloc, handles NULL using Malloc.
X */
Xchar *Realloc(ptr, size)
X        char *ptr;
X        int size;
X{
X	char *new_ptr, *realloc();
X
X	if (!ptr)
X	  return(Malloc(size));
X
X	if (!(new_ptr = realloc(ptr, size)))
X	  Fatal_Error("Out of memory!");
X
X	return(new_ptr);
X}
X
X
X/*
X * Get_Display_Name (argc, argv) Look for -display, -d, or host:dpy (obselete)
X * If found, remove it from command line.  Don't go past a lone -.
X */
Xchar *Get_Display_Name(pargc, argv)
X    int *pargc;  /* MODIFIED */
X    char **argv; /* MODIFIED */
X{
X    int argc = *pargc;
X    char **pargv = argv+1;
X    char *displayname = NULL;
X    int i;
X
X    for (i = 1; i < argc; i++) {
X	char *arg = argv[i];
X
X	if (!strcmp (arg, "-display") || !strcmp (arg, "-d")) {
X	    if (++i >= argc) usage ();
X
X	    displayname = argv[i];
X	    *pargc -= 2;
X	    continue;
X	}
X	if (!strcmp(arg,"-")) {
X		while (i<argc)
X			*pargv++ = argv[i++];
X		break;
X	}
X	*pargv++ = arg;
X    }
X
X    *pargv = NULL;
X    return (displayname);
X}
X
X
X/*
X * Open_Display: Routine to open a display with correct error handling.
X *               Does not require dpy or screen defined on entry.
X */
XDisplay *Open_Display(display_name)
Xchar *display_name;
X{
X	Display *d;
X
X	d = XOpenDisplay(display_name);
X	if (d == NULL) {
X	    fprintf (stderr, "%s:  unable to open display '%s'\n",
X		     program_name, XDisplayName (display_name));
X	    usage ();
X	    /* doesn't return */
X	}
X
X	return(d);
X}
X
X
X/*
X * Setup_Display_And_Screen: This routine opens up the correct display (i.e.,
X *                           it calls Get_Display_Name) and then stores a
X *                           pointer to it in dpy.  The default screen
X *                           for this display is then stored in screen.
X *                           Does not require dpy or screen defined.
X */
Xvoid Setup_Display_And_Screen(argc, argv)
Xint *argc;      /* MODIFIED */
Xchar **argv;    /* MODIFIED */
X{
X	dpy = Open_Display (Get_Display_Name(argc, argv));
X	screen = DefaultScreen(dpy);
X}
X
X
X/*
X * Open_Font: This routine opens a font with error handling.
X */
XXFontStruct *Open_Font(name)
Xchar *name;
X{
X	XFontStruct *font;
X
X	if (!(font=XLoadQueryFont(dpy, name)))
X	  Fatal_Error("Unable to open font %s!", name);
X
X	return(font);
X}
X
X
X/*
X * Beep: Routine to beep the display.
X */
Xvoid Beep()
X{
X	XBell(dpy, 50);
X}
X
X
X/*
X * ReadBitmapFile: same as XReadBitmapFile except it returns the bitmap
X *                 directly and handles errors using Fatal_Error.
X */
Xstatic void _bitmap_error(status, filename)
X     int status;
X     char *filename;
X{
X  if (status == BitmapOpenFailed)
X    Fatal_Error("Can't open file %s!", filename);
X  else if (status == BitmapFileInvalid)
X    Fatal_Error("file %s: Bad bitmap format.", filename);
X  else
X    Fatal_Error("Out of memory!");
X}
X
XPixmap ReadBitmapFile(d, filename, width, height, x_hot, y_hot)
X     Drawable d;
X     char *filename;
X     int *width, *height, *x_hot, *y_hot;
X{
X  Pixmap bitmap;
X  int status;
X
X  status = XReadBitmapFile(dpy, RootWindow(dpy, screen), filename, width,
X			   height, &bitmap, x_hot, y_hot);
X  if (status != BitmapSuccess)
X    _bitmap_error(status, filename);
X
X  return(bitmap);
X}
X
X
X/*
X * WriteBitmapFile: same as XWriteBitmapFile except it handles errors
X *                  using Fatal_Error.
X */
Xvoid WriteBitmapFile(filename, bitmap, width, height, x_hot, y_hot)
X     char *filename;
X     Pixmap bitmap;
X     int width, height, x_hot, y_hot;
X{
X  int status;
X
X  status= XWriteBitmapFile(dpy, filename, bitmap, width, height, x_hot,
X			   y_hot);
X  if (status != BitmapSuccess)
X    _bitmap_error(status, filename);
X}
X
X
X/*
X * Select_Window_Args: a rountine to provide a common interface for
X *                     applications that need to allow the user to select one
X *                     window on the screen for special consideration.
X *                     This routine implements the following command line
X *                     arguments:
X *
X *                       -root            Selects the root window.
X *                       -id <id>         Selects window with id <id>. <id> may
X *                                        be either in decimal or hex.
X *                       -name <name>     Selects the window with name <name>.
X *
X *                     Call as Select_Window_Args(&argc, argv) in main before
X *                     parsing any of your program's command line arguments.
X *                     Select_Window_Args will remove its arguments so that
X *                     your program does not have to worry about them.
X *                     The window returned is the window selected or 0 if
X *                     none of the above arguments was present.  If 0 is
X *                     returned, Select_Window should probably be called after
X *                     all command line arguments, and other setup is done.
X *                     For examples of usage, see xwininfo, xwd, or xprop.
X */
XWindow Select_Window_Args(rargc, argv)
X     int *rargc;
X     char **argv;
X#define ARGC (*rargc)
X{
X	int nargc=1;
X	int argc;
X	char **nargv;
X	Window w=0;
X
X	nargv = argv+1; argc = ARGC;
X#define OPTION argv[0]
X#define NXTOPTP ++argv, --argc>0
X#define NXTOPT if (++argv, --argc==0) usage()
X#define COPYOPT nargv++[0]=OPTION; nargc++
X
X	while (NXTOPTP) {
X		if (!strcmp(OPTION, "-")) {
X			COPYOPT;
X			while (NXTOPTP)
X			  COPYOPT;
X			break;
X		}
X		if (!strcmp(OPTION, "-root")) {
X			w=RootWindow(dpy, screen);
X			continue;
X		}
X		if (!strcmp(OPTION, "-name")) {
X			NXTOPT;
X			w = Window_With_Name(dpy, RootWindow(dpy, screen),
X					     OPTION);
X			if (!w)
X			  Fatal_Error("No window with name %s exists!",OPTION);
X			continue;
X		}
X		if (!strcmp(OPTION, "-id")) {
X			NXTOPT;
X			w=0;
X			sscanf(OPTION, "0x%lx", &w);
X			if (!w)
X			  sscanf(OPTION, "%ld", &w);
X			if (!w)
X			  Fatal_Error("Invalid window id format: %s.", OPTION);
X			continue;
X		}
X		COPYOPT;
X	}
X	ARGC = nargc;
X	
X	return(w);
X}
X
X/*
X * Other_stuff: A group of routines which do common X11 tasks.
X *
X * Written by Mark Lillibridge.   Last updated 7/1/87
X *
X * Send bugs, etc. to chariot at athena.mit.edu.
X */
X
X
X#define NULL 0
X
Xextern Display *dpy;
Xextern int screen;
X
X/*
X * Resolve_Color: This routine takes a color name and returns the pixel #
X *                that when used in the window w will be of color name.
X *                (WARNING:  The colormap of w MAY be modified! )
X *                If colors are run out of, only the first n colors will be
X *                as correct as the hardware can make them where n depends
X *                on the display.  This routine does not require wind to
X *                be defined.
X */
Xunsigned long Resolve_Color(w, name)
X     Window w;
X     char *name;
X{
X	XColor c;
X	Colormap colormap;
X	XWindowAttributes wind_info;
X
X	/*
X	 * The following is a hack to insure machines without a rgb table
X	 * handle at least white & black right.
X	 */
X	if (!strcmp(name, "white"))
X	  name="#ffffffffffff";
X	if (!strcmp(name, "black"))
X	  name="#000000000000";
X
X	XGetWindowAttributes(dpy, w, &wind_info);
X	colormap = wind_info.colormap;
X
X	if (!XParseColor(dpy, colormap, name, &c))
X	  Fatal_Error("Bad color format '%s'.", name);
X
X	if (!XAllocColor(dpy, colormap, &c))
X	  Fatal_Error("XAllocColor failed!");
X
X	return(c.pixel);
X}
X
X
X/*
X * Bitmap_To_Pixmap: Convert a bitmap to a 2 colored pixmap.  The colors come
X *                   from the foreground and background colors of the gc.
X *                   Width and height are required solely for efficiency.
X *                   If needed, they can be obtained via. XGetGeometry.
X */
XPixmap Bitmap_To_Pixmap(dpy, d, gc, bitmap, width, height)
X     Display *dpy;
X     Drawable d;
X     GC gc;
X     Pixmap bitmap;
X     int width, height;
X{
X  Pixmap pix;
X  int x, depth;
X  Drawable root;
X
X  if (!XGetGeometry(dpy, d, &root, &x, &x, &x, &x, &x, &depth))
X    return(0);
X
X  pix = XCreatePixmap(dpy, d, width, height, depth);
X
X  XCopyPlane(dpy, bitmap, pix, gc, 0, 0, width, height, 0, 0, 1);
X
X  return(pix);
X}
X
X
X/*
X * outl: a debugging routine.  Flushes stdout then prints a message on stderr
X *       and flushes stderr.  Used to print messages when past certain points
X *       in code so we can tell where we are.  Outl may be invoked like
X *       printf with up to 7 arguments.
X */
Xoutl(msg, arg0,arg1,arg2,arg3,arg4,arg5,arg6)
X     char *msg;
X     char *arg0, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
X{
X	fflush(stdout);
X	fprintf(stderr, msg, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
X	fprintf(stderr, "\n");
X	fflush(stderr);
X}
X
X
X/*
X * blip: a debugging routine.  Prints Blip! on stderr with flushing. 
X */
Xvoid blip()
X{
X  outl("blip!");
X}
X
X
X/*
X * Routine to let user select a window using the mouse
X */
X
XWindow Select_Window(dpy)
X     Display *dpy;
X{
X  int status;
X  Cursor cursor;
X  XEvent event;
X  Window target_win = None;
X  int buttons = 0;
X
X  /* Make the target cursor */
X  cursor = XCreateFontCursor(dpy, XC_dot);
X
X  /* Grab the pointer using target cursor, letting it room all over */
X  status = XGrabPointer(dpy, RootWindow(dpy, screen), False,
X			ButtonPressMask|ButtonReleaseMask, GrabModeSync,
X			GrabModeAsync, None, cursor, CurrentTime);
X  if (status != GrabSuccess) Fatal_Error("Can't grab the mouse.");
X
X  /* Let the user select a window... */
X  while ((target_win == None) || (buttons != 0)) {
X    /* allow one more event */
X    XAllowEvents(dpy, SyncPointer, CurrentTime);
X    XWindowEvent(dpy, RootWindow(dpy, screen),
X		 ButtonPressMask|ButtonReleaseMask, &event);
X    switch (event.type) {
X    case ButtonPress:
X      if (target_win == None) {
X	target_win = event.xbutton.subwindow; /* window selected */
X	if (target_win == None)
X	  target_win = RootWindow(dpy, screen);
X      }
X      buttons++;
X      break;
X    case ButtonRelease:
X      if (buttons > 0) /* there may have been some down before we started */
X	buttons--;
X       break;
X    }
X  } 
X  XUngrabPointer(dpy, CurrentTime);      /* Done with pointer */
X
X  return(target_win);
X}
X
X
X/*
X * Window_With_Name: routine to locate a window with a given name on a display.
X *                   If no window with the given name is found, 0 is returned.
X *                   If more than one window has the given name, the first
X *                   one found will be returned.  Only top and its subwindows
X *                   are looked at.  Normally, top should be the RootWindow.
X */
XWindow Window_With_Name(dpy, top, name)
X     Display *dpy;
X     Window top;
X     char *name;
X{
X	Window *children, dummy;
X	int nchildren, i;
X	Window w=0;
X	char *window_name;
X
X	if (XFetchName(dpy, top, &window_name) && !strcmp(window_name, name))
X	  return(top);
X
X	if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren))
X	  return(0);
X
X	for (i=0; i<nchildren; i++) {
X		w = Window_With_Name(dpy, children[i], name);
X		if (w)
X		  break;
X	}
X	XFree(children);
X	return(w);
X}
//E*O*F dsimple.c//

echo x - dsimple.h
sed -e 's/^X//' > "dsimple.h" << '//E*O*F dsimple.h//'
X/* $Header: dsimple.h,v 1.1 87/09/11 08:17:50 toddb Exp $ */
X/*
X * Just_display.h: This file contains the definitions needed to use the
X *                 functions in just_display.c.  It also declares the global
X *                 variables dpy, screen, and program_name which are needed to
X *                 use just_display.c.
X *
X * Written by Mark Lillibridge.   Last updated 7/1/87
X *
X * Send bugs, etc. to chariot at athena.mit.edu.
X */
X
X    /* Global variables used by routines in just_display.c */
X
Xchar *program_name = "unknown_program";       /* Name of this program */
XDisplay *dpy;                                 /* The current display */
Xint screen;                                   /* The current screen */
X
X#define INIT_NAME program_name=argv[0]        /* use this in main to setup
X                                                 program_name */
X
X    /* Declaritions for functions in just_display.c */
X
Xvoid Fatal_Error();
Xchar *Malloc();
Xchar *Realloc();
Xchar *Get_Display_Name();
XDisplay *Open_Display();
Xvoid Setup_Display_And_Screen();
XXFontStruct *Open_Font();
Xvoid Beep();
XPixmap ReadBitmapFile();
Xvoid WriteBitmapFile();
XWindow Select_Window_Args();
X
X#define X_USAGE "[host:display]"              /* X arguments handled by
X						 Get_Display_Name */
X#define SELECT_USAGE "[{-root|-id <id>|-font <font>|-name <name>}]"
X
X/*
X * Other_stuff.h: Definitions of routines in other_stuff.
X *
X * Written by Mark Lillibridge.   Last updated 7/1/87
X *
X * Send bugs, etc. to chariot at athena.mit.edu.
X */
X
Xunsigned long Resolve_Color();
XPixmap Bitmap_To_Pixmap();
XWindow Select_Window();
Xvoid out();
Xvoid blip();
XWindow Window_With_Name();
//E*O*F dsimple.h//

echo x - extern.h
sed -e 's/^X//' > "extern.h" << '//E*O*F extern.h//'
X/*	List of external variable and headers to be included in xwps	*/
X
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <stdio.h>
X#include <signal.h>
X
X#define SAVE	0
X#define PRINT	1
X#define FILENAME	"xwpsfile"
X#define BITS_PER_SAMPLE 8
X
X#ifdef DECLARE
X    Bool debug		= False;
X    Bool inverse	= False;	/* inverse Flag */
X    Bool bdrs		= True;		/* borders Flag */
X    Bool output		= PRINT;	/* Save to File or Print */
X    int format		= ZPixmap;	/* XYBitmap, XYPixmap, ZPixmap */
X    int rotation	= 0;		/* In degrees counterclockwise */
X    float scaleX	= 6.0;		/* In inches */
X    float scaleY	= 6.0;		/* In inches */
X    float translateX	= 1.0;		/* In inches */
X    float translateY	= 1.0;		/* In inches */
X
X    Window target_win;			/* User selected target window */
X    FILE *out_file	= stdout;	/* File to save to */
X#else
X    extern Bool debug, inverse, bdrs, output;
X    extern int format, rotation;
X    extern float scaleX, scaleY, translateX, translateY;
X    extern Window target_win;
X    extern FILE *out_file;
X#endif
X
X
//E*O*F extern.h//

echo x - psfile.c
sed -e 's/^X//' > "psfile.c" << '//E*O*F psfile.c//'
X#include "extern.h"
X
X/*
X* Assuming 8.5 X 11 inch paper with .5 inch margins
X*
X* Modified by Bob Meyer at Calspan ATC (meyer at planck.uucp) to
X* automagically do proper aspect ratio scaling to fill the
X* page as much as possible.
X*
X* Also added code to treat colormaps in a more portable way.
X*/
X#define MAXWIDTH 7.5
X#define MAXHEIGHT 10.0
X#define BORDER 0.5
X
X/* portrait format */
X#define NORMAL 0
X
X/* landscape mode */
X#define SIDEWAYS -90;
X
Xvoid openImage(psFile,width,height)
XFILE *psFile;
Xint width, height;
X{
X	int lside,sside;
X	double ratio;
X	if(scaleX == 0.0 && scaleY == 0.0){
X		/*
X		* user requests that image be proper aspect ratio and
X		* as large as can be fit on 8.5 X 11 paper
X		*/
X		if(width > height){
X			/* the pic is wider than it is high */
X			rotation = SIDEWAYS;
X			translateY = MAXHEIGHT + BORDER;
X			translateX = BORDER;
X
X			ratio = (double)width/(double)height;
X			if(MAXWIDTH * ratio > MAXHEIGHT){
X				scaleY = MAXHEIGHT;
X				scaleX = MAXHEIGHT / ratio;
X			} else{
X				scaleY = MAXWIDTH * ratio;
X				scaleX = MAXWIDTH;
X			}
X		} else{
X			/* the pic is either square or higher than it is wide */
X			rotation = NORMAL;
X			translateX = BORDER;
X			translateY = BORDER;
X			ratio = (double)height/(double)width;
X			if(MAXHEIGHT / ratio > MAXWIDTH){
X				scaleX = MAXWIDTH;
X				scaleY = MAXWIDTH * ratio;
X			} else{
X				scaleX = MAXHEIGHT / ratio;
X				scaleY = MAXHEIGHT;
X			}
X		}
X	}
X	fprintf(psFile, "%%!\n");
X	fprintf(psFile, "/inch {72 mul} def\n");
X	fprintf(psFile, "/picstr %d string def\n", width);
X	fprintf(psFile, "/plotimage\n");
X	fprintf(psFile, " {%d %d %d [%d 0 0 %d 0 %d] \n", width, height,
X	    BITS_PER_SAMPLE, width, -height, height);
X	fprintf(psFile,"   {currentfile picstr readhexstring pop} \n");
X	fprintf(psFile,"   image\n } def\n");
X	fprintf(psFile, "gsave\n");
X	fprintf(psFile, "%.2f inch %.2f inch translate\n", translateX, translateY);
X	fprintf(psFile, "%.2f inch %.2f inch scale\n", scaleX, scaleY);
X	fprintf(psFile, "%d rotate\n", rotation);
X	fflush(psFile);
X}
X
Xvoid closeImage(psFile)
XFILE *psFile;
X{
X	fprintf(psFile, "grestore\n");
X	fprintf(psFile, "showpage\n");
X	fflush(psFile);
X}
X
Xvoid writeImage(psFile, ximage, width, height,colors,ncolors)
XFILE *psFile;
XXImage *ximage;
Xint width, height;
XXColor *colors;
Xint ncolors;
X{
X	int x, y;
X	XColor *pix;
X
X	pix = (XColor *)malloc(sizeof(XColor));
X	/* Output is hexadecimal */
X	fprintf(psFile, "plotimage\n");
X	if(ncolors != 0){
X		/* lookup table driven or monochrome display */
X		for(y=0;y<height;y++){
X			for(x=0;x<width;x++){
X				pix->pixel = XGetPixel(ximage,x,y);
X				pix->red = colors[pix->pixel].red >> 8;
X				pix->green = colors[pix->pixel].green >> 8;
X				pix->blue = colors[pix->pixel].blue >> 8;
X				pix->pixel = luminance(*pix);
X				fprintf(psFile, "%02x", pix->pixel);
X			}
X			fprintf(psFile, "\n");
X		}
X	} else {
X		/* truecolor (direct color) display */
X		for(y=0;y<height;y++){
X			for(x=0;x<width;x++){
X				pix->pixel = XGetPixel(ximage,x,y);
X				pix->red = (pix->pixel >> 16) & 0xFF;
X				pix->green = (pix->pixel >> 8) & 0xFF;
X				pix->blue = pix->pixel & 0xFF;
X				pix->pixel = luminance(*pix);
X				fprintf(psFile, "%02x", pix->pixel);
X			}
X			fprintf(psFile, "\n");
X		}
X	}
X	fprintf(psFile, "\n");
X}
X
Xint luminance(colorSpec)
XXColor colorSpec;
X{
X	int r, g, b, l;
X
X	r = 255 - (colorSpec.red);
X	g = 255 - (colorSpec.green);
X	b = 255 - (colorSpec.blue);
X	l = (0.33*r) + (0.33*g) + (0.34*b);
X	if(inverse) return(l);
X	else return(abs(l - 255));
X}
//E*O*F psfile.c//

echo x - xwps.c
sed -e 's/^X//' > "xwps.c" << '//E*O*F xwps.c//'
X#include <X11/copyright.h>
X
X/* Copyright 1987 Massachusetts Institute of Technology */
X
X/*
X * xwps.c MIT Project Athena, X Window system window raster image dumper.
X *
X * This program will dump a raster image of the contents of a window into a 
X * file for output on graphics printers or for other uses.
X *
X *  Author:	Tony Della Fera, DEC
X *		17-Jun-85
X * 
X *  Modification history:
X *
X *  11/14/86 Bill Wyatt, Smithsonian Astrophysical Observatory
X *    - Removed Z format option, changing it to an XY option. Monochrome 
X *      windows will always dump in XY format. Color windows will dump
X *      in Z format by default, but can be dumped in XY format with the
X *      -xy option.
X *
X *  11/18/86 Bill Wyatt
X *    - VERSION 6 is same as version 5 for monchrome. For colors, the 
X *      appropriate number of Color structs are dumped after the header,
X *      which has the number of colors (=0 for monochrome) in place of the
X *      V5 padding at the end. Up to 16-bit displays are supported. I
X *      don't yet know how 24- to 32-bit displays will be handled under
X *      the Version 11 protocol.
X *
X *  6/15/87 David Krikorian, MIT Project Athena
X *    - VERSION 7 runs under the X Version 11 servers, while the previous
X *      versions of xwd were are for X Version 10.  This version is based
X *      on xwd version 6, and should eventually have the same color
X *      abilities. (Xwd V7 has yet to be tested on a color machine, so
X *      all color-related code is commented out until color support
X *      becomes practical.)
X *
X *  9/15/89 Bob Meyer, Calspan Advanced Technology Center (meyer at planck.uucp)
X *    - Modified 'xwps' version of code to allow for automagic aspect
X *      scaling and more portable colormap handling.  This version should
X *      support any X display and generates Postscript output.
X */
X
X#ifndef lint
Xstatic char *rcsid_xwd_c = "$Header: xwd.c,v 1.34 88/02/12 13:24:59 jim Exp $";
X#endif
X
X#define FEEP_VOLUME 0
X#define DECLARE
X#include "extern.h"
X
X/* Include routines to do parsing */
X#include "dsimple.h"
X
Xextern int (*_XErrorFunction)();
Xextern int _XDefaultError();
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	register i;
X	FILE *fopen();
X
X	INIT_NAME;
X
X	Setup_Display_And_Screen(&argc, argv);
X
X	/* Get window select on command line, if any */
X	target_win = Select_Window_Args(&argc, argv);
X
X	for (i = 1; i < argc; i++) {
X		if (!strcmp(argv[i], "-borders")) {
X			/* we don't want borders in image */
X			bdrs = False;
X			continue;
X		}
X		if (!strcmp(argv[i], "-debug")) {
X			debug = True;
X			continue;
X		}
X		if (!strcmp(argv[i], "-help"))
X			usage();
X		if (!strcmp(argv[i], "-out")) {
X			if (++i >= argc) usage();
X			if (!(out_file = fopen(argv[i], "w"))){
X				Error("Can't open output file as specified.");
X				out_file = stdout;
X			}
X			continue;
X		}
X		if (!strcmp(argv[i], "-xy")) {
X			format = XYPixmap;
X			continue;
X		}
X		if(!strcmp(argv[i], "-rot")) {
X			sscanf(argv[++i],"%d",&rotation);
X			continue;
X		}
X		if(!strcmp(argv[i], "-scale")){
X			sscanf(argv[++i],"%f",&scaleX);
X			sscanf(argv[++i],"%f",&scaleY);
X			continue;
X		}
X		if(!strcmp(argv[i],"-off")){
X			sscanf(argv[++i],"%f",&translateX);
X			sscanf(argv[++i],"%f",&translateY);
X			continue;
X		}
X		if(!strcmp(argv[i],"-inv")){
X			inverse = 1;
X			continue;
X		}
X
X		usage();
X	}
X
X	/*
X	 * Let the user select the target window.
X	 */
X	if (!target_win)
X		target_win = Select_Window(dpy);
X
X	/*
X	 * Dump the window 
X	 */
X	Window_Dump(target_win,out_file);
X
X	fclose(out_file);
X
X}
X
X
X/*
X * Window_Dump: dump a window to a file which must already be open for
X *              writting.
X */
X
Xchar *calloc();
X
X#include "X11/XWDFile.h"
X
XWindow_Dump(window, out)
XWindow window;
XFILE *out;
X{
X	unsigned long swaptest = 1;
X	XColor *colors;
X	unsigned buffer_size;
X	int win_name_size;
X	int header_size;
X	int ncolors, i;
X	char *win_name;
X	XWindowAttributes win_info;
X	XImage *image;
X
X	XWDFileHeader header;
X
X
X	/*
X	 * Inform the user not to alter the screen.
X	 */
X	Beep();
X	XFlush(dpy);
X	/*
X	 * give the window time to stuff it's colormap
X	 * back into the display (if the window changes it)
X	 */
X	sleep(2);
X
X	/*
X	 * Get the parameters of the window being dumped.
X	 */
X	if (debug) outl("xwps: Getting target window information.\n");
X	if(!XGetWindowAttributes(dpy, window, &win_info))
X		Fatal_Error("Can't get target window attributes.");
X
X	XFetchName(dpy, window, &win_name);
X	if (!win_name || !win_name[0])
X		win_name = "xwdump";
X
X	/* sizeof(char) is included for the null string terminator. */
X	win_name_size = strlen(win_name) + sizeof(char);
X
X	/*
X	 * Snarf the pixmap with XGetImage.
X	 */
X
X	if (!bdrs) {
X		if (debug) outl("xwps: Image without borders selected.\n");
X		image = XGetImage ( dpy, window, 0, 0, win_info.width,
X		    win_info.height, ~0, format);
X	}
X	else {
X		if (debug) outl("xwps: Image with borders selected.\n");
X		image = XGetImage ( dpy, window,
X		    -win_info.border_width, -win_info.border_width, 
X		    win_info.width + (win_info.border_width << 1),
X		    win_info.height + (win_info.border_width << 1),
X		    ~0, format);
X	}
X	if (debug) outl("xwps: Getting pixmap.\n");
X
X	/*
X	 * Determine the pixmap size.
X	 */
X	buffer_size = Image_Size(image);
X
X	if (debug) outl("xwps: Getting Colors.\n");
X
X	ncolors = Get_XColors(&win_info, &colors);
X
X	/*
X	 * Inform the user that the image has been retrieved.
X	 */
X	XBell(dpy, FEEP_VOLUME);
X	XBell(dpy, FEEP_VOLUME);
X	XFlush(dpy);
X
X	/*
X	 * Calculate header size.
X	 */
X	if (debug) outl("xwps: Calculating header size.\n");
X	header_size = sizeof(header) + win_name_size;
X
X	/*
X	 * Write out header information.
X	 */
X	if (debug) outl("xwps: Constructing and dumping file header.\n");
X	header.header_size = (xwdval) header_size;
X	header.file_version = (xwdval) XWD_FILE_VERSION;
X	header.pixmap_format = (xwdval) format;
X	header.pixmap_depth = (xwdval) image->depth;
X	header.pixmap_width = (xwdval) image->width;
X	header.pixmap_height = (xwdval) image->height;
X	header.xoffset = (xwdval) image->xoffset;
X	header.byte_order = (xwdval) image->byte_order;
X	header.bitmap_unit = (xwdval) image->bitmap_unit;
X	header.bitmap_bit_order = (xwdval) image->bitmap_bit_order;
X	header.bitmap_pad = (xwdval) image->bitmap_pad;
X	header.bits_per_pixel = (xwdval) image->bits_per_pixel;
X	header.bytes_per_line = (xwdval) image->bytes_per_line;
X	header.visual_class = (xwdval) win_info.visual->class;
X	header.red_mask = (xwdval) win_info.visual->red_mask;
X	header.green_mask = (xwdval) win_info.visual->green_mask;
X	header.blue_mask = (xwdval) win_info.visual->blue_mask;
X	header.bits_per_rgb = (xwdval) win_info.visual->bits_per_rgb;
X	header.colormap_entries = (xwdval) win_info.visual->map_entries;
X	header.ncolors = ncolors;
X	header.window_width = (xwdval) win_info.width;
X	header.window_height = (xwdval) win_info.height;
X	if (!bdrs) {
X		header.window_x = (xwdval) (win_info.x + win_info.border_width);
X		header.window_y = (xwdval) (win_info.y + win_info.border_width);
X	} else {
X		header.window_x = (xwdval) win_info.x;
X		header.window_y = (xwdval) win_info.y;
X	}
X	header.window_bdrwidth = (xwdval) win_info.border_width;
X
X	if (*(char *) &swaptest) {
X		_swaplong((char *) &header, sizeof(header));
X		for (i = 0; i < ncolors; i++) {
X			_swaplong((char *) &colors[i].pixel, sizeof(long));
X			_swapshort((char *) &colors[i].red, 3 * sizeof(short));
X		}
X	}
X
X	openImage(out, header.pixmap_width, header.pixmap_height);
X	writeImage(out,image,header.pixmap_width, header.pixmap_height,colors,ncolors);
X	closeImage(out);
X
X	/*
X	 * free the color buffer.
X	 */
X	if(debug && ncolors > 0) outl("xwps: Freeing colors.\n");
X	if(ncolors > 0) free(colors);
X
X	/*
X	 * Free image
X	 */
X	XDestroyImage(image);
X}
X
X/*
X * Report the syntax for calling xwps.
X */
Xusage()
X{
X	fprintf (stderr,
X	    "usage: %s [-display host:dpy] [-debug] [-help] [-borders] [-out <file>]",
X	    program_name);
X	fprintf (stderr, " [-xy]\n\t[-rot <rotation>] [-scale <x y>] [-off <x y>] [-inv]\n");
X	exit(1);
X}
X
X
X/*
X * Error - Fatal xwps error.
X */
Xextern int errno;
X
XError(string)
Xchar *string;	/* Error description string. */
X{
X	outl("\nxwps: Error => %s\n", string);
X	if (errno != 0) {
X		perror("xwps");
X		outl("\n");
X	}
X
X	exit(1);
X}
X
X
X/*
X * Determine the pixmap size.
X */
X
Xint Image_Size(image)
XXImage *image;
X{
X	if (format != ZPixmap)
X		return(image->bytes_per_line * image->height * image->depth);
X
X	return(image->bytes_per_line * image->height);
X}
X
X
X/*
X * Get the XColors of all pixels in image - returns # of colors
X */
Xint Get_XColors(win_info, colors)
XXWindowAttributes *win_info;
XXColor **colors;
X{
X	int i, ncolors;
X
X	if (!win_info->colormap)
X		return(0);
X
X	if (win_info->visual->class == TrueColor ||
X	    win_info->visual->class == DirectColor)
X		return(0);    /* XXX punt for now */
X
X	ncolors = win_info->visual->map_entries;
X	if (!(*colors = (XColor *) malloc (sizeof(XColor) * ncolors)))
X		Fatal_Error("Out of memory!");
X
X	for (i=0; i<ncolors; i++)
X		(*colors)[i].pixel = i;
X
X	XQueryColors(dpy, win_info->colormap, *colors, ncolors);
X
X	return(ncolors);
X}
X
X_swapshort (bp, n)
Xregister char *bp;
Xregister unsigned n;
X{
X	register char c;
X	register char *ep = bp + n;
X
X	while (bp < ep) {
X		c = *bp;
X		*bp = *(bp + 1);
X		bp++;
X		*bp++ = c;
X	}
X}
X
X_swaplong (bp, n)
Xregister char *bp;
Xregister unsigned n;
X{
X	register char c;
X	register char *ep = bp + n;
X	register char *sp;
X
X	while (bp < ep) {
X		sp = bp + 3;
X		c = *sp;
X		*sp = *bp;
X		*bp++ = c;
X		sp = bp + 1;
X		c = *sp;
X		*sp = *bp;
X		*bp++ = c;
X		bp += 2;
X	}
X}
//E*O*F xwps.c//

echo x - xwps.man
sed -e 's/^X//' > "xwps.man" << '//E*O*F xwps.man//'
X.TH XWPS 1 "24 October 1988" "X Version 11"
X.SH NAME
Xxwps - dump Postscript image of an X window
X.SH SYNOPSIS
X.B "xwd"
X[-debug] [-help] [-borders] [-out \fIfile\fP] [-xy] [-inv]
X[-display \fIdisplay\fP] [-scale \fIxsize ysize\fP] [-rot \fIdegrees\fP]
X.SH DESCRIPTION
X.PP
X.I Xwps
Xis an X Window System window dumping utility.
X.I Xwps
Xallows X users to dump window images in Postscript form for 
Xredisplay, printing, editing, formatting, archiving, image processing, etc.
XThe target window is selected by clicking the mouse in the desired window.
XThe keyboard bell is rung once at the beginning of the dump and twice when
Xthe dump is completed.
X.PP
XThis program knows about colors and will generate a luminance mapped
Xgray scale image from a color screen.  The mapping is very simple and
Xdoes not know about all of the wild things like gamma correction etc.
X.SH OPTIONS
X.PP
X.TP 8
X.B "-display \fIdisplay\fP"
XThis argument allows you to specify the server to connect to; see \fIX(1)\fP.
X.PP
X.TP 8
X.B "-help"
XPrint out the `Usage:' command syntax summary.
X.PP
X.TP 8
X.B "-inv"
XGenerate a reverse video (negative) of the image.
X.PP
X.TP 8
X.B "-borders"
XThis argument specifies that the window dump should not include the
Xpixels that compose the X window border.  This is useful in situations
Xwhere you may wish to include the window contents in a document 
Xas an illustration.
X.PP
X.TP 8
X.B "-out \fIfile\fP"
XThis argument allows the user to explicitly specify the output
Xfile on the command line.  The default is standard output.
X.PP
X.TP 8
X.B "-xy"
XThis option applies to color displays only. It selects `XY' format dumping
Xinstead of the default `Z' format.
X.PP
X.TP 8
X.B "-add \fIvalue\fP"
XThis option specifies a signed value to be added to every pixel.
X.PP
X.TP 8
X.B "-scale \fIxsize ysize\fP"
XAllows the user to specify the size of the output image in inches.  As
Xa special case, the value `0' for both \fIxsize\fP and \fIysize\fP
Xwill cause the program to automatically scale the image for best fit
Xon an 8 1/2 X 11 inch page allowing for 1/2 inch borders.  The image will
Xbe generated in true aspect ratio (assuming that pixels are square) as
Xit is displayed on the screen.  The default scale is 6 X 6 inches.
X\fIxsize\fP and \fIysize\fP can be specified in floating point units.
X.PP
X.TP 8
X.B "-rot \fIvalue\fP"
XThis option specifies image rotation angle in degrees.
X.SH ENVIRONMENT
X.PP
X.TP 8
X.B DISPLAY
XTo get default host and display number.
X.SH FILES
X.PP
X.TP 8
X.B XWDFile.h
XX Window Dump File format definition file.
X.SH SEE ALSO
Xxwd(1), xwud(1), xpr(1), X(1)
X.SH COPYRIGHT
XCopyright 1988, Massachusetts Institute of Technology.
X.br
XSee \fIX(1)\fP for a full statement of rights and permissions.
X.SH AUTHORS
XTony Della Fera, Digital Equipment Corp., MIT Project Athena
X.br
XWilliam F. Wyatt, Smithsonian Astrophysical Observatory
X.br
XRobert M. Meyer, Calspan Advanced Technology Center, Buffalo, NY
//E*O*F xwps.man//

echo Possible errors detected by \'wc\' [hopefully none]:
temp=/tmp/shar$$
trap "rm -f $temp; exit" 0 1 2 3 15
cat > $temp <<\!!!
      20      53     315 Makefile
     499    1633   12545 dsimple.c
      53     189    1648 dsimple.h
      36     160    1051 extern.h
     139     463    3447 psfile.c
     392    1218    9406 xwps.c
      91     490    2899 xwps.man
    1230    4206   31311 total
!!!
wc  Makefile dsimple.c dsimple.h extern.h psfile.c xwps.c xwps.man | sed 's=[^ ]*/==' | diff -b $temp -
exit 0
-- 
   Thinking quickly, the IBM System Jock     # Bob Meyer
uttered an incantation in EBCDIC and made    # Calspan Advanced Tech. Center
the sign of the Terminated Fork.             # ...!sunybcs!planck!meyer
   The UNIX Guru only smiled and trapped him in a recursive SED script.



More information about the Comp.sources.x mailing list