SUMMARY - Making an X application show up on multiple displays

From: John Hearns - System Manager (johnh@gerbil.umds.ac.uk)
Date: Thu Oct 27 1994 - 17:52:50 CDT


----------
X-Sun-Data-Type: text
X-Sun-Data-Description: text
X-Sun-Data-Name: text
X-Sun-Content-Lines: 29

My sincerest thanks to all the people who responded to my query on the
Sunmanagers list.

Original problem was:
>I am giving a small talk tomorrow, and would like to do some live demos
>using a SUN workstation (4.1.3 and Openwindows) plus maybe a couple
>of HP X-terminals.
>I would like to have the 'recipe' on how to make other workstations have
>exactly the same screen display as the one I am working on, ie.
>something along the lines of

>setenv DISPLAY workstationa:0.0 workstationb:0.0

Three main soultions were proposed

1) xwatchwin This is a simple program, if a little slow (my demo din't look
     too flashy as I tried to copy the root window onto an IPX running
     Solaris, which really doesntr have enough memory for the job)
     Anyway, xwatchwin fitted the bill admirably. I've enclosed it below as
       a shell archive.

2) XMX (an X Protocol Multiplexor) is available from wilma.cs.brown.edu

3) the ShowMe product from SunSoft (it is described on your
      Sun Solve CD) (by the way, I cant now unmount my sun solve CD.
            the system is convinced the drive is busy, as I think a daemon
           process is still kicking around waiting for sunsolve to be started.
           Sigh.

----------
X-Sun-Data-Type: default
X-Sun-Data-Description: default
X-Sun-Data-Name: xwatchwin.shar
X-Sun-Content-Lines: 668

Path: uunet!island!argv
From: argv@island.uu.net (Dan Heller)
Newsgroups: comp.sources.x
Subject: v03i069: xwatchwin2 -- improved version of xwatchwin, Part01/01
Message-ID: <683@island.uu.net>
Date: 7 Apr 89 18:37:29 GMT
Organization: Island Graphics, Marin County, California
Lines: 658
Approved: island!argv@sun.com

Submitted-by: John Bradley <bradley@cis.upenn.edu>
Posting-number: Volume 3, Issue 69
Archive-name: xwatchwin2/part01

[ Besure to read the README to find out why this is a whole new posting.
  I included the Imakefile, but not the Makefile -- you can use the other
  one or make a new one. On my sun3/60, I just issued the command:
        cc -O -s xwatchwin.c -lX11 -o xwatchwin
  Try "xwatchwin <host> root" Someone should modify to typing can go
  both ways. --argv ]

#!/bin/sh
# This is a shell archive file. Remove everything above this line
# to unbundle. chmod +x "thisfile", then run it: e.g. % thisfile
# SHAR archive format. Archive created Fri Apr 7 11:29:46 PDT 1989
# file contains:
# README
# xwatchwin.man
# xwatchwin.c
# Imakefile
echo x - README
sed 's/^X//' > README <<'+END+OF+README'
X
XI've taken the 'xwatchwin' code that was posted on comp.sources.x a few days
Xago, and added two new features to it. The major feature is you can now
Xrun the program and have it work out even when the two displays (yours, and
Xthe one you're monitoring) are of different depths. It should work for any
Xcombinations of depths, and it has special case code for displaying a 1-bit
Xwindow on an 8-bit display, and displaying an 8-bit window on a 1-bit display.
XIt does this reasonably quickly, however, I can't guarantee that the special
Xcase code'll work on every server. I've tried it out on all combinations of
X8-bit RTs, 8-bit Suns, and 1-bit Suns.
X
XThe second win is that you can now specify the root window by name. (Either
X'root' or 'X Root Window').
X
XJohn Bradley - University of Pennsylvania - bradley@cis.upenn.edu
X
XP.S. I was going to submit a patch, but the patch wound up being larger than
Xthe actual source code, so I'm just sending the whole thing again.
X
+END+OF+README
echo '-rw-rw-r-- 1 argv 979 Apr 6 00:15 README (as sent)'
chmod u=rw,g=rw,o=r README
ls -l README
echo x - xwatchwin.man
sed 's/^X//' > xwatchwin.man <<'+END+OF+xwatchwin.man'
X.TH xwatchwin 1 "17 March 1989" "X Version 11"
X.SH NAME
Xxwatchwin - watch a window on another X server
X.SH SYNOPSIS
X.B "xwatchwin"
Xhostname
X[\-u \fIupdatetime\fP] [\-w \fIwindowID\fP] [window name]
X.SH DESCRIPTION
X.PP
X\fIxwatchwin\fP allows you to peek at a window on another X server.
XTo use it, you must specify the name of the machine you want to watch, then
Xthe name of the window on that machine. \fIXwatchwin\fP will attempt to
Xconnect with the X server \fIhostname\fP:0.0, and if successful, will try
Xto retrieve a copy of the window in which you specified interest.
X
XYou may specify the window you want to watch either by name or by its
Xwindow id, usually a hexidecimal number. Usually specifying the
Xwindow by name is simpler, although not all windows have names
Xassociated with them; in that case you must use the window id option.
X
XIf the window you want to watch is not in a viewable state,
X\fIxwatchwin\fP will tell you so and exit. If while you are watching a
Xwindow it becomes 'unviewable', \fIxwatchwin\fP will print a message to
Xstdout and wait until the window becomes 'viewable' again.
X
X\fIxwatchwin\fP was written as an aid to a class for people learning to
Xuse X. The idea is that the instructor would type into an xterm
Xwindow on his/her display and the students would use \fIxwatchwin\fP to
Xsee what the instructor typed. The students could then type the same
Xthing in their own terminal windows. I hope that others will find
Xequally (if not more) constructive uses.
X
X.SH OPTIONS
X.TP 8
X.B \-u \fIupdatetime\fP
XThis option specifies how often (in seconds) you want to get a new copy
Xof the window you're watching. It is in effect a 'sample rate'. By default,
X\fIxwatchwin\fP updates your copy of the window as often as it can. The time
Xit takes to actually do the update is dependent on the speed of the X server
Xon both machines, the speed of the intervening network, and other factors.
X.TP 8
X.B \-w \fIwindowID\fP
XThis option specifies the window you want to watch by number, for example,
X"0x50000b". Use the xlswins(1) command to get a list of window id's and
Xpossibly their names on the remote server.
X
XYou must specify a window to watch either by name or by id. Specifying
Xa window to watch by name is usually easier if you know what you're looking for.
X.SH EXAMPLES
XIf there is an X server on the remote machine "crow" and if on that server
Xthere is a window called "X Terminal Emulator", you can watch that window
Xby typing
X
Xxwatchwin crow X Terminal Emulator
X
XIf there is a window on "crow" that has no name but has a window id of
X"0x50000b", you can watch it by typing
X
Xxwatchwin crow -w 0x50000b
X
XIf you want to get new copies of a window only every 30 seconds, you can
Xdo so by typing
X
Xxwatchwin crow -u 30 -w 0x50000b
X.SH "SEE ALSO"
Xxlswins(1), xwininfo(1), xdpyinfo(1),
X.SH BUGS
X\fIxwatchwin\fP doesn't support the \-display option. You must set the
Xdisplay on which the \fIxwatchwin\fP window is created by changing your
XDISPLAY environment variable.
X
XIf the window you're watching is unmapped (made 'invisible')
Xwhile \fIxwatchwin\fP
Xis getting a new copy of that window, the program will crash. The smaller
Xyour update interval, the more likely you are to experience this bug (although
Xit hasn't happened all that often to me).
X
XParsing arguments is messy and not as forgiving as it should be.
X
XThe event loop is a mess.
X
X\fIxwatchwin\fP can now deal with two displays of different depths. There
Xis special-case code for the conversions between 1-bit displays and 8-bit
Xdisplays (either direction) which may garble the image on some machines.
XThe general case code should work on anything, albeit somewhat more slowly.
XOne note: ABSOLUTELY no attempt is made to make the colors match up. If
Xyou're on a 5-bit display, and you're monitoring someone elses 8-bit display,
Xthe conversion just takes his 8 bits and chops the top 3 bits off, and puts
Xit on the screen. Maybe in the next version...
X.SH COPYRIGHT
XCopyright 1989, George D. Drapeau
X.SH AUTHOR
XGeorge D. Drapeau
X.PP
XStanford University
X.br
XAcademic Information Resources / Systems Development
X.br
XInternet: drapeau@jessica.stanford.edu
X.br
XUUCP: labrea!drapeau@jessica
X.PP
XDisplay depth conversion code added by John Bradley (bradley@cis.upenn.edu)
+END+OF+xwatchwin.man
echo '-rw-rw-r-- 1 argv 4264 Apr 7 10:51 xwatchwin.man (as sent)'
chmod u=rw,g=rw,o=r xwatchwin.man
ls -l xwatchwin.man
echo x - xwatchwin.c
sed 's/^X//' > xwatchwin.c <<'+END+OF+xwatchwin.c'
X#include <stdio.h>
X#include <ctype.h>
X#include <sys/time.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X
X#define STRINGLENGTH 256
X#define SLEEPTIME 0 /* Sleep for this many seconds before redrawing */
X
Xint dpy2depth;
X
Xtypedef unsigned char byte;
X
Xextern byte *malloc();
X
Xchar **Argv;
Xint Argc;
XDisplay *dpy;
X
X
Xmain(argc,argv)
X int argc;
X char **argv;
X{
X Window watchWin,GetWindowByName();
X int i,strPos,optIndex;
X char displayName[64],xWatchName[STRINGLENGTH];
X char *optstring;
X extern char *optarg;
X extern int optind,opterr;
X int windowID,windowIDSet,updateTime,updateTimeSet;
X
X
X if (argc < 3) /* Did user enter enough arguments? */
X { /* Nope, print an error message and exit */
X printf("Usage:\t%s HostName [-u UpdateTime] [-w windowID] [WindowName]\n",
X argv[0]);
X exit(1);
X }
X
X /* Initialize var to update every SLEEPTIME seconds. */
X updateTime = SLEEPTIME;
X updateTimeSet = 0;
X windowIDSet = 0;
X optind = 2; /* Skip over first, obligatory argument (hostname) */
X
X while ((optIndex = getopt(argc,argv,"u:w:")) != -1) /* get arguments */
X switch (optIndex)
X {
X case 'u': /* User wants to update every 'optarg' seconds. */
X updateTime = atoi(optarg);
X updateTimeSet = 1; /* Set flag saying user specified this option. */
X break;
X case 'w': /* User wants to specify window by id instead of by name */
X sscanf(&optarg[2],"%lx",&windowID);
X windowIDSet = 1; /* Set flag saying user specified this option. */
X break;
X } /* end switch (optIndex) */
X
X Argv = argv;
X Argc = argc;
X
X /* if no ':' in display name, tack default ':0.0' onto end */
X if (index(argv[1],':')==NULL) sprintf(displayName,"%s:0.0",argv[1]);
X else strcpy(displayName,argv[1]);
X
X if (!windowIDSet) /* Did user specify window to watch by number? */
X for (i=2, bzero(xWatchName, STRINGLENGTH); i < argc; i++)
X /* No, parse rest of arguments as window name to watch */
X {
X if (!strcmp(argv[i],"-u")) /* Don't parse optional arguments */
X {
X i++; /* Skip over argument to '-u' switch. */
X continue;
X }
X /* Get current length of xWatchName string */
X strPos = strlen(xWatchName);
X /* Copy another argument to the end of the string */
X strcpy(&xWatchName[strPos],argv[i]);
X }
X
X /* Attempt to open a connection with the remote X server */
X if ((dpy = XOpenDisplay(displayName)) == NULL)
X {
X /* Couldn't open the display for some reason, so... */
X fprintf(stderr,"%s: Could not open remote display %s\n",
X argv[0],displayName);
X exit(1); /* ...report the error and exit with an error code */
X }
X
X if (!windowIDSet) /* Did user specify a window to watch by id? */
X /* No, get window id from window name. */
X watchWin = GetWindowByName(XDefaultRootWindow(dpy),xWatchName);
X else watchWin = windowID; /* Yes, use user-specified window id. */
X
X if (watchWin) /* Did the user find the window s/he was looking for? */
X /* Yes, periodically show the contents of that window */
X WatchWindow(watchWin,updateTime);
X else /* No, report that the window was not found, and exit. */
X {
X printf("Could not find the window you specified.\n");
X exit(1);
X }
X
X} /* end function main */
X
X
X
X
X/* Takes two strings, removes spaces from the second,... */
X/* ...and compares them.. Returns 1 if equal, 0 if not. */
XWinNamesEqual(str1,str2)
X char *str1,*str2;
X{
X char tempStr[STRINGLENGTH],*tempStrPtr;
X int index;
X
X bzero(tempStr,STRINGLENGTH); /* Clear the contents of the string, if any */
X /* Go through each character in the second string. */
X for (tempStrPtr=tempStr; *str2; str2++)
X {
X if (!isspace(*str2)) /* Is this character a space? */
X *tempStrPtr++ = *str2; /* No, copy this character to a temp string. */
X }
X if (!strcmp(str1,tempStr)) /* Are the two resulting string equal? */
X return(1); /* Yes, return 1 */
X else
X return(0); /* No, return 0 */
X} /* end function WinNamesEqual */
X
X
XWatchWindow(win,updateTime)
X Window win;
X int updateTime;
X{
X Display *dpy2;
X Window copyWin;
X GC gc;
X XWindowAttributes copyWinInfo,newWinInfo;
X XSetWindowAttributes copyWinAttrs;
X XWMHints wmHints;
X XSizeHints sizeHints;
X XImage *image;
X struct timeval currentTime;
X struct timezone zone;
X long timeInSecs;
X Bool srcWinUnmapped;
X int imageform;
X
X /* Get the window attributes of the window we're watching */
X XGetWindowAttributes(dpy,win,&copyWinInfo);
X
X /* Is the original window in a state to be watched? */
X if (copyWinInfo.map_state != IsViewable)
X { /* Nope, tell the user of the problem and exit. */
X printf("The window you wish to look at is not in a state to be viewed\n");
X printf("(perhaps it is iconified or not mapped)\n");
X exit(1);
X }
X
X /* Attempt to open a connection with the local X server */
X if ((dpy2 = XOpenDisplay(NULL)) == NULL)
X {
X /* Couldn't open the display for some reason, so... */
X fprintf(stderr,"%s: Could not open local display.\n", Argv[0]);
X exit(1); /* ...report the error and exit with an error code */
X }
X
X /* Set a couple more attributes */
X copyWinAttrs.colormap = XDefaultColormap(dpy2,XDefaultScreen(dpy2));
X copyWinAttrs.bit_gravity = copyWinInfo.bit_gravity;
X
X /* Check for different depths b/w source & dest displays */
X dpy2depth = XDefaultDepth(dpy2,XDefaultScreen(dpy2));
X
X if ((copyWinInfo.depth == dpy2depth) ||
X (copyWinInfo.depth == 1 && dpy2depth == 8) ||
X (copyWinInfo.depth == 8 && dpy2depth == 1) ) imageform = ZPixmap;
X else imageform = XYPixmap;
X
X /* Create a copy of the window we're watching */
X copyWin = XCreateWindow(dpy2,XDefaultRootWindow(dpy2),
X copyWinInfo.x,copyWinInfo.y,
X copyWinInfo.width,copyWinInfo.height,
X copyWinInfo.border_width,
X dpy2depth,
X CopyFromParent,
X XDefaultVisual(dpy2,XDefaultScreen(dpy2)),
X (CWColormap|CWBitGravity),
X &copyWinAttrs);
X
X /* Get size hints for window being watched */
X XGetNormalHints(dpy,win,&sizeHints);
X
X /* Set standard window properties for my window */
X XSetStandardProperties(dpy2,copyWin,"XWatchWin","XWatchWin",
X None,Argv,Argc,&sizeHints);
X
X /* Get window mgr hints for the window being watched */
X XGetWMHints(dpy,win,&wmHints);
X
X /* Tell the X server about my window manager hints */
X XSetWMHints(dpy2,copyWin,&wmHints);
X gc = XDefaultGC(dpy2,0); /* Get a default graphics context */
X
X /* Only interested in exposures and button presses */
X XSelectInput(dpy2,copyWin,(ExposureMask|ButtonPressMask));
X
X /* Put the window up on the display */
X XMapWindow(dpy2,copyWin);
X XSelectInput(dpy,win, /* Only interested if the source window is... */
X /* ...iconified or if it's mapped/unmapped */
X (VisibilityChangeMask|StructureNotifyMask));
X
X /* Store an image of the original window in an XImage */
X image = XGetImage(dpy, win, 0,0, copyWinInfo.width, copyWinInfo.height,
X AllPlanes, imageform);
X ConvertImage(image);
X
X gettimeofday(&currentTime,&zone); /* Get the current time. */
X timeInSecs = currentTime.tv_sec; /* Save the current time in seconds */
X
X /* Set variable saying it's okay to watch the src window. */
X srcWinUnmapped = 0;
X while (1) /* Enter an infinite event loop */
X {
X XEvent event;
X
X /* Check if the source window was turned into an... */
X /* ...icon or back into a window */
X
X if (XCheckWindowEvent(dpy,win,
X (VisibilityChangeMask|StructureNotifyMask),
X &event))
X {
X /* Get the window attributes of the window we're watching */
X XGetWindowAttributes(dpy,win,&newWinInfo);
X
X /* Is the original window in a state to be watched? */
X if (newWinInfo.map_state != IsViewable)
X {
X /* Let program know that the src window is unwatchable. */
X srcWinUnmapped = 1;
X printf("The window you are watching just became 'invisible'.\n");
X printf("I will wait until it is 'visible' again...\n");
X continue;
X }
X else
X /* Let program know that src window is watchable again. */
X srcWinUnmapped = 0;
X } /* end if(XCheckWindowEvent... */
X
X /* Look for window events, but don't sit around... */
X if (XCheckWindowEvent(dpy2,copyWin,
X (ExposureMask|ButtonPressMask),
X /* ...waiting for one (i.e., don't block) */
X &event))
X switch (event.type)
X {
X case ButtonPress:
X XDestroyImage(image);/* Free memory resources used by the image */
X exit(0); /* Get outtahere */
X break;
X case Expose:
X /* Put the original window's image into the copy of the window */
X XPutImage(dpy2, copyWin, gc, image, 0,0,0,0,
X copyWinInfo.width, copyWinInfo.height);
X
X break;
X } /* end switch (event.type) */
X
X gettimeofday(&currentTime,&zone); /* Get the current time. */
X
X /* Have 'updateTime' seconds passed? */
X if (currentTime.tv_sec > (timeInSecs + updateTime))
X { /* Yes, update the local copy of the window. */
X
X if (srcWinUnmapped) /* Is the source window watchable? */
X continue; /* No, go through the event loop again. */
X else /* Yes, it's watchable, so get a new copy of the window. */
X {
X XDestroyImage(image); /* Free memory used by the image */
X /* Store an image of the original window in an XImage */
X image = XGetImage(dpy,(Drawable)win,
X 0,0,
X copyWinInfo.width,copyWinInfo.height,
X AllPlanes,imageform);
X ConvertImage(image);
X } /* end else XDestroyImage... */
X
X /* Put the original window's image into the copy of the window */
X XPutImage(dpy2, copyWin, gc, image, 0,0,0,0,
X copyWinInfo.width, copyWinInfo.height);
X
X timeInSecs = currentTime.tv_sec; /* Update the current time */
X } /* end if currentTime... */
X } /* end while(1) */
X} /* end function WatchWindow */
X
X
X/* Given the name of a window and the top of a ... */
X/* ...window tree, this function will try to find... */
X/* the Window ID corresponding to the window name... */
X/* ...given as argument. */
XWindow GetWindowByName(window,windowName)
X Window window;
X char *windowName;
X{
X Window rootWin,parentWin,wID;
X Window *childWinList;
X int numChildren,i;
X char *childWinName;
X
X if (strcmp(windowName,"root")==0 || strcmp(windowName,"XRootWindow")==0)
X return XDefaultRootWindow(dpy);
X
X /* Get information about windows that are children... */
X XQueryTree(dpy,window,
X &rootWin,&parentWin,&childWinList, /* ...of 'window'. */
X &numChildren);
X for (i=0;i<numChildren;i++) /* Look at each child of 'window' */
X {
X /* Get the name of that window */
X XFetchName(dpy,childWinList[i],&childWinName);
X if (childWinName != NULL) /* Is there a name attached to this window? */
X {
X /* Is this the window the user is looking for? */
X if (WinNamesEqual(windowName,childWinName))
X {
X XFree(childWinList);/* Free up space taken by list of windows */
X XFree(childWinName);/* Return space taken by this window's name */
X /* Yes, return the Window ID of this window */
X return(childWinList[i]);
X }
X XFree(childWinName);/* Return space taken by this window's name */
X } /* end if childWinName... */
X } /* end for i=0... */
X /* If this section of code is reached, then no match was found at this
X * level of the tree
X */
X for (i=0;i<numChildren;i++) /* Recurse on the children of this window */
X {
X wID = GetWindowByName(childWinList[i],windowName);
X if (wID) /* Was a match found in this window's children? */
X {
X XFree(childWinList); /* Free up space taken by list of windows */
X return(wID); /* Return the ID of the window that matched */
X }
X } /* end for i=0... */
X /* If this section of code is reached, then no match was found below
X * this level of the tree
X */
X XFree(childWinList); /* Free up space taken by list of windows */
X return((Window)0); /* No match was found, return 0. */
X} /* end function GetWindowByName */
X
X
X
X
X
X
XConvertImage(image)
XXImage *image;
X{
X int i,j;
X static byte bit[8] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
X
X /* conversion between images of different depths. if the two depths
X are the same, nothing is done. If the two depths are '1' and '8'
X (either way), uses special case code and ZPixmaps. Otherwise, uses
X XYPixmap and general code below */
X
X
X /* note: on every color/greyscale server I've had the pleasure to deal
X with (IBM RT Megapel and Sun cgfour), XGetImage(XYPixmap) returns an
X image in which the planes are (in my opinion) reversed. That is, plane 0
X (the first plane in the image) corresponds to the highest order bit
X plane returned by the server.
X
X So, in order to correctly display the image when the two depths are
X different, I have to move the planes around. Examples: when displaying
X a 1-bit image on an 8-bit display, I convert the image by making up
X an 8-bit image, and copying the 1-bit plane to the 8th plane in the
X 8-bit image, rather than to the 1st plane.
X
X Likewise, when displaying an 8-bit image on a 1-bit display, I make
X up a 1-bit image, and copy the 8th plane to the (only) plane in the
X 1-bit image.
X
X In theory, if I was displaying a 4 bit image on an 8-bit display, I'd
X copy planes 0-3 of the 4-bit image to planes 4-7, respectively, in the
X 8-bit image.
X
X The code does this, though I haven't checked to see if it does it
X correctly, or even if this is the right thing to do.
X
X --jhb */
X
X if (dpy2depth == image->depth) return;
X
X else if (dpy2depth == 8 || image->depth == 1) { /* expand ZPixmap 1->8 */
X byte *iptr, *optr, *ilptr, *olptr, *tmp;
X int obperlin,bit;
X
X obperlin = ((image->width*8 + image->bitmap_pad - 1)
X / image->bitmap_pad) * (image->bitmap_pad / 8);
X
X ilptr = (byte *) image->data;
X olptr = tmp = malloc(image->height * obperlin);
X if (!olptr) { fprintf(stderr,"couldn't allocate image\n"); exit(1); }
X
X for (i=0; i<image->height; i++) {
X iptr = ilptr; optr = olptr;
X for (j=bit=0; j<image->width; j++) {
X *optr++ = (*iptr&0x80) ? 1 : 0;
X *iptr <<= 1;
X if (!(++bit&7)) iptr++;
X }
X ilptr += image->bytes_per_line; olptr += obperlin;
X }
X
X free(image->data);
X image->data = (char *) tmp;
X image->bytes_per_line = obperlin;
X image->depth = image->bits_per_pixel = dpy2depth;
X }
X
X
X else if (dpy2depth == 1 || image->depth == 8) { /* compress ZPixmap 8->1 */
X byte *iptr, *optr, *ilptr, *olptr, *tmp;
X int obperlin,bit;
X
X obperlin = ((image->width + image->bitmap_pad - 1)
X / image->bitmap_pad) * (image->bitmap_pad / 8);
X
X ilptr = (byte *) image->data;
X olptr = tmp = malloc(image->height * obperlin);
X if (!olptr) { fprintf(stderr,"couldn't allocate image\n"); exit(1); }
X
X for (i=0; i<image->height; i++) {
X iptr = ilptr; optr = olptr;
X for (j=bit=0; j<image->width; j++) {
X *optr = (*optr<<1) | (*iptr++ & 0x01);
X if (!(++bit&7)) optr++;
X }
X ilptr += image->bytes_per_line; olptr += obperlin;
X }
X
X free(image->data);
X image->data = (char *) tmp;
X image->bytes_per_line = obperlin;
X image->depth = image->bits_per_pixel = dpy2depth;
X }
X
X
X else if (dpy2depth > image->depth) { /* expand XYPixmap */
X byte *tmp;
X long planelen = image->height * image->bytes_per_line;
X tmp = malloc(planelen * dpy2depth);
X if (!tmp) { fprintf(stderr,"couldn't allocate image\n"); exit(1); }
X bzero(tmp,planelen * dpy2depth);
X
X bcopy(image->data, tmp + (dpy2depth - image->depth)*planelen,
X image->depth * planelen);
X
X free(image->data);
X image->data = (char *) tmp;
X image->depth = dpy2depth;
X }
X
X else if (dpy2depth < image->depth) { /* compress XYPixmap */
X byte *tmp;
X long planelen = image->height * image->bytes_per_line;
X tmp = malloc(planelen * dpy2depth);
X if (!tmp) { fprintf(stderr,"couldn't allocate image\n"); exit(1); }
X
X bcopy(image->data + (image->depth - dpy2depth)*planelen, tmp,
X dpy2depth * planelen);
X
X free(image->data);
X image->data = (char *) tmp;
X image->depth = dpy2depth;
X }
X}
X
+END+OF+xwatchwin.c
echo '-rw-rw-r-- 1 argv 16138 Apr 7 10:51 xwatchwin.c (as sent)'
chmod u=rw,g=rw,o=r xwatchwin.c
ls -l xwatchwin.c
echo x - Imakefile
sed 's/^X//' > Imakefile <<'+END+OF+Imakefile'
X#ifdef SunSharedLibs
XSYS_LIBRARIES = -lX11
X#else
XLOCAL_LIBRARIES = $(XLIB)
X#endif
XSimpleProgramTarget(xwatchwin)
+END+OF+Imakefile
echo '-rw-rw-r-- 1 argv 113 Apr 6 00:15 Imakefile (as sent)'
chmod u=rw,g=rw,o=r Imakefile
ls -l Imakefile
exit 0



This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:09:13 CDT