diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 15:54:54 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 15:54:54 +0000 |
commit | 31f434e2df14612e3cf18fe45a6c161eb3c225ff (patch) | |
tree | 65d53468220245d1fcfa6a593680ea183cf239e3 |
R6.6 is the Xorg base-lineXORG-MAIN
-rw-r--r-- | CutPaste.c | 135 | ||||
-rw-r--r-- | RootWin.c | 86 | ||||
-rw-r--r-- | RootWin.h | 67 | ||||
-rw-r--r-- | RootWinP.h | 60 | ||||
-rw-r--r-- | Scale.c | 1044 | ||||
-rw-r--r-- | Scale.h | 115 | ||||
-rw-r--r-- | Scale.txt | 107 | ||||
-rw-r--r-- | ScaleP.h | 104 | ||||
-rw-r--r-- | Xmag.ad | 27 | ||||
-rw-r--r-- | xmag.c | 1125 | ||||
-rw-r--r-- | xmag.icon | 14 | ||||
-rw-r--r-- | xmag.man | 98 |
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 */ @@ -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); +} @@ -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 */ + + + + @@ -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 @@ -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. |