xzoom (0.3-23) direct (non packaging) changes

Summary

 Imakefile |    6 -
 scale.h   |  102 +++++++++++++++++++++++++++++
 xzoom.c   |  213 +++++++++++++++++++++++++++++++++++---------------------------
 xzoom.man |   14 +---
 4 files changed, 232 insertions(+), 103 deletions(-)

    
download this patch

Patch contents

--- xzoom-0.3.orig/Imakefile
+++ xzoom-0.3/Imakefile
@@ -15,11 +15,11 @@
 
 DEFINES = -DFRAME -DXSHM
 
-LOCAL_LIBRARIES = -lXext -lX11
+LOCAL_LIBRARIES = -lXext -lX11 -lXt
 
 NAME = xzoom
 
-BINDIR = /usr/local/bin
-MANPATH = /usr/local/man
+BINDIR = /usr/bin
+MANPATH = /usr/share/man
 
 SimpleProgramTarget($(NAME))
--- xzoom-0.3.orig/scale.h
+++ xzoom-0.3/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
+
--- xzoom-0.3.orig/xzoom.c
+++ xzoom-0.3/xzoom.c
@@ -12,13 +12,22 @@
    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().
+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>
@@ -48,6 +57,9 @@
 Display *dpy;
 Screen *scr;
 Window win;
+Atom wm_delete_window;
+Atom wm_protocols;
+Status status;
 
 GC gc;
 #ifdef FRAME
@@ -87,8 +99,12 @@
 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.  */
@@ -106,6 +122,7 @@
 void
 timeout_func(int signum) {
 	set_title = True;
+	signum = signum;          /* UNUSED */
 }
 
 #ifdef FRAME
@@ -116,9 +133,6 @@
 void
 allocate_images(void) {
 	int i;
-#ifndef XSHM
-	char *data;
-#endif
 
 	for(i = 0; i < 2; i++) {
 
@@ -137,7 +151,7 @@
 		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);
@@ -163,20 +177,21 @@
 
 		shmctl(shminfo[i].shmid, IPC_RMID, 0);
 #else
-		data = malloc(width[i] * height[i]);
+		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], 8, width[i]);
+			width[i], height[i], 32, 0);
 
 		if(ximage[i] == NULL) {
 			perror("XCreateImage");
 			exit(-1);
 		}
 
-#endif XSHM
+#endif /* XSHM */
 	}
 	created_images = True;
 }
@@ -185,6 +200,9 @@
 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 */
@@ -195,6 +213,8 @@
 		ximage[i]->data = NULL;			/* remove refrence to that address */
 		XDestroyImage(ximage[i]);		/* and destroy image */
 	}
+
+	created_images = False;
 }
 
 void
@@ -230,8 +250,7 @@
 void
 resize(int new_width, int new_height) {
 
-	if(created_images)
-		destroy_images();		/* we can get rid of these */
+	destroy_images();		/* we can get rid of these */
 
 	/* find new dimensions for source */
 
@@ -244,9 +263,13 @@
 		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);
 
@@ -270,12 +293,34 @@
 		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;
-	int i, j, k;
-	char c;
-	char *p1, *p2;
 	XEvent event;
 	int buttonpressed = False;
 	int unmapped = True;
@@ -286,8 +331,9 @@
 	int source_geom_mask = NoValue,
 	    dest_geom_mask = NoValue,
 	    copy_from_src_mask;
-	int xpos = 0, ypos = 0; 
+	int xpos = 0, ypos = 0;
 
+	atexit(destroy_images);
 	progname = strrchr(argv[0], '/');
 	if(progname)
 		++progname;
@@ -312,7 +358,7 @@
 
 			if(magx <= 0)
 				Usage();
-			
+
 
 			magy = argc > 1 ? atoi(argv[1]) : -1;
 
@@ -340,7 +386,7 @@
 			flipxy = True;
 			continue;
 		}
-		
+
 		if(!strcmp(argv[0], "-source")) {
 			++argv; --argc;
 
@@ -438,23 +484,24 @@
 
 	scr = DefaultScreenOfDisplay(dpy);
 
-	if(DefaultDepthOfScreen(scr) != 8) {
-		fprintf(stderr, "%s: can work only with 8 bits/pixel\n", progname);
+	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;
@@ -463,24 +510,33 @@
 	xswa.background_pixel = BlackPixelOfScreen(scr);
 
 	win = XCreateWindow(dpy, RootWindowOfScreen(scr),
-	    xpos, ypos, width[DST], height[DST], 0, 
+	    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, 
+	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, 
+	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;
 
-	XMapWindow(dpy, win);
+	status = XMapWindow(dpy, win);
 
 	gcv.plane_mask = AllPlanes;
 	gcv.subwindow_mode = IncludeInferiors;
@@ -512,7 +568,7 @@
 	{
 		static char bitmap_data[] = { 0 };
 		static XColor col = { 0 };
-		Pixmap curs = XCreatePixmapFromBitmapData(dpy, 
+		Pixmap curs = XCreatePixmapFromBitmapData(dpy,
 			RootWindowOfScreen(scr), bitmap_data, 1, 1, 0, 0, 1);
 
 		when_button = XCreatePixmapCursor(dpy, curs, curs, &col, &col, 0, 0);
@@ -526,11 +582,22 @@
 
 	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]) {
@@ -567,6 +634,7 @@
 
 				case '+':
 				case '=':
+				case XK_KP_Add:
 					if(!yzoom_flag) ++magx;
 					if(!xzoom_flag) ++magy;
 					xzoom_flag = yzoom_flag = False;
@@ -575,6 +643,7 @@
 					break;
 
 				case '-':
+				case XK_KP_Subtract:
 					if(!yzoom_flag) --magx;
 					if(!xzoom_flag) --magy;
 					xzoom_flag = yzoom_flag = False;
@@ -585,6 +654,7 @@
 					break;
 
 				case XK_Left:
+				case XK_KP_Left:
 					if(flipxy)
 						if(flipx)
 							ygrab += scroll;
@@ -598,6 +668,7 @@
 					break;
 
 				case XK_Right:
+				case XK_KP_Right:
 					if(flipxy)
 						if(flipx)
 							ygrab -= scroll;
@@ -611,6 +682,7 @@
 					break;
 
 				case XK_Up:
+				case XK_KP_Up:
 					if(flipxy)
 						if(flipy)
 							xgrab -= scroll;
@@ -624,6 +696,7 @@
 					break;
 
 				case XK_Down:
+				case XK_KP_Down:
 					if(flipxy)
 						if(flipy)
 							xgrab += scroll;
@@ -666,12 +739,17 @@
 					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, 
+					XChangeProperty(dpy, win, XA_WM_NAME, XA_STRING, 8,
 						PropModeReplace,
 						(unsigned char *)title, strlen(title));
 					signal(SIGALRM, timeout_func);
@@ -717,6 +795,7 @@
 #endif
 				}
 				break;
+
 			}
 
 			/* trying XShmGetImage when part of the rect is
@@ -736,6 +815,7 @@
 
 			if(ygrab > HeightOfScreen(scr)-height[SRC])
 				ygrab = HeightOfScreen(scr)-height[SRC];
+
 		}
 
 #ifdef XSHM
@@ -753,63 +833,12 @@
 		}
 #endif
 
-		/* copy scaled lines from src to dst */
-		for(j = flipxy?width[SRC]:height[SRC]; --j >= 0; ) {
-			/* p1 point to begining of scanline j*magy in DST */
-			p1 = &ximage[DST]->data[ximage[DST]->xoffset +
-					j*magy*ximage[DST]->bytes_per_line ];
-			/* p2 point to begining of scanline j in SRC */
-			/* if flipy then line height[SRC]-1-j */
-			p2 = &ximage[SRC]->data[ximage[SRC]->xoffset +
-					(flipy?(height[SRC]-1-j):j)*ximage[SRC]->bytes_per_line ];
-
-			if(flipxy) {
-				int p2step = ximage[SRC]->bytes_per_line;
-				p2 = &ximage[SRC]->data[ximage[SRC]->xoffset + (flipy?j:(width[SRC]-1-j))];
-
-				if(flipx) {
-					p2 += p2step * (height[SRC]-1);
-					p2step = -p2step;
-				}
-
-				for(i = height[SRC]; --i >= 0;) {
-					c = *p1++ = *p2;
-					p2 += p2step;
-					for(k = magx; --k > 0; )
-						*p1++ = c;
-				}	
-			}
-			else if(flipx) {
-				p2 += width[SRC];
-				for(i = width[SRC]; --i >= 0;) {
-					c = *p1++ = *--p2;
-					for(k = magx; --k > 0; )
-						*p1++ = c;
-				}	
-			}
-			else {
-				for(i = width[SRC]; --i >= 0;) {
-					c = *p1++ = *p2++;
-					for(k = magx; --k > 0; )
-						*p1++ = c;
-				}	
-			}
-
-			/* p1 point to begining of scanline j*magy in DST */
-			p1 = &ximage[DST]->data[ximage[DST]->xoffset +
-										  j*magy*ximage[DST]->bytes_per_line ];
-			/* p2 points to begining of next line */
-			p2 = p1 + ximage[DST]->bytes_per_line;
-			/* duplicate that line as needed */
-			for(k = magy; --k > 0; ) {
-#ifdef BCOPY
-				bcopy(p1, p2, width[DST]);
-#else
-				memmove(p2, p1, width[DST]);
-#endif
-				p2 += ximage[DST]->bytes_per_line;
-			}
-		}
+		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);
@@ -825,7 +854,7 @@
 						flipx?"-":"", magx,
 						flipxy?" <=>":";",
 						flipy?"-":"", magy);
-			XChangeProperty(dpy, win, XA_WM_NAME, XA_STRING, 8, 
+			XChangeProperty(dpy, win, XA_WM_NAME, XA_STRING, 8,
 				PropModeReplace,
 				(unsigned char *)title, strlen(title));
 			set_title = False;
--- xzoom-0.3.orig/xzoom.man
+++ xzoom-0.3/xzoom.man
@@ -1,9 +1,9 @@
 .\" xzoom.man
 .\" Copyright Itai Nahshon
 .\"
-.TH XZOOM 1X
+.TH XZOOM 1x
 .SH NAME
-xzoom \- 
+xzoom \- magnify part of the screen, with fast updates
 .SH SYNOPSIS
 .B xzoom
 [ \-display \fIdisplayname\fP ] [ \-mag \fImag\fP [ \fImag\fP ] ]
@@ -18,7 +18,7 @@
 .TP 5
 .B \-mag \fImag\fP [ \fImag\fP ]
 What magnification to use. If two number arguments are supplied the
-first is used for X magniications and the second is used for Y magnification.
+first is used for X magnifications and the second is used for Y magnification.
 Magnification should be greater than 0.
 .TP 5
 .B \-x
@@ -85,6 +85,9 @@
 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
@@ -147,11 +150,6 @@
 display is not on the local host.
 .LP 5
 \(dg
-The Ximage data is accessed directly, in a way which may
-not be portable. Xzoom will not run with display depth other
-than 8 bits per pixel.
-.LP 5
-\(dg
 Xzoom is given with no warranty. It was tested only under
 Linux with Xfree86 release 3.1.2 (X11R6).
 .LP 5