Initial commit of xzoom 0.3 with 0.4. - xzoom - A simple screen magnifier for X11.
       
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
 (DIR) commit 29cb8033f8cda420ff86769aa71d42af81b1b540
 (HTM) Author: Christoph Lohmann <20h@r-36.net>
       Date:   Fri, 21 Oct 2011 10:29:00 +0200
       
       Initial commit of xzoom 0.3 with 0.4.
       
       Diffstat:
         Imakefile                           |      25 +++++++++++++++++++++++++
         README                              |      29 +++++++++++++++++++++++++++++
         changelog                           |     178 +++++++++++++++++++++++++++++++
         copyright                           |      22 ++++++++++++++++++++++
         scale.h                             |     102 +++++++++++++++++++++++++++++++
         xzoom.c                             |     894 +++++++++++++++++++++++++++++++
         xzoom.lsm                           |      18 ++++++++++++++++++
         xzoom.man                           |     169 +++++++++++++++++++++++++++++++
       
       8 files changed, 1437 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/Imakefile b/Imakefile
       @@ -0,0 +1,25 @@
       +#ifndef XCOMM
       +#define XCOMM #
       +#endif
       +XCOMM Imakefile for xzoom
       +XCOMM Copyright Itai Nahshon 1995, 1996
       +XCOMM
       +XCOMM Valid compile time options:
       +XCOMM -DFRAME: source area is marked with a rectangular frame.
       +XCOMM -DXSHM:  use X11 shared memory extension.
       +XCOMM -DTIMER: count time between window updates (just for testing).
       +XCOMM -DNO_USLEEP: for system that do not have the usleep function
       +XCOMM -DBCOPY: use bcopy() instead of memmove()
       +
       +XCOMM DEFINES = -DFRAME -DXSHM -DTIMER -DNO_USLEEP
       +
       +DEFINES = -DFRAME -DXSHM
       +
       +LOCAL_LIBRARIES = -lXext -lX11 -lXt
       +
       +NAME = xzoom
       +
       +BINDIR = /usr/bin
       +MANPATH = /usr/share/man
       +
       +SimpleProgramTarget($(NAME))
 (DIR) diff --git a/README b/README
       @@ -0,0 +1,29 @@
       +This is xzoom 0.3.
       +
       +I got a few letters from people who tried xzoom-0.1.
       +I want to thank all these people for the responses.
       +Some people have requested to add features. Some
       +also suggested their own contribution.
       +I am sory that I could not satisfy all. I will try
       +tto do so in the next releases.
       +
       +What's changed since release 0.1:
       +
       +Mainly I added command line options. With these
       +you can start xzoom and focus at any point in the screen
       +and at any magnification which you want. Look at the
       +man page for details.
       +
       +A second thing that you might have noticed is a memory
       +leak in 0.1 (funny, I did not get any mail about it).
       +As I finally found, the leak was due to some X events queing
       +up and not discarded. Finally I found the documentation
       +for XSHM in the X11R6 CDROM (disk 2, file
       +distrib/xc/doc/specs/Xext/mit-shm.ms). The MS macros
       +came from the BSD cdrom and with that help I could
       +find the bug and fix it.
       +
       +Plese send comments, requests, suggestions to
       +nahshon@best.com.
       +
       +Itai Nahshon
 (DIR) diff --git a/changelog b/changelog
       @@ -0,0 +1,178 @@
       +xzoom (0.3-23) unstable; urgency=low
       +
       +  [ Anibal Avelar ]
       +  * New mantainer 
       +  * Fixed the FTBFS bug added the xutils-dev dependency.
       +    (Closes: #485733)
       +  * Bumped to Standards-version 3.8.0.
       +  * Added the Homepage field in the debian/control file.
       +  * Cleaned the debian/copyright file with cosmetic changes.
       +
       +  [ Piotr Ożarowski ]
       +  * debian/watch file added
       +
       + -- Anibal Avelar <aavelar@cofradia.org>  Sun, 15 Jun 2008 22:27:53 -0400
       +
       +xzoom (0.3-22) unstable; urgency=low
       +
       +  * Cap menu item. Closes: #438103
       +
       + -- Joey Hess <joeyh@debian.org>  Wed, 15 Aug 2007 13:29:53 -0400
       +
       +xzoom (0.3-21) unstable; urgency=low
       +
       +  * Maintaining this package again.
       +  * Improve description, fix typos.
       +  * Remove debian/pbuild-test directory, seems to be added by accident.
       +  * De-dpatchify (personal preference).
       +  * Clean up rules file.
       +  * Remove various autogenerated files from source package, seems they were
       +    added by accident.
       +  * debhelper v5.
       +  * The Apps/Tools menu is obsolete. Use Applications/Accessibility, 
       +    hope that's not too big a stretch.
       +  * Remove CVS dirs from debian patch.
       +
       + -- Joey Hess <joeyh@debian.org>  Tue, 07 Aug 2007 22:01:43 -0700
       +
       +xzoom (0.3-20) unstable; urgency=low
       +
       +  * orphan
       +
       + -- Junichi Uekawa <dancer@debian.org>  Sat, 04 Aug 2007 09:37:51 +0900
       +
       +xzoom (0.3-19) unstable; urgency=low
       +
       +  * Standards-version: 3.7.2
       +  * debian/compat: 4
       +
       + -- Junichi Uekawa <dancer@debian.org>  Sat,  2 Sep 2006 19:42:17 +0900
       +
       +xzoom (0.3-18) unstable; urgency=low
       +
       +  * support for X11R7, and install to standard FHS locations.
       +    (Closes: #364168).
       +  * use dpatch.
       +  * quote menu item string.
       +  * Standards-version: 3.6.2
       +
       + -- Junichi Uekawa <dancer@debian.org>  Sat, 22 Apr 2006 12:50:12 +0900
       +
       +xzoom (0.3-17) unstable; urgency=low
       +
       +  * Bug fix: "xzoom: FTBFS: build-depends on removed xlibs-dev"
       +    Changed to x-dev, libxext-dev, libxt-dev (Closes: #346867). 
       +  * Bug fix: "'man xzoom' typo: "magniications"", thanks to A
       +    Costa (Closes: #306710).
       +  * add simple test for resulting binary.
       +
       + -- Junichi Uekawa <dancer@debian.org>  Mon,  9 Jan 2006 13:10:09 +0900
       +
       +xzoom (0.3-16) unstable; urgency=low
       +
       +  * New maintainer (closes: #202330)
       +  * Standards-version: 3.6.0
       +  * Modified the package description.
       +
       + -- Junichi Uekawa <dancer@debian.org>  Sat,  9 Aug 2003 07:38:11 +0900
       +
       +xzoom (0.3-15) unstable; urgency=low
       +
       +  * orphaned; set maintainer to packages@qa.debian.org
       +
       + -- tony mancill <tmancill@debian.org>  Mon, 21 Jul 2003 15:46:51 -0700
       +
       +xzoom (0.3-14) unstable; urgency=low
       +
       +  * updated build-depends for sid (closes: #170185)
       +
       + -- tony mancill <tmancill@debian.org>  Sat, 23 Nov 2002 16:04:04 -0800
       +
       +xzoom (0.3-13) unstable; urgency=low
       +
       +  * updated manpage (closes: #93253)
       +  * hacked in WM_DELETE_WINDOW support (closes: #93250)
       +    (you can now use standard window manager methods to close the client)
       +
       + -- tony mancill <tmancill@debian.org>  Tue, 12 Feb 2002 22:59:09 -0800
       +
       +xzoom (0.3-12) unstable; urgency=low
       +
       +  * binaries built against xfree 4.x for woody release
       +
       + -- tony mancill <tmancill@debian.org>  Mon, 26 Nov 2001 20:08:29 -0800
       +
       +xzoom (0.3-11) unstable; urgency=low
       +
       +  * new maintainer <tmancill@debian.org> (Closes: bug#69658)
       +
       + -- tony mancill <tmancill@debian.org>  Mon, 28 Aug 2000 17:43:02 -0700
       +
       +xzoom (0.3-10) unstable; urgency=low
       +
       +  * Build deps.
       +
       + -- Joey Hess <joeyh@debian.org>  Sat,  4 Dec 1999 18:42:28 -0800
       +
       +xzoom (0.3-9) unstable; urgency=low
       +
       +  * FHS
       +
       + -- Joey Hess <joeyh@debian.org>  Sun, 12 Sep 1999 14:27:43 -0700
       +
       +xzoom (0.3-8) unstable; urgency=low
       +
       +  * Fixed package description: no longer limited to 8bpp.
       +  * Documented the 'g' key in the man page.
       +
       + -- Joey Hess <joeyh@debian.org>  Wed, 25 Feb 1998 11:09:59 -0800
       +
       +xzoom (0.3-7) unstable; urgency=low
       +
       +  * Added changes from Markus F.X.J. Oberhumer 
       +    <k3040e4@c210.edvz.uni-linz.ac.at>, for greater than 8 bpp support 
       +    plus some other features.
       +
       + -- Joey Hess <joeyh@debian.org>  Thu, 19 Feb 1998 10:59:43 -0800
       +
       +xzoom (0.3-6) unstable; urgency=low
       +
       +  * Moved binary to /usr/X11R6/bin.
       +
       + -- Joey Hess <joeyh@debian.org>  Mon,  9 Feb 1998 12:44:08 -0800
       +
       +xzoom (0.3-5) unstable; urgency=low
       +
       +  * Use debhelper.
       +
       + -- Joey Hess <joeyh@debian.org>  Sat,  7 Feb 1998 20:48:22 -0800
       +
       +xzoom (0.3-4) unstable; urgency=low
       +
       +  * libc6.
       +  * Routine update of debian/rules:
       +    Fixed binary-indep target.
       +
       + -- Joey Hess <joeyh@debian.org>  Mon,  8 Sep 1997 14:08:03 -0400
       +
       +xzoom (0.3-3) unstable; urgency=low
       +
       +  * Added note to description that it only works at 8bpp.
       +
       + -- Joey Hess <joeyh@debian.org>  Thu,  5 Jun 1997 19:36:27 -0400
       +
       +xzoom (0.3-2) unstable; urgency=low
       +
       +  * Fixed man page permissions. (#10275)
       +  * Moved man page to X11R6.
       +  * Updated menu file to menu-1 format.
       +  * Routine update of debian/rules:
       +    Run dpkg-gencontrol after debstd, and delete substvars during clean.
       +
       + -- Joey Hess <joeyh@debian.org>  Sun,  1 Jun 1997 14:12:42 -0400
       +
       +xzoom (0.3-1) unstable; urgency=low
       +
       +  * First release.
       +
       + -- Joey Hess <joeyh@debian.org>  Sat, 8 Mar 1997 15:30:09 -0500
 (DIR) diff --git a/copyright b/copyright
       @@ -0,0 +1,22 @@
       +This package was maintained by tony mancill <tmancill@debian.org>, for a 
       +while, and then picked up by Junichi Uekawa <dancer@debian.org>. Since Sun, 15 Jun 2008 maintained by Anibal Avelar <aavelar@cofradia.org>.
       +
       +This package was put together by Joey Hess <joeyh@debian.org>, using
       +sources from:
       +        ftp://sunsite.unc.edu/pub/linux/libs/X/xzoom-0.3.tgz
       +
       +Copyright: 1995-2008 Itai Nahshon
       +
       +License:
       +
       +   This program is distributed with no warranty.
       +
       +   Source files for this program may be distributed freely.
       +   Modifications to this file are okay as long as:
       +    a. This copyright notice and comment are preserved and
       +     left at the top of the file.
       +    b. The man page is fixed to reflect the change.
       +    c. The author of this change adds his name and change
       +     description to the list of changes below.
       +   Executable files may be distributed with sources, or with
       +   exact location where the source code can be obtained.
 (DIR) diff --git a/scale.h b/scale.h
       @@ -0,0 +1,102 @@
       +/* scale image from SRC to DST - parameterized by type T */
       +
       +/* get pixel address of point (x,y) in image t */
       +#define getP(t,x,y) \
       +        (T *) (&ximage[t]->data[(ximage[t]->xoffset+(x))*sizeof(T) + \
       +                                (y)*ximage[t]->bytes_per_line])
       +
       +{
       +        int i, j, k;
       +
       +        /* copy scaled lines from SRC to DST */
       +        j = flipxy ? width[SRC] - 1 : height[SRC] - 1;
       +        do {
       +                T *p1;
       +                T *p2;
       +                int p2step;
       +                T *p1_save;
       +
       +                /* p1 point to begining of scanline j*magy in DST */
       +                p1 = getP(DST,0,j*magy);
       +                p1_save = p1;
       +                /* p2 point to begining of scanline j in SRC */
       +                /* if flipy then line height[SRC]-1-j */
       +                p2 = getP(SRC,0,flipy ? (height[SRC]-1-j) : j);
       +
       +                if (flipxy)
       +                {
       +                        p2 = getP(SRC,flipy ? j : (width[SRC]-1-j),0);
       +                        p2step = ximage[SRC]->bytes_per_line / sizeof(T);
       +
       +                        if (flipx)
       +                        {
       +                                p2 += p2step * (height[SRC]-1);
       +                                p2step = -p2step;
       +                        }
       +
       +                        i = height[SRC];
       +                        do {
       +                                T c = *p2; p2 += p2step;
       +                                k = magx; do *p1++ = c; while (--k > 0);
       +                        } while (--i > 0);
       +                }
       +                else if (flipx)
       +                {
       +                        p2 += width[SRC];
       +                        i = width[SRC];
       +                        do {
       +                                T c = *--p2;
       +                                k = magx; do *p1++ = c; while (--k > 0);
       +                        } while (--i > 0);
       +                }
       +                else
       +                {
       +                        i = width[SRC];
       +                        do {
       +                                T c = *p2++;
       +                                k = magx; do *p1++ = c; while (--k > 0);
       +                        } while (--i > 0);
       +                }
       +
       +                /* draw vertical grid */
       +                if (gridy && magx >= 2)
       +                {
       +                        p1 = p1_save - 1;
       +                        i = magx;
       +                        k = flipxy ? height[SRC] : width[SRC];
       +                        do {
       +                                p1 += i;
       +                                *p1 ^= ~((T)0);
       +                        } while (--k > 0);
       +                }
       +
       +                /* duplicate that line as needed */
       +                if (magy > 1)
       +                {
       +                        /* p1 point to begining of scanline j*magy in DST */
       +                        p1 = p1_save;
       +                        /* p2 points to begining of next line */
       +                        p2 = p1;
       +                        p2step = ximage[DST]->bytes_per_line / sizeof(T);
       +
       +                        i = width[DST] * sizeof(T);
       +                        k = magy - 1;
       +                        do {
       +                                p2 += p2step;
       +                                memcpy(p2, p1, i);
       +                        } while (--k > 0);
       +
       +                        /* draw horizontal grid */
       +                        if (gridx && magy >= 2)
       +                        {
       +                                k = width[DST];
       +                                do {
       +                                        *p2++ ^= ~((T)0);
       +                                } while (--k > 0);
       +                        }
       +                }
       +        } while (--j >= 0);
       +}
       +
       +#undef getP
       +
 (DIR) diff --git a/xzoom.c b/xzoom.c
       @@ -0,0 +1,894 @@
       +/* Copyright Itai Nahshon 1995, 1996.
       +   This program is distributed with no warranty.
       +
       +   Source files for this program may be distributed freely.
       +   Modifications to this file are okay as long as:
       +    a. This copyright notice and comment are preserved and
       +           left at the top of the file.
       +        b. The man page is fixed to reflect the change.
       +        c. The author of this change adds his name and change
       +           description to the list of changes below.
       +   Executable files may be distributed with sources, or with
       +   exact location where the source code can be obtained.
       +
       +Changelist:
       +Author                    Description
       +------                    -----------
       +Itai Nahshon              Version 0.1, Nov. 21 1995
       +Itai Nahshon              Version 0.2, Apr. 17 1996
       +                          include <sys/types.h>
       +                          Use memmove() instead of memcopy()
       +                          Optional macro to replace call to usleep().
       +Markus F.X.J. Oberhumer   Version 0.4, Feb. 18 1998
       +                          split into 2 files (scale.h)
       +                          added support for 15, 16, 24 and 32 bpp displays
       +                          added a grid (press key 'g')
       +                          optimized scaling routines
       +                          use memcpy() instead of memmove() ;-)
       +                          some other minor changes/fixes
       +ttony mancill                2002/02/13 <tmancill@debian.org>       
       +                        hacked in support for WM_DELETE_WINDOW
       +*/
       +
       +#include <stdio.h>
       +#include <string.h>
       +#include <stdlib.h>
       +#include <sys/types.h>
       +#include <sys/signal.h>
       +
       +#include <X11/Xlib.h>
       +#include <X11/Xatom.h>
       +#include <X11/Xutil.h>
       +
       +#ifdef XSHM
       +#include <sys/ipc.h>
       +#include <sys/shm.h>
       +#include <X11/extensions/XShm.h>
       +#endif
       +
       +#include <X11/cursorfont.h>
       +#include <X11/keysym.h>
       +
       +#ifdef TIMER
       +#include <sys/time.h>
       +#include <unistd.h>
       +#endif
       +
       +Display *dpy;
       +Screen *scr;
       +Window win;
       +Atom wm_delete_window;
       +Atom wm_protocols;
       +Status status;
       +
       +GC gc;
       +#ifdef FRAME
       +GC framegc;
       +#endif
       +
       +#ifdef TIMER
       +Font font;
       +struct timeval old_time;
       +#endif
       +
       +Cursor when_button;
       +Cursor crosshair;
       +
       +char *progname;
       +int set_title;
       +
       +#define SRC                0                                /* index for source image */
       +#define        DST                1                                /* index for dest image */
       +
       +#define WIDTH        256                                /* default width */
       +#define HEIGHT        256                                /* default height */
       +
       +#define MAG                2                                /* default magnification */
       +#define MAGX        MAG                                /* horizontal magnification */
       +#define MAGY        MAG                                /* vertical magnification */
       +
       +int xgrab, ygrab;                                /* where do we take the picture from */
       +
       +int magx = MAGX;
       +int magy = MAGY;
       +
       +int flipxy = False;                                /* flip x and y */
       +int flipx = False;                                /* flip display about y axis */
       +int flipy = False;                                /* flip display about x axiz */
       +
       +int xzoom_flag = False;                        /* next mag change only to magx */
       +int yzoom_flag = False;                        /* next mag change only to magy */
       +
       +int gridx = False;
       +int gridy = False;
       +
       +int width[2] = { 0, WIDTH };
       +int height[2] = { 0, HEIGHT };
       +unsigned depth = 0;
       +
       +#ifdef XSHM
       +XShmSegmentInfo shminfo[2];                        /* Segment info.  */
       +#endif
       +XImage *ximage[2];                                        /* Ximage struct. */
       +
       +int created_images = False;
       +
       +#define NDELAYS 5
       +
       +int delays[NDELAYS] = { 200000, 100000, 50000, 10000, 0 };
       +int delay_index = 0;
       +int delay = 200000;                        /* 0.2 second between updates */
       +
       +void
       +ttimeout_func(int signum) {
       +        set_title = True;
       +        signum = signum;          /* UNUSED */
       +}
       +
       +#ifdef FRAME
       +#define DRAW_FRAME() \
       +        XDrawRectangle(dpy, RootWindowOfScreen(scr), framegc, xgrab, ygrab, width[SRC]-1, height[SRC]-1)
       +#endif
       +
       +void
       +allocate_images(void) {
       +        int i;
       +
       +        for(i = 0; i < 2; i++) {
       +
       +#ifdef XSHM
       +                ximage[i] = XShmCreateImage(dpy,
       +                        DefaultVisualOfScreen(scr),
       +                        DefaultDepthOfScreen(scr),
       +                        ZPixmap, NULL, &shminfo[i],
       +                        width[i], height[i]);
       +
       +                if(ximage[i] == NULL) {
       +                        perror("XShmCreateImage");
       +                        exit(-1);
       +                }
       +
       +                shminfo[i].shmid = shmget(IPC_PRIVATE,
       +                        (unsigned int)(ximage[i]->bytes_per_line * ximage[i]->height),
       +                        IPC_CREAT | 0777);
       +
       +                if(shminfo[i].shmid < 0) {
       +                        perror("shmget");
       +                        exit(-1);
       +                }
       +
       +                shminfo[i].shmaddr = (char *)shmat(shminfo[i].shmid, 0, 0);
       +
       +                if (shminfo[i].shmaddr == ((char *) -1)) {
       +                        perror("shmat");
       +                        exit(-1);
       +                }
       +
       +#ifdef DEBUG
       +                fprintf(stderr, "new shared memory segment at 0x%08x size %d\n",
       +                        shminfo[i].shmaddr, ximage[i]->bytes_per_line * ximage[i]->height);
       +#endif
       +
       +                ximage[i]->data = shminfo[i].shmaddr;
       +                shminfo[i].readOnly = False;
       +
       +                XShmAttach(dpy, &shminfo[i]);
       +                XSync(dpy, False);
       +
       +                shmctl(shminfo[i].shmid, IPC_RMID, 0);
       +#else
       +                char *data;
       +                data = malloc(BitmapUnit(dpy) / 8 * width[i] * height[i]);
       +
       +                ximage[i] = XCreateImage(dpy,
       +                        DefaultVisualOfScreen(scr),
       +                        DefaultDepthOfScreen(scr),
       +                        ZPixmap, 0, data,
       +                        width[i], height[i], 32, 0);
       +
       +                if(ximage[i] == NULL) {
       +                        perror("XCreateImage");
       +                        exit(-1);
       +                }
       +
       +#endif /* XSHM */
       +        }
       +        created_images = True;
       +}
       +
       +void
       +destroy_images(void) {
       +        int i;
       +
       +        if (!created_images)
       +                return;
       +
       +        for(i = 0; i < 2; i++) {
       +#ifdef XSHM
       +                XShmDetach(dpy, &shminfo[i]);        /* ask X11 to detach shared segment */
       +                shmdt(shminfo[i].shmaddr);                /* detach it ourselves */
       +#else
       +                free(ximage[i]->data);
       +#endif
       +                ximage[i]->data = NULL;                        /* remove refrence to that address */
       +                XDestroyImage(ximage[i]);                /* and destroy image */
       +        }
       +
       +        created_images = False;
       +}
       +
       +void
       +Usage(void) {
       +        fprintf(stderr, "Usage: %s [ args ]\n"
       +                "Command line args:\n"
       +                "-display displayname\n"
       +                "-mag magnification [ magnification ]\n"
       +                "-geometry geometry\n"
       +                "-source geometry\n"
       +                "-x\n"
       +                "-y\n"
       +                "-xy\n\n"
       +                "Window commands:\n"
       +                "+: Zoom in\n"
       +                "-: Zoom out\n"
       +                "x: Flip right and left\n"
       +                "y: Flip top and bottom\n"
       +                "z: Rotate 90 degrees counter-clockwize\n"
       +                "w: Next '+' or '-' only change width scaling\n"
       +                "h: Next '+' or '-' only change height scaling\n"
       +                "d: Change delay between frames\n"
       +                "q: Quit\n"
       +                "Arrow keys: Scroll in direction of arrow\n"
       +                "Mouse button drag: Set top-left corner of viewed area\n",
       +                progname);
       +        exit(1);
       +}
       +
       +/* resize is called with the dest size.
       +   we call it then manification changes or when
       +   actual window size is changed */
       +void
       +resize(int new_width, int new_height) {
       +
       +        destroy_images();                /* we can get rid of these */
       +
       +        /* find new dimensions for source */
       +
       +        if(flipxy) {
       +                height[SRC] = (new_width+magx-1) / magx;
       +                width[SRC] = (new_height+magy-1) / magy;
       +        }
       +        else {
       +                width[SRC] = (new_width+magx-1) / magx;
       +                height[SRC] = (new_height+magy-1) / magy;
       +        }
       +
       +        if(width[SRC] < 1)
       +                width[SRC] = 1;
       +        if(width[SRC] > WidthOfScreen(scr))
       +                width[SRC] = WidthOfScreen(scr);
       +
       +        if(height[SRC] < 1)
       +                height[SRC] = 1;
       +        if(height[SRC] > HeightOfScreen(scr))
       +                height[SRC] = HeightOfScreen(scr);
       +
       +        /* temporary, the dest image may be larger than the
       +           actual window */
       +        if(flipxy) {
       +                width[DST] = magx * height[SRC];
       +                height[DST] = magy * width[SRC];
       +        }
       +        else {
       +                width[DST] = magx * width[SRC];
       +                height[DST] = magy * height[SRC];
       +        }
       +
       +        allocate_images();                /* allocate new images */
       +
       +        /* remember actual window size */
       +        if(width[DST] > new_width)
       +                width[DST] = new_width;
       +        if(height[DST] > new_height)
       +                height[DST] = new_height;
       +}
       +
       +
       +void scale8(void)
       +{
       +#define T unsigned char
       +#include "scale.h"
       +#undef T
       +}
       +
       +
       +void scale16(void)
       +{
       +#define T unsigned short
       +#include "scale.h"
       +#undef T
       +}
       +
       +
       +void scale32(void)
       +{
       +#define T unsigned int
       +#include "scale.h"
       +#undef T
       +}
       +
       +
       +int
       +main(int argc, char **argv) {
       +        XSetWindowAttributes xswa;
       +        XEvent event;
       +        int buttonpressed = False;
       +        int unmapped = True;
       +        int scroll = 1;
       +        char title[80];
       +        XGCValues gcv;
       +        char *dpyname = NULL;
       +        int source_geom_mask = NoValue,
       +            dest_geom_mask = NoValue,
       +            copy_from_src_mask;
       +        int xpos = 0, ypos = 0;
       +
       +        atexit(destroy_images);
       +        progname = strrchr(argv[0], '/');
       +        if(progname)
       +                ++progname;
       +        else
       +                progname = argv[0];
       +
       +        /* parse command line options */
       +        while(--argc > 0) {
       +                ++argv;
       +
       +                if(argv[0][0] == '=') {
       +                        dest_geom_mask = XParseGeometry(argv[0],
       +                                &xpos, &ypos,
       +                                &width[DST], &height[DST]);
       +                        continue;
       +                }
       +
       +                if(!strcmp(argv[0], "-mag")) {
       +                        ++argv; --argc;
       +
       +                        magx = argc > 0 ? atoi(argv[0]) : -1;
       +
       +                        if(magx <= 0)
       +                                Usage();
       +
       +
       +                        magy = argc > 1 ? atoi(argv[1]) : -1;
       +
       +                        if(magy <= 0)
       +                                magy = magx;
       +                        else {
       +                                ++argv; --argc;
       +                        }
       +
       +                        continue;
       +                }
       +
       +                if(!strcmp(argv[0], "-x")) {
       +                        flipx = True;
       +                        continue;
       +                }
       +
       +                if(!strcmp(argv[0], "-y")) {
       +                        flipy = True;
       +                        continue;
       +                }
       +
       +                if(!strcmp(argv[0], "-z") ||
       +                   !strcmp(argv[0], "-xy")) {
       +                        flipxy = True;
       +                        continue;
       +                }
       +
       +                if(!strcmp(argv[0], "-source")) {
       +                        ++argv; --argc;
       +
       +                        if(argc < 1)
       +                                Usage();
       +
       +                        source_geom_mask = XParseGeometry(argv[0],
       +                                &xgrab, &ygrab,
       +                                &width[SRC], &height[SRC]);
       +
       +                        continue;
       +                }
       +
       +                if(!strcmp(argv[0], "-dest") ||
       +                   !strcmp(argv[0], "-geometry")) {
       +                        ++argv; --argc;
       +
       +                        if(argc < 1)
       +                                Usage();
       +
       +                        dest_geom_mask = XParseGeometry(argv[0],
       +                                &xpos, &ypos,
       +                                &width[DST], &height[DST]);
       +
       +                        continue;
       +                }
       +
       +                if(!strcmp(argv[0], "-d") ||
       +                   !strcmp(argv[0], "-display")) {
       +
       +                           ++argv; --argc;
       +
       +                        if(argc < 1)
       +                                Usage();
       +
       +                           dpyname = argv[0];
       +                        continue;
       +                }
       +
       +                if(!strcmp(argv[0], "-delay")) {
       +
       +                           ++argv; --argc;
       +
       +                        if(argc < 1)
       +                                Usage();
       +
       +                        if(sscanf(argv[0], "%u", &delay) != 1)
       +                                Usage();
       +
       +                        delay *= 1000;
       +
       +                        continue;
       +                }
       +
       +                Usage();
       +        }
       +
       +        if (!(dpy = XOpenDisplay(dpyname))) {
       +                perror("Cannot open display");
       +                exit(-1);
       +        }
       +
       +        /* Now, see if we have to calculate width[DST] and height[DST]
       +           from the SRC parameters */
       +
       +        copy_from_src_mask = NoValue;
       +
       +        if(source_geom_mask & WidthValue) {
       +                if(flipxy) {
       +                        height[DST] = magy * width[SRC];
       +                        copy_from_src_mask |= HeightValue;
       +
       +                }
       +                else {
       +                        width[DST] = magx * width[SRC];
       +                        copy_from_src_mask |= WidthValue;
       +                }
       +        }
       +
       +        if(source_geom_mask & HeightValue) {
       +                if(flipxy) {
       +                        width[DST] = magx * height[SRC];
       +                        copy_from_src_mask |= WidthValue;
       +                }
       +                else {
       +                        height[DST] = magy * height[SRC];
       +                        copy_from_src_mask |= HeightValue;
       +                }
       +        }
       +
       +        if(copy_from_src_mask & dest_geom_mask) {
       +                fprintf(stderr, "Conflicting dimensions between source and dest geometry\n");
       +                Usage();
       +        }
       +
       +        scr = DefaultScreenOfDisplay(dpy);
       +
       +        depth = DefaultDepthOfScreen(scr);
       +        if (depth < 8) {
       +                fprintf(stderr, "%s: need at least 8 bits/pixel\n", progname);
       +                exit(1);
       +        }
       +
       +        if(source_geom_mask & XNegative)
       +                xgrab += WidthOfScreen(scr);
       +
       +        if(source_geom_mask & YNegative)
       +                ygrab += HeightOfScreen(scr);
       +
       +        if(dest_geom_mask & XNegative)
       +                xpos += WidthOfScreen(scr);
       +
       +        if(source_geom_mask & YNegative)
       +                ypos += HeightOfScreen(scr);
       +
       +        /* printf("=%dx%d+%d+%d\n", width[DST], height[DST], xpos, ypos); */
       +
       +        xswa.event_mask = ButtonPressMask|ButtonReleaseMask|ButtonMotionMask;
       +        xswa.event_mask |= StructureNotifyMask;        /* resize etc.. */
       +        xswa.event_mask |= KeyPressMask|KeyReleaseMask;                /* commands */
       +        xswa.background_pixel = BlackPixelOfScreen(scr);
       +
       +        win = XCreateWindow(dpy, RootWindowOfScreen(scr),
       +            xpos, ypos, width[DST], height[DST], 0,
       +            DefaultDepthOfScreen(scr), InputOutput,
       +            DefaultVisualOfScreen(scr),
       +            CWEventMask | CWBackPixel, &xswa);
       +
       +        XChangeProperty(dpy, win, XA_WM_ICON_NAME, XA_STRING, 8,
       +                        PropModeReplace,
       +                        (unsigned char *)progname, strlen(progname));
       +
       +        /*
       +        XChangeProperty(dpy, win, XA_WM_NAME, XA_STRING, 8,
       +                        PropModeReplace,
       +                        (unsigned char *)progname, strlen(progname));
       +        */
       +
       +        
       +         /***        20020213
       +                code added by <tmancill@debian.org> to handle
       +                window manager "close" event 
       +        ***/
       +        wm_delete_window = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
       +        wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);                  
       +        status = XSetWMProtocols(dpy, win, &wm_delete_window, 1);                   
       +
       +        set_title = True;
       +
       +        status = XMapWindow(dpy, win);
       +
       +        gcv.plane_mask = AllPlanes;
       +        gcv.subwindow_mode = IncludeInferiors;
       +        gcv.function = GXcopy;
       +        gcv.foreground = WhitePixelOfScreen(scr);
       +        gcv.background = BlackPixelOfScreen(scr);
       +        gc = XCreateGC(dpy, RootWindowOfScreen(scr),
       +                GCFunction|GCPlaneMask|GCSubwindowMode|GCForeground|GCBackground,
       +                &gcv);
       +
       +#ifdef FRAME
       +        gcv.foreground = AllPlanes;
       +        gcv.plane_mask = WhitePixelOfScreen(scr)^BlackPixelOfScreen(scr);
       +        gcv.subwindow_mode = IncludeInferiors;
       +        gcv.function = GXxor;
       +        framegc = XCreateGC(dpy, RootWindowOfScreen(scr),
       +                GCFunction|GCPlaneMask|GCSubwindowMode|GCForeground,
       +                &gcv);
       +#endif
       +
       +#ifdef TIMER
       +        font = XLoadFont(dpy, "fixed");
       +#endif
       +
       +        resize(width[DST], height[DST]);
       +
       +#ifdef FRAME
       +
       +        {
       +                static char bitmap_data[] = { 0 };
       +                static XColor col = { 0 };
       +                Pixmap curs = XCreatePixmapFromBitmapData(dpy,
       +                        RootWindowOfScreen(scr), bitmap_data, 1, 1, 0, 0, 1);
       +
       +                when_button = XCreatePixmapCursor(dpy, curs, curs, &col, &col, 0, 0);
       +        }
       +#else
       +        when_button = XCreateFontCursor(dpy, XC_ul_angle);
       +#endif
       +        crosshair = XCreateFontCursor(dpy, XC_crosshair);
       +
       +        XDefineCursor(dpy, win, crosshair);
       +
       +        for(;;) {
       +
       +                /*****
       +                old event loop updated to support WM messages
       +                while(unmapped?
       +                        (XWindowEvent(dpy, win, (long)-1, &event), 1):
       +                        XCheckWindowEvent(dpy, win, (long)-1, &event)) {
       +                ******/
       +                
       +                while(XPending(dpy)) {
       +                        XNextEvent(dpy, &event);
       +                        switch(event.type) {
       +                        case ClientMessage:
       +                                if ((event.xclient.message_type == wm_protocols) &&
       +                                    (event.xclient.data.l[0] == wm_delete_window)) {
       +                                        exit(0);
       +                                }
       +                                break;
       +                        case ConfigureNotify:
       +                                if(event.xconfigure.width != width[DST] ||
       +                                   event.xconfigure.height != height[DST]) {
       +
       +                                        resize(event.xconfigure.width, event.xconfigure.height);
       +                                }
       +                                break;
       +                        case ReparentNotify:
       +                                break;        /* what do we do with it? */
       +
       +                        case MapNotify:
       +                                unmapped = False;
       +                                break;
       +
       +                        case UnmapNotify:
       +                                unmapped = True;
       +                                break;
       +
       +                        case KeyRelease:
       +                                switch(XKeycodeToKeysym(dpy, event.xkey.keycode, 0)) {
       +                                case XK_Control_L:
       +                                case XK_Control_R:
       +                                        scroll = 1;
       +                                        break;
       +                                }
       +                                break;
       +
       +                        case KeyPress:
       +                                switch(XKeycodeToKeysym(dpy, event.xkey.keycode, 0)) {
       +                                case XK_Control_L:
       +                                case XK_Control_R:
       +                                        scroll = 10;
       +                                        break;
       +
       +                                case '+':
       +                                case '=':
       +                                case XK_KP_Add:
       +                                        if(!yzoom_flag) ++magx;
       +                                        if(!xzoom_flag) ++magy;
       +                                        xzoom_flag = yzoom_flag = False;
       +                                        resize(width[DST], height[DST]);
       +                                        set_title = True;
       +                                        break;
       +
       +                                case '-':
       +                                case XK_KP_Subtract:
       +                                        if(!yzoom_flag) --magx;
       +                                        if(!xzoom_flag) --magy;
       +                                        xzoom_flag = yzoom_flag = False;
       +                                        if(magx < 1) magx = 1;
       +                                        if(magy < 1) magy = 1;
       +                                        resize(width[DST], height[DST]);
       +                                        set_title = True;
       +                                        break;
       +
       +                                case XK_Left:
       +                                case XK_KP_Left:
       +                                        if(flipxy)
       +                                                if(flipx)
       +                                                        ygrab += scroll;
       +                                                else
       +                                                        ygrab -= scroll;
       +                                        else
       +                                                if(flipx)
       +                                                        xgrab += scroll;
       +                                                else
       +                                                        xgrab -= scroll;
       +                                        break;
       +
       +                                case XK_Right:
       +                                case XK_KP_Right:
       +                                        if(flipxy)
       +                                                if(flipx)
       +                                                        ygrab -= scroll;
       +                                                else
       +                                                        ygrab += scroll;
       +                                        else
       +                                                if(flipx)
       +                                                        xgrab -= scroll;
       +                                                else
       +                                                        xgrab += scroll;
       +                                        break;
       +
       +                                case XK_Up:
       +                                case XK_KP_Up:
       +                                        if(flipxy)
       +                                                if(flipy)
       +                                                        xgrab -= scroll;
       +                                                else
       +                                                        xgrab += scroll;
       +                                        else
       +                                                if(flipy)
       +                                                        ygrab += scroll;
       +                                                else
       +                                                        ygrab -= scroll;
       +                                        break;
       +
       +                                case XK_Down:
       +                                case XK_KP_Down:
       +                                        if(flipxy)
       +                                                if(flipy)
       +                                                        xgrab += scroll;
       +                                                else
       +                                                        xgrab -= scroll;
       +                                        else
       +                                                if(flipy)
       +                                                        ygrab -= scroll;
       +                                                else
       +                                                        ygrab += scroll;
       +                                        break;
       +
       +                                case 'x':
       +                                        flipx = !flipx;
       +                                        set_title = True;
       +                                        break;
       +
       +                                case 'y':
       +                                        flipy = !flipy;
       +                                        set_title = True;
       +                                        break;
       +
       +                                case 'z':
       +                                        if(flipx^flipy^flipxy) {
       +                                                flipx = !flipx;
       +                                                flipy = !flipy;
       +                                        }
       +                                        flipxy = !flipxy;
       +                                        resize(width[DST], height[DST]);
       +                                        set_title = True;
       +                                        break;
       +
       +                                case 'w':
       +                                        xzoom_flag = True;
       +                                        yzoom_flag = False;
       +                                        break;
       +
       +                                case 'h':
       +                                        yzoom_flag = True;
       +                                        xzoom_flag = False;
       +                                        break;
       +
       +                                case 'g':
       +                                        gridx = !gridx;
       +                                        gridy = !gridy;
       +                                        break;
       +
       +                                case 'd':
       +                                        if(++delay_index >= NDELAYS)
       +                                                delay_index = 0;
       +                                        delay = delays[delay_index];
       +                                        sprintf(title, "delay = %d ms", delay/1000);
       +                                        XChangeProperty(dpy, win, XA_WM_NAME, XA_STRING, 8,
       +                                                PropModeReplace,
       +                                                (unsigned char *)title, strlen(title));
       +                                        signal(SIGALRM, timeout_func);
       +                                        alarm(2);
       +                                        break;
       +
       +                                case 'q':
       +                                        exit(0);
       +                                        break;
       +                                }
       +
       +                                break;
       +
       +                        case ButtonPress:
       +#ifdef FRAME
       +                                xgrab = event.xbutton.x_root - width[SRC]/2;
       +                                ygrab = event.xbutton.y_root - height[SRC]/2;
       +#else
       +                                xgrab = event.xbutton.x_root;
       +                                ygrab = event.xbutton.y_root;
       +#endif
       +                                XDefineCursor(dpy, win, when_button);
       +                                buttonpressed = True;
       +                                break;
       +
       +                        case ButtonRelease:
       +                                /*
       +                                xgrab = event.xbutton.x_root - width[SRC]/2;
       +                                ygrab = event.xbutton.y_root - height[SRC]/2;
       +                                */
       +                                XDefineCursor(dpy, win, crosshair);
       +                                buttonpressed = False;
       +                                break;
       +
       +                        case MotionNotify:
       +                                if(buttonpressed) {
       +#ifdef FRAME
       +                                        xgrab = event.xmotion.x_root - width[SRC]/2;
       +                                        ygrab = event.xmotion.y_root - height[SRC]/2;
       +#else
       +                                        xgrab = event.xmotion.x_root;
       +                                        ygrab = event.xmotion.y_root;
       +#endif
       +                                }
       +                                break;
       +
       +                        }
       +
       +                        /* trying XShmGetImage when part of the rect is
       +                           not on the screen will fail LOUDLY..
       +                           we have to veryfy this after anything that may
       +                           may modified xgrab or ygrab or the size of
       +                           the source ximage */
       +
       +                        if(xgrab < 0)
       +                                xgrab = 0;
       +
       +                        if(xgrab > WidthOfScreen(scr)-width[SRC])
       +                                xgrab =  WidthOfScreen(scr)-width[SRC];
       +
       +                        if(ygrab < 0)
       +                                ygrab = 0;
       +
       +                        if(ygrab > HeightOfScreen(scr)-height[SRC])
       +                                ygrab = HeightOfScreen(scr)-height[SRC];
       +
       +                }
       +
       +#ifdef XSHM
       +                XShmGetImage(dpy, RootWindowOfScreen(scr), ximage[SRC],
       +                        xgrab, ygrab, AllPlanes);
       +#else
       +                XGetSubImage(dpy, RootWindowOfScreen(scr),
       +                        xgrab, ygrab, width[SRC], height[SRC], AllPlanes,
       +                        ZPixmap, ximage[SRC], 0, 0);
       +#endif
       +#ifdef FRAME
       +                if(buttonpressed) {        /* show the frame */
       +                        DRAW_FRAME();
       +                        XSync(dpy, False);
       +                }
       +#endif
       +
       +                if (depth == 8)
       +                        scale8();
       +                else if (depth <= 8*sizeof(short))
       +                        scale16();
       +                else if (depth <= 8*sizeof(int))
       +                        scale32();
       +
       +#ifdef XSHM
       +                XShmPutImage(dpy, win, gc, ximage[DST], 0, 0, 0, 0, width[DST], height[DST], False);
       +#else
       +                XPutImage(dpy, win, gc, ximage[DST], 0, 0, 0, 0, width[DST], height[DST]);
       +#endif
       +                if(set_title) {
       +                        if(magx == magy && !flipx && !flipy && !flipxy)
       +                                sprintf(title, "%s x%d", progname, magx);
       +                        else
       +                                sprintf(title, "%s X %s%d%s Y %s%d",
       +                                        progname,
       +                                                flipx?"-":"", magx,
       +                                                flipxy?" <=>":";",
       +                                                flipy?"-":"", magy);
       +                        XChangeProperty(dpy, win, XA_WM_NAME, XA_STRING, 8,
       +                                PropModeReplace,
       +                                (unsigned char *)title, strlen(title));
       +                        set_title = False;
       +                }
       +#ifdef TIMER
       +                {
       +                        struct timeval current_time;
       +                        double DT;
       +
       +                        gettimeofday(&current_time, NULL);
       +                        DT = current_time.tv_sec - old_time.tv_sec;
       +                        DT += 1e-6*(current_time.tv_usec - old_time.tv_usec);
       +                        sprintf(title, "DT=%6.3f", DT);
       +                        XDrawString(dpy, win, gc, 20, 20, title, strlen(title));
       +                        old_time = current_time;
       +                }
       +#endif
       +                XSync(dpy, 0);
       +
       +#ifdef NO_USLEEP
       +#define usleep(_t)                                                                \
       +        {                                                                                        \
       +                struct timeval timeout;                                        \
       +                timeout.tv_sec =  0;                                        \
       +                timeout.tv_usec = _t;                                        \
       +                select(0, NULL, NULL, NULL, &timeout);        \
       +        }
       +#endif
       +
       +                if(!buttonpressed && delay > 0)
       +                        usleep(delay);
       +#ifdef FRAME
       +                if(buttonpressed)        /* erase the frame */
       +                        DRAW_FRAME();
       +#endif
       +        }
       +}
 (DIR) diff --git a/xzoom.lsm b/xzoom.lsm
       @@ -0,0 +1,18 @@
       +Begin3
       +Title:          xzoom
       +Version:        0.3
       +Entered-date:   May 30 1996
       +Description:    xzoom can magnify (by integer value) rotate
       +                (by a multiple if 90 degrees) and mirror about
       +                                the X or Y axes areas on X11 screen and display
       +                                them in it's window.
       +Keywords:       X11 zoom magnify xmag
       +Author:         Itai Nahshon <nahshon@best.com>
       +Maintained-by:  Itai Nahshon <nahshon@best.com>
       +Primary-site:   sunsite.unc.edu
       +                probably in /pub/Linux/X11/xutils/xzoom-0.3.tgz
       +Platforms:      Linux+11. Support only for 8-bit depth.
       +                Tested only in Linux pre-2.0.* with the XSVGA 3.1.2 driver.
       +                                Needs the XSHM extension.
       +Copying-policy: Free
       +End
 (DIR) diff --git a/xzoom.man b/xzoom.man
       @@ -0,0 +1,169 @@
       +.\" xzoom.man
       +.\" Copyright Itai Nahshon
       +.\"
       +.TH XZOOM 1x
       +.SH NAME
       +xzoom \- magnify part of the screen, with fast updates
       +.SH SYNOPSIS
       +.B xzoom
       +t[ \-display \fIdisplayname\fP ] [ \-mag \fImag\fP [ \fImag\fP ] ]
       +t[ \-x ] [ \-y ] [ \-xy ]
       +t[ \-geometry \fIgeometry\fP ] [ \-source \fIgeometry\fP ]
       +.SH OPTIONS
       +.LP
       +.TP 5
       +.B \-display \fIdisplayname\fP \fR|\fP \-d \fIdisplayname\fP
       +The name of the display to use
       +(not very useful).
       +.TP 5
       +.B \-mag \fImag\fP [ \fImag\fP ]
       +What magnification to use. If two number arguments are supplied the
       +first is used for X magnifications and the second is used for Y magnification.
       +Magnification should be greater than 0.
       +.TP 5
       +.B \-x
       +Mirror horizontally.
       +.TP 5
       +.B \-y
       +Mirror vertically.
       +.TP 5
       +.B \-xy \fR|\fP \-z
       +Exchange X and Y axes before any magnification is performed.
       +.TP 5
       +.B \-geometry \fIgeometry\fP \fR|\fP =\fIgeometry\fP
       +Size and position \fBxzoom\fR's window.
       +.TP 5
       +.B \-source \fIgeometry\fP
       +Size and position the initial source area which is magnified.
       +The dimensions of this area are multiplied by the magnification to
       +get the size of \fBxzoom\fR's window. If these dimensions are given
       +separately (by use of \-geometry ) then an error is reported.
       +.br
       +.SH DESCRIPTION
       +.IR Xzoom
       +displays in its window a magnified area of the X11 display.
       +The user can interactively change the zoomed area, the window
       +size, magnification (optionally different magnification for
       +X and Y axes) or rotate or mirror the image.
       +.SH COMMANDS
       +.LP
       +Once xzoom has started the user can enter simple commands
       +using the keyboard.
       +.LP
       +.TP 5
       +.B q
       +quit.
       +.TP 5
       +.B \+
       +increase magnification value by 1.
       +.TP 5
       +.B \-
       +decrease magnification value by 1.
       +.TP 5
       +.B w
       +next \+ or \- command only affect X magnification.
       +.TP 5
       +.B h
       +next \+ or \- command only affect Y magnification.
       +.TP 5
       +.B x
       +mirror the display image horizontally.
       +.TP 5
       +.B y
       +mirror the display image vertically.
       +.TP 5
       +.B z
       +rotate the displayed image 90 degrees counter-clockwise.
       +.TP 5
       +.B arrow keys
       +scroll the zoomed area 1 pixel in the direction of the arrow.
       +if the
       +.B control
       +key is pressed the zoomed area will scroll 10 pixels.
       +.TP 5
       +.B d
       +sets the delay between frame updates. 
       +Built-in delays are 200, 100, 50, 10 and 0 ms.
       +.TP 5
       +.B g
       +ttoggle grid on and off.
       +.TP 5
       +.B Mouse buttons
       +To set the location of the magnified are click the left mouse
       +button inside xzoom's window and then move it (keep the button
       +pressed) to the place which you want to see magnified.
       +.sp 1
       +Xzoom allow you to resize it's window at any time.
       +.sp 1
       +When xzoom is iconified it simply waits to get deiconified.
       +.SH DISPLAYS
       +Xzoom uses the window's title bar to inform the user about
       +it's status. Normally the title says something like
       +.B "xzoom x2"
       +which means the magnification is 2 both in X and Y axes.
       +If the image is stretched differently on the X and Y axes
       +tthe title will say
       +.B "xzoom X 2; Y 4."
       +Negative numbers mean reflection.
       +If the image is rotated by 90 or 270 degrees the title
       +will show
       +.B "<=>"
       +between the X and Y values.
       +.sp 1
       +When
       +.B d
       +is depressed the title will display the new delay value for
       +approximately 2 seconds and then revert to the default display
       +of magnification values.
       +.SH PERFORMANCE
       +Xzoom is fast enough to display enlarged or mirrored animations
       +in small windows. On my 486 DX2-66 and Cirrus Logic CL-GD5428
       +display card (attached to Vesa local bus) update of a 256x256
       +window magnified by 2 (ie, source rect is 128x128) takes
       +approximately 30 ms. This time varies, off course when
       +a different size window or different magnification is used.
       +If we chose 50 ms between updates we can get about 12.5 frames per
       +second and still let an animation program do it's work.
       +It is possible to compile xzoom without X shared memory support.
       +In that case window update may be about 3 times slower (if we
       +are using a local display, using LAN is a different story).
       +.SH SEE ALSO
       +xmag.1x.
       +.br
       +I got the motivation for writing xzoom after I saw a similar
       +WindowsNT program, zoomin working. It started just as a test
       +for X11 performance. I don't have the fancy menus and scrollbar
       +like zoomin but I do have all their features (and more) accessible
       +from the keyboard.
       +.SH BUGS
       +.LP 5
       +\(dg
       +The maximum internal built in delay (see command
       +.B d
       +above) was set to 200 ms. Xzoom completes the delay before
       +polling the X event queue for the next command. Larger
       +delays would feel like poor response to user commands.
       +.LP 5
       +\(dg
       +For best performance the shared memory extension for X11 is
       +used. Xzoom will fail if it is compiled to use XSHM and its
       +display is not on the local host.
       +.LP 5
       +\(dg
       +Xzoom is given with no warranty. It was tested only under
       +Linux with Xfree86 release 3.1.2 (X11R6).
       +.LP 5
       +\(dg
       +Some strange behavior may occur if the requested magnified area
       +falls beyond the borders of the screen. Example is when you have
       +magnification of 1 and a window whose width is greater than the
       +height of the screen and you want 90 degrees rotation. In that
       +case part of the window will not get updated.
       +.LP 5
       +\(dg
       +The frame used to mark the zoomed area may corrupt the contents
       +of other windows if they are modified when the frame is visible.
       +If you don't like it disable the \-DFRAME option when compiling
       +xzoom.
       +.SH AUTHOR
       +Itai Nahshon