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