commit 29cb8033f8cda420ff86769aa71d42af81b1b540
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(-)
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))
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
+to 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
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
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.
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
+
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
+tony 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
+timeout_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(¤t_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
+	}
+}
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
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
+[ \-display \fIdisplayname\fP ] [ \-mag \fImag\fP [ \fImag\fP ] ]
+[ \-x ] [ \-y ] [ \-xy ]
+[ \-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
+toggle 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
+the 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