summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:54 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:54 +0000
commit31f434e2df14612e3cf18fe45a6c161eb3c225ff (patch)
tree65d53468220245d1fcfa6a593680ea183cf239e3
R6.6 is the Xorg base-lineXORG-MAIN
-rw-r--r--CutPaste.c135
-rw-r--r--RootWin.c86
-rw-r--r--RootWin.h67
-rw-r--r--RootWinP.h60
-rw-r--r--Scale.c1044
-rw-r--r--Scale.h115
-rw-r--r--Scale.txt107
-rw-r--r--ScaleP.h104
-rw-r--r--Xmag.ad27
-rw-r--r--xmag.c1125
-rw-r--r--xmag.icon14
-rw-r--r--xmag.man98
12 files changed, 2982 insertions, 0 deletions
diff --git a/CutPaste.c b/CutPaste.c
new file mode 100644
index 0000000..a110744
--- /dev/null
+++ b/CutPaste.c
@@ -0,0 +1,135 @@
+/* $Xorg: CutPaste.c,v 1.4 2001/02/09 02:05:55 xorgcvs Exp $ */
+/*
+
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+/*
+ * Author: Davor Matic, MIT X Consortium
+ */
+
+#include <X11/IntrinsicP.h>
+#include <X11/Xmu/StdSel.h>
+#include <X11/Xmu/Atoms.h>
+#include <X11/Xatom.h>
+#include "ScaleP.h" /* This file should be part of the Scale widget */
+#include "Scale.h"
+#include <stdio.h>
+
+extern Pixmap SWGetPixmap();
+extern void SWAutoscale();
+
+/*ARGSUSED*/
+static Boolean
+ConvertSelection(w, selection, target, type, value, length, format)
+ Widget w;
+ Atom *selection, *target, *type;
+ XtPointer *value;
+ unsigned long *length;
+ int *format;
+{
+ Boolean success;
+
+ if (*target == XA_PIXMAP || *target == XA_BITMAP) {
+ ScaleWidget sw = (ScaleWidget) w;
+ Pixmap *pixmap = (Pixmap *) XtMalloc(sizeof(Pixmap));
+ *pixmap = XCreatePixmap(XtDisplay(w), XtWindow(w),
+ sw->scale.image->width,
+ sw->scale.image->height,
+ sw->scale.image->depth);
+ XPutImage(XtDisplay(w), *pixmap, sw->scale.gc, sw->scale.image,
+ 0, 0, 0, 0, sw->scale.image->width, sw->scale.image->height);
+ *type = XA_PIXMAP;
+ *value = (XtPointer) pixmap;
+ *length = 1;
+ *format = 32;
+ success = True;
+ } else {
+ /* Xt will always respond to selection requests for the TIMESTAMP
+ target, so we can pass a bogus time to XmuConvertStandardSelection.
+ In addition to the targets provided by XmuConvertStandardSelection,
+ Xt converts MULTIPLE, and we convert PIXMAP and BITMAP.
+ */
+ success = XmuConvertStandardSelection(w, (Time)0, selection, target,
+ type, (XPointer *)value, length,
+ format);
+ if (success && *target == XA_TARGETS(XtDisplay(w))) {
+ Atom* tmp;
+ tmp = (Atom *) XtRealloc(*value, (*length + 3) * sizeof(Atom));
+ tmp[(*length)++] = XInternAtom(XtDisplay(w), "MULTIPLE", False);
+ tmp[(*length)++] = XA_PIXMAP;
+ tmp[(*length)++] = XA_BITMAP;
+ *value = (XtPointer) tmp;
+ }
+ }
+ return success;
+}
+
+void SWGrabSelection(w, time)
+ Widget w;
+ Time time;
+{
+ (void) XtOwnSelection(w, XA_PRIMARY, time, ConvertSelection, NULL, NULL);
+}
+
+
+/*ARGSUSED*/
+static void
+SelectionCallback(w, client_data, selection, type, value, length, format)
+ Widget w;
+ XtPointer client_data; /* unused */
+ Atom *selection, *type;
+ XtPointer value;
+ unsigned long *length;
+ int *format;
+{
+
+ if (*type == XA_PIXMAP) {
+ Pixmap *pixmap;
+ XImage *image;
+ Window root;
+ int x, y;
+ unsigned int width, height, border_width, depth;
+
+ pixmap = (Pixmap *) value;
+ XGetGeometry(XtDisplay(w), *pixmap, &root, &x, &y,
+ &width, &height, &border_width, &depth);
+ image = XGetImage(XtDisplay(w), *pixmap, 0, 0, width, height,
+ AllPlanes, ZPixmap);
+ SWAutoscale(w);
+ SWSetImage(w, image);
+ XtFree(value);
+ XDestroyImage(image);
+ }
+}
+
+void SWRequestSelection(w, time)
+ Widget w;
+ Time time;
+{
+ XtGetSelectionValue(w, XA_PRIMARY, XA_PIXMAP, SelectionCallback, NULL,
+ time);
+}
diff --git a/RootWin.c b/RootWin.c
new file mode 100644
index 0000000..8a5127a
--- /dev/null
+++ b/RootWin.c
@@ -0,0 +1,86 @@
+/* $Xorg: RootWin.c,v 1.4 2001/02/09 02:05:55 xorgcvs Exp $ */
+/*
+
+Copyright 1990, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include "RootWinP.h"
+
+static void Realize();
+
+RootWindowClassRec rootWindowClassRec = {
+ { /* core fields */
+ /* superclass */ (WidgetClass) &widgetClassRec,
+ /* class_name */ "RootWindow",
+ /* widget_size */ sizeof(RootWindowRec),
+ /* class_initialize */ NULL,
+ /* class_part_initialize */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ NULL,
+ /* initialize_hook */ NULL,
+ /* realize */ Realize,
+ /* actions */ NULL,
+ /* num_actions */ 0,
+ /* resources */ NULL,
+ /* num_resources */ 0,
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ TRUE,
+ /* compress_enterleave */ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ NULL,
+ /* resize */ NULL,
+ /* expose */ NULL,
+ /* set_values */ NULL,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback_private */ NULL,
+ /* tm_table */ NULL,
+ /* query_geometry */ XtInheritQueryGeometry,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },
+ { /* rootWindow fields */
+ /* empty */ 0
+ }
+};
+
+WidgetClass rootWindowWidgetClass = (WidgetClass)&rootWindowClassRec;
+
+/*ARGSUSED*/
+static void Realize(w, value_mask, attributes)
+ Widget w;
+ XtValueMask *value_mask;
+ XSetWindowAttributes *attributes;
+{
+ w->core.window = RootWindowOfScreen(w->core.screen);
+}
diff --git a/RootWin.h b/RootWin.h
new file mode 100644
index 0000000..ae61794
--- /dev/null
+++ b/RootWin.h
@@ -0,0 +1,67 @@
+/* $Xorg: RootWin.h,v 1.4 2001/02/09 02:05:55 xorgcvs Exp $ */
+/*
+
+Copyright 1990, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+
+#ifndef _RootWindow_h
+#define _RootWindow_h
+
+/****************************************************************
+ *
+ * RootWindow widget
+ *
+ ****************************************************************/
+
+/* Resources:
+
+ Name Class RepType Default Value
+ ---- ----- ------- -------------
+ background Background Pixel XtDefaultBackground
+ border BorderColor Pixel XtDefaultForeground
+ borderWidth BorderWidth Dimension 1
+ destroyCallback Callback Pointer NULL
+ height Height Dimension 0
+ mappedWhenManaged MappedWhenManaged Boolean True
+ sensitive Sensitive Boolean True
+ width Width Dimension 0
+ x Position Position 0
+ y Position Position 0
+
+*/
+
+
+/* declare specific RootWindowWidget class and instance datatypes */
+
+typedef struct _RootWindowClassRec* RootWindowWidgetClass;
+typedef struct _RootWindowRec* RootWindowWidget;
+
+/* declare the class constant */
+
+extern WidgetClass rootWindowWidgetClass;
+
+#endif /* _RootWindow_h */
diff --git a/RootWinP.h b/RootWinP.h
new file mode 100644
index 0000000..363cdd9
--- /dev/null
+++ b/RootWinP.h
@@ -0,0 +1,60 @@
+/* $Xorg: RootWinP.h,v 1.4 2001/02/09 02:05:55 xorgcvs Exp $ */
+/*
+
+Copyright 1990, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+
+#ifndef _RootWindoP_h
+#define _RootWindoP_h
+
+#include "RootWin.h"
+/* include superclass private header file */
+#include <X11/CoreP.h>
+
+typedef struct {
+ int empty;
+} RootWindowClassPart;
+
+typedef struct _RootWindowClassRec {
+ CoreClassPart core_class;
+ RootWindowClassPart root_class;
+} RootWindowClassRec;
+
+extern RootWindowClassRec rootClassRec;
+
+typedef struct {
+ /* resources */
+ char* resource;
+ /* private state */
+} RootWindowPart;
+
+typedef struct _RootWindowRec {
+ CorePart core;
+ RootWindowPart root;
+} RootWindowRec;
+
+#endif /* _RootWindoP_h */
diff --git a/Scale.c b/Scale.c
new file mode 100644
index 0000000..05f4b6a
--- /dev/null
+++ b/Scale.c
@@ -0,0 +1,1044 @@
+/* $Xorg: Scale.c,v 1.4 2001/02/09 02:05:55 xorgcvs Exp $ */
+/*
+
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+/*
+ * Author: Davor Matic, MIT X Consortium
+ */
+
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/Xos.h>
+#include <X11/Xaw/XawInit.h>
+
+#include "ScaleP.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+
+#define myrint(x) floor(x + 0.5)
+
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h>
+#endif
+
+#if defined(ISC) && __STDC__ && !defined(ISC30)
+extern double atof(char *);
+#endif
+
+#define streq(a,b) (strcmp( (a), (b) ) == 0)
+#define min(x, y) (x > y ? y : x)
+#define max(x, y) (x < y ? y : x)
+
+#define DefaultBufferSize 1024
+#define DefaultScaleFactor NULL
+
+#define Offset(field) XtOffsetOf(ScaleRec, scale.field)
+
+static XtResource resources[] = {
+{XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
+ Offset(foreground_pixel), XtRString, (XtPointer) XtDefaultForeground},
+{XtNgravity, XtCGravity, XtRGravity, sizeof(XtGravity),
+ Offset(gravity), XtRImmediate, (XtPointer) "ForgetGravity"},
+{XtNinternalWidth, XtCWidth, XtRDimension, sizeof(Dimension),
+ Offset(internal_width), XtRImmediate, (XtPointer) 2},
+{XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension),
+ Offset(internal_height), XtRImmediate, (XtPointer) 2},
+{XtNresize, XtCResize, XtRBoolean, sizeof(Boolean),
+ Offset(resize), XtRImmediate, (XtPointer) True},
+{XtNautoscale, XtCAutoscale, XtRBoolean, sizeof(Boolean),
+ Offset(autoscale), XtRImmediate, (XtPointer) True},
+{XtNproportional, XtCProportional, XtRBoolean, sizeof(Boolean),
+ Offset(proportional), XtRImmediate, (XtPointer) True},
+{XtNscaleX, XtCScaleFactor, XtRString, sizeof(String),
+ Offset(scale_x_str), XtRImmediate, (XtPointer) DefaultScaleFactor},
+{XtNscaleY, XtCScaleFactor, XtRString, sizeof(String),
+ Offset(scale_y_str), XtRImmediate, (XtPointer) DefaultScaleFactor},
+{XtNaspectRatio, XtCAspectRatio, XtRString, sizeof(String),
+ Offset(aspect_ratio_str), XtRImmediate, (XtPointer) "1.0"},
+{XtNprecision, XtCPrecision, XtRString, sizeof(String),
+ Offset(precision_str), XtRImmediate, (XtPointer) "0.001"},
+{XtNimage, XtCImage, XtRImage, sizeof(XImage*),
+ Offset(image), XtRImmediate, (XtPointer) NULL},
+{XtNpasteBuffer, XtCPasteBuffer, XtRBoolean, sizeof(Boolean),
+ Offset(paste_buffer), XtRImmediate, (XtPointer) False},
+{XtNbufferSize, XtCBufferSize, XtRCardinal, sizeof(Cardinal),
+ Offset(buffer_size), XtRImmediate, (XtPointer) DefaultBufferSize},
+{XtNuserData, XtCuserData, XtRuserData, sizeof(XtPointer),
+ Offset(userData), XtRImmediate, (XtPointer) NULL},
+{ XtNvisual, XtCvisual, XtRVisual, sizeof(Visual*),
+ Offset(visual), XtRImmediate, CopyFromParent}
+};
+
+#undef Offset
+
+static void ClassInitialize();
+static void Initialize();
+static void Realize();
+static void Redisplay();
+static void Resize();
+static void Destroy();
+static Boolean SetValues();
+
+void SWUnscale();
+void SWAutoscale();
+void SWInitialSize();
+void RequestSelection();
+void GrabSelection();
+
+static XtActionsRec actions[] =
+{
+{"unscale", SWUnscale},
+{"autoscale", SWAutoscale},
+{"initial-size", SWInitialSize},
+{"paste", RequestSelection},
+{"cut", GrabSelection}
+};
+
+static char translations[] =
+"\
+ <Key>u: unscale()\n\
+ <Key>a: autoscale()\n\
+ <Key>i: initial-size()\n\
+";
+
+ScaleClassRec scaleClassRec = {
+{ /* core fields */
+ /* superclass */ (WidgetClass) &simpleClassRec,
+ /* class_name */ "Scale",
+ /* widget_size */ sizeof(ScaleRec),
+ /* class_initialize */ ClassInitialize,
+ /* class_part_initialize */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ Realize,
+ /* actions */ actions,
+ /* num_actions */ XtNumber(actions),
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ XtExposeCompressMaximal|
+ XtExposeGraphicsExposeMerged,
+ /* compress_enterleave */ TRUE,
+ /* visible_interest */ TRUE,
+ /* destroy */ Destroy,
+ /* resize */ Resize,
+ /* expose */ Redisplay,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback_private */ NULL,
+ /* tm_table */ translations,
+ /* query_geometry */ XtInheritQueryGeometry,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },
+ {
+ /* change_sensitive */ XtInheritChangeSensitive,
+ }
+};
+
+WidgetClass scaleWidgetClass = (WidgetClass) &scaleClassRec;
+
+
+
+/*
+ * Private Procedures
+ */
+
+
+static void ClassInitialize()
+{
+}
+
+
+
+void GetGC(sw)
+ ScaleWidget sw;
+{
+ XGCValues values;
+
+ values.foreground = sw->scale.foreground_pixel;
+ values.background = sw->core.background_pixel;
+ values.function = GXcopy;
+
+ sw->scale.gc = XtGetGC((Widget) sw,
+ GCForeground |
+ GCBackground |
+ GCFunction,
+ &values);
+}
+
+
+
+void Proportional();
+
+void GetInitialScaleValues(sw)
+ ScaleWidget sw;
+{
+ if (sw->scale.proportional) {
+ sw->scale.scale_x = sw->scale.scale_y =
+ ((sw->scale.aspect_ratio > 1.0) ?
+ sw->scale.aspect_ratio : 1.0 / sw->scale.aspect_ratio) *
+ (sw->scale.precision > 1.0 ?
+ sw->scale.precision : 1.0);
+ Proportional(sw); /* need to cut them down to proper values */
+ }
+ else
+ sw->scale.scale_x = sw->scale.scale_y = 1.0;
+}
+
+
+
+void GetRectangleBuffer(sw, buffer_size)
+ ScaleWidget sw;
+ Cardinal buffer_size;
+ /*
+ * This procedure will realloc a new rectangles buffer.
+ * If the new buffer size is less than nrectangles, some
+ * information will be lost.
+ */
+{
+ if (buffer_size == 0) {
+ buffer_size = DefaultBufferSize;
+ XtWarning("buffer size has to be a positive number greater than zero");
+ }
+ sw->scale.rectangles = (XRectangle *)
+ XtRealloc((char *) sw->scale.rectangles,
+ buffer_size * sizeof(XRectangle));
+ sw->scale.buffer_size = buffer_size;
+}
+
+
+
+/* ARGSUSED */
+static void Initialize(request, new, args, num_args)
+ Widget request, new;
+ ArgList args;
+ Cardinal *num_args;
+{
+ ScaleWidget new_sw = (ScaleWidget) new;
+
+ new_sw->scale.table.x = (Position *) NULL;
+ new_sw->scale.table.y = (Position *) NULL;
+ new_sw->scale.table.width = (Dimension *) NULL;
+ new_sw->scale.table.height = (Dimension *) NULL;
+
+ new_sw->scale.nrectangles = 0;
+ new_sw->scale.rectangles = (XRectangle *) NULL;
+
+ GetRectangleBuffer(new_sw, new_sw->scale.buffer_size);
+
+ GetGC(new_sw);
+
+ if (new_sw->scale.image != NULL) {
+ if (new_sw->core.width == 0)
+ new_sw->core.width =
+ new_sw->scale.image->width + 2 * new_sw->scale.internal_width;
+ if (new_sw->core.height == 0)
+ new_sw->core.height =
+ new_sw->scale.image->height + 2 *new_sw->scale.internal_height;
+ }
+ else {
+ if (new_sw->core.width == 0)
+ new_sw->core.width = 1 + 2 * new_sw->scale.internal_width;
+ if (new_sw->core.height == 0)
+ new_sw->core.height = 1 + 2 * new_sw->scale.internal_height;
+ new_sw->scale.image = XCreateImage(XtDisplay(new),
+ DefaultVisual(XtDisplay(new),
+ DefaultScreen(XtDisplay(new))),
+ 1, XYBitmap, 0,
+ XtCalloc(1, sizeof(char)),
+ 1, 1, 8, 0);
+ }
+
+ if ((new_sw->scale.aspect_ratio =
+ atof(new_sw->scale.aspect_ratio_str)) < 0.0) {
+ new_sw->scale.aspect_ratio = 1.0;
+ XtWarning("AspectRatio has to be a positive number. (forced to 1.0)");
+ }
+
+ if ((new_sw->scale.precision =
+ atof(new_sw->scale.precision_str)) < 0.0) {
+ new_sw->scale.precision = 0.001;
+ XtWarning("Precision has to be a positive number. (forced to 0.001)");
+ }
+
+ if (new_sw->scale.scale_x_str == DefaultScaleFactor
+ ||
+ new_sw->scale.scale_y_str == DefaultScaleFactor)
+ GetInitialScaleValues(new_sw);
+ else {
+ if ((new_sw->scale.scale_x =
+ atof(new_sw->scale.scale_x_str)) < 0.0) {
+ new_sw->scale.scale_x = 1.0;
+ XtWarning("ScaleValue has to be a positive number. (forced to 1.0)");
+ }
+ if ((new_sw->scale.scale_y =
+ atof(new_sw->scale.scale_y_str)) < 0.0) {
+ new_sw->scale.scale_y = 1.0;
+ XtWarning("ScaleValue has to be a positive number. (forced to 1.0)");
+ }
+ }
+}
+
+
+
+void BuildTable(sw)
+ ScaleWidget sw;
+ /*
+ * This procedure builds scaling table for image in the scale struct
+ * Requires image, scale_x and scale_y to be set properly
+ */
+{
+ Position x, y;
+
+ XtFree((char *) sw->scale.table.x);
+ XtFree((char *) sw->scale.table.y);
+ XtFree((char *) sw->scale.table.width);
+ XtFree((char *) sw->scale.table.height);
+ sw->scale.table.x =
+ (Position *) XtMalloc(sizeof(Position) * sw->scale.image->width);
+ sw->scale.table.y =
+ (Position *) XtMalloc(sizeof(Position) * sw->scale.image->height);
+ sw->scale.table.width =
+ (Dimension *) XtMalloc(sizeof(Dimension) * sw->scale.image->width);
+ sw->scale.table.height =
+ (Dimension *) XtMalloc(sizeof(Dimension) * sw->scale.image->height);
+
+ /* Build the scaling table */
+ for (x = 0; x < sw->scale.image->width; x++) {
+ sw->scale.table.x[(int) x] = (Position) myrint(sw->scale.scale_x * x);
+ sw->scale.table.width[(int) x] = (Dimension)
+ myrint(sw->scale.scale_x *(x + 1)) - myrint(sw->scale.scale_x * x);
+ }
+ for (y = 0; y < sw->scale.image->height; y++) {
+ sw->scale.table.y[(int) y] = (Position) myrint(sw->scale.scale_y * y);
+ sw->scale.table.height[(int) y] = (Dimension)
+ myrint(sw->scale.scale_y *(y + 1)) - myrint(sw->scale.scale_y * y);
+ }
+}
+
+
+
+void FlushRectangles(sw, drawable, gc)
+ ScaleWidget sw;
+ Drawable drawable;
+ GC gc;
+{
+ XFillRectangles(XtDisplay(sw), drawable, gc,
+ sw->scale.rectangles, sw->scale.nrectangles);
+
+ sw->scale.nrectangles = 0;
+}
+
+
+
+void FillRectangle(sw, drawable, gc, x, y, width, height)
+ ScaleWidget sw;
+ Drawable drawable;
+ GC gc;
+ Position x, y;
+ Dimension width, height;
+{
+
+ if (sw->scale.nrectangles == sw->scale.buffer_size)
+ FlushRectangles(sw, drawable, gc);
+
+ sw->scale.rectangles[(int) sw->scale.nrectangles].x = x;
+ sw->scale.rectangles[(int) sw->scale.nrectangles].y = y;
+ sw->scale.rectangles[(int) sw->scale.nrectangles].width = width;
+ sw->scale.rectangles[(int) sw->scale.nrectangles].height = height;
+
+ ++sw->scale.nrectangles;
+}
+
+
+
+void ScaleImage(sw, drawable, img_x, img_y, dst_x, dst_y, img_width,img_height)
+ ScaleWidget sw;
+ Drawable drawable;
+ Position img_x, img_y;
+ Position dst_x, dst_y;
+ Dimension img_width, img_height;
+ /*
+ * This procedure scales image into the specified drawable
+ * It assumes scaling table was already built
+ */
+{
+ GC gc;
+ XGCValues gcv;
+ Position x, y;
+ Pixel pixel;
+
+ /* Clip the img coordinates */
+ img_x = min(max(img_x, 0), (Position) sw->scale.image->width - 1);
+ img_y = min(max(img_y, 0), (Position) sw->scale.image->height - 1);
+ img_width =
+ min(img_width, (Dimension)(sw->scale.image->width - (Dimension)img_x));
+ img_height =
+ min(img_height, (Dimension)(sw->scale.image->height - (Dimension)img_y));
+
+ if (sw->scale.scale_x == 1.0 && sw->scale.scale_y == 1.0)
+ XPutImage(XtDisplay(sw), drawable, sw->scale.gc, sw->scale.image,
+ img_x, img_y, dst_x, dst_y,
+ img_width, img_height);
+ else {
+ dst_x = dst_x - sw->scale.table.x[(int) img_x];
+ dst_y = dst_y - sw->scale.table.y[(int) img_y];
+
+ gc = XCreateGC(XtDisplay(sw), drawable, 0, NULL);
+
+ gcv.function = GXcopy;
+ XChangeGC(XtDisplay(sw), gc, GCFunction, &gcv);
+
+ /* make sure gc knows the right background */
+ gcv.background = sw->core.background_pixel;
+ XChangeGC(XtDisplay(sw), gc, GCBackground, &gcv);
+
+ /* Set the background of drawable. If the most frequent color
+ is the background color it can speed up scaling process. */
+ gcv.foreground = gcv.background;
+ XChangeGC(XtDisplay(sw), gc, GCForeground, &gcv);
+ XFillRectangle(XtDisplay(sw), drawable, gc,
+ sw->scale.table.x[(int) img_x] + dst_x,
+ sw->scale.table.y[(int) img_y] + dst_y,
+ sw->scale.table.x[(int) img_x + img_width - 1] -
+ sw->scale.table.x[(int) img_x],
+ sw->scale.table.y[(int) img_y + img_height - 1] -
+ sw->scale.table.y[(int) img_y]);
+
+ if (sw->scale.image->format == XYBitmap) {
+ for (x = img_x; x < img_x + (Position)img_width; x++)
+ for (y = img_y; y < img_y + (Position)img_height; y++) {
+ pixel = XGetPixel(sw->scale.image, x, y);
+ if (pixel) /* Do not draw background */
+ FillRectangle(sw, drawable, sw->scale.gc,
+ sw->scale.table.x[(int) x] + dst_x,
+ sw->scale.table.y[(int) y] + dst_y,
+ sw->scale.table.width[(int) x],
+ sw->scale.table.height[(int) y]);
+ }
+ FlushRectangles(sw, drawable, sw->scale.gc);
+ }
+ else {
+ for (x = img_x; x < img_x + (Position)img_width; x++)
+ for (y = img_y; y < img_y + (Position)img_height; y++) {
+ pixel = XGetPixel(sw->scale.image, x, y);
+ if (pixel != gcv.background) { /* Do not draw background */
+ if (gcv.foreground != pixel) { /* Change fg to pixel */
+ gcv.foreground = pixel;
+ XChangeGC(XtDisplay(sw), gc, GCForeground, &gcv);
+ }
+ XFillRectangle(XtDisplay(sw), drawable, gc,
+ sw->scale.table.x[(int) x] + dst_x,
+ sw->scale.table.y[(int) y] + dst_y,
+ sw->scale.table.width[(int) x],
+ sw->scale.table.height[(int) y]);
+ }
+ }
+ }
+ XFreeGC(XtDisplay(sw), gc);
+ }
+}
+
+
+
+int FindPixel(sw, x, y, img_x, img_y, img_pixel)
+ ScaleWidget sw;
+ Position x, y; /* (x,y) == (0,0) where image starts in sw window*/
+ Position *img_x, *img_y;
+ Pixel *img_pixel;
+{
+ if (*img_x < 0 || *img_x >= sw->scale.image->width
+ ||
+ *img_y < 0 || *img_y >= sw->scale.image->height)
+ return (-1);
+
+ if (sw->scale.table.x[(int) *img_x] >= x) {
+ --*img_x;
+ return FindPixel(sw, x, y, img_x, img_y, img_pixel);
+ }
+ if (sw->scale.table.x[(int) *img_x] +
+ (Position)sw->scale.table.width[(int) *img_x] < x) {
+ ++*img_x;
+ return FindPixel(sw, x, y, img_x, img_y, img_pixel);
+ }
+ if (sw->scale.table.y[(int) *img_y] >= y) {
+ --*img_y;
+ return FindPixel(sw, x, y, img_x, img_y, img_pixel);
+ }
+ if (sw->scale.table.y[(int) *img_y] +
+ (Position)sw->scale.table.height[(int) *img_y] < y) {
+ ++*img_y;
+ return FindPixel(sw, x, y, img_x, img_y, img_pixel);
+ }
+
+ *img_pixel = XGetPixel(sw->scale.image, *img_x, *img_y);
+
+ return (0);
+}
+
+
+
+int SWGetImagePixel(w, x, y, img_x, img_y, img_pixel)
+ Widget w;
+ Position x, y;
+ Position *img_x, *img_y;
+ Pixel *img_pixel;
+{
+ ScaleWidget sw = (ScaleWidget) w;
+
+ x -= sw->scale.x;
+ y -= sw->scale.y;
+
+ *img_x = (Position) floor(x / sw->scale.scale_x);
+ *img_y = (Position) floor(y / sw->scale.scale_y);
+
+ return FindPixel(sw, x, y, img_x, img_y, img_pixel);
+}
+
+
+
+/* ARGSUSED */
+static void Redisplay(w, event, region)
+ Widget w;
+ XEvent *event;
+ Region region;
+{
+ ScaleWidget sw = (ScaleWidget) w;
+ Position x, y, img_x, img_y;
+ Dimension width, height;
+
+ if (event->type == Expose) {
+
+ if (event->xexpose.x < sw->scale.x) {
+ x = 0;
+ width = event->xexpose.width -
+ (sw->scale.x - event->xexpose.x);
+ }
+ else {
+ x = event->xexpose.x - sw->scale.x;
+ width = event->xexpose.width;
+ }
+
+ if (event->xexpose.y < sw->scale.y) {
+ y = 0;
+ height = event->xexpose.height -
+ (sw->scale.y - event->xexpose.y);
+ }
+ else {
+ y = event->xexpose.y - sw->scale.y;
+ height = event->xexpose.height;
+ }
+
+ img_x = min(max((Position) floor((float) x
+ / (float) sw->scale.scale_x), 0),
+ (Position) sw->scale.image->width - 1);
+
+ img_y = min(max((Position) floor((float) y
+ / (float) sw->scale.scale_y), 0),
+ (Position) sw->scale.image->height - 1);
+
+ if (sw->core.visible) {
+ ScaleImage(sw, XtWindow(w),
+ img_x, img_y,
+ sw->scale.x + sw->scale.table.x[(int) img_x],
+ sw->scale.y + sw->scale.table.y[(int) img_y],
+ (Dimension) ceil((float) width
+ / sw->scale.scale_x) + 1,
+ (Dimension) ceil((float) height
+ / sw->scale.scale_y) + 1);
+ }
+ }
+}
+
+
+
+void TryResize(sw)
+ ScaleWidget sw;
+{
+ Dimension width, height;
+ XtGeometryResult result;
+
+ width = (Dimension)
+ floor(sw->scale.image->width * sw->scale.scale_x)
+ + 2 * sw->scale.internal_width;
+ height = (Dimension)
+ floor(sw->scale.image->height * sw->scale.scale_y)
+ + 2 * sw->scale.internal_height;
+
+ while ((result =
+/* SUPPRESS 530 */XtMakeResizeRequest((Widget)sw,width,height,&width,&height))
+ == XtGeometryAlmost);
+
+ if (result != XtGeometryNo) {
+ sw->core.width = width;
+ sw->core.height = height;
+ }
+}
+
+
+
+void Precision(sw)
+ ScaleWidget sw;
+{
+ if (sw->scale.scale_x != 1.0)
+ sw->scale.scale_x = floor(sw->scale.scale_x / sw->scale.precision)
+ * sw->scale.precision;
+
+ if (sw->scale.scale_y != 1.0)
+ sw->scale.scale_y = floor(sw->scale.scale_y / sw->scale.precision)
+ * sw->scale.precision;
+}
+
+
+
+void Proportional(sw)
+ ScaleWidget sw;
+{
+ float scale_x, scale_y;
+
+ scale_x = sw->scale.scale_y / sw->scale.aspect_ratio;
+ scale_y = sw->scale.scale_x * sw->scale.aspect_ratio;
+
+ if (scale_x <= sw->scale.scale_x && scale_y <= sw->scale.scale_y) {
+ if (scale_x > scale_y)
+ sw->scale.scale_x = scale_x;
+ else
+ sw->scale.scale_y = scale_y;
+ }
+ else if (scale_x <= sw->scale.scale_x)
+ sw->scale.scale_x = scale_x;
+ else if (scale_y <= sw->scale.scale_y)
+ sw->scale.scale_y = scale_y;
+ else {
+ float x_ratio, y_ratio;
+
+ x_ratio = scale_x / sw->scale.scale_x;
+ y_ratio = scale_y / sw->scale.scale_y;
+
+ if (x_ratio < y_ratio)
+ sw->scale.scale_y /= x_ratio;
+ else
+ sw->scale.scale_x /= y_ratio;
+ }
+
+ if (fabs(sw->scale.scale_x / sw->scale.scale_y * sw->scale.aspect_ratio
+ - 1.0) > sw->scale.precision)
+ XtWarning("can not preserve aspect ratio");
+}
+
+
+
+void GetScaledSize(sw)
+ ScaleWidget sw;
+{
+ sw->scale.width = (Dimension)
+ max(myrint(sw->scale.scale_x * sw->scale.image->width), 1);
+ sw->scale.height = (Dimension)
+ max(myrint(sw->scale.scale_y * sw->scale.image->height), 1);
+}
+
+
+
+void GetScaleValues(sw)
+ ScaleWidget sw;
+{
+ /*
+ * Make sure to subtract internal width and height.
+ */
+
+ sw->scale.scale_x =
+ (float) max((int)(sw->core.width - 2 * sw->scale.internal_width), 1)
+ / (float) sw->scale.image->width;
+
+ sw->scale.scale_y =
+ (float) max((int)(sw->core.height - 2 * sw->scale.internal_height), 1)
+ / (float) sw->scale.image->height;
+}
+
+
+
+void Unscale(sw)
+ ScaleWidget sw;
+{
+ sw->scale.scale_x = sw->scale.scale_y = 1.0;
+
+ GetScaledSize(sw);
+
+ BuildTable(sw);
+}
+
+
+
+void Autoscale(sw)
+ ScaleWidget sw;
+{
+ GetScaleValues(sw);
+
+ if (sw->scale.proportional) Proportional(sw);
+
+ Precision(sw);
+
+ GetScaledSize(sw);
+
+ BuildTable(sw);
+}
+
+
+
+void PositionImage(sw)
+ ScaleWidget sw;
+{
+ /*
+ * Set as if for ForgegGravity (that is center the image)
+ */
+ sw->scale.x = (Position)
+ (sw->core.width - sw->scale.width) / 2;
+ sw->scale.y = (Position)
+ (sw->core.height - sw->scale.height) / 2;
+
+/*****
+ if (sw->scale.gravity & WestGravity) {
+ }
+ if (sw->scale.gravity & EastGravity) {
+ }
+ if (sw->scale.gravity & NorthGravity) {
+ }
+ if (sw->scale.gravity & SouthGravity) {
+ }
+*****/
+}
+
+
+
+static void Resize(w)
+ Widget w;
+{
+ ScaleWidget sw = (ScaleWidget) w;
+
+ if (sw->scale.autoscale) Autoscale(sw);
+
+ PositionImage(sw);
+}
+
+
+
+static void Realize(wid, vmask, attr)
+ Widget wid;
+ Mask *vmask;
+ XSetWindowAttributes *attr;
+{
+ ScaleWidget sw = (ScaleWidget) wid;
+ XtCreateWindow(wid, (unsigned int) InputOutput,
+ (Visual *) sw->scale.visual, *vmask, attr);
+}
+
+
+
+static void Destroy(w)
+ Widget w;
+{
+ ScaleWidget sw = (ScaleWidget) w;
+
+ XtFree((char *) sw->scale.table.x);
+ XtFree((char *) sw->scale.table.y);
+ XtFree((char *) sw->scale.table.width);
+ XtFree((char *) sw->scale.table.height);
+
+ XtFree((char *) sw->scale.rectangles);
+
+ XtReleaseGC(w, sw->scale.gc);
+
+ XDestroyImage(sw->scale.image);
+}
+
+
+
+/* ARGSUSED */
+static Boolean SetValues(current, request, new, args, num_args)
+ Widget current, request, new;
+ ArgList args;
+ Cardinal *num_args;
+{
+ ScaleWidget cur_sw = (ScaleWidget) current;
+ /* ScaleWidget req_sw = (ScaleWidget) request; */
+ ScaleWidget new_sw = (ScaleWidget) new;
+ Boolean redisplay = False;
+ int i;
+
+ for (i = 0; i < *num_args; i++) {
+ if (streq(XtNbackground, args[i].name)) {
+ XSetBackground(XtDisplay(new), new_sw->scale.gc,
+ new_sw->core.background_pixel);
+ }
+ if (streq(XtNforeground, args[i].name)) {
+ XSetForeground(XtDisplay(new), new_sw->scale.gc,
+ new_sw->scale.foreground_pixel);
+ }
+ if (streq(XtNimage, args[i].name)) {
+ XDestroyImage(cur_sw->scale.image);
+ if (new_sw->scale.image == NULL)
+ new_sw->scale.image = XCreateImage(XtDisplay(new),
+ DefaultVisual(XtDisplay(new),
+ DefaultScreen(XtDisplay(new))),
+ 1, XYBitmap, 0,
+ XtCalloc(1, sizeof(char)),
+ 1, 1, 8, 0);
+ else
+ new_sw->scale.image =
+ XSubImage(new_sw->scale.image,
+ 0, 0,
+ new_sw->scale.image->width,
+ new_sw->scale.image->height);
+
+ if (new_sw->scale.resize)
+ TryResize(new_sw);
+ if (new_sw->scale.autoscale)
+ Autoscale(new_sw);
+ else {
+ GetScaledSize(new_sw);
+ BuildTable(new_sw);
+ }
+ PositionImage(new_sw);
+ redisplay = True;
+ }
+
+ if (streq(XtNuserData, args[i].name))
+ new_sw->scale.userData = (XtPointer)args[i].value;
+
+ if (streq(XtNbufferSize, args[i].name)) {
+ if (new_sw->scale.buffer_size != cur_sw->scale.buffer_size) {
+ GetRectangleBuffer(new_sw, new_sw->scale.buffer_size);
+ }
+ }
+
+ if (streq(XtNaspectRatio, args[i].name)) {
+ if ((new_sw->scale.aspect_ratio =
+ atof(new_sw->scale.aspect_ratio_str)) < 0.0) {
+ new_sw->scale.aspect_ratio = cur_sw->scale.aspect_ratio;
+ XtWarning("AspectRatio has to be a positive number.");
+ }
+ else if (new_sw->scale.aspect_ratio != cur_sw->scale.aspect_ratio){
+ if (new_sw->scale.proportional) {
+ Proportional(new_sw);
+ Precision(new_sw);
+ GetScaledSize(new_sw);
+ BuildTable(new_sw);
+ PositionImage(new_sw);
+ redisplay = True;
+ }
+ }
+ }
+
+ if (streq(XtNproportional, args[i].name)) {
+ if (new_sw->scale.proportional != cur_sw->scale.proportional) {
+ if (new_sw->scale.proportional) Proportional(new_sw);
+ Precision(new_sw);
+ GetScaledSize(new_sw);
+ BuildTable(new_sw);
+ PositionImage(new_sw);
+ redisplay = True;
+ }
+ }
+
+ if (streq(XtNscaleX, args[i].name)
+ ||
+ streq(XtNscaleY, args[i].name)) {
+ if (new_sw->scale.scale_x_str == DefaultScaleFactor
+ ||
+ new_sw->scale.scale_y_str == DefaultScaleFactor)
+ GetInitialScaleValues(new_sw);
+ else {
+ if ((new_sw->scale.scale_x =
+ atof(new_sw->scale.scale_x_str)) < 0.0) {
+ new_sw->scale.scale_x = cur_sw->scale.scale_x;
+ XtWarning("ScaleValue has to be a positive number.");
+ }
+ if ((new_sw->scale.scale_y =
+ atof(new_sw->scale.scale_y_str)) < 0.0) {
+ new_sw->scale.scale_y = cur_sw->scale.scale_y;
+ XtWarning("ScaleValue has to be a positive number.");
+ }
+ }
+ if (new_sw->scale.scale_x != cur_sw->scale.scale_x
+ ||
+ new_sw->scale.scale_y != cur_sw->scale.scale_y) {
+
+ /*?*?*?*?*?*?*?*?*?*?*?*?*?*?**?*?*?*?*?*?*?*?*?***?*/
+ fprintf(stderr, "================>>%f %f\n",
+ new_sw->scale.scale_x, new_sw->scale.scale_y);
+
+ if (new_sw->scale.proportional) Proportional(new_sw);
+ Precision(new_sw);
+ if (new_sw->scale.resize)
+ TryResize(new_sw);
+ GetScaledSize(new_sw);
+ BuildTable(new_sw);
+ PositionImage(new_sw);
+ redisplay = True;
+ }
+ }
+
+ if (streq(XtNprecision, args[i].name)) {
+ if ((new_sw->scale.precision =
+ atof(new_sw->scale.precision_str)) < 0.0) {
+ new_sw->scale.precision = cur_sw->scale.precision;
+ XtWarning("Precision has to be a positive number.");
+ }
+ if (new_sw->scale.precision != cur_sw->scale.precision) {
+ if (new_sw->scale.proportional) Proportional(new_sw);
+ Precision(new_sw);
+ GetScaledSize(new_sw);
+ BuildTable(new_sw);
+ PositionImage(new_sw);
+ redisplay = True;
+ }
+ }
+ }
+ return(redisplay);
+}
+
+
+
+void SWUnscale(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ ScaleWidget sw = (ScaleWidget) w;
+
+ Unscale(sw);
+ PositionImage(sw);
+ XClearArea(XtDisplay(w), XtWindow(w), 0, 0, 0, 0, True);
+}
+
+
+
+void SWAutoscale(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ ScaleWidget sw = (ScaleWidget) w;
+
+ Autoscale(sw);
+ PositionImage(sw);
+ XClearArea(XtDisplay(w), XtWindow(w), 0, 0, 0, 0, True);
+}
+
+
+
+void SWInitialSize(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ ScaleWidget sw = (ScaleWidget) w;
+
+ GetInitialScaleValues(sw);
+
+ if (sw->scale.proportional) Proportional(sw);
+ Precision(sw);
+ if (sw->scale.resize)
+ TryResize(sw);
+ GetScaledSize(sw);
+ BuildTable(sw);
+ PositionImage(sw);
+ XClearArea(XtDisplay(w), XtWindow(w), 0, 0, 0, 0, True);
+}
+
+
+
+void SWSetImage(w, image)
+ Widget w;
+ XImage *image;
+{
+ int n;
+ Arg wargs[2];
+
+ n = 0;
+ XtSetArg(wargs[n], XtNimage, (XtArgVal) image); n++;
+ XtSetValues(w, wargs, n);
+}
+
+
+
+extern void SWRequestSelection();
+
+void RequestSelection(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ SWRequestSelection(w, event->xbutton.time);
+}
+
+
+
+extern void SWGrabSelection();
+
+void GrabSelection(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ SWGrabSelection(w, event->xbutton.time);
+}
+
+
+
+Pixmap SWGetPixmap(w)
+ Widget w;
+{
+ ScaleWidget sw = (ScaleWidget) w;
+ Pixmap pixmap;
+
+ pixmap = XCreatePixmap(XtDisplay(w), XtWindow(w),
+ sw->scale.width,
+ sw->scale.height,
+ sw->scale.image->depth);
+ ScaleImage(sw, pixmap,
+ 0, 0, 0, 0,
+ (Dimension) sw->scale.image->width,
+ (Dimension) sw->scale.image->height);
+
+ return(pixmap);
+}
diff --git a/Scale.h b/Scale.h
new file mode 100644
index 0000000..75be7f6
--- /dev/null
+++ b/Scale.h
@@ -0,0 +1,115 @@
+/* $Xorg: Scale.h,v 1.4 2001/02/09 02:05:55 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+#ifndef _XawScale_h
+#define _XawScale_h
+
+/***********************************************************************
+ *
+ * Scale Widget
+ *
+ ***********************************************************************/
+
+#include <X11/Xaw/Simple.h>
+#include <X11/Xmu/Converters.h>
+
+/* Resources:
+
+ All the SimpleWidget resources plus...
+ Name Class RepType Default Value
+ ---- ----- ------- -------------
+ aspectRatio AspectRatio Float 1.0
+ autoscale Autoscale Boolean True
+ bufferSize BufferSize Cardinal 1024
+ foreground Foreground Pixel XtDefaultForeground
+ gravity Gravity XtGravity ForgetGravity
+ image Image XImage* NULL
+ internalHeight Height Dimension 2
+ internalWidth Width Dimension 2
+ pasteBuffer PasteBuffer Boolean False
+ precision Precision Float 0.001
+ proportional Proportional Boolean False
+ resize Resize Boolean True
+ scaleX ScaleValue Float 1.0
+ scaleY ScaleValue Float 1.0
+ userData UserData XtPointer NULL
+ visual Visual Visual* CopyFromParent
+*/
+
+#ifndef _XtStringDefs_h_
+#define XtNforeground "foreground"
+#define XtNinternalWidth "internalWidth"
+#define XtNinternalHeight "internalHeight"
+#define XtNresize "resize"
+#define XtCResize "Resize"
+#endif
+
+#define XtNaspectRatio "aspectRatio"
+#define XtCAspectRatio "AspectRatio"
+#define XtNbufferSize "bufferSize"
+#define XtCBufferSize "BufferSize"
+#define XtNscaleX "scaleX"
+#define XtNscaleY "scaleY"
+#define XtCScaleFactor "ScaleFactor"
+#define XtNautoscale "autoscale"
+#define XtCAutoscale "Autoscale"
+#define XtNproportional "proportional"
+#define XtCProportional "Proportional"
+#define XtNprecision "precision"
+#define XtCPrecision "Precision"
+#define XtNgravity "gravity"
+#define XtCGravity "Gravity"
+#define XtNpasteBuffer "pasteBuffer"
+#define XtCPasteBuffer "PasteBuffer"
+#define XtNimage "image"
+#define XtCImage "image"
+#define XtNexponent "exponent"
+#define XtCExponent "Exponent"
+#define XtNuserData "userData"
+#define XtCuserData "UserData"
+#define XtRuserData "UserData"
+#define XtRImage "Image"
+#ifndef XtNvisual
+#define XtNvisual "visual"
+#endif
+#define XtCvisual "Visual"
+#define XtRvisual "Visual"
+
+extern void AWSetImage();
+extern void SWSetImage();
+
+/* Class record constants */
+
+extern WidgetClass scaleWidgetClass;
+
+typedef struct _ScaleClassRec *ScaleWidgetClass;
+typedef struct _ScaleRec *ScaleWidget;
+
+#endif /* _XawScale_h */
+
diff --git a/Scale.txt b/Scale.txt
new file mode 100644
index 0000000..1db99e8
--- /dev/null
+++ b/Scale.txt
@@ -0,0 +1,107 @@
+
+Scale Widget
+
+Header file Scale.h
+Class scaleWidgetClass
+Class Name Scale
+Superclass Simple
+
+The Scale widget is an immutable image displayed within a rectangular
+region of the screen. When the widget is selected, it is highlighted,
+and an application callback routine is invoked. When the
+widget is resized the image can be autoscaled to fit new size of the
+widget window. The widget can also cut and paste its contents.
+
+When creating a Scale widget instance, the following resources are
+retreived from the argument list or from the resource database:
+
+All the Simple Widget resources plus...
+-------------------------------------------------------------------------------
+ Name Cass Type Default Value
+-------------------------------------------------------------------------------
+ aspectRatio AspectRatio Float 1.0
+ autoscale Autoscale Boolean True
+ bufferSize BufferSize Cardinal 1024
+ foreground Foreground Pixel XtDefaultForeground
+ gravity Gravity XtGravity ForgetGravity
+ image Image XImage* NULL
+ internalHeight Height Dimension 2
+ internalWidth Width Dimension 2
+ pasteBuffer PasteBuffer Boolean False
+ precision Precision Float 0.001
+ proportional Proportional Boolean True
+ resize Resize Boolean True
+ scaleX ScaleFactor Float DefaultScaleValue
+ scaleY ScaleFactor Float DefaultScaleValue
+ exponent Exponent integer -3
+-------------------------------------------------------------------------------
+
+ aspectRatio This resource specifies the aspect ratio of the scaled image
+ in the x / y * aspectRatio = 1 form. It is effective within
+ the precision resource only if proportional resource is set
+ to true. AspectRatio resource can be any positive number
+ greater than zero.
+
+ autoscale If this resource is set to True then the image will be
+ autoscaled to fit the window size within internal width
+ and internal height resource values. If the resource is
+ False, the widget will only reposition the image
+ according to the gravity resource value.
+
+ bufferSize This resource specifies the buffer size in XRectangle's for
+ buffering the XFillRectangle calls. It is effective only
+ for XYBitmap image type.
+
+ background This resource has the same meaning as for the Simple widget.
+ However, it is worth mentioning that if the most frequent
+ pixel value in the XYPixmap or ZPixmap image is specified
+ as backgroud, the scaling process can be speeded up noticably.
+
+ foreground The color used to paint the image if in XYBitmap format.
+ If the image is XYPixmap or ZPixmap format, the foreground
+ resource has no effect.
+
+ gravity This resource will determine where to put the image if it does
+ not fit the window size minus internal width and height.
+ The widget will try to preserve gravity rather than internal
+ width and height resources.
+
+ image This is the image to be displayed in the widget window.
+ If no image is desired, the NULL value can be passed.
+ The passed image is copied and set to the resource value.
+ Applications should destroy the passed image argument
+ if they do not intend to use it at some later time.
+
+ internalHeight
+ internalWidth These resources specify the minimum distance from the boarder
+ of the widget window to be maintanied when manipulating the
+ image. If image is too big or small to satisfy given
+ conditions, the widget will position the image to preserve
+ gravity rather than internalWidth or internalHeight.
+
+ pasteBuffer If this resource is true then the widget owns the paste
+ selection buffer. This resource can only be queried.
+
+ precision This resource specifies the precision of the scale factors
+ when scaling the image. The precision resource can be any
+ positive number greater than zero. (For example, if precision
+ is 1.0 then the image will be scaled only by integer values.)
+
+ proportional If this resource is set to true it will make sure that the
+ image proportions, as specified by aspectRatio resource,
+ are being kept whenever it is scaled.
+
+ resize If this resource is true the widget will try to resize when
+ addopting a new image thus preserveing the scale values.
+ If it is false the scale values will not be preserved unless
+ the image can fit in the current window size with the same
+ scale values.
+
+ scaleX
+ scaleY These resources specify the scaling values for the widget
+ image. They will be floored to satisfy precision resource
+ values. If uniform resource is true the scale values will
+ be only integers. These resources can be any positive number
+ greater than zero.
+
+ shiftFactor ...
diff --git a/ScaleP.h b/ScaleP.h
new file mode 100644
index 0000000..181ae46
--- /dev/null
+++ b/ScaleP.h
@@ -0,0 +1,104 @@
+/* $Xorg: ScaleP.h,v 1.4 2001/02/09 02:05:55 xorgcvs Exp $ */
+/*
+
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+/*
+ * Author: Davor Matic, MIT X Consortium
+ */
+
+#ifndef _ScaleP_h
+#define _ScaleP_h
+
+#include "Scale.h"
+#include <X11/Xaw/SimpleP.h>
+
+typedef struct {
+ int foo;
+} ScaleClassPart;
+
+/* Full class record declaration */
+typedef struct _ScaleClassRec {
+ CoreClassPart core_class;
+ SimpleClassPart simple_class;
+ ScaleClassPart scale_class;
+} ScaleClassRec;
+
+extern ScaleClassRec scaleClassRec;
+
+typedef struct {
+ Position *x, *y;
+ Dimension *width, *height;
+} Table;
+
+/* New fields for the Scale widget record */
+
+#ifndef XtGravity
+#define XtGravity int
+#endif
+
+typedef struct {
+ /* resources */
+ Pixel foreground_pixel;
+ Dimension internal_width;
+ Dimension internal_height;
+ XtGravity gravity;
+ String scale_x_str, scale_y_str;
+ String aspect_ratio_str;
+ String precision_str;
+ XImage *image;
+ Boolean resize;
+ Boolean autoscale;
+ Boolean proportional;
+ Boolean paste_buffer;
+ Cardinal buffer_size;
+ XtPointer userData;
+ Visual *visual;
+ /* private */
+ float scale_x, scale_y;
+ float aspect_ratio;
+ float precision;
+ GC gc;
+ Position x, y;
+ Dimension width, height;
+ Table table;
+ XRectangle *rectangles;
+ Cardinal nrectangles;
+} ScalePart;
+
+/* Full instance record declaration */
+typedef struct _ScaleRec {
+ CorePart core;
+ SimplePart simple;
+ ScalePart scale;
+} ScaleRec;
+
+#endif /* _ScaleP_h */
+
+
+
+
diff --git a/Xmag.ad b/Xmag.ad
new file mode 100644
index 0000000..08fd004
--- /dev/null
+++ b/Xmag.ad
@@ -0,0 +1,27 @@
+.\ "$Xorg: Xmag.ad,v 1.3 2000/08/17 19:54:54 cpqbld Exp $
+*Font: fixed
+*pane2*orientation: horizontal
+*pane2*showGrip: False
+*allowShellResize: on
+*Scale.baseTranslations:#augment\
+ <EnterWindow>: set-colors()\n\
+ <LeaveWindow>: unset-colors()\n\
+ <Btn1Down>:popup-pixel()\n\
+ Button1<Enter>:popup-pixel()\n\
+ <Btn1Motion>:update-pixel()\n\
+ <Btn1Up>:popdown-pixel()\n\
+ <Leave>:popdown-pixel()\n\
+ <Key>n:new()\n\
+ <Key>q:close()\n\
+ Ctrl<Key>c:close()\n\
+ <Key>space:replace()
+*close.accelerators:#augment\
+ <Key>q:set()notify()unset()\n\
+ Ctrl<Key>c:set()notify()unset()
+*replace.accelerators:#augment\
+ <Key>space:set()notify()unset()\n\
+ <Btn2Up>:set()notify()unset()\n\
+ <Btn3Up>:set()notify()unset()
+*pixLabel.Translations:<Enter>:popdown-pixel()
+*helpLabel.font: 8x13bold
+*helpLabel.label: xmag
diff --git a/xmag.c b/xmag.c
new file mode 100644
index 0000000..7b77b6a
--- /dev/null
+++ b/xmag.c
@@ -0,0 +1,1125 @@
+/* $Xorg: xmag.c,v 1.4 2001/02/09 02:05:55 xorgcvs Exp $ */
+/*
+
+Copyright 1991, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xaw/Paned.h>
+#include <X11/Xaw/Command.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Shell.h>
+#include "RootWin.h"
+#include "Scale.h"
+#include <X11/cursorfont.h>
+
+#include <stdio.h>
+#include <X11/Xmu/Error.h>
+
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h> /* for exit() and abs() */
+#endif
+
+#define SRCWIDTH 64
+#define SRCHEIGHT 64
+
+#define min(a, b) a < b ? a : b
+
+extern void SWGrabSelection();
+extern void SWRequestSelection();
+extern int SWGetImagePixel();
+
+
+
+/* highlight interval */
+#define HLINTERVAL 10
+
+/* highlight mode */
+typedef enum { drag, resize, done } hlMode;
+
+/* highlight data structure */
+typedef struct {
+ Boolean newScale;
+ hlMode selectMode;
+ GC gc;
+ XWindowAttributes win_info;
+ XImage *image;
+ Position homeX, homeY, x, y;
+ Dimension width, height;
+ Widget scaleShell, scaleInstance, pixShell, pixLabel, cmapWinList [2];
+ } hlStruct, *hlPtr;
+
+static XtIntervalId hlId;
+
+
+
+/* global variables */
+static XtAppContext app;
+static Cursor ulAngle, urAngle, lrAngle, llAngle;
+static Display *dpy;
+static int scr;
+static GC selectGC;
+static XGCValues selectGCV;
+static Widget toplevel, root;
+static Atom wm_delete_window;
+static int numXmags = 0;
+static int srcStat, srcX, srcY;
+static unsigned int srcWidth, srcHeight;
+
+/* forward declarations */
+
+static void
+ CloseAP(),
+ SetCmapPropsAP(),
+ UnsetCmapPropsAP(),
+ NewAP(),
+ ReplaceAP(),
+ PopupPixelAP(),
+ UpdatePixelAP(),
+ PopdownPixelAP(),
+ SelectRegionAP(),
+ CheckPoints(),
+ HighlightTO(),
+ CloseCB(),
+ ReplaceCB(),
+ NewCB(),
+ SelectCB(),
+ SetupGC(),
+ ResizeEH(),
+ DragEH(),
+ StartRootPtrGrab(),
+ CreateRoot(),
+ GetImageAndAttributes(),
+ PopupNewScale(),
+ RedoOldScale(),
+ InitCursors(),
+ ParseSourceGeom();
+
+static Window
+ FindWindow();
+
+static int
+ Error(),
+ Get_XColors();
+
+static Pixel
+ GetMaxIntensity(),
+ GetMinIntensity();
+
+
+
+/* application resources */
+
+typedef struct { String geometry, source, mag, title; } OptionsRec;
+static OptionsRec options;
+
+#define Offset(field) XtOffsetOf(OptionsRec, field)
+static XtResource resources[] = {
+ {"geometry", "Geometry", XtRString, sizeof(String),
+ Offset(geometry), XtRString, (XtPointer)NULL},
+ {"mag", "Mag", XtRString, sizeof(String),
+ Offset(mag), XtRString, (XtPointer)"5.0"},
+ {"source", "Source", XtRString, sizeof(String),
+ Offset(source), XtRString, (XtPointer)"SRCWIDTHxSRCHEIGHT"},
+ {"title", XtCString, XtRString, sizeof(char *),
+ Offset(title), XtRString, "xmag"},
+};
+#undef Offset
+
+static XrmOptionDescRec optionDesc[] = {
+ {"-bd", "*borderColor", XrmoptionSepArg, (XtPointer)NULL},
+ {"-bg", "*background", XrmoptionSepArg, (XtPointer)NULL},
+ {"-bw", "*borderWidth", XrmoptionSepArg, (XtPointer)NULL},
+
+ {"-geometry", "*geometry", XrmoptionSepArg, (XtPointer)NULL},
+ {"-mag", "*mag", XrmoptionSepArg, (XtPointer)NULL},
+ {"-source", "*source", XrmoptionSepArg, (XtPointer)NULL},
+ {"-title", "*title", XrmoptionSepArg, (XtPointer)NULL},
+};
+
+
+
+/* action table */
+
+static XtActionsRec actions_table[] = {
+ {"close", CloseAP},
+ {"set-colors", SetCmapPropsAP},
+ {"unset-colors", UnsetCmapPropsAP},
+ {"new", NewAP},
+ {"replace", ReplaceAP},
+ {"popup-pixel", PopupPixelAP},
+ {"update-pixel", UpdatePixelAP},
+ {"popdown-pixel", PopdownPixelAP},
+ {"select-region", SelectRegionAP}
+};
+
+
+
+/*
+ * Error() -- Error handler: Catch a bad match in magnifing an
+ * area that contains bits of different depths.
+ */
+static int
+Error(dpy, err)
+ Display *dpy; XErrorEvent *err;
+{
+ (void) XmuPrintDefaultErrorMessage (dpy, err, stderr);
+ return 0;
+}
+
+
+/*
+ * CloseAP() -- Close this dialog. If its the last one exit the program.
+ *
+ */
+static void /* ARGSUSED */
+CloseAP(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ Arg wargs[2]; int n; hlPtr data;
+ if (!--numXmags) exit(0);
+ if (event->type != ClientMessage) {
+ n = 0; /* get user data */
+ XtSetArg(wargs[0], XtNuserData, &data); n++;
+ XtGetValues(w, wargs, n);
+ w = data->scaleShell;
+ }
+ XtPopdown(w);
+ XtDestroyWidget(w);
+}
+
+
+
+/*
+ * SetCmapPropsAP() -- Put the scale widget first in WM_COLORMAP_WINDOWS
+ *
+ */
+static void /* ARGSUSED */
+SetCmapPropsAP(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ Arg wargs[2]; int n; hlPtr data;
+ n = 0; /* get user data */
+ XtSetArg(wargs[0], XtNuserData, &data); n++;
+ XtGetValues(w, wargs, n);
+ if (data->win_info.colormap != DefaultColormap(dpy, scr)) {
+ data->cmapWinList[0] = data->scaleInstance;
+ data->cmapWinList[1] = data->scaleShell;
+ XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2);
+ }
+}
+
+
+
+/*
+ * UnsetCmapPropsAP() -- Put the shell first in WM_COLORMAP_WINDOWS
+ *
+ */
+static void /* ARGSUSED */
+UnsetCmapPropsAP(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ Arg wargs[2]; int n; hlPtr data;
+ n = 0; /* get user data */
+ XtSetArg(wargs[0], XtNuserData, &data); n++;
+ XtGetValues(w, wargs, n);
+ if (data->win_info.colormap != DefaultColormap(dpy, scr)) {
+ data->cmapWinList[0] = data->scaleShell;
+ data->cmapWinList[1] = data->scaleInstance;
+ XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2);
+ }
+}
+
+
+
+/*
+ * NewAP() -- Create an additional xmag dialog. THIS IS A COPY OF NewEH
+ * FIND A BETTER WAY....
+ */
+static void /* ARGSUSED */
+NewAP(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ StartRootPtrGrab(True, NULL);
+}
+
+
+
+/*
+ * ReplaceAP() -- Replace this particular xmag dialog.
+ */
+static void /* ARGSUSED */
+ReplaceAP(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ Arg wargs[2]; int n; hlPtr data;
+ n = 0; /* get user data */
+ XtSetArg(wargs[0], XtNuserData, &data); n++;
+ XtGetValues(w, wargs, n);
+ StartRootPtrGrab(False, data);
+}
+
+
+
+/*
+ * PopupPixelAP() -- Show pixel information.
+ */
+static void /* ARGSUSED */
+PopupPixelAP(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ Position scale_x, scale_y;
+ Dimension scale_height;
+ Position label_x, label_y;
+ Dimension label_height;
+ int n;
+ Arg wargs[3];
+ hlPtr data;
+
+ n = 0; /* get user data */
+ XtSetArg(wargs[0], XtNuserData, &data); n++;
+ XtGetValues(w, wargs, n);
+
+ n = 0;
+ XtSetArg(wargs[n], XtNheight, &scale_height); n++;
+ XtGetValues(w, wargs, n);
+ XtTranslateCoords(w, -1, -1, &scale_x, &scale_y);
+
+ XtRealizeWidget(data->pixShell); /* to get the right height */
+
+ n = 0;
+ XtSetArg(wargs[n], XtNheight, &label_height); n++;
+ XtGetValues(data->pixShell, wargs, n);
+
+ if ((double) event->xbutton.y / (double) scale_height > 0.5) {
+ label_x = scale_x;
+ label_y = scale_y;
+ }
+ else {
+ label_x = scale_x;
+ label_y = scale_y + scale_height - label_height;
+ }
+
+ n = 0;
+ XtSetArg(wargs[n], XtNx, label_x); n++;
+ XtSetArg(wargs[n], XtNy, label_y); n++;
+ XtSetValues(data->pixShell, wargs, n);
+
+ UpdatePixelAP(w, event);
+}
+
+
+
+/*
+ * UpdatePixelAP() -- Update pixel information.
+ */
+static void /* ARGSUSED */
+UpdatePixelAP(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ Position x, y;
+ Pixel pixel;
+ XColor color;
+ int n;
+ Arg wargs[3];
+ char string[80];
+ hlPtr data;
+
+ n = 0;
+ XtSetArg(wargs[0], XtNuserData, &data); n++;
+ XtGetValues(w, wargs, n);
+
+ if (SWGetImagePixel(w, event->xbutton.x, event->xbutton.y, &x, &y, &pixel))
+ XtPopdown(data->pixShell);
+ else {
+ color.pixel = pixel;
+ XQueryColor(dpy, data->win_info.colormap, &color);
+ sprintf(string, "Pixel %d at (%d,%d) colored (%x,%x,%x).",
+ pixel, x + data->x, y + data->y,
+ color.red, color.green, color.blue);
+ n = 0;
+ XtSetArg(wargs[n], XtNlabel, string); n++;
+ XtSetValues(data->pixLabel, wargs, n);
+ XtPopup(data->pixShell, XtGrabNone);
+ }
+}
+
+
+
+/*
+ * PopdownPixelAP() -- Remove pixel info.
+ */
+static void /* ARGSUSED */
+PopdownPixelAP(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ int n;
+ Arg wargs[3];
+ hlPtr data;
+
+ n = 0;
+ XtSetArg(wargs[0], XtNuserData, &data); n++;
+ XtGetValues(w, wargs, n);
+ XtPopdown(data->pixShell);
+}
+
+
+
+static void /* ARGSUSED */
+SelectRegionAP(w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+/***** NOT SURE WHAT TO DO WITH THIS
+ if (app_resources.unmap)
+ XtUnmapWidget(toplevel);
+ Redisplay(XtDisplay(w), RootWindow(XtDisplay(w),
+ DefaultScreen(XtDisplay(w))),
+ source.width, source.height,
+ app_resources.freq, app_resources.puls,
+ ul_angle, lr_angle,
+ app_resources.grab);
+
+ if (app_resources.unmap)
+ XtMapWidget(toplevel);
+******/
+}
+
+
+
+/*
+ * CheckPoints() -- Change the cursor for the correct quadrant.
+ * Make sure the first point is less than the second
+ * for drawing the selection rectangle.
+ *
+ */
+static void
+CheckPoints(x1, x2, y1, y2)
+ Position *x1, *x2, *y1, *y2; /* Coordinates */
+{
+ Position tmp;
+ Boolean above, left;
+ Cursor newC;
+ above = (*y2 < *y1); left = (*x2 < *x1);
+ if (above&&left) newC = ulAngle;
+ else if (above&&!left) newC = urAngle;
+ else if (!above&&!left) newC = lrAngle;
+ else newC = llAngle;
+ XChangeActivePointerGrab
+ (dpy, PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
+ newC, CurrentTime);
+ if (*x2 < *x1) { tmp = *x1; *x1 = *x2; *x2 = tmp; }
+ if (*y2 < *y1) { tmp = *y1; *y1 = *y2; *y2 = tmp; }
+}
+
+
+
+/*
+ * HighlightTO() -- Timer to highlight the selection box
+ */
+static void
+HighlightTO(closure, id) /* ARGSUSED */
+ XtPointer closure; XtIntervalId *id;
+{
+ hlPtr data = (hlPtr)closure;
+ XGrabServer(dpy);
+ if (data->selectMode == drag) {
+ XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc,
+ data->x, data->y, data->width, data->height);
+ XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc,
+ data->x, data->y, data->width, data->height);
+ }
+ else if (data->selectMode == resize) {
+ Position x1 = data->homeX,
+ x2 = data->x,
+ y1 = data->homeY,
+ y2 = data->y;
+ CheckPoints(&x1, &x2, &y1, &y2);
+ XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc,
+ x1, y1, x2 - x1, y2 - y1);
+ XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc,
+ x1, y1, x2 - x1, y2 - y1);
+ }
+ XUngrabServer(dpy);
+ if (data->selectMode != done)
+ XtAppAddTimeOut(app, HLINTERVAL, HighlightTO, (XtPointer)data);
+}
+
+
+
+/*
+ * CloseCB() -- Delete this xmag dialog. If its the only one on the screen
+ * then exit.
+ */
+static void /* ARGSUSED */
+CloseCB(w, clientData, callData)
+ Widget w; XtPointer clientData, callData;
+{
+ Widget shell = (Widget)clientData;
+ if (!--numXmags) exit(0);
+ XtPopdown(shell);
+ XtDestroyWidget(shell);
+}
+
+
+
+/*
+ * ReplaceCB() -- Replace this particular xmag dialog.
+ */
+static void /* ARGSUSED */
+ReplaceCB(w, clientData, callData)
+ Widget w; XtPointer clientData, callData;
+{
+ hlPtr data = (hlPtr)clientData;
+ StartRootPtrGrab(False, data);
+}
+
+
+
+/*
+ * NewCB() -- Create an additional xmag dialog.
+ */
+static void /* ARGSUSED */
+NewCB(w, clientData, callData)
+ Widget w; XtPointer clientData, callData;
+{
+ StartRootPtrGrab(True, NULL);
+}
+
+
+
+/*
+ * SelectCB() -- Own the primary selection.
+ */
+static void /* ARGSUSED */
+SelectCB(w, clientData, callData)
+ Widget w; XtPointer clientData, callData;
+{
+ hlPtr data = (hlPtr)clientData;
+ SWGrabSelection(data->scaleInstance, XtLastTimestampProcessed(dpy));
+}
+
+
+
+/*
+ * PasteCB() -- Paste from the primary selectin into xmag.
+ */
+static void /* ARGSUSED */
+PasteCB(w, clientData, callData)
+ Widget w; XtPointer clientData, callData;
+{
+ hlPtr data = (hlPtr)clientData;
+ SWRequestSelection(data->scaleInstance, XtLastTimestampProcessed(dpy));
+}
+
+
+
+/*
+ * SetupGC() -- Graphics context for magnification selection.
+ */
+static void
+SetupGC()
+{
+ selectGCV.function = GXxor;
+ selectGCV.foreground = 1L;
+ selectGCV.subwindow_mode = IncludeInferiors;
+ selectGC = XtGetGC(toplevel, GCFunction|GCForeground|GCSubwindowMode,
+ &selectGCV);
+}
+
+
+
+/*
+ * FindWindow() -- Determin window the pointer is over.
+ *
+ */
+static Window
+FindWindow(x, y)
+ int x, y; /* Locatation of cursor */
+{
+ XWindowAttributes wa;
+ Window findW = DefaultRootWindow(dpy), stopW, childW;
+ XTranslateCoordinates(dpy, findW, findW,
+ x, y, &x, &y, &stopW);
+ while (stopW) {
+ XTranslateCoordinates(dpy, findW, stopW,
+ x, y, &x, &y, &childW);
+ findW = stopW;
+ if (childW &&
+ XGetWindowAttributes(dpy, childW, &wa) &&
+ wa.class != InputOutput)
+ break;
+ stopW = childW;
+ }
+ return findW;
+}
+
+
+
+/*
+ * ResizeEH() -- Event Handler for resize of selection box.
+ */
+static void
+ResizeEH(w, closure, event, continue_to_dispatch) /* ARGSUSED */
+ Widget w; XtPointer closure; XEvent *event; Boolean *continue_to_dispatch;
+{
+ hlPtr data = (hlPtr)closure;
+ switch (event->type) {
+ case MotionNotify:
+ data->x = event->xmotion.x_root;
+ data->y = event->xmotion.y_root;
+ break;
+ case ButtonRelease:
+ GetImageAndAttributes(FindWindow(event->xmotion.x_root,
+ event->xmotion.y_root),
+ min(data->homeX,event->xbutton.x_root),
+ min(data->homeY,event->xbutton.y_root),
+ abs(data->homeX - event->xbutton.x_root),
+ abs(data->homeY - event->xbutton.y_root),
+ data);
+ if (data->newScale)
+ PopupNewScale(data);
+ else
+ SWSetImage(data->scaleInstance, data->image);
+ XtUngrabPointer(w, CurrentTime);
+/*****
+ XtRemoveRawEventHandler(w, PointerMotionMask|ButtonReleaseMask,
+ True, ResizeEH, (XtPointer)data);
+*****/
+ XtRemoveEventHandler(w, PointerMotionMask|ButtonReleaseMask,
+ True, ResizeEH, (XtPointer)data);
+ data->selectMode = done;
+ break;
+ }
+}
+
+
+
+/*
+ * DragEH() -- Event Handler for draging selection box.
+ */
+static void
+DragEH(w, closure, event, continue_to_dispatch) /* ARGSUSED */
+ Widget w; XtPointer closure; XEvent *event; Boolean *continue_to_dispatch;
+{
+ hlPtr data = (hlPtr)closure;
+ switch (event->type) {
+ case MotionNotify: /* drag mode */
+ data->x = event->xmotion.x_root;
+ data->y = event->xmotion.y_root;
+ break;
+ case ButtonRelease: /* end drag mode */
+ if (event->xbutton.button == Button1) { /* get image */
+ /* Problem: You can't get bits with XGetImage outside of its window.
+ * xmag will only do a GetImage on the actual window in the case
+ * where the depth of the window does not match the depth of
+ * the root window.
+ */
+ GetImageAndAttributes(FindWindow(event->xmotion.x_root,
+ event->xmotion.y_root),
+ event->xbutton.x_root,
+ event->xbutton.y_root,
+ srcWidth, srcHeight, data);
+ if (data->newScale)
+ PopupNewScale(data);
+ else
+ RedoOldScale(data);
+ XtUngrabPointer(w, CurrentTime);
+ XtRemoveRawEventHandler(w, PointerMotionMask|ButtonPressMask|
+ ButtonReleaseMask, True, DragEH,
+ (XtPointer)data);
+ data->selectMode = done;
+ }
+
+ break;
+ case ButtonPress:
+ if (event->xbutton.button == Button2) { /* turn on resize mode */
+ data->homeX = event->xbutton.x_root;
+ data->homeY = event->xbutton.y_root;
+ data->x = event->xbutton.x_root + srcWidth;
+ data->y = event->xbutton.y_root + srcHeight;
+ data->selectMode = resize;
+ XtRemoveRawEventHandler(w, PointerMotionMask|ButtonPressMask|
+ ButtonReleaseMask, True, DragEH, (XtPointer)data);
+ XChangeActivePointerGrab
+ (dpy, PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
+ lrAngle, CurrentTime);
+ XWarpPointer(dpy, None, None, 0, 0, 0, 0,
+ srcWidth, srcHeight);
+ XtAddEventHandler(w, PointerMotionMask|ButtonReleaseMask,
+ True, ResizeEH, (XtPointer)data);
+ }
+ break;
+ }
+}
+
+
+
+
+/*
+ * StartRootPtrGrab() -- Bring up the selection box.
+ *
+ */
+static void
+StartRootPtrGrab(new, data)
+ Boolean new; /* do we cretate a new scale instance? */
+ hlPtr data; /* highligh data */
+{
+ Window rootR, childR;
+ int rootX, rootY, winX, winY;
+ unsigned int mask;
+ hlPtr hlData;
+ XtGrabPointer
+ (root, False,
+ PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
+ GrabModeAsync, GrabModeAsync, None, ulAngle, CurrentTime);
+ XQueryPointer(dpy, DefaultRootWindow(dpy), &rootR, &childR,
+ &rootX, &rootY, &winX, &winY, &mask);
+ if (new) {
+ numXmags++;
+ hlData = (hlPtr)XtMalloc(sizeof(hlStruct));
+ }
+ else hlData = data;
+ hlData->newScale = new;
+ hlData->selectMode = drag;
+ hlData->x = rootX;
+ hlData->y = rootY;
+ hlData->gc = selectGC;
+ hlData->width = srcWidth;
+ hlData->height = srcHeight;
+ XtAddRawEventHandler
+ (root, PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
+ True, DragEH, (XtPointer)hlData);
+ hlId = XtAppAddTimeOut(app, HLINTERVAL, HighlightTO, (XtPointer)hlData);
+}
+
+
+
+/*
+ * CreateRoot() -- Create a root window widget. If the user specified x and y
+ * in his source geometry then use this to directly get the
+ * image.
+ */
+static void
+CreateRoot()
+{
+ hlPtr data;
+ root = XtCreateWidget("root", rootWindowWidgetClass, toplevel, NULL, 0);
+ XtRealizeWidget(root);
+ if (XValue & srcStat && YValue &srcStat) {
+ numXmags = 1;
+ data = (hlPtr)XtMalloc(sizeof(hlStruct));
+ data = data;
+ data->newScale = True;
+ data->selectMode = drag;
+ data->x = srcX;
+ data->y = srcY;
+ data->gc = selectGC;
+ data->width = srcWidth;
+ data->height = srcHeight;
+ GetImageAndAttributes(RootWindow(dpy, scr), srcX, srcY, srcWidth,
+ srcHeight, data);
+ PopupNewScale(data);
+ return;
+ }
+}
+
+
+/*
+ * GetImageAndAttributes() -- Get the image bits from the screen.
+ * We will also determin here the colormap, depth, and
+ * visual to be used for the magnification image.
+ */
+static void
+GetImageAndAttributes(w, x, y, width, height, data)
+ Window w; int x, y, width, height; hlPtr data;
+{
+ /* get parameters of window being magnified */
+ XGetWindowAttributes(dpy, w, &data->win_info);
+
+ if (data->win_info.depth == DefaultDepth(dpy, scr)) {
+ /* avoid off screen pixels */
+ if (x < 0) x = 0; if (y < 0) y = 0;
+ if (x + width > DisplayWidth(dpy,scr)) x = DisplayWidth(dpy,scr) - width;
+ if (y + height > DisplayHeight(dpy,scr))
+ y = DisplayHeight(dpy,scr) - height;
+ data->x = x; data->y = y;
+ /* get image pixels */
+ data->image = XGetImage (dpy,
+ RootWindow(dpy, scr),
+ x, y,
+ width, height,
+ AllPlanes, ZPixmap);
+ }
+ else {
+ int xInWin, yInWin; Window childWin;
+ XTranslateCoordinates(dpy, DefaultRootWindow(dpy), w, x, y,
+ &xInWin, &yInWin, &childWin);
+ /* avoid off screen pixels */
+ if (x + data->win_info.x < 0) x = abs(data->win_info.x);
+ if (y + data->win_info.y < 0) y = abs(data->win_info.y);
+ if (x + width > DisplayWidth(dpy,scr)) x = DisplayWidth(dpy,scr) - width;
+ if (y + height > DisplayHeight(dpy,scr))
+ y = DisplayHeight(dpy,scr) - height;
+ data->x = x; data->y = y;
+ data->image = XGetImage (dpy,
+ w,
+ xInWin, yInWin,
+ width, height,
+ AllPlanes, ZPixmap);
+
+ }
+}
+
+
+
+/*
+ * Get_XColors() Get the XColors of all pixels in image - returns # of colors
+ * This function was taken from xwd (thanks Bob...)
+ */
+#define lowbit(x) ((x) & (~(x) + 1))
+static int
+Get_XColors(win_info, colors)
+ XWindowAttributes *win_info;
+ XColor **colors;
+{
+ int i, ncolors;
+
+ if (!win_info->colormap)
+ return(0);
+
+ ncolors = win_info->visual->map_entries;
+ if (!(*colors = (XColor *) XtMalloc (sizeof(XColor) * ncolors)))
+ XtError("Out of memory!");
+
+ if (win_info->visual->class == DirectColor ||
+ win_info->visual->class == TrueColor) {
+ Pixel red, green, blue, red1, green1, blue1;
+
+ red = green = blue = 0;
+ red1 = lowbit(win_info->visual->red_mask);
+ green1 = lowbit(win_info->visual->green_mask);
+ blue1 = lowbit(win_info->visual->blue_mask);
+ for (i=0; i<ncolors; i++) {
+ (*colors)[i].pixel = red|green|blue;
+ (*colors)[i].pad = 0;
+ red += red1;
+ if (red > win_info->visual->red_mask)
+ red = 0;
+ green += green1;
+ if (green > win_info->visual->green_mask)
+ green = 0;
+ blue += blue1;
+ if (blue > win_info->visual->blue_mask)
+ blue = 0;
+ }
+ } else {
+ for (i=0; i<ncolors; i++) {
+ (*colors)[i].pixel = i;
+ (*colors)[i].pad = 0;
+ }
+ }
+
+ XQueryColors(dpy, win_info->colormap, *colors, ncolors);
+
+ return(ncolors);
+}
+
+
+
+#define Intensity(cptr) (3.0*cptr->red+0.59*cptr->green+0.11*cptr->blue)
+
+/*
+ * GetMaxIntensity() -- Find the maximum intensity pixel value for a colormap.
+ */
+static Pixel
+GetMaxIntensity(data)
+ hlPtr data;
+{
+ XColor *colors = NULL, *mptr, *tptr;
+ int i, ncolors;
+
+ if (data->win_info.colormap == DefaultColormap(dpy, scr))
+ return WhitePixel(dpy, scr);
+ ncolors = Get_XColors(&data->win_info, &colors);
+ mptr = tptr = colors; tptr++;
+ for (i=1; i<ncolors; i++) {
+ if ((int)Intensity(mptr) < (int)Intensity(tptr))
+ mptr = tptr;
+ tptr++;
+ }
+ return mptr->pixel;
+}
+
+/*
+ * GetMinIntensity() -- Find the minimum intensity pixel value for a colormap.
+ */
+static Pixel
+GetMinIntensity(data)
+ hlPtr data;
+{
+ XColor *colors = NULL, *mptr, *tptr;
+ int i, ncolors;
+
+ if (data->win_info.colormap == DefaultColormap(dpy, scr))
+ return BlackPixel(dpy, scr);
+ ncolors = Get_XColors(&data->win_info, &colors);
+ mptr = tptr = colors; tptr++;
+ for (i=1; i<ncolors; i++) {
+ if ((int)Intensity(mptr) > (int)Intensity(tptr))
+ mptr = tptr;
+ tptr++;
+ }
+ return mptr->pixel;
+}
+
+
+
+
+static Widget pane1, pane2, pane3, cclose, replace, new, select_w, paste, label;
+
+/*
+ * PopupNewScale() -- Create and popup a new scale composite.
+ */
+static void
+PopupNewScale(data)
+ hlPtr data;
+{
+ Arg warg;
+
+ data->scaleShell =
+ XtVaCreatePopupShell("xmag", topLevelShellWidgetClass, toplevel,
+ XtNgeometry, (XtArgVal)options.geometry,
+ XtNtitle, (XtArgVal)options.title,
+ NULL);
+ pane1 = XtCreateManagedWidget("pane1", panedWidgetClass, data->scaleShell,
+ (Arg *) NULL, 0);
+ pane2 = XtCreateManagedWidget("pane2", panedWidgetClass, pane1,
+ (Arg *) NULL, 0);
+ cclose = XtCreateManagedWidget("close", commandWidgetClass, pane2,
+ (Arg *) NULL, 0);
+ XtAddCallback(cclose, XtNcallback, CloseCB, (XtPointer)data->scaleShell);
+ replace = XtCreateManagedWidget("replace", commandWidgetClass, pane2,
+ (Arg *) NULL, 0);
+ XtAddCallback(replace, XtNcallback, ReplaceCB, (XtPointer)data);
+ new = XtCreateManagedWidget("new", commandWidgetClass, pane2,
+ (Arg *) NULL, 0);
+ XtAddCallback(new, XtNcallback, NewCB, (XtPointer)NULL);
+ select_w = XtCreateManagedWidget("select", commandWidgetClass, pane2,
+ (Arg *) NULL, 0);
+ XtAddCallback(select_w, XtNcallback, SelectCB, (XtPointer)data);
+ paste = XtCreateManagedWidget("paste", commandWidgetClass, pane2,
+ (Arg *) NULL, 0);
+ XtAddCallback(paste, XtNcallback, PasteCB, (XtPointer)data);
+ label = XtCreateManagedWidget("helpLabel", labelWidgetClass, pane2,
+ (Arg *) NULL, 0);
+ pane3 = XtCreateManagedWidget("pane2", panedWidgetClass, pane1,
+ (Arg *) NULL, 0);
+ data->scaleInstance =
+ XtVaCreateManagedWidget("scale", scaleWidgetClass,
+ pane3,
+ XtNvisual, (XtArgVal)data->win_info.visual,
+ XtNcolormap, (XtArgVal)data->win_info.colormap,
+ XtNdepth, (XtArgVal)data->win_info.depth,
+ XtNscaleX, (XtArgVal)options.mag,
+ XtNscaleY, (XtArgVal)options.mag,
+ NULL);
+ SWSetImage(data->scaleInstance, data->image);
+ XtOverrideTranslations
+ (data->scaleShell,
+ XtParseTranslationTable ("<Message>WM_PROTOCOLS: close()"));
+ XtSetArg(warg, XtNuserData, data);
+ XtSetValues(data->scaleInstance, &warg, 1);
+ data->pixShell =
+ XtVaCreatePopupShell("pixShell", overrideShellWidgetClass,
+ toplevel,
+ XtNvisual, (XtArgVal)data->win_info.visual,
+ XtNcolormap, (XtArgVal)data->win_info.colormap,
+ XtNdepth, (XtArgVal)data->win_info.depth,
+ XtNborderWidth, (XtPointer)0,
+ NULL);
+ data->pixLabel =
+ XtVaCreateManagedWidget("pixLabel", labelWidgetClass,
+ data->pixShell,
+ XtNforeground, (XtPointer)GetMaxIntensity(data),
+ XtNbackground, (XtPointer)GetMinIntensity(data),
+ XtNborderWidth, (XtPointer)0,
+ NULL);
+ XtInstallAllAccelerators(pane1, pane1); /* install accelerators */
+ if (data->newScale) {
+ XtPopup(data->scaleShell, XtGrabNone);
+ (void) XSetWMProtocols /* ICCCM delete window */
+ (dpy, XtWindow(data->scaleShell), &wm_delete_window, 1);
+ }
+ if (data->win_info.colormap != DefaultColormap(dpy, scr)) {
+ data->cmapWinList[0] = data->scaleShell;
+ data->cmapWinList[1] = data->scaleInstance;
+ XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2);
+ }
+}
+
+
+
+/*
+ * RedoOldScale() -- If the visual, depth, or colormap has changed, unrealize
+ * the scale widget and change its colormap/depth/visual.
+ * Then re-realize it. Also do this for the pixel display
+ * widget.
+ */
+static void
+RedoOldScale(data)
+ hlPtr data;
+{
+ Arg wargs[3];
+ int n;
+ Visual *oldVis;
+ int oldDepth;
+ Colormap oldCmap;
+
+ n=0;
+ XtSetArg(wargs[n], XtNvisual, &oldVis); n++;
+ XtSetArg(wargs[n], XtNdepth, &oldDepth); n++;
+ XtSetArg(wargs[n], XtNcolormap, &oldCmap); n++;
+ XtGetValues(data->scaleInstance, wargs, n);
+ if (oldVis == data->win_info.visual && oldDepth == data->win_info.depth
+ && oldCmap == data->win_info.colormap) {
+ SWSetImage(data->scaleInstance, data->image);
+ return;
+ }
+ /* get width and height, save and reuse them */
+ XtUnmanageChild(data->scaleInstance);
+ XtUnrealizeWidget(data->scaleInstance);
+ n=0;
+ XtSetArg(wargs[n], XtNcolormap, data->win_info.colormap); n++;
+ XtSetArg(wargs[n], XtNdepth, data->win_info.depth); n++;
+ XtSetArg(wargs[n], XtNvisual, data->win_info.visual); n++;
+ XtSetValues(data->scaleInstance, wargs, n);
+ n=0;
+ XtSetArg(wargs[n], XtNforeground, GetMaxIntensity(data)); n++;
+ XtSetArg(wargs[n], XtNbackground, GetMinIntensity(data)); n++;
+ XtSetValues(data->pixLabel, wargs, n);
+ SWSetImage(data->scaleInstance, data->image);
+ XtRealizeWidget(data->scaleInstance);
+ XtManageChild(data->scaleInstance);
+}
+
+
+
+/*
+ * InitCursors() -- Create our cursors for area selection.
+ */
+static void
+InitCursors()
+{
+ ulAngle = XCreateFontCursor(dpy, XC_ul_angle);
+ urAngle = XCreateFontCursor(dpy, XC_ur_angle);
+ lrAngle = XCreateFontCursor(dpy, XC_lr_angle);
+ llAngle = XCreateFontCursor(dpy, XC_ll_angle);
+}
+
+
+
+/*
+ * ParseSourceGeom() -- Determin dimensions of area to magnify from resources.
+ */
+static void
+ParseSourceGeom()
+{
+ /* source */
+ srcStat =
+ XParseGeometry(options.source, &srcX, &srcY, &srcWidth, &srcHeight);
+ if (!srcWidth) srcWidth = SRCWIDTH;
+ if (!srcHeight) srcHeight = SRCHEIGHT;
+ if (XNegative & srcStat) srcX = DisplayWidth(dpy, scr) + srcX - srcWidth;
+ if (YNegative & srcStat) srcY = DisplayHeight(dpy, scr) + srcY - srcHeight;
+ /* mag */
+}
+
+
+
+/*
+ * Main program.
+ */
+void main(argc, argv)
+ int argc;
+ char **argv;
+{
+ XSetErrorHandler(Error);
+
+ /* SUPPRESS 594 */
+ toplevel = XtAppInitialize(&app, "Xmag", optionDesc, XtNumber(optionDesc),
+ &argc, argv, NULL,
+ NULL, 0);
+
+ dpy = XtDisplay(toplevel);
+ scr = DefaultScreen(dpy);
+ XtGetApplicationResources(toplevel, (XtPointer) &options, resources,
+ XtNumber(resources), NULL, 0);
+ if (argc != 1) {
+ fprintf (stderr,
+ "usage: xmag [-source geom] [-mag magfactor] [-toolkitoption]\n");
+ exit(1);
+ }
+
+
+ ParseSourceGeom();
+ XtAppAddActions(app, actions_table, XtNumber(actions_table));
+ InitCursors();
+ SetupGC();
+ CreateRoot();
+ if (!(XValue & srcStat && YValue & srcStat))
+ StartRootPtrGrab(True, (hlPtr)NULL);
+ wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+ XtAppMainLoop(app);
+}
diff --git a/xmag.icon b/xmag.icon
new file mode 100644
index 0000000..94f9fdf
--- /dev/null
+++ b/xmag.icon
@@ -0,0 +1,14 @@
+#define xmag_width 32
+#define xmag_height 32
+static char xmag_bits[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0x7f, 0x00, 0xff, 0xff,
+ 0x1f, 0x00, 0xfc, 0xff, 0x0f, 0x00, 0xf8, 0xff, 0x07, 0x00, 0xf0, 0xff,
+ 0x07, 0x00, 0xf0, 0xff, 0x03, 0x00, 0xe0, 0xff, 0x03, 0x00, 0xe0, 0xff,
+ 0x03, 0x00, 0xe0, 0xff, 0x01, 0x00, 0xc0, 0xff, 0x01, 0x00, 0xc0, 0xff,
+ 0x01, 0x00, 0xc0, 0xff, 0x03, 0x00, 0xe0, 0xff, 0x03, 0x00, 0xe0, 0xff,
+ 0x03, 0x00, 0xe0, 0xff, 0x07, 0x00, 0xf0, 0xff, 0x07, 0x00, 0xf0, 0xff,
+ 0x0f, 0x00, 0xf0, 0xff, 0x1f, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0xc7, 0xff,
+ 0xff, 0xe3, 0x8f, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x3f, 0xfe,
+ 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xf1,
+ 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xc7,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
diff --git a/xmag.man b/xmag.man
new file mode 100644
index 0000000..5ecdf6d
--- /dev/null
+++ b/xmag.man
@@ -0,0 +1,98 @@
+.\" $Xorg: xmag.man,v 1.4 2001/02/09 02:05:55 xorgcvs Exp $
+.\" Copyright 1991, 1994, 1998 The Open Group
+.\"
+.\" Permission to use, copy, modify, distribute, and sell this software and its
+.\" documentation for any purpose is hereby granted without fee, provided that
+.\" the above copyright notice appear in all copies and that both that
+.\" copyright notice and this permission notice appear in supporting
+.\" documentation.
+.\"
+.\" The above copyright notice and this permission notice shall be included
+.\" in all copies or substantial portions of the Software.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+.\" IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+.\" OTHER DEALINGS IN THE SOFTWARE.
+.\"
+.\" Except as contained in this notice, the name of The Open Group shall
+.\" not be used in advertising or otherwise to promote the sale, use or
+.\" other dealings in this Software without prior written authorization
+.\" from The Open Group.
+.TH XMAG 1 "Release 6.4" "X Version 11"
+.SH NAME
+xmag \- magnify parts of the screen
+.SH SYNOPSIS
+.B xmag
+[
+.B \-mag
+.I magfactor
+] [
+.B \-source
+.I geom
+] [
+.I \-toolkitoption
+\&.\|.\|. ]
+.SH DESCRIPTION
+The \fIxmag\fP program allows you to magnify portions of an X screen. If no
+explicit region is specified, a square with the pointer in the upper left
+corner is displayed indicating the area to be enlarged. The area can be
+dragged out to the desired size by pressing Button 2. Once a region has
+been selected, a window is popped up showing a blown up version of the region
+in which each pixel in the source image is represented by a small square of
+the same color. Pressing Button1 in the enlargement window
+shows the position and RGB value
+of the pixel under the pointer until the button is released. Typing ``Q''
+or ``^C'' in the enlargement window exits the program. The application has
+5 buttons across its top.
+\fIClose\fP deletes this particular magnification instance.
+\fIReplace\fP brings up the rubber band selector again to select another
+region for this magnification instance.
+\fINew\fP brings up the rubber band
+selector to create a new magnification instance.
+\fICut\fP puts the magnification image into the primary selection.
+\fIPaste\fP copies the primary selection buffer into \fIxmag\fP.
+Note that you can cut and paste between \fIxmag\fP and the \fIbitmap\fP
+program. Resizing \fIxmag\fP resizes the magnification area.
+\fIxmag\fP preserves
+the colormap, visual, and window depth of the source.
+.SH WIDGETS
+\fIxmag\fP uses the X Toolkit and the Athena Widget Set.
+The magnified image is displayed in the Scale widget.
+For more information, see the Athena Widget Set documentation.
+Below is the widget structure of the \fIxmag\fP application.
+Indentation indicates hierarchical structure. The widget class
+name is given first, followed by the widget instance name.
+.sp
+.nf
+ Xmag xmag
+ RootWindow root
+ TopLevelShell xmag
+ Paned pane1
+ Paned pane2
+ Command close
+ Command replace
+ Command new
+ Command select
+ Command paste
+ Label xmag label
+ Paned pane2
+ Scale scale
+ OverrideShell pixShell
+ Label pixLabel
+
+.fi
+.SH OPTIONS
+.TP 15
+.B \-source\fI geom\fP
+This option specifies the size and/or location of the source region
+on the screen. By default, a 64x64 square is provided for the user to select
+an area of the screen.
+.TP 15
+.B \-mag\fI integer\fP
+This option indicates the magnification to be used. 5 is the default.
+.SH AUTHORS
+Dave Sternlicht and Davor Matic, MIT X Consortium.