aboutsummaryrefslogtreecommitdiff
path: root/vendor/x11iraf/obm/gterm.c
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
commitfa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch)
treebdda434976bc09c864f2e4fa6f16ba1952b1e555 /vendor/x11iraf/obm/gterm.c
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'vendor/x11iraf/obm/gterm.c')
-rw-r--r--vendor/x11iraf/obm/gterm.c4407
1 files changed, 4407 insertions, 0 deletions
diff --git a/vendor/x11iraf/obm/gterm.c b/vendor/x11iraf/obm/gterm.c
new file mode 100644
index 00000000..71856353
--- /dev/null
+++ b/vendor/x11iraf/obm/gterm.c
@@ -0,0 +1,4407 @@
+/* Copyright(c) 1993 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <ObmP.h>
+#include "widget.h"
+
+/*
+ * Gterm-Image widget class (a subclass of Widget).
+ * -------------------------------------------------
+ * The gterm-image widget is a general 2D graphics-imaging widget providing
+ * a wide range of facilities for drawing graphics and text, for image
+ * display, and for graphics interaction. Normally the client communicates
+ * directly with the Gterm widget to draw graphics, download image data,
+ * and so on, using some communications protocol outside the domain of the
+ * object manager. Nonetheless so far as possible the facilities of the Gterm
+ * widget have also been made available to GUI code via the commands listed
+ * here.
+ *
+ * The gterm class uses a special OBM callback known as OBMCB_setGterm.
+ * A client application can use this to post a procedure to be called when
+ * a gterm widget receives the setGterm command. The calling sequence for
+ * the setGterm callback is as follows:
+ *
+ * setgterm (client_data, gterm_widget)
+ *
+ * The purpose of this callback is to tell the client which gterm widget is
+ * the "active" gterm widget. This is used by clients which only support
+ * one active Gterm widget, i.e., which can only direct graphics output to
+ * one Gterm widget at a time.
+ *
+ * The messages or commands that can be sent to the Gterm widget by GUI
+ * code follow.
+ *
+ * General commands:
+ *
+ * setGterm [arg [arg ...]] # make widget the active Gterm
+ *
+ * activate
+ * deactivate
+ * addCallback procedure-name callback-type
+ * deleteCallback procedure-name
+ * reset
+ * flush
+ *
+ * setCursorPos x y [raster]
+ * getCursorPos x y
+ * setCursorType cursortype
+ * bell
+ *
+ * Graphics drawing commands:
+ *
+ * setRaster raster
+ * raster = getRaster [raster]
+ *
+ * setLogRes width height
+ * getLogRes width height
+ * setPhysRes width height
+ * getPhysRes width height
+ * setTextRes rows cols
+ * setDataLevel level
+ * setLineWidth width
+ * setLineStyle style
+ * setColorIndex index
+ * setFillType filltype
+ *
+ * clearScreen
+ * drawPolyline vector
+ * drawPolymarker vector
+ * drawPolygon vector
+ * drawMarker type x y xsize ysize [rotangle]
+ *
+ * drawAlphaText x y text
+ * width = getAlphaTextSize [string [width [height [base]]]]
+ * startDialog
+ * endDialog
+ * eraseDialog
+ * drawDialogText x y text
+ *width = getDialogTextSize [string [width [height [base]]]]
+ *
+ * The coordinates used in the graphics drawing commands are logical
+ * coordinates as defined by setLogRes, in the coordinate system of the
+ * reference drawing raster as defined by setRaster. The default reference
+ * raster is raster zero, the widget's window. Vectors are specified as
+ * a list of points, e.g., { {x y} {x y} ... }.
+ *
+ * Imaging commands:
+ *
+ * rasterInit
+ * assignRaster raster drawable
+ * createRaster raster width height [type [depth]]
+ * destroyRaster raster
+ * exists = queryRaster raster [width [height [type [depth]]]]
+ * raster = nextRaster
+ * n = activeRasters
+ *
+ * setPixel raster x y value
+ * value = getPixel raster x y
+ * writePixels raster pixels encoding x1 y1 nx ny [bias]
+ * pixels = readPixels raster encoding x1 y1 nx ny [bias]
+ * refreshPixels raster ct x1 y1 nx ny
+ * setPixels raster color [ct x1 y1 nx ny [rop]]
+ * extractPixmap pixmap src [x y [width height]]
+ * insertPixmap pixmap dst [x y [width height]]
+ *
+ * colormap = nextColormap
+ * freeColormap colormap
+ * writeColormap colormap colors [offset]
+ * ncolors = readColormap colormap colors [offset [ncolors]]
+ * loadColormap colormap offset scale
+ * pixel = clientPixel gterm_pixel
+ * bias = getBias [nelem [maxelem]]
+ *
+ * initMappings
+ * mapping = nextMapping
+ * freeMapping mapping
+ * raiseMapping mapping [reference]
+ * lowerMapping mapping [reference]
+ * enableMapping mapping [refresh]
+ * disableMapping mapping [erase]
+ * active = activeMapping mapping
+ * refreshMapping mapping
+ *
+ * copyRaster rop src st sx sy snx sny dst dt dx dy dnx dny
+ * setMapping mapping rop
+ * src st sx sy snx sny dst dt dx dy dnx dny
+ * getMapping mapping rop
+ * src st sx sy snx sny dst dt dx dy dnx dny
+ *
+ * raster = selectRaster dras dt dx dy rt rx ry [map]
+ * unmapPixel sx sy raster rx ry [rz]
+ *
+ * flip mapping axis [axis...]
+ *
+ * Pixel arrays are long strings consisting either of a sequence of numeric
+ * pixel values separated by whitespace (space or newline), or a hex encoded
+ * sequence of bytes (1 or 2 hex digits per 8 bit pixel). Hex encoded pixel
+ * arrays may optionally be compressed using a simple run length encoding
+ # scheme. Colors are specified as a list of RGB triplets, e.g., { {R G B}
+ # {R G B} ... }.
+ *
+ * Refer to the documentation for the Gterm widget for a detailed description
+ * of rasters, mappings, and colormaps.
+ *
+ * Markers:
+ *
+ * createMarker name [attribute-list]
+ * markerInit
+ *
+ * New markers may be created with createMarker. Once created, a marker
+ * functions under the Object Manager as a named object of class "marker".
+ * Refer to the marker class for a description of the commands defined for
+ * a marker.
+ */
+
+#define MAX_COLORS 256
+#define MAX_POLYPTS 4096
+#define FIRST_COLOR 10
+#define CB_Input 1
+#define CB_Resize 2
+#define CB_Reset 3
+
+/* Gterm class instance descriptor. */
+struct gtermPrivate {
+ ObmCallback callback_list;
+ int colormap;
+ float offset, scale;
+};
+
+typedef struct gtermPrivate *GtermPrivate;
+
+struct gtermObject {
+ struct obmObjectCore core;
+ struct widgetPrivate widget;
+ struct gtermPrivate gterm;
+};
+
+typedef struct gtermObject *GtermObject;
+
+/* Gterm class class record private data. */
+typedef struct {
+ /* standard MsgContext fields. */
+ Tcl_Interp *tcl; /* class interpreter */
+ ObmObject object[MAX_LEVELS]; /* object which received last message */
+ int level;
+
+ /* Gterm specific fields. */
+ /* (none) */
+} gtermClassData, *GtermClassData;
+
+
+void GtermDestroy();
+void GtermClassDestroy();
+ObmObject GtermCreate();
+
+static int gtermActivate(), gtermActiveMapping(), gtermActiveRasters();
+static int gtermAddCallback(), gtermDeleteCallback();
+static int gtermAssignRaster(), gtermBell(), gtermGetBias();
+static int gtermClearScreen(), gtermClientPixel(), gtermCopyRaster();
+static int gtermCreateMarker(), gtermCreateRaster(), gtermDeactivate();
+static int gtermDestroyRaster(), gtermDisableMapping(), gtermDrawAlphaText();
+static int gtermDrawDialogText(), gtermDrawMarker(), gtermDrawPolygon();
+static int gtermDrawPolyline(), gtermDrawPolymarker(), gtermEnableMapping();
+static int gtermEndDialog(), gtermEraseDialog(), gtermExtractPixmap();
+static int gtermFlip(), gtermFlush(), gtermFreeColormap();
+static int gtermFreeMapping(), gtermRaiseMapping(), gtermLowerMapping();
+static int gtermGetAlphaTextSize(), gtermGetCursorPos();
+static int gtermGetDialogTextSize(), gtermGetLogRes(), gtermGetMapping();
+static int gtermGetPhysRes(), gtermGetPixel(), gtermGetRaster();
+static int gtermInitMappings(), gtermInsertPixmap(), gtermLoadColormap();
+static int gtermMarkerInit(), gtermNextColormap(), gtermNextMapping();
+static int gtermNextRaster(), gtermQueryRaster(), gtermRasterInit();
+static int gtermReadColormap(), gtermReadPixels(), gtermRefreshMapping();
+static int gtermRefreshPixels(), gtermReset(), gtermSelectRaster();
+static int gtermSetColorIndex(), gtermSetCursorPos(), gtermSetCursorType();
+static int gtermSetDataLevel(), gtermSetFillType(), gtermSetGterm();
+static int gtermSetLineStyle(), gtermSetLineWidth(), gtermSetLogRes();
+static int gtermSetMapping(), gtermSetPhysRes(), gtermSetPixel();
+static int gtermSetPixels(), gtermSetRaster(), gtermSetTextRes();
+static int gtermStartDialog(), gtermUnmapPixel(), gtermWriteColormap();
+static int gtermWritePixels();
+
+static void gtermInputCallback();
+static void gtermResizeCallback(), gtermResetCallback();
+static void get_mapping(), put_mapping();
+static XPoint *get_points();
+extern double strtod(), atof();
+
+
+/* GtermClassInit -- Initialize the class record for the gterm widget class.
+ */
+void
+GtermClassInit (obm, classrec)
+ObmContext obm;
+register ObjClassRec classrec;
+{
+ register GtermClassData gcd;
+ register Tcl_Interp *tcl;
+ register ClientData c_gcd;
+
+ /* Install the class methods. */
+ classrec->ClassDestroy = GtermClassDestroy;
+ classrec->Create = (ObmFunc) GtermCreate;
+ classrec->Destroy = GtermDestroy;
+ classrec->Evaluate = WidgetEvaluate;
+
+ /* The gterm widget subclass has its own command set hence has its
+ * own interpreter. The widget will respond both to all the commands
+ * defined here, and to all the commands implemented by the base
+ * Widget class.
+ */
+ if (!classrec->class_data) {
+ gcd = (GtermClassData) XtCalloc (1, sizeof (gtermClassData));
+ gcd->tcl = tcl = Tcl_CreateInterp();
+ classrec->class_data = (XtPointer) gcd;
+ c_gcd = (ClientData)gcd;
+ gcd->level = 0;
+
+ Tcl_CreateCommand (tcl,
+ "activate", gtermActivate, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "activeMapping", gtermActiveMapping, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "activeRasters", gtermActiveRasters, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "addCallback", gtermAddCallback, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "deleteCallback", gtermDeleteCallback, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "assignRaster", gtermAssignRaster, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "bell", gtermBell, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "clearScreen", gtermClearScreen, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "clientPixel", gtermClientPixel, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "copyRaster", gtermCopyRaster, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "createMarker", gtermCreateMarker, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "createRaster", gtermCreateRaster, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "deactivate", gtermDeactivate, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "destroyRaster", gtermDestroyRaster, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "disableMapping", gtermDisableMapping, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "drawAlphaText", gtermDrawAlphaText, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "drawDialogText", gtermDrawDialogText, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "drawMarker", gtermDrawMarker, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "drawPolygon", gtermDrawPolygon, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "drawPolyline", gtermDrawPolyline, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "drawPolymarker", gtermDrawPolymarker, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "enableMapping", gtermEnableMapping, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "endDialog", gtermEndDialog, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "eraseDialog", gtermEraseDialog, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "extractPixmap", gtermExtractPixmap, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "flip", gtermFlip, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "flush", gtermFlush, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "freeColormap", gtermFreeColormap, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "freeMapping", gtermFreeMapping, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "raiseMapping", gtermRaiseMapping, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "lowerMapping", gtermLowerMapping, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "getAlphaTextSize", gtermGetAlphaTextSize, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "getBias", gtermGetBias, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "getCursorPos", gtermGetCursorPos, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "getDialogTextSize", gtermGetDialogTextSize, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "getLogRes", gtermGetLogRes, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "getMapping", gtermGetMapping, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "getPhysRes", gtermGetPhysRes, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "getPixel", gtermGetPixel, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "getRaster", gtermGetRaster, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "initMappings", gtermInitMappings, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "insertPixmap", gtermInsertPixmap, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "loadColormap", gtermLoadColormap, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "markerInit", gtermMarkerInit, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "nextColormap", gtermNextColormap, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "nextMapping", gtermNextMapping, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "nextRaster", gtermNextRaster, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "queryRaster", gtermQueryRaster, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "rasterInit", gtermRasterInit, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "readColormap", gtermReadColormap, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "readPixels", gtermReadPixels, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "refreshMapping", gtermRefreshMapping, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "refreshPixels", gtermRefreshPixels, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "reset", gtermReset, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "selectRaster", gtermSelectRaster, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setColorIndex", gtermSetColorIndex, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setCursorPos", gtermSetCursorPos, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setCursorType", gtermSetCursorType, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setDataLevel", gtermSetDataLevel, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setFillType", gtermSetFillType, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setGterm", gtermSetGterm, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setLineStyle", gtermSetLineStyle, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setLineWidth", gtermSetLineWidth, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setLogRes", gtermSetLogRes, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setMapping", gtermSetMapping, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setPhysRes", gtermSetPhysRes, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setPixel", gtermSetPixel, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setPixels", gtermSetPixels, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setRaster", gtermSetRaster, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setTextRes", gtermSetTextRes, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "startDialog", gtermStartDialog, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "unmapPixel", gtermUnmapPixel, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "writeColormap", gtermWriteColormap, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "writePixels", gtermWritePixels, c_gcd, NULL);
+ }
+}
+
+
+/* GtermClassDestroy -- Custom destroy procedure for the widget class.
+ */
+void
+GtermClassDestroy (obm, classrec)
+ObmContext obm;
+register ObjClassRec classrec;
+{
+ register GtermClassData gcd = (GtermClassData) classrec->class_data;
+
+ if (gcd) {
+ if (gcd->tcl)
+ Tcl_DeleteInterp (gcd->tcl);
+ XtFree ((char *)gcd);
+ classrec->class_data = NULL;
+ }
+}
+
+
+/* GtermCreate -- Create an instance of a gterm object.
+ */
+ObmObject
+GtermCreate (obm, name, classrec, parent, args, nargs)
+ObmContext obm;
+char *name;
+ObjClassRec classrec;
+char *parent;
+ArgList args;
+int nargs;
+{
+ register GtermObject obj;
+ Widget w, pw;
+
+ obj = (GtermObject) WidgetCreate (obm, name,
+ classrec, parent, args, nargs);
+ if (obj == NULL)
+ return (NULL);
+
+ obj = (GtermObject) XtRealloc ((char *)obj, sizeof(struct gtermObject));
+ if (obj == NULL)
+ return (NULL);
+
+ /* Initialize GtermPrivate instance structure. */
+ obj->gterm.callback_list = NULL;
+ obj->gterm.colormap = 0;
+ obj->gterm.offset = 0.5;
+ obj->gterm.scale = 1.0;
+
+ return ((ObmObject) obj);
+}
+
+
+/* GtermDestroy -- Destroy an instance of a gterm object.
+ */
+void
+GtermDestroy (object)
+ObmObject object;
+{
+ GtermObject obj = (GtermObject) object;
+ ObjClassRec classrec = obj->core.classrec;
+ register GtermClassData gcd = (GtermClassData) classrec->class_data;
+ register ObmCallback cb, cb_next;
+ ObmContext obm = obj->widget.obm;
+ Widget w = obj->widget.w;
+
+ /* Destroy the object in the second final call to Destroy. */
+ if (!obj->core.being_destroyed++)
+ return;
+
+ /* Invoke any posted setGterm callbacks. This is not completely
+ * correct; in principle we should call the setGterm callback only
+ * if the active gterm widget is destroyed.
+ */
+ for (cb = obm->callback_list; cb; cb = cb->next)
+ if ((cb->callback_type & OBMCB_setGterm) && cb->u.fcn)
+ (*cb->u.fcn) (cb->client_data, NULL);
+
+ /* Free any gterm callback descriptors. */
+ for (cb = obj->gterm.callback_list; cb; cb = cb_next) {
+ cb_next = cb->next;
+
+ /* Delete the widget level callback. */
+ switch (cb->callback_type) {
+ case CB_Input:
+ GtDeleteInputProc (w, gtermInputCallback, (XtPointer)cb);
+ break;
+ case CB_Resize:
+ GtDeleteResizeProc (w, gtermResizeCallback, (XtPointer)cb);
+ break;
+ case CB_Reset:
+ GtDeleteResetProc (w, gtermResetCallback, (XtPointer)cb);
+ break;
+ }
+
+ XtFree ((char *)cb);
+ }
+
+ WidgetDestroy (object);
+}
+
+
+/*
+ * GTERM class commands.
+ * -----------------------
+ */
+
+
+/* SetGterm -- Set the active Gterm widget. Call any OBMCB_setGterm callbacks
+ * registered by the client code, passing the client the Xt Widget handle of
+ * the active gterm widget.
+ *
+ * Usage: setGterm [arg [arg ...]]
+ *
+ * This feature may be used during GUI execution to identify the currently
+ * active gterm widget to the client, or during startup to pass the Widget id
+ * to the client code so that it can talk directly to the gterm widget.
+ */
+static int
+gtermSetGterm (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ register GtermClassData gcd = (GtermClassData) msg;
+ GtermObject obj = (GtermObject) gcd->object[gcd->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmCallback cb;
+ ObmContext obm = wp->obm;
+ char *message;
+
+ message = (argc > 1) ? Tcl_Concat (argc-1, &argv[1]) : NULL;
+
+ for (cb = obm->callback_list; cb; cb = cb->next)
+ if ((cb->callback_type & OBMCB_setGterm) && cb->u.fcn)
+ (*cb->u.fcn) (cb->client_data, wp->w, message);
+
+ if (message)
+ free ((char *)message);
+
+ return (TCL_OK);
+}
+
+
+/* Activate -- Activate the gterm widget. This causes the next GIN mode
+ * setCursorType to warp the pointer into the gterm window.
+ *
+ * Usage: activate
+ */
+static int
+gtermActivate (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+
+ GtActivate (w);
+ return (TCL_OK);
+}
+
+
+/* Deactivate -- Deactivate the gterm widget. If the cursor has been warped
+ * into the window by a previous activate/setCursorType GIN mode, this causes
+ * the cursor to be warped back to where it was previously.
+ *
+ * Usage: deactivate
+ */
+static int
+gtermDeactivate (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+
+ GtDeactivate (w);
+ return (TCL_OK);
+}
+
+
+/* Reset -- Reset the gterm widget. This causes a number of state variables
+ * affecting graphics drawing options to be set to their default values.
+ *
+ * Usage: reset
+ */
+static int
+gtermReset (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+
+ GtReset (w);
+ return (TCL_OK);
+}
+
+
+/* Flush -- Flush any graphics output and synchronize the state of the widget
+ * with what is shown on the display.
+ *
+ * Usage: flush
+ *
+ * The gterm widget uses XLIB, which buffers graphics drawing commands and
+ * automatically sends them to the X server when 1) the buffer fills,
+ * 2) input is requested from the server. Such buffering of data is necessary
+ * for efficient operation and it should rarely be necessary to explicitly
+ * flush graphics output since XLIB does this automatically in most cases.
+ * An example of when explicitly flushing the ouptut might be necessary is in
+ * cases where smooth animation is desired and drawing the graphics in batches
+ * could cause the display to appear "jerky".
+ */
+static int
+gtermFlush (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+
+ GtFlush (w);
+ return (TCL_OK);
+}
+
+
+/* AddCallback -- Post a callback for a Gterm widget event.
+ *
+ * Usage: addCallback procedure-name [callback-type]
+ *
+ * The recognized Gterm callbacks are
+ *
+ * input Called when the graphics-input action is invoked in
+ * a translation table. The default Gterm translation
+ * table invokes this action when a KeyPress event occurs
+ * in the Gterm window.
+ *
+ * Callback: widget-name input-type event-data
+ *
+ * resize Called when the gterm window is resized.
+ *
+ * Callback: widget-name width height
+ *
+ * reset Called when the "reset" action is invoked.
+ *
+ * Callback: widget-name
+ *
+ * If no callback is specified the default is "input".
+ *
+ * Note that in GUI code one can also use the translation table to directly
+ * invoke GUI procedures without need to use the Gterm input mechanism. This
+ * is more flexible but we support the Gterm input callback here for
+ * applications that use the default translations.
+ */
+static int
+gtermAddCallback (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register GtermPrivate gp = &obj->gterm;
+ register Widget w = wp->w;
+ char *userproc, *callback_type;
+ ObmCallback cb, new;
+ int type;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ userproc = argv[1];
+ callback_type = (argc > 2) ? argv[2] : "input";
+
+ if (strcmp (callback_type, "input") == 0)
+ type = CB_Input;
+ else if (strcmp (callback_type, "resize") == 0)
+ type = CB_Resize;
+ else if (strcmp (callback_type, "reset") == 0)
+ type = CB_Reset;
+ else
+ return (TCL_ERROR);
+
+ /* Initialize callback descriptor. */
+ new = (ObmCallback) XtCalloc (1, sizeof (obmCallback));
+ new->u.obj = (ObmObject) obj;
+ new->callback_type = type;
+ strncpy (new->name, userproc, SZ_NAME);
+
+ /* Append descriptor to callback list for widget. */
+ for (cb = gp->callback_list; cb && cb->next; cb = cb->next)
+ ;
+ if (cb)
+ cb->next = new;
+ else
+ gp->callback_list = new;
+
+ /* Register the callback with the widget. */
+ switch (type) {
+ case CB_Input:
+ GtPostInputProc (w, gtermInputCallback, (XtPointer)new);
+ break;
+ case CB_Resize:
+ GtPostResizeProc (w, gtermResizeCallback, (XtPointer)new);
+ break;
+ case CB_Reset:
+ GtPostResetProc (w, gtermResetCallback, (XtPointer)new);
+ break;
+ }
+
+ return (TCL_OK);
+}
+
+
+/* DeleteCallback -- Delete a gterm callback.
+ *
+ * Usage: deleteCallback procedure
+ */
+static int
+gtermDeleteCallback (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register GtermPrivate gp = &obj->gterm;
+ register ObmCallback cb, prev;
+ Widget w = obj->widget.w;
+ char *procedure;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+ procedure = argv[1];
+
+ /* Locate and delete procedure entry in callback list. */
+ for (prev=NULL, cb=gp->callback_list; cb; prev=cb, cb=cb->next)
+ if (strcmp (cb->name, procedure) == 0) {
+ /* Delete the widget level callback. */
+ switch (cb->callback_type) {
+ case CB_Input:
+ GtDeleteInputProc (w, gtermInputCallback, (XtPointer)cb);
+ break;
+ case CB_Resize:
+ GtDeleteResizeProc (w, gtermResizeCallback, (XtPointer)cb);
+ break;
+ case CB_Reset:
+ GtDeleteResetProc (w, gtermResetCallback, (XtPointer)cb);
+ break;
+ }
+ if (prev)
+ prev->next = cb->next;
+ else
+ gp->callback_list = cb->next;
+ XtFree ((char *)cb);
+ break;
+ }
+
+ return (TCL_OK);
+}
+
+
+/* gtermInputCallback -- Low level callback procedure, called by the Gterm
+ * widget when an input event occurs.
+ *
+ * Callback: userproc widget-name input-type x y data
+ * Example: userproc widget-name keyPress x y {a shift}
+ *
+ * where input-type is keyPress, keyRelease, buttonPress, or buttonRelease,
+ * and data depends upon the type of input event. data is a list of strings
+ * delimited by braces. The first string is the key or button pressed and
+ * the following strings give the state of any modifier keys ("shift",
+ * "control" and so on).
+ */
+static void
+gtermInputCallback (cb, w, event)
+ObmCallback cb;
+Widget w;
+XEvent *event;
+{
+ GtermObject obj = (GtermObject) cb->u.obj;
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ char s_x[SZ_NUMBER], s_y[SZ_NUMBER];
+ char message_data[SZ_LINE];
+ char *event_type;
+ int status;
+
+ switch (event->type) {
+ case KeyPress:
+ case KeyRelease:
+ { XKeyPressedEvent *ev = (XKeyPressedEvent *) event;
+ register char *ip, *op = message_data;
+ char buf[SZ_MESSAGE];
+ int n;
+
+ if (event->type == KeyPress)
+ event_type = "keyPress";
+ else
+ event_type = "keyRelease";
+
+ sprintf (s_x, "%d", ev->x);
+ sprintf (s_y, "%d", ev->y);
+
+ if ((n = XLookupString(ev,buf,sizeof(buf),NULL,NULL)) > 0) {
+ for (ip=buf; --n >= 0; )
+ if (*ip <= ' ') {
+ *op++ = '^';
+ *op++ = *ip++ + 'A' - 1;
+ } else if (isprint (*ip)) {
+ *op++ = *ip++;
+ } else
+ ip++;
+ } else {
+ /* This case occurs when only a modifier is typed. */
+ for (ip = "??"; *op++ = *ip++; )
+ ;
+ }
+ *op++ = ' ';
+ op = widgetEventState (op, ev->state);
+ while (op > message_data && isspace (*(op-1)))
+ --op;
+ *op = '\0';
+ }
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ { XButtonPressedEvent *ev = (XButtonPressedEvent *) event;
+ register char *op = message_data;
+
+ if (event->type == KeyPress)
+ event_type = "buttonPress";
+ else
+ event_type = "buttonRelease";
+
+ sprintf (s_x, "%d", ev->x);
+ sprintf (s_y, "%d", ev->y);
+
+ sprintf (op, "%d ", ev->button);
+ while (*op)
+ op++;
+ *op++ = ' ';
+ op = widgetEventState (op, ev->state);
+ while (op > message_data && isspace (*(op-1)))
+ --op;
+ *op = '\0';
+ }
+ break;
+
+ default:
+ strcpy (message_data, "unknown none");
+ }
+
+ status = Tcl_VarEval (obm->tcl,
+ cb->name, " ",
+ obj->core.name, " ",
+ event_type, " ",
+ s_x, " ",
+ s_y, " ",
+ "{", message_data, "}",
+ NULL);
+
+ if (status != TCL_OK) {
+ char *errstr = Tcl_GetVar (obm->tcl, "errorInfo", 0);
+ fprintf (stderr, "Error on line %d in %s: %s\n",
+ obm->tcl->errorLine, cb->name,
+ errstr ? errstr : obm->tcl->result);
+ }
+}
+
+
+/* gtermResizeCallback -- Low level callback procedure, called by the Gterm
+ * widget when a resize event occurs.
+ *
+ * Callback: userproc widget-name width height
+ */
+static void
+gtermResizeCallback (cb, w)
+ObmCallback cb;
+Widget w;
+{
+ GtermObject obj = (GtermObject) cb->u.obj;
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ int rtype, width, height, depth, status;
+ char s_width[SZ_NUMBER], s_height[SZ_NUMBER];
+
+ GtQueryRaster (wp->w, 0, &rtype, &width, &height, &depth);
+ sprintf (s_width, "%d", width);
+ sprintf (s_height, "%d", height);
+
+ status = Tcl_VarEval (obm->tcl,
+ cb->name, " ",
+ obj->core.name, " ",
+ s_width, " ",
+ s_height, " ",
+ NULL);
+
+ if (status != TCL_OK) {
+ char *errstr = Tcl_GetVar (obm->tcl, "errorInfo", 0);
+ fprintf (stderr, "Error on line %d in %s: %s\n",
+ obm->tcl->errorLine, cb->name,
+ errstr ? errstr : obm->tcl->result);
+ }
+}
+
+
+/* gtermResetCallback -- Low level callback procedure, called by the Gterm
+ * widget when a reset event occurs.
+ *
+ * Callback: userproc
+ */
+static void
+gtermResetCallback (cb, w)
+ObmCallback cb;
+Widget w;
+{
+ GtermObject obj = (GtermObject) cb->u.obj;
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ int status;
+
+ status = Tcl_VarEval (obm->tcl,
+ cb->name, " ",
+ obj->core.name, " ",
+ NULL);
+
+ if (status != TCL_OK) {
+ char *errstr = Tcl_GetVar (obm->tcl, "errorInfo", 0);
+ fprintf (stderr, "Error on line %d in %s: %s\n",
+ obm->tcl->errorLine, cb->name,
+ errstr ? errstr : obm->tcl->result);
+ }
+}
+
+
+/* SetCursorPos -- Warp the cursor (pointer) to the given coordinates. This
+ * is a graphics drawing command and if no raster number is specified the
+ * current reference drawing raster, as set with setRaster, defines the
+ * coordinate system.
+ *
+ * Usage: setCursorPos x y [raster]
+ *
+ * A raster number may optionally given to define the raster coordinate system
+ * to be used. raster=0 yields screen coordinates.
+ */
+static int
+gtermSetCursorPos (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ int raster, sv_raster, x, y;
+
+ if (argc < 3)
+ return (TCL_ERROR);
+
+ x = (int) atof (argv[1]);
+ y = (int) atof (argv[2]);
+ raster = (argc > 3) ? atoi (argv[3]) : -1;
+
+ if (raster >= 0) {
+ sv_raster = GtGetRaster (wp->w);
+ if (raster != sv_raster)
+ GtSetRaster (wp->w, raster);
+ }
+
+ GtSetCursorPos (wp->w, x, y);
+
+ if (raster >= 0)
+ if (raster != sv_raster)
+ GtSetRaster (wp->w, sv_raster);
+
+ return (TCL_OK);
+}
+
+
+/* GetCursorPos -- Get the cursor position (raster 0 or screen coordinates).
+ *
+ * Usage: getCursorPos x y
+ */
+static int
+gtermGetCursorPos (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ char *xout, *yout, buf[SZ_NUMBER];
+ int x, y;
+
+ if (argc < 3)
+ return (TCL_ERROR);
+
+ xout = argv[1];
+ yout = argv[2];
+
+ GtGetCursorPos (wp->w, &x, &y);
+ sprintf (buf, "%d", x);
+ Tcl_SetVar (obm->tcl, xout, buf, 0);
+ sprintf (buf, "%d", y);
+ Tcl_SetVar (obm->tcl, yout, buf, 0);
+
+ return (TCL_OK);
+}
+
+
+/* setCursorType -- Set the cursor type.
+ *
+ * Usage: setCursorType cursor-type
+ *
+ * idle default cursor
+ *
+ * busy busy cursor, e.g, when program is busy
+ *
+ * ginMode graphics input mode cursor, set when program is
+ * waiting for graphics input
+ */
+static int
+gtermSetCursorType (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ char *cursor_type;
+ int type;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ cursor_type = argv[1];
+ if (strcmp (cursor_type, "idle") == 0)
+ type = GtIdleCursor;
+ else if (strcmp (cursor_type, "busy") == 0)
+ type = GtBusyCursor;
+ else if (strcmp (cursor_type, "ginMode") == 0)
+ type = GtGinmodeCursor;
+ else
+ return (TCL_ERROR);
+
+ GtSetCursorType (w, type);
+
+ return (TCL_OK);
+}
+
+
+/* Bell -- Gterm widget sound output.
+ *
+ * Usage: bell
+ */
+static int
+gtermBell (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+
+ GtBell (w);
+ return (TCL_OK);
+}
+
+
+/* setRaster -- Set the number of the raster to be used to define the drawing
+ * context (e.g. coordinate system) for graphics and text drawing functions.
+ *
+ * Usage: setRaster raster-number
+ */
+static int
+gtermSetRaster (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int raster;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ raster = atoi (argv[1]);
+ GtSetRaster (w, raster);
+
+ return (TCL_OK);
+}
+
+
+/* getRaster -- Get the number of the raster which defines the drawing
+ * context, as set in the last setRaster call.
+ *
+ * Usage: raster = getRaster [raster]
+ *
+ * If the name of a variable is given the raster number will be stored
+ * directly in that variable.
+ */
+static int
+gtermGetRaster (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ char buf[SZ_NUMBER], *raster_var;
+ int raster;
+
+ raster = GtGetRaster (w);
+ sprintf (buf, "%d", raster);
+
+ if (argc == 2)
+ Tcl_SetVar (obm->tcl, argv[1], buf, 0);
+ Tcl_SetResult (obm->tcl, buf, TCL_VOLATILE);
+
+ return (TCL_OK);
+}
+
+
+/* setLogRes -- Set the logical resolution of the graphics drawing surface
+ * in pixels. This defines the range of coordinates in drawing commands
+ * for drawing graphics such as lines, areas, or text.
+ *
+ * Usage: setLogRes width height
+ *
+ * Note that this has nothing to do with imaging and the resolution of an
+ * image raster. The logical resolution of the graphics system is independent
+ * of the physical resolution of the drawing surface.
+ */
+static int
+gtermSetLogRes (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int width, height;
+
+ if (argc < 3)
+ return (TCL_ERROR);
+
+ width = atoi (argv[1]);
+ height = atoi (argv[2]);
+ GtSetLogRes (w, width, height);
+
+ return (TCL_OK);
+}
+
+
+/* getLogRes -- Get the logical resolution of the graphics drawing surface
+ * in pixels.
+ *
+ * Usage: getLogRes width height
+ */
+static int
+gtermGetLogRes (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ char *s_width, *s_height;
+ char buf[SZ_NUMBER];
+ int width, height;
+
+ if (argc < 3)
+ return (TCL_ERROR);
+
+ s_width = argv[1];
+ s_height = argv[2];
+ GtGetLogRes (w, &width, &height);
+
+ sprintf (buf, "%d", width);
+ Tcl_SetVar (obm->tcl, s_width, buf, 0);
+ sprintf (buf, "%d", height);
+ Tcl_SetVar (obm->tcl, s_height, buf, 0);
+
+ return (TCL_OK);
+}
+
+
+/* setPhysRes -- Set the physical resolution of the graphics drawing surface
+ * in pixels. This represents an attempt to resize the graphics window to
+ * provide the requested resolution, i.e., to the given size width*height.
+ *
+ * Usage: setPhysRes width height [raster]
+ *
+ * This function is equivalent to a createRaster request for the indicated
+ * raster. The default raster is the current drawing raster.
+ */
+static int
+gtermSetPhysRes (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int raster, width, height;
+
+ if (argc < 3)
+ return (TCL_ERROR);
+
+ width = atoi (argv[1]);
+ height = atoi (argv[2]);
+ raster = (argc > 3) ? atoi(argv[3]) : GtGetRaster(w);
+ GtSetPhysRes (w, raster, width, height);
+
+ return (TCL_OK);
+}
+
+
+/* getPhysRes -- Get the physical resolution of the graphics drawing surface
+ * in pixels.
+ *
+ * Usage: raster = getPhysRes width height [raster]
+ *
+ * If no raster number is specified the dimensions of the current drawing
+ * raster are returned.
+ */
+static int
+gtermGetPhysRes (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ char *s_width, *s_height;
+ int raster, width, height;
+ char buf[SZ_NUMBER];
+
+ if (argc < 3)
+ return (TCL_ERROR);
+
+ s_width = argv[1];
+ s_height = argv[2];
+ raster = (argc > 3) ? atoi(argv[3]) : GtGetRaster(w);
+ GtGetPhysRes (w, raster, &width, &height);
+
+ sprintf (buf, "%d", width);
+ Tcl_SetVar (obm->tcl, s_width, buf, 0);
+ sprintf (buf, "%d", height);
+ Tcl_SetVar (obm->tcl, s_height, buf, 0);
+
+ sprintf (buf, "%d", raster);
+ Tcl_SetResult (obm->tcl, buf, TCL_VOLATILE);
+
+ return (TCL_OK);
+}
+
+
+/* setTextRes -- Set the resolution of the graphics drawing surface in
+ * characters (e.g., 80x35).
+ *
+ * Usage: setTextRes rows cols
+ *
+ * When drawing text the widget will space characters to achieve the desired
+ * resolution. When the drawing window is resized the widget will use this
+ * number to select the best font.
+ */
+static int
+gtermSetTextRes (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int rows, cols;
+
+ if (argc < 3)
+ return (TCL_ERROR);
+
+ rows = atoi (argv[1]);
+ cols = atoi (argv[2]);
+ GtSetTextRes (w, rows, cols);
+
+ return (TCL_OK);
+}
+
+
+/* setDataLevel -- Set the logical drawing function used when drawing graphics
+ * or text.
+ *
+ * Usage: setDataLevel level
+ *
+ * The recognized data levels for drawing are "set", "clear", and "invert".
+ * Once set the data level remains in effect until the next clearScreen or
+ * reset.
+ */
+static int
+gtermSetDataLevel (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int level;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+ if ((level = dataLevelType (argv[1])) < 0)
+ return (TCL_ERROR);
+ GtSetDataLevel (w, level);
+
+ return (TCL_OK);
+}
+
+
+/* setLineWidth -- Set the line width for drawing operations.
+ *
+ * Usage: setLineWidth width
+ *
+ * The line width is specified in integer pixels. The value width=0 is
+ * equivalent to width=1 but may permit faster drawing in some cases.
+ * Once set the line width remains in effect until the next clearScreen or
+ * reset.
+ */
+static int
+gtermSetLineWidth (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int width;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+ if ((width = atoi (argv[1])) < 0)
+ return (TCL_ERROR);
+ GtSetLineWidth (w, width);
+
+ return (TCL_OK);
+}
+
+
+/* setLineStyle -- Set the line style for drawing operations.
+ *
+ * Usage: setLineStyle style
+ *
+ * The line style determines whether a solid or dashed line is drawn. The
+ * recognized line styles are "solid", "dashed", "dotted", dashDot", and
+ * "dash3dot". Once set the line style remains in effect until the next
+ * clearScreen or reset.
+ */
+static int
+gtermSetLineStyle (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int style;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+ if ((style = lineStyle (argv[1])) < 0)
+ return (TCL_ERROR);
+ GtSetLineStyle (w, style);
+
+ return (TCL_OK);
+}
+
+
+/* setColorIndex -- Set the gterm widget color index for drawing graphics and
+ * text.
+ *
+ * Usage: setColorIndex index
+ *
+ * The color index is an integer in the range 0 to N, where N is the maximum
+ * number of color table entries permitted by the widget. The gterm widget
+ * implements a simple color allocation scheme: color index 0 is the background
+ * color, 1 is the foreground, 2-9 are fixed, statically allocated colors (red,
+ * green, blue, etc.) and color indices 10 and greater are dynamically
+ * allocated private colors allocated at runtime by the application.
+ *
+ * Colors may be specified by number or by one of the names "background"
+ * "foreground", "black", "white", "red", "green", "blue", "cyan", "yellow",
+ * "magenta", "user1", or "user2". These names are aliases for color indices
+ * 0-9 and the actual color may differ from the logical color associated with
+ * the given statically defined color index.
+ *
+ * Once set the drawing color remains in effect until the next clearScreen or
+ * reset.
+ */
+static int
+gtermSetColorIndex (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int color;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+ if ((color = colorToIndex (argv[1])) < 0)
+ return (TCL_ERROR);
+ GtSetColorIndex (w, color);
+
+ return (TCL_OK);
+}
+
+
+/* setFillType -- Set the type of fill for area-fill drawing operations.
+ *
+ * Usage: setFillType filltype
+ *
+ * The fill type may be "solid" or "outline". Once set the fill type remains
+ * in effect until the next clearScreen or reset.
+ */
+static int
+gtermSetFillType (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int filltype;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+ if ((filltype = fillType (argv[1])) < 0)
+ return (TCL_ERROR);
+ GtSetFillType (w, filltype);
+
+ return (TCL_OK);
+}
+
+
+/* clearScreen -- Clear the "screen", i.e., window. This action clears the
+ * drawing window and sets a number of drawing state variables to their default
+ * values.
+ *
+ * Usage: clearScreen
+ */
+static int
+gtermClearScreen (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+
+ GtClearScreen (w);
+ return (TCL_OK);
+}
+
+
+/* drawPolyline -- Draw a polyline.
+ *
+ * Usage: drawPolyline points
+ *
+ * The points vector is a list of points, wherein each point is itself a list
+ * consisting of two elements, the X and Y coordinates of the point. The
+ * coordinate system is the logical coordinate system defined by setLogRes.
+ * All drawing attributes such as the line width, style, color, context raster
+ * if any, and so on will affect the drawing operation.
+ */
+static int
+gtermDrawPolyline (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ register XPoint *pv;
+ int npoints;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ if ((pv = get_points (argv[1], &npoints)) == NULL)
+ return (TCL_ERROR);
+ GtDrawPolyline (w, pv, npoints);
+
+ XtFree ((char *)pv);
+ return (TCL_OK);
+}
+
+
+/* drawPolymarker -- Draw a polymarker, or sequence of points.
+ *
+ * Usage: drawPolymarker points
+ *
+ * The points vector is a list of points, wherein each point is itself a list
+ * consisting of two elements, the X and Y coordinates of the point. The
+ * coordinate system is the logical coordinate system defined by setLogRes.
+ * All drawing attributes such as the line width, style, color, context raster
+ * if any, and so on will affect the drawing operation.
+ */
+static int
+gtermDrawPolymarker (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ register XPoint *pv;
+ int npoints;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ if ((pv = get_points (argv[1], &npoints)) == NULL)
+ return (TCL_ERROR);
+ GtDrawPolymarker (w, pv, npoints);
+
+ XtFree ((char *)pv);
+ return (TCL_OK);
+}
+
+
+/* drawPolygon -- Draw a polygon, or filled area.
+ *
+ * Usage: drawPolygon points
+ *
+ * The points vector is a list of points, wherein each point is itself a list
+ * consisting of two elements, the X and Y coordinates of the point. The
+ * coordinate system is the logical coordinate system defined by setLogRes.
+ * All drawing attributes such as the line width, style, color, context raster
+ * if any, and so on will affect the drawing operation.
+ */
+static int
+gtermDrawPolygon (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ register XPoint *pv;
+ int npoints;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ if ((pv = get_points (argv[1], &npoints)) == NULL)
+ return (TCL_ERROR);
+ GtDrawPolygon (w, pv, npoints);
+
+ XtFree ((char *)pv);
+ return (TCL_OK);
+}
+
+
+/* drawMarker -- Draw a marker.
+ *
+ * Usage: drawMarker type x y xsize ysize [rotangle]
+ *
+ * A marker of the indicated size and type is drawn at the indicated position.
+ * The marker type is one of "box", "circle", "ellipse", and so on.
+ */
+static int
+gtermDrawMarker (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+
+ /* not yet implemented. */
+ return (TCL_ERROR);
+}
+
+
+/* drawAlphaText -- Draw a graphics text string.
+ *
+ * Usage: drawAlphaText x y text
+ *
+ * A text string is drawn at the indicated position using the current alpha
+ * text font. The font is selected based on the window size from a resource
+ * defined list of alpha fonts of different sizes. Alpha text is drawn like
+ * line graphics, i.e., the background is visible through the text. Drawing
+ * attributes such as color, data level, context raster, etc. apply to text
+ * as well as to line graphics. Rotation of text strings is not supported.
+ * The coordinaes X,Y refer to the lower left corner of the text string where
+ * "lower" refers to the baseline of the font. That is, if the text string
+ * is "E", the coordinates x,y refer to the lower left corner of the E.
+ */
+static int
+gtermDrawAlphaText (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ char *text;
+ int x, y;
+
+ if (argc < 4)
+ return (TCL_ERROR);
+
+ x = atoi (argv[1]);
+ y = atoi (argv[2]);
+ text = argv[3];
+ GtDrawAlphaText (w, x, y, text);
+
+ return (TCL_OK);
+}
+
+
+/* getAlphaTextSize -- Get the size in destination drawable pixels of an
+ * alpha text string in terms of the current graphics context.
+ *
+ * Usage: width = getAlphaTextSize [string [width [height [base]]]]
+ *
+ * The size in pixels of the given string is returned in the WIDTH and HEIGHT
+ * output variables. If no string or the null string is given the maximum
+ * width and height of a single character in the font are returned. If a BASE
+ * output variable is given this variable will be set to the Y offset from the
+ * top of the string to the baseline of the characters forming the string.
+ */
+static int
+gtermGetAlphaTextSize (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ register XPoint *pv;
+
+ char *s_width, *s_height, *s_base;
+ int width, height, base;
+ char buf[SZ_NUMBER];
+ char *text;
+
+ if (argc > 1 && (int)strlen(argv[1]) > 0)
+ text = argv[1];
+ else
+ text = NULL;
+
+ s_width = (argc > 2) ? argv[2] : NULL;
+ s_height = (argc > 3) ? argv[3] : NULL;
+ s_base = (argc > 4) ? argv[4] : NULL;
+
+ GtGetAlphaTextSize (w, text, &width, &height, &base);
+ if (s_width) {
+ sprintf (buf, "%d", width);
+ Tcl_SetVar (obm->tcl, s_width, buf, 0);
+ }
+ if (s_height) {
+ sprintf (buf, "%d", height);
+ Tcl_SetVar (obm->tcl, s_height, buf, 0);
+ }
+ if (s_base) {
+ sprintf (buf, "%d", base);
+ Tcl_SetVar (obm->tcl, s_base, buf, 0);
+ }
+
+ sprintf (buf, "%d", width);
+ Tcl_SetResult (obm->tcl, buf, TCL_VOLATILE);
+
+ return (TCL_OK);
+}
+
+
+/* startDialog -- Activate the dialog area for dialog text drawing.
+ *
+ * Usage: startDialog
+ *
+ * Dialog text is text which is drawn into the dialog area at the bottom of
+ * the gterm window. Dialog text is transient and is not a permanent part of
+ * the graphics being drawn. Dialog text is normally used to interact with
+ * the user or to display messages during program operation, without affecting
+ * the graphics being drawn.
+ *
+ * startDialog is called to prepare the dialog area and initialize dialog
+ * text mode, prior to drawing dialog text with drawDialogText.
+ */
+static int
+gtermStartDialog (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ register XPoint *pv;
+
+ GtStartDialog (w);
+ return (TCL_OK);
+}
+
+
+/* endDialog -- Deactivate the dialog area used for dialog text drawing.
+ *
+ * Usage: endDialog
+ *
+ * endDialog is called when one is finished drawing dialog text, erasing
+ * the dialog text area and terminating dialog text mode.
+ */
+static int
+gtermEndDialog (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ register XPoint *pv;
+
+ GtEndDialog (w);
+ return (TCL_OK);
+}
+
+
+/* eraseDialog -- Erase the dialog text area.
+ *
+ * Usage: eraseDialog
+ *
+ * eraseDialog may be called at any time to erase the dialog text area without
+ * exiting dialog text mode.
+ */
+static int
+gtermEraseDialog (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ register XPoint *pv;
+
+ GtEraseDialog (w);
+ return (TCL_OK);
+}
+
+
+/* drawDialogText -- Draw a dialog box text string.
+ *
+ * Usage: drawDialogText x y text
+ *
+ * A text string is drawn at the indicated position using the current dialog
+ * text font. The font is selected based on the window size from a resource
+ * defined list of dialog fonts of different sizes. The attributes of dialog
+ * text (color etc.) are determined by the widget resources and the window
+ * size and are independent of the graphics context used for alpha text and
+ * other graphics. The coordinaes X,Y refer to the lower left corner of the
+ * text string where "lower" refers to the baseline of the font. That is, if
+ * the text string is "E", the coordinates x,y refer to the lower left corner
+ * of the E.
+ */
+static int
+gtermDrawDialogText (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ register XPoint *pv;
+ char *text;
+ int x, y;
+
+ if (argc < 4)
+ return (TCL_ERROR);
+
+ x = atoi (argv[1]);
+ y = atoi (argv[2]);
+ text = argv[3];
+ GtDrawDialogText (w, x, y, text);
+
+ return (TCL_OK);
+}
+
+
+/* getDialogTextSize -- Get the size in destination drawable pixels of an
+ * dialog text string in terms of the current graphics context.
+ *
+ * Usage: width = getDialogTextSize [string [width [height [base]]]]
+ *
+ * The size in pixels of the given string is returned in the WIDTH and HEIGHT
+ * output variables. If no string or the null string is given the maximum
+ * width and height of a single character in the font are returned. If a BASE
+ * output variable is given this variable will be set to the Y offset from the
+ * top of the string to the baseline of the characters forming the string.
+ */
+static int
+gtermGetDialogTextSize (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ register XPoint *pv;
+
+ char *s_width, *s_height, *s_base;
+ int width, height, base;
+ char buf[SZ_NUMBER];
+ char *text;
+
+ if (argc > 1 && (int)strlen(argv[1]) > 0)
+ text = argv[1];
+ else
+ text = NULL;
+
+ s_width = (argc > 2) ? argv[2] : NULL;
+ s_height = (argc > 3) ? argv[3] : NULL;
+ s_base = (argc > 4) ? argv[4] : NULL;
+
+ GtGetDialogTextSize (w, text, &width, &height, &base);
+ if (s_width) {
+ sprintf (buf, "%d", width);
+ Tcl_SetVar (obm->tcl, s_width, buf, 0);
+ }
+ if (s_height) {
+ sprintf (buf, "%d", height);
+ Tcl_SetVar (obm->tcl, s_height, buf, 0);
+ }
+ if (s_base) {
+ sprintf (buf, "%d", base);
+ Tcl_SetVar (obm->tcl, s_base, buf, 0);
+ }
+
+ sprintf (buf, "%d", width);
+ Tcl_SetResult (obm->tcl, buf, TCL_VOLATILE);
+
+ return (TCL_OK);
+}
+
+
+/* rasterInit -- Initialize the raster subsystem, deleting all rasters and
+ * mappings and freeing the dynamic part of the colortable.
+ *
+ * Usage: rasterInit
+ */
+static int
+gtermRasterInit (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+
+ GtRasterInit (w);
+ return (TCL_OK);
+}
+
+
+/* assignRaster -- Assign a raster to a preexisting, externally defined
+ * drawable (e.g. widget window or server pixmap).
+ *
+ * Usage: assignRaster raster drawable
+ *
+ * The drawable may be the name of a widget object elsewhere in the GUI,
+ * or the numeric server code for an arbitrary server pixmap or window.
+ * A special case occurs when the named widget object is another gterm
+ * widget. In this case graphics pipelines can be constructed piping data
+ * from the rasters and mappings of the first widget to those of the second,
+ * using a mapping to connect the two. When the destination raster is in
+ * another gterm widget the widget code will automatically execute any
+ * mappings defined on the affected raster when it is modified by the
+ * mapping from the first widget. This allows a raster to be mapped to
+ * and displayed in multiple destination windows.
+ */
+static int
+gtermAssignRaster (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject gt_obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &gt_obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ XtPointer drawable;
+ ObmObject obj;
+ int raster, type;
+ char *object;
+
+ if (argc < 3)
+ return (TCL_ERROR);
+
+ raster = atoi (argv[1]);
+ object = argv[2];
+
+ /* Get the drawable handle and type.
+ */
+ if (isdigit (*object)) {
+ /* A server pixmap or window passed by server ID. */
+ drawable = (XtPointer) atoi(object);
+ type = GtWindow;
+
+ } else {
+ /* A named object. */
+ if ((obj = obmFindObject (obm, object)) == NULL)
+ return (TCL_ERROR);
+ if (obj->core.classrec->object_type != OtNonShell)
+ return (TCL_ERROR); /* no window */
+
+ if (obmClass (obj->core.classrec, WtGterm)) {
+ /* Gterm widget.
+ drawable = (XtPointer) widgetGetPointer (obj);
+ */
+ drawable = (XtPointer) XtWindow (widgetGetPointer(obj));
+ type = GtWidget;
+
+ } else {
+ /* Some other type of widget. */
+ drawable = (XtPointer) XtWindow (widgetGetPointer(obj));
+ type = GtWindow;
+ }
+ }
+
+ if (GtAssignRaster (w, raster, drawable, type) == OK)
+ return (TCL_OK);
+ else
+ return (TCL_ERROR);
+}
+
+
+/* createRaster -- Create a raster of the given type and size.
+ *
+ * Usage: createRaster raster width height [type [depth]]
+ *
+ * A raster number RASTER is created with the given size and type. The
+ * possible raster types are "client", and "server", the default being
+ * to create a client raster. Rasters created in client memory are the
+ * most general and are best for most applications. Server side rasters
+ * are used only in special applications; server rasters can be copied to
+ * the display window very quickly but server memory is a limited resource
+ * and a program using large amounts of server memory may not run on some
+ * servers. Mappings other than one-to-one are *less* efficient on server
+ * rasters than on client rasters.
+ *
+ * Currently only rasters of depth 8 bits are supported. A createRaster on
+ * an existing raster will destroy the old raster, along with any mappings
+ * defined on it, and create a new one.
+ *
+ * Raster number zero is the gterm widget's display window. If one attempts
+ * a createRaster on this window the widget will try to resize the window.
+ * The resize attempt may or may not succeed, depending upon the resize
+ * restrictions of the geometry or window managers in use, shell resources,
+ * and so on.
+ *
+ * There is a limit on the maximum number of rasters which can be created,
+ * set by the gterm widget resource maxRasters at widget creation.
+ */
+static int
+gtermCreateRaster (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int raster, width, height, type, depth;
+ char *s_type;
+
+ if (argc < 4)
+ return (TCL_ERROR);
+
+ raster = atoi (argv[1]);
+ width = atoi (argv[2]);
+ height = atoi (argv[3]);
+ s_type = (argc > 4) ? argv[4] : "client";
+ depth = (argc > 5) ? atoi(argv[5]) : 0;
+
+ if (strcmp (s_type, "server") == 0)
+ type = GtServer;
+ else
+ type = GtClient;
+
+ if (GtCreateRaster (w, raster, type, width, height, depth) == ERR)
+ return (TCL_ERROR);
+
+ return (TCL_OK);
+}
+
+
+/* destroyRaster -- Destroy a raster.
+ *
+ * Usage: destroyRaster raster
+ *
+ * Raster number RASTER is destroyed along with all of its mappings. This is
+ * a no-op if the raster is not currently defined. Attempts to destroy raster
+ * number zero (the widget's window) are ignored.
+ */
+static int
+gtermDestroyRaster (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int raster;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ raster = atoi (argv[1]);
+ GtDestroyRaster (w, raster);
+
+ return (TCL_OK);
+}
+
+
+/* queryRaster -- Query a raster's attributes.
+ *
+ * Usage: exists = queryRaster raster [width height [type [depth]]]
+ *
+ * The width and height, and optionally the type and depth, of raster number
+ * RASTER are returned in the named output variables. The boolean function
+ * value indicates whether or not the raster is currently defined. If the
+ * raster does not exist the output variables may be undefined after the call.
+ */
+static int
+gtermQueryRaster (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+
+ char *s_width, *s_height, *s_type, *s_depth;
+ int exists, raster, width, height, type, depth;
+ char buf[SZ_NUMBER], *v_type;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ raster = atoi (argv[1]);
+ s_width = (argc > 2) ? argv[2] : NULL;
+ s_height = (argc > 3) ? argv[3] : NULL;
+ s_type = (argc > 4) ? argv[4] : NULL;
+ s_depth = (argc > 5) ? argv[5] : NULL;
+
+ if (GtQueryRaster (w, raster, &type, &width, &height, &depth)) {
+ if (s_width) {
+ sprintf (buf, "%d", width);
+ Tcl_SetVar (obm->tcl, s_width, buf, 0);
+ }
+ if (s_height) {
+ sprintf (buf, "%d", height);
+ Tcl_SetVar (obm->tcl, s_height, buf, 0);
+ }
+ if (s_type) {
+ v_type = (type == GtServer) ? "server" : "client";
+ Tcl_SetVar (obm->tcl, s_type, v_type, 0);
+ }
+ if (s_depth) {
+ sprintf (buf, "%d", depth);
+ Tcl_SetVar (obm->tcl, s_depth, buf, 0);
+ }
+ Tcl_SetResult (obm->tcl, TRUESTR, TCL_STATIC);
+
+ } else {
+ Tcl_SetResult (obm->tcl, FALSESTR, TCL_STATIC);
+ }
+
+ return (TCL_OK);
+}
+
+
+/* nextRaster -- Return the number of the next available, unused raster.
+ *
+ * Usage: raster = nextRaster
+ *
+ */
+static int
+gtermNextRaster (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ char buf[SZ_NUMBER];
+ int raster;
+
+ if ((raster = GtNextRaster (w)) < 0)
+ return (TCL_ERROR);
+ else {
+ sprintf (buf, "%d", raster);
+ Tcl_SetResult (obm->tcl, buf, TCL_VOLATILE);
+ }
+
+ return (TCL_OK);
+}
+
+
+/* activeRasters -- Return the number of currently defined rasters.
+ *
+ * Usage: count = activeRasters
+ *
+ */
+static int
+gtermActiveRasters (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ char buf[SZ_NUMBER];
+
+ sprintf (buf, "%d", GtNRasters(w));
+ Tcl_SetResult (obm->tcl, buf, TCL_VOLATILE);
+
+ return (TCL_OK);
+}
+
+
+/* setPixel -- Set the value of a single pixel.
+ *
+ * Usage: setPixel raster x y value
+ *
+ * raster The raster number.
+ *
+ * x, y The pixel to be set.
+ *
+ * value The pixel value.
+ *
+ * This routine is more efficient than writePixels for setting the value of
+ * a single pixel, but is a lot less efficient if a block of pixels are to
+ * be set.
+ */
+static int
+gtermSetPixel (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ ObmContext obm = wp->obm;
+ Widget w = wp->w;
+ int raster, x, y;
+ uchar data[1];
+
+ if (argc < 5)
+ return (TCL_ERROR);
+
+ raster = atoi (argv[1]);
+ x = atoi (argv[2]);
+ y = atoi (argv[3]);
+ data[0] = atoi (argv[4]);
+ GtWritePixels (w, raster, data, 8, x, y, 1, 1);
+
+ return (TCL_OK);
+}
+
+
+/* getPixel -- Get the value of a single pixel.
+ *
+ * Usage: getPixel raster x y
+ *
+ * raster The raster number.
+ *
+ * x, y The pixel to be set.
+ *
+ * This routine is more efficient than readPixels for getting the value of
+ * a single pixel, but is a lot less efficient if a block of pixels are to
+ * be read.
+ */
+static int
+gtermGetPixel (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ ObmContext obm = wp->obm;
+ Widget w = wp->w;
+ char buf[SZ_NUMBER];
+ int raster, x, y;
+ uchar data[1];
+
+ if (argc < 4)
+ return (TCL_ERROR);
+
+ raster = atoi (argv[1]);
+ x = atoi (argv[2]);
+ y = atoi (argv[3]);
+ GtReadPixels (w, raster, data, 8, x, y, 1, 1);
+
+ sprintf (buf, "%d", data[0]);
+ Tcl_SetResult (obm->tcl, buf, TCL_VOLATILE);
+
+ return (TCL_OK);
+}
+
+
+/* writePixels -- Set the values of some subset of the pixels in a raster.
+ * If any mappings are defined on the affected region and are enabled, any
+ * destination rasters will be automatically updated as defined by the mapping.
+ *
+ * Usage: writePixels raster pixels encoding nbits x1 y1 nx ny [bias]
+ *
+ * raster The raster number.
+ *
+ * pixels The pixel array, encoded as a string.
+ *
+ * encoding The pixel encoding. "numeric" means each pixel is
+ * encoded as a decimal integer delimited by whitespace.
+ *
+ * "hex1" means the pixel array is hex encoded, 1 bytes
+ * per 8 bit pixel, as a printable text string. Hex1
+ * encoding can only be used for pixel values in the
+ * range 0-63. The 64 possible pixel values are encoded
+ * as follows: '0'-'9', 'A'-'Z', 'a'-'z', '$', '_'.
+ * (Since there are 26 letters this is 10+26+26+1+1=64).
+ *
+ * "hex2" means the pixel array is hex encoded, 2 bytes
+ * per 8 bit pixel, as a printable text string. The
+ * two bytes are defined as follows (v = pixel value):
+ *
+ * byte1 = ((v >> 4) & 017) in hex [0-9A-F]
+ * byte2 = ((v ) & 017) in hex [0-9A-F]
+ *
+ * Either "hex1" or "hex2" followed by "-rle", e.g.,
+ * "hex2-rle" means that the hex-encoded data is in
+ * turn run length encoded. In a run length encoded
+ * string all characters are data characters except
+ * for "@" and "%", which are repeat operators. "@" is
+ * followed by a single hex1-encoded character giving
+ * the repeat count minus one: the hex1-encoded number
+ * is decoded as N and the most recent pixel value is
+ * repeated N+1 times. "%" is similar, but is followed
+ * by a 2 character hex2-encoded repeat count.
+ *
+ * Whitespace in a hex encoded string is ignored.
+ * Hex2 encoding reduces the data volume by about a factor
+ * of two (compared to numeric) and is only a factor of
+ * two less space efficient than binary. Hex1 encoding
+ * is as space efficient as binary but pixel values larger
+ * than 63 (64 possible values) cannot be represented.
+ *
+ * nbits Number of bits per pixel - currently only 8 bit pixels
+ * are supported.
+ *
+ * x1,y1,nx,ny Region of the raster to be written to.
+ *
+ * bias If a bias value is given this value is added to the
+ * value of each input pixel.
+ *
+ * Most real-world image processing applications get the Gterm widget handle
+ * with setGterm and pass binary data to the widget by calling GtWritePixels
+ * directly. This is the most efficient approach for serious image processing
+ * where large amounts of data are involved. However, being able to read and
+ * write raster pixels directly in a GUI can be useful in specialized
+ * applications, e.g., where the image is computed or modified by the GUI.
+ */
+static int
+gtermWritePixels (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ ObmContext obm = wp->obm;
+ Widget w = wp->w;
+
+ register char *ip;
+ register uchar *op;
+ register int v, i, j;
+ static uchar hex1[256], hex2[256];
+ static int have_tables = 0;
+ int raster, nbits, bias;
+ char *pixels, *encoding;
+ int x1, y1, nx, ny;
+ uchar *data, *otop;
+
+ if (argc < 9)
+ return (TCL_ERROR);
+
+ raster = atoi (argv[1]);
+ pixels = argv[2];
+ encoding = argv[3];
+ nbits = atoi (argv[4]);
+ x1 = atoi (argv[5]);
+ y1 = atoi (argv[6]);
+ nx = atoi (argv[7]);
+ ny = atoi (argv[8]);
+ bias = (argc > 9) ? atoi(argv[9]) : 0;
+
+ if (nbits != 8)
+ return (TCL_ERROR);
+
+ /* Generate hex to binary lookup tables in first call. */
+ if (!have_tables) {
+ /* Generate char-to-binary table for the hex1 encoding. */
+ for (i=0; i < 256; i++)
+ hex1[i] = 0177;
+ for (i='0'; i <= '9'; i++)
+ hex1[i] = i - '0';
+ for (i='A'; i <= 'Z'; i++)
+ hex1[i] = i - 'A' + 10;
+ for (i='a'; i <= 'z'; i++)
+ hex1[i] = i - 'a' + 36;
+ hex1['$'] = 62;
+ hex1['_'] = 63;
+
+ /* Generate char-to-binary table for the hex2 encoding. */
+ for (i=0; i < 256; i++)
+ hex2[i] = 0177;
+ for (i='0'; i <= '9'; i++)
+ hex2[i] = i - '0';
+ for (i='a'; i <= 'f'; i++)
+ hex2[i] = i - 'a' + 10;
+ for (i='A'; i <= 'F'; i++)
+ hex2[i] = i - 'A' + 10;
+
+ have_tables++;
+ }
+
+ /* Decode the pixel data. */
+ if (!(data = (uchar *) XtMalloc (nx * ny)))
+ return (TCL_ERROR);
+ otop = data + nx * ny;
+
+ /* Uncompress the input if RLE compression is indicated. */
+ if (strcmp (&encoding[strlen(encoding)-4], "-rle") == 0) {
+ int buflen = nx * ny * 2;
+ char *ibuf, *op;
+ int ch;
+
+ /* Get buffer to hold the uncompressed pixel data array. */
+ if (!(ibuf = (char *) XtMalloc (buflen + 1)))
+ goto err;
+
+ /* Uncompress the pixel array. */
+ for (ip=pixels, op=ibuf; *ip; ) {
+ while (isspace (*ip))
+ ip++;
+
+ if ((ch = *ip++) == '@') {
+ if ((i = hex1[*ip++]) >= 0x7f)
+ while (*ip && ((i = hex1[*ip++]) >= 0x7f))
+ ;
+ if (op-ibuf + i + 1 > buflen)
+ goto err;
+ for (v = *(op-1), i++; --i >= 0; )
+ *op++ = v;
+
+ } else if (ch == '%') {
+ if ((i = hex2[*ip++]) >= 0x7f)
+ while (*ip && ((i = hex2[*ip++]) >= 0x7f))
+ ;
+ if ((j = hex2[*ip++]) >= 0x7f)
+ while (*ip && ((j = hex2[*ip++]) >= 0x7f))
+ ;
+ i = ((i << 4) | j) + 1;
+ if (op-ibuf + i > buflen)
+ goto err;
+ for (v = *(op-1); --i >= 0; )
+ *op++ = v;
+
+ } else
+ *op++ = ch;
+ }
+
+ *op = '\0';
+ pixels = ibuf;
+ }
+
+ /* Convert the ascii pixels array to a binary data array.
+ */
+ if (strcmp (encoding, "numeric") == 0) {
+ for (ip=pixels; isspace(*ip) || *ip == '{'; ip++)
+ ;
+ for (op=data; *ip && op < otop; ) {
+ for (v=0; isdigit(*ip); )
+ v = v * 10 + *ip++ - '0';
+ *op++ = v + bias;
+ while (isspace(*ip) || *ip == '}')
+ ip++;
+ }
+ } else if (strncmp (encoding, "hex1", 4) == 0) {
+ for (ip=pixels, op=data; *ip && op < otop; ) {
+ if ((v = hex1[*ip++]) > 0xf)
+ while (*ip && ((v = hex1[*ip++]) > 0xf))
+ ;
+ *op++ = v + bias;
+ }
+ } else if (strncmp (encoding, "hex2", 4) == 0) {
+ for (ip=pixels, op=data; *ip && op < otop; ) {
+ if ((v = hex2[*ip++]) > 0xf)
+ while (*ip && ((v = hex2[*ip++]) > 0xf))
+ ;
+ if ((i = hex2[*ip++]) > 0xf)
+ while (*ip && ((i = hex2[*ip++]) > 0xf))
+ ;
+ *op++ = ((v << 4) | i) + bias;
+ }
+ } else {
+err: XtFree ((char *)data);
+ if (pixels != argv[2])
+ XtFree (pixels);
+ return (TCL_ERROR);
+ }
+
+ /* Write the pixels. */
+ GtWritePixels (w, raster, data, nbits, x1, y1, nx, ny);
+ XtFree ((char *)data);
+ if (pixels != argv[2])
+ XtFree (pixels);
+
+ return (TCL_OK);
+}
+
+
+/* readPixels -- Get the values of some subset of the pixels in a raster.
+ *
+ * Usage: pixels = readPixels raster encoding nbits x1 y1 nx ny [bias]
+ *
+ * raster The raster number.
+ *
+ * encoding The pixel encoding. "numeric" means each pixel is
+ * encoded as a decimal integer delimited by whitespace.
+ * "hex1", hex2", and "hex1-rle or "hex2-rle" are
+ * possible encodings. See writePixels for details.
+ *
+ * nbits Number of bits per pixel - currently only 8 bit pixels
+ * are supported.
+ *
+ * x1,y1,nx,ny Region of the raster to be read.
+ *
+ * bias The bias value is subtracted from the pixel value
+ * returned by readPixels.
+ *
+ * The pixel array, encoded as a string, is returned as the function value.
+ * Use readPixels to read a block of pixels, and getPixel to get the value
+ * of a single pixel.
+ */
+static int
+gtermReadPixels (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ ObmContext obm = wp->obm;
+ Widget w = wp->w;
+
+ register int v, i;
+ register uchar *ip, *op;
+ int bias, nchars, npix, n, j;
+ char *pixels, *encoding;
+ int x1, y1, nx, ny;
+ int raster, nbits;
+ uchar *data;
+ char *buf;
+
+ if (argc < 8)
+ return (TCL_ERROR);
+
+ raster = atoi (argv[1]);
+ encoding = argv[2];
+ nbits = atoi (argv[3]);
+ x1 = atoi (argv[4]);
+ y1 = atoi (argv[5]);
+ nx = atoi (argv[6]);
+ ny = atoi (argv[7]);
+ bias = (argc > 8) ? atoi(argv[8]) : 0;
+ npix = nx * ny;
+
+ if (nbits != 8)
+ return (TCL_ERROR);
+
+ /* Get the pixel data. */
+ if (!(data = (uchar *) XtMalloc (npix * sizeof(uchar))))
+ return (TCL_ERROR);
+ if (GtReadPixels (w, raster, data, nbits, x1, y1, nx, ny) == ERR) {
+ XtFree ((char *)data);
+ return (TCL_ERROR);
+ }
+
+ /* Get a text buffer large enough to hold the encoded data. */
+ nchars = npix * 4 + (npix/16) * 3 + 5;
+ if (!(buf = (char *) XtMalloc (nchars))) {
+ XtFree ((char *)data);
+ return (TCL_ERROR);
+ }
+
+ /* Encode the pixel data as a printable text string using the
+ * encoding specified by the caller.
+ */
+ if (strcmp (encoding, "numeric") == 0) {
+ /* Encode the data as {ddd ddd ddd ... ddd}. */
+ op = (uchar *)buf;
+ *op++ = '{';
+ *op++ = ' ';
+
+ for (ip=data, n=npix, j=0; --n >= 0; ) {
+ v = *ip++ - bias;
+
+ i = (v / 100);
+ if (i) {
+ *op++ = i + '0';
+ v -= i * 100;
+ } else
+ *op++ = ' ';
+
+ i = (v / 10);
+ if (i) {
+ *op++ = i + '0';
+ v -= i * 10;
+ } else
+ *op++ = ' ';
+
+ *op++ = v + '0';
+ *op++ = ' ';
+
+ if (++j >= 16) {
+ *op++ = '\n';
+ *op++ = ' ';
+ *op++ = ' ';
+ j = 0;
+ }
+ }
+
+ if (j)
+ *op++ = '\n';
+ *op++ = '}';
+ *op++ = '\0';
+
+ } else if (strncmp (encoding, "hex", 3) == 0) {
+ static uchar hex1[256], hex2[256*2];
+ static int have_tables = 0;
+ uchar *obuf, *cbuf;
+
+ if (!have_tables) {
+ /* Generate binary to hex1 (64 element) lookup table. */
+ for (n=0, op=hex1; n < 256; n++) {
+ i = (n % 64);
+ if (i < 10)
+ *op++ = i + '0';
+ else if (i < 36)
+ *op++ = (i - 10) + 'A';
+ else if (i < 62)
+ *op++ = (i - 36) + 'a';
+ else if (i == 62)
+ *op++ = '$';
+ else
+ *op++ = '_';
+ }
+
+ /* Generate binary to hex2 (256 element) lookup table. */
+ for (n=0, op=hex2; n < 256; n++) {
+ i = ((n >> 4) & 017);
+ *op++ = (i < 10) ? i + '0' : (i-10) + 'A';
+ i = (n & 017);
+ *op++ = (i < 10) ? i + '0' : (i-10) + 'A';
+ }
+
+ have_tables++;
+ }
+
+ if ((obuf = (uchar *) XtMalloc (npix*2)) == NULL)
+ return (TCL_ERROR);
+
+ if (strncmp (encoding, "hex1", 4) == 0) {
+ /* Hex1 encoding uses only one character per pixel but the
+ * pixel range is restricted to 0 to 63.
+ */
+ for (j=0, ip=data, op=obuf; j < ny; j++) {
+ for (i=0; i < nx; i++)
+ *op++ = hex1[*ip++ - bias];
+ }
+ *op = '\0';
+
+ } else if (strncmp (encoding, "hex2", 4) == 0) {
+ /* Hex2 encoding uses 2 characters per pixel and supports
+ * pixel values in the range 0 to 255.
+ */
+ for (j=0, ip=data, op=obuf; j < ny; j++) {
+ for (i=0; i < nx; i++) {
+ v = (*ip++ - bias) * 2;
+ *op++ = hex2[v];
+ *op++ = hex2[v+1];
+ }
+ if (nx % 2)
+ ip++;
+ }
+ *op = '\0';
+ }
+
+ /* Run length compress the data. The compressed data stream
+ * contains a mixture of literal data codes and repeat codes.
+ * A "@" followed by a hex1-encoded number N causes the most
+ * recent pixel value to be repeated N+1 times, where N < 64.
+ * A "%" followed by a hex2-encoded number N causes the most
+ * recent pixel value to be repeated N+1 times, where N < 256.
+ */
+ if (strcmp (&encoding[strlen(encoding)-4], "-rle") == 0) {
+ if ((cbuf = (unsigned char *) XtMalloc (npix*3)) == NULL)
+ return (TCL_ERROR);
+
+ ip = obuf;
+ op = cbuf;
+ *op++ = v = *ip++;
+ while (*ip) {
+ for (n=0; n < 256 && *ip == v; ip++, n++)
+ ;
+ if (n == 0) {
+ *op++ = v = *ip++;
+ } else if (n < 3) {
+ while (--n >= 0)
+ *op++ = v;
+ } else if (n <= 64) {
+ *op++ = '@';
+ *op++ = hex1[n-1];
+ } else if (n <= 256) {
+ *op++ = '%';
+ *op++ = hex2[(n-1)*2];
+ *op++ = hex2[(n-1)*2+1];
+ }
+ }
+ *op = '\0';
+
+ XtFree ((char *)obuf);
+ obuf = cbuf;
+ }
+
+ /* Output the encoded pixel data.
+ */
+ op = (uchar *)buf;
+ *op++ = '{';
+ *op++ = ' ';
+
+ for (ip=obuf, n=1; *ip; ip++, n++) {
+ *op++ = *ip;
+ if (n && n > 72) {
+ *op++ = '\n';
+ *op++ = ' ';
+ *op++ = ' ';
+ n = 0;
+ }
+ }
+
+ if (n)
+ *op++ = '\n';
+ *op++ = '}';
+ *op++ = '\0';
+ XtFree ((char *)obuf);
+
+ } else {
+ XtFree ((char *)data);
+ return (TCL_ERROR);
+ }
+
+ Tcl_SetResult (obm->tcl, buf, TCL_VOLATILE);
+ XtFree ((char *)data);
+ XtFree ((char *)buf);
+
+ return (TCL_OK);
+}
+
+
+/* refreshPixels -- Refresh any mappings the source rect of which intersects
+ * the given region of the specified raster.
+ *
+ * Usage: refreshPixels raster ctype x1 y1 nx ny
+ *
+ * Any mappings defined on the region [x1,y1,nx,ny] of the given raster are
+ * updated, redisplaying the indicated region. refreshPixels is like
+ * writePixels except that the affected pixels are redisplayed without
+ * actually having been modified. Raster coordinates may be given in either
+ * raster pixel coordinates (ctype=Pixel) or NDC coordinates (ctype=NDC)
+ * in the range 0-1 floating. The origin in the upper left for raster
+ * coordinates and in the lower left for NDC coordinates. Raster coordinates
+ * are zero indexed.
+ */
+static int
+gtermRefreshPixels (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ float x1, y1, nx, ny;
+ int raster, ctype;
+
+ if (argc < 7)
+ return (TCL_ERROR);
+
+ raster = atoi (argv[1]);
+ ctype = coordType (argv[2]);
+ x1 = atof (argv[3]);
+ y1 = atof (argv[4]);
+ nx = atof (argv[5]);
+ ny = atof (argv[6]);
+
+ GtRefreshPixels (w, raster, ctype, x1, y1, nx, ny);
+
+ return (TCL_OK);
+}
+
+
+/* setPixels -- Set a region of a raster to a single color.
+ *
+ * Usage: setPixels raster [color [ctype x1 y1 nx ny [rop]]]
+ *
+ * The region [x1,y1,nx,ny] of raster RASTER, specified in the coordinate
+ * system CTYPE (Pixel or NDC) is set to the color number COLOR. If no
+ * region is specified the entire raster is assumed. The color number is
+ * specified in the color system defined by the client, which may or may not
+ * be the same as the internal gterm widget color system (the client and
+ * widget color systems are the same only if no iomap has been specified,
+ * or, equivalently, if the iomap is one-to-one). If no color is given the
+ * background color is assumed. Any mappings mapped to the affected pixels
+ * will be updated to propagate and possibly display the changes.
+ *
+ * Although this routine permits an optional rasterop argument (ROP) there
+ * is currently no support for symbolically defining the bitfields used to
+ * form this word. Most applications do not need to specify a rasterop.
+ */
+static int
+gtermSetPixels (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int color, rop, raster, ctype;
+ float x1, y1, nx, ny;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ raster = atoi (argv[1]);
+ color = (argc > 2) ? atoi(argv[2]) : GtGetClientPixel(w,0);
+
+ if (argc >= 8) {
+ ctype = coordType (argv[3]);
+ x1 = atof (argv[4]);
+ y1 = atof (argv[5]);
+ nx = atof (argv[6]);
+ ny = atof (argv[7]);
+ } else {
+ ctype = GtNDC;
+ x1 = 0;
+ y1 = 0;
+ nx = 1.0;
+ ny = 1.0;
+ }
+
+ rop = (argc > 8) ? atoi(argv[8]) : 0;
+
+ if (ctype == GtNDC) {
+ x1 *= MAXNDC; y1 *= MAXNDC;
+ nx *= MAXNDC; ny *= MAXNDC;
+ }
+
+ if (GtSetPixels (w, raster, ctype, (int)x1, (int)y1, (int)nx, (int)ny,
+ color, rop) == ERR)
+ return (TCL_ERROR);
+
+ return (TCL_OK);
+}
+
+
+/* extractPixmap -- Extract a region of a raster into a pixmap.
+ *
+ * Usage: extractPixmap pixmap raster [ctype x1 y1 nx ny]
+ *
+ * The given region of raster RASTER is extracted and placed into a pixmap
+ * object with name PIXMAP. The pixmap object is created if it does not
+ * already exist. The size of the pixmap object will be the size of the
+ * extracted region. If no region is given the entire raster is assumed.
+ */
+static int
+gtermExtractPixmap (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ float x1, y1, nx, ny;
+ int raster, ctype;
+ Pixmap pixmap;
+ char *s_pixmap;
+
+ if (argc < 3)
+ return (TCL_ERROR);
+
+ s_pixmap = argv[1];
+ raster = atoi (argv[2]);
+
+ if (argc >= 8) {
+ ctype = coordType (argv[3]);
+ x1 = atof (argv[4]);
+ y1 = atof (argv[5]);
+ nx = atof (argv[6]);
+ ny = atof (argv[7]);
+ } else {
+ ctype = GtNDC;
+ x1 = 0;
+ y1 = 0;
+ nx = 1.0;
+ ny = 1.0;
+ }
+
+ if (pixmap = GtExtractPixmap (w, raster, ctype, x1, y1, nx, ny))
+ createPixmap (obm, s_pixmap, nx, ny, 8, pixmap, NULL, 0, 0);
+ else
+ return (TCL_ERROR);
+
+ return (TCL_OK);
+}
+
+
+/* insertPixmap -- Insert a pixmap into a region of a raster.
+ *
+ * Usage: insertPixmap pixmap raster [ctype x1 y1 nx ny]
+ *
+ * The given pixmap PIXMAP is inserted to raster RASTER at the given
+ * location. If no region is given the entire raster is assumed.
+ */
+static int
+gtermInsertPixmap (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ float x1, y1, nx, ny;
+ int raster, ctype;
+ Pixmap pixmap;
+ char *s_pixmap;
+
+ if (argc < 3)
+ return (TCL_ERROR);
+
+ s_pixmap = argv[1];
+ raster = atoi (argv[2]);
+
+ if (argc >= 8) {
+ ctype = coordType (argv[3]);
+ x1 = atof (argv[4]);
+ y1 = atof (argv[5]);
+ nx = atof (argv[6]);
+ ny = atof (argv[7]);
+ } else {
+ ctype = GtNDC;
+ x1 = 0;
+ y1 = 0;
+ nx = 1.0;
+ ny = 1.0;
+ }
+
+ if (pixmap = findPixmap (obm, s_pixmap)) {
+ if (GtInsertPixmap (w, pixmap, raster, ctype,x1,y1,nx,ny) == ERR)
+ return (TCL_ERROR);
+ } else
+ return (TCL_ERROR);
+
+ return (TCL_OK);
+}
+
+
+/* nextColormap -- Get the index of the next unused colormap.
+ *
+ * Usage: colormap = nextColormap
+ *
+ * Colormaps are dynamically allocated so there is no builtin limit on the
+ * number of colormaps.
+ */
+static int
+gtermNextColormap (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ char buf[SZ_NUMBER];
+
+ sprintf (buf, "%d", GtNextColormap (w));
+ Tcl_SetResult (obm->tcl, buf, TCL_VOLATILE);
+
+ return (TCL_OK);
+}
+
+
+/* freeColormap -- Free a colormap.
+ *
+ * Usage: freeColormap colormap
+ *
+ * The given colormap and all of its resources are freed. This is a no-op if
+ * the given colormap is not defined.
+ */
+static int
+gtermFreeColormap (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int colormap;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ colormap = atoi (argv[1]);
+ GtFreeColormap (w, colormap);
+
+ return (TCL_OK);
+}
+
+
+/* writeColormap -- Write to a colormap.
+ *
+ * Usage: writeColormap colormap colors [offset]
+ *
+ * The given list of colors are loaded into the given colormap. If no
+ * offset is specified the offset will default to the offset of the first
+ * dynamically allocatable color cell (e.g. 10). Colormap zero is the
+ * window colormap and writing to this colormap will immediately affect
+ * the display. The nonzero colormaps are merely stored within the gterm
+ * widget and will not take effect until loaded with loadColormap.
+ *
+ * Colors are specified as a list of RGB color triplets in the range 0-255.
+ * For example, { {R G B} {R G B} ...}.
+ *
+ * The gterm widget supports both private colormaps and the default colormap.
+ * Which is used is controlled by the cmapName resource; writeColormap works
+ * the same way for both types of colormaps.
+ */
+static int
+gtermWriteColormap (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ ObmContext obm = obj->widget.obm;
+ GtermPrivate gp = &obj->gterm;
+ Widget w = obj->widget.w;
+
+ register int ncolors;
+ register char *ip;
+ char *colors, *ip_save;
+ ushort r[MAX_COLORS];
+ ushort g[MAX_COLORS];
+ ushort b[MAX_COLORS];
+ int offset, colormap;
+ char *ipp;
+
+ if (argc < 3)
+ return (TCL_ERROR);
+
+ colormap = atoi (argv[1]);
+ colors = argv[2];
+ offset = (argc > 3) ? atoi(argv[3]) : FIRST_COLOR;
+
+ for (ncolors=0, ip=colors; *ip && ncolors < MAX_COLORS; ) {
+ while (isspace(*ip) || *ip == '{')
+ ip++;
+
+ ip_save = ip;
+ r[ncolors] = (strtol (ip, &ipp, 10)) << 8; ip = ipp;
+ g[ncolors] = (strtol (ip, &ipp, 10)) << 8; ip = ipp;
+ b[ncolors] = (strtol (ip, &ipp, 10)) << 8; ip = ipp;
+ if (ip == ip_save)
+ return (TCL_ERROR);
+
+ while (isspace(*ip) || *ip == '}')
+ ip++;
+
+ ncolors++;
+ }
+
+ if (GtWriteColormap (w, colormap, offset, ncolors, r, g, b) == ERR)
+ return (TCL_ERROR);
+
+ return (TCL_OK);
+}
+
+
+/* readColormap -- Read from a colormap.
+ *
+ * Usage: ncolors = readColormap colormap colors [offset [ncolors]]
+ *
+ * The given region of the colormap is read and return in the output variable
+ * COLORS. The actual number of color values read is returned as the function
+ * value. If no offset is specified the offset will default to the offset of
+ * the first dynamically allocatable color cell (e.g. 10). If the number of
+ * colors to be read (NCOLORS) is not specified readColormap will return a
+ * list of all the allocated colors starting at the specified colortable
+ * offset.
+ *
+ * Colors are returned as a list of RGB color triplets in the range 0-255.
+ * For example, { {R G B} {R G B} ...}.
+ */
+static int
+gtermReadColormap (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ ObmContext obm = obj->widget.obm;
+ GtermPrivate gp = &obj->gterm;
+ Widget w = obj->widget.w;
+
+ register int i;
+ register char *op;
+ char colors[MAX_COLORS * 3 * 20];
+ ushort r[MAX_COLORS];
+ ushort g[MAX_COLORS];
+ ushort b[MAX_COLORS];
+ int offset, colormap;
+ int ncolors, request;
+ char buf[SZ_NUMBER];
+ char *s_colors;
+
+ if (argc < 3)
+ return (TCL_ERROR);
+
+ colormap = atoi (argv[1]);
+ s_colors = argv[2];
+ offset = (argc > 3) ? atoi(argv[3]) : FIRST_COLOR;
+ request = (argc > 4) ? atoi(argv[4]) : MAX_COLORS;
+
+ ncolors = GtReadColormap (w, colormap, offset, request, r, g, b);
+
+ op = colors;
+ *op++ = '{';
+ *op++ = ' ';
+ for (i=0; i < ncolors; i++) {
+ sprintf (op, "{%d %d %d} ", (r[i] >> 8), (g[i] >> 8), (b[i] >> 8));
+ while (*op)
+ op++;
+ }
+ *op++ = '}';
+ *op++ = '\0';
+ Tcl_SetVar (obm->tcl, s_colors, colors, 0);
+
+ sprintf (buf, "%d", ncolors);
+ Tcl_SetResult (obm->tcl, buf, TCL_VOLATILE);
+
+ return (TCL_OK);
+}
+
+
+/* loadColormap -- Load a colormap.
+ *
+ * Usage: loadColormap colormap [offset [scale]]
+ *
+ * The offset and scale parameters may be used to adjust the brightness and
+ * contrast of the image when the colormap is loaded. The normalized colormap
+ * has offset=0.5, scale=1.0. Colormap zero is the hardware colormap.
+ */
+static int
+gtermLoadColormap (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ ObmContext obm = obj->widget.obm;
+ GtermPrivate gp = &obj->gterm;
+ Widget w = obj->widget.w;
+ float offset, scale;
+ int colormap;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ colormap = atoi (argv[1]);
+ offset = (argc > 2) ? atof(argv[2]) : gp->offset;
+ scale = (argc > 3) ? atof(argv[3]) : gp->scale;
+
+ GtLoadColormap (w, colormap, offset, scale);
+
+ gp->colormap = colormap;
+ gp->offset = offset;
+ gp->scale = scale;
+
+ return (TCL_OK);
+}
+
+
+/* clientPixel -- Convert a gterm pixel to a client pixel.
+ *
+ * Usage: pixel = clientPixel gterm_pixel
+ *
+ * If the client has an iomap installed, gterm i/o operations which deal
+ * with pixel values will map to and from client (external) pixels and the
+ * internal gterm widget color model. The clientPixel routine can be used to
+ * convert a pixel (i.e. color) in the gterm color model to the corresponding
+ * client pixel in the client's color model. For example "clientPixel 0"
+ * will return the client pixel corresponding to the gterm widget background
+ * color.
+ */
+static int
+gtermClientPixel (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int pixel, client_pixel;
+ char buf[SZ_NUMBER];
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ pixel = atoi (argv[1]);
+ client_pixel = GtGetClientPixel (w, pixel);
+
+ sprintf (buf, "%d", client_pixel);
+ Tcl_SetResult (obm->tcl, buf, TCL_VOLATILE);
+
+ return (TCL_OK);
+}
+
+
+/* getBias -- Get the colormap bias value.
+ *
+ * Usage: bias = getBias [nelem [maxelem]]
+ *
+ * The colormap bias value is the pixel value corresponding to the first
+ * dynamically allocatable colormap cell. That is, the gterm widget
+ * defines N preallocated static colors 0 to N-1, followed by an arbitrary
+ * number of dynamically allocatable colors. The bias value is the pixel
+ * value of the first dynamically allocatable color.
+ *
+ * If the optional arguments nelem and maxelem are given then the number
+ * of currently allocated colors and the maximum number of allocatable colors
+ * are returned. The latter values do not include the N=bias static colors,
+ * i.e. nelem=0 if no dynamic colors have been allocated.
+ */
+static int
+gtermGetBias (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int first, nelem, maxelem;
+ char buf[SZ_NUMBER];
+
+ GtQueryColormap (w, 0, &first, &nelem, &maxelem);
+
+ if (argc > 1) {
+ sprintf (buf, "%d", nelem);
+ Tcl_SetVar (obm->tcl, argv[1], buf, 0);
+ }
+ if (argc > 2) {
+ sprintf (buf, "%d", maxelem);
+ Tcl_SetVar (obm->tcl, argv[2], buf, 0);
+ }
+
+ sprintf (buf, "%d", first);
+ Tcl_SetResult (obm->tcl, buf, TCL_VOLATILE);
+
+ return (TCL_OK);
+}
+
+
+/* initMappings -- Initialize the mapping subsystem, deleting any existing
+ * mappings.
+ *
+ * Usage: initMappings
+ */
+static int
+gtermInitMappings (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+
+ GtInitMappings (w);
+ return (TCL_OK);
+}
+
+
+/* nextMapping -- Return the index of the next unused mapping.
+ *
+ * Usage: mapping = nextMapping
+ *
+ * Returns the mapping number as the function value.
+ */
+static int
+gtermNextMapping (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ ObmContext obm = wp->obm;
+ Widget w = wp->w;
+ char buf[SZ_NUMBER];
+ int mapping;
+
+ mapping = GtNextMapping (w);
+ sprintf (buf, "%d", mapping);
+ Tcl_SetResult (obm->tcl, buf, TCL_VOLATILE);
+
+ return (TCL_OK);
+}
+
+
+/* freeMapping -- Free or delete a mapping.
+ *
+ * Usage: freeMapping mapping
+ *
+ * The given mapping descriptor is freed and any resources used by the mapping
+ * are freed.
+ */
+static int
+gtermFreeMapping (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int mapping, erase;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ mapping = atoi (argv[1]);
+ GtDisableMapping (w, mapping, erase=1);
+ GtFreeMapping (w, mapping);
+
+ return (TCL_OK);
+}
+
+
+/* lowerMapping -- Lower a mapping, i.e., change its stacking order so that
+ * it is drawn below other mappings.
+ *
+ * Usage: lowerMapping mapping [reference]
+ *
+ * If a reference mapping is named the stacking order of the target mapping
+ * will be modified to make it appear just beneath the reference mapping.
+ * If no reference mapping is given the mapping will be moved to the bottom
+ * of the mapping stacking order, making it be drawn below all other mappings.
+ */
+static int
+gtermLowerMapping (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int mapping, reference;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ mapping = atoi (argv[1]);
+ reference = (argc > 2) ? atoi(argv[2]) : 0;
+ GtLowerMapping (w, mapping, reference);
+
+ return (TCL_OK);
+}
+
+
+/* raiseMapping -- Raise a mapping, i.e., change its stacking order so that
+ * it is drawn above other mappings.
+ *
+ * Usage: raiseMapping mapping [reference]
+ *
+ * If a reference mapping is named the stacking order of the target mapping
+ * will be modified to make it appear just above the reference mapping.
+ * If no reference mapping is given the mapping will be moved to the top
+ * of the mapping stacking order, making it be drawn above all other mappings.
+ */
+static int
+gtermRaiseMapping (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int mapping, reference;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ mapping = atoi (argv[1]);
+ reference = (argc > 2) ? atoi(argv[2]) : 0;
+ GtRaiseMapping (w, mapping, reference);
+
+ return (TCL_OK);
+}
+
+
+/* enableMapping -- Reenable a mapping.
+ *
+ * Usage: enableMapping mapping [refresh]
+ *
+ * The given mapping is enabled and optionally refreshed. This is a no-op
+ * if the mapping is already enabled.
+ */
+static int
+gtermEnableMapping (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int mapping, refresh;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ mapping = atoi (argv[1]);
+ refresh = (argc > 2) ? (strcmp(argv[2],"refresh") == 0) : False;
+
+ if (GtEnableMapping (w, mapping, refresh) == ERR)
+ return (TCL_ERROR);
+
+ return (TCL_OK);
+}
+
+
+/* disableMapping -- Disable a mapping.
+ *
+ * Usage: disableMapping mapping [erase]
+ *
+ * The given mapping is disabled and optionally erased. This is a no-op
+ * if the mapping is not enabled.
+ */
+static int
+gtermDisableMapping (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int mapping, erase;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ mapping = atoi (argv[1]);
+ erase = (argc > 2) ? (strcmp(argv[2],"erase") == 0) : False;
+
+ if (GtDisableMapping (w, mapping, erase) == ERR)
+ return (TCL_ERROR);
+
+ return (TCL_OK);
+}
+
+
+/* activeMapping -- Test whether a given mapping is active (enabled).
+ *
+ * Usage: active = activeMapping mapping
+ *
+ * Returns True if the mapping is defined and enabled, False otherwise.
+ */
+static int
+gtermActiveMapping (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ char buf[SZ_NUMBER];
+ int mapping, active;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ mapping = atoi (argv[1]);
+ active = GtActiveMapping (w, mapping);
+
+ Tcl_SetResult (obm->tcl, active ? TRUESTR : FALSESTR, TCL_STATIC);
+ return (TCL_OK);
+}
+
+
+/* refreshMapping -- Refresh a mapping.
+ *
+ * Usage: refreshMapping mapping
+ *
+ * The given mapping is unconditionally refreshed, i.e., the destination
+ * rect is repainted.
+ */
+static int
+gtermRefreshMapping (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int mapping;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ mapping = atoi (argv[1]);
+ GtRefreshMapping (w, mapping);
+
+ return (TCL_OK);
+}
+
+
+/* copyRaster -- Copy a region from one raster to another.
+ *
+ * Usage: copyRaster rop
+ * src st sx sy snx sny
+ * dst dt dx dy dnx dny
+ *
+ * The specified region of the source raster is scaled as necessary and
+ * written to the specified region of the destination raster. This is
+ * equivalent to defining a mapping between the source and destination,
+ * refreshing the mapping, and then freeing the mapping. Refer to setMapping
+ * for a description of the arguments.
+ *
+ * Copyraster may be used to manually display rasters (without setting up a
+ * mapping) by copying rasters to raster zero, the display window. If the
+ * source raster is a server raster and the mapping is one-to-one this can
+ * be done very quickly. For the fastest possible results the transient
+ * flag should be set in the rasterop (ROP) to prevent saving of the displayed
+ * data in an off-screen pixmap (this may prevent the window from being
+ * refreshed properly in response to window system expose events).
+ */
+static int
+gtermCopyRaster (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int rop, src, st, dst, dt, status;
+ int sx, sy, snx, sny, dx, dy, dnx, dny;
+
+ if (argc != 14)
+ return (TCL_ERROR);
+
+ rop = atoi (argv[1]);
+ get_mapping (&argv[2],
+ &src, &st, &sx, &sy, &snx, &sny,
+ &dst, &dt, &dx, &dy, &dnx, &dny);
+
+ status = GtCopyRaster (w, rop,
+ src, st, sx, sy, snx, sny,
+ dst, dt, dx, dy, dnx, dny);
+
+ return (status == ERR ? TCL_ERROR : TCL_OK);
+}
+
+
+/* setMapping -- Set or modify a mapping.
+ *
+ * Usage: setMapping mapping rop
+ * src st sx sy snx sny
+ * dst dt dx dy dnx dny
+ *
+ * setMapping defines a new mapping function, or modifies an old one. If a new
+ * mapping is defined it is merely enabled, and no refreshing of the screen
+ * takes place until either some mapped source data is modified or the mapping
+ * is explicitly refreshed. If an existing mapping is modified the old and new
+ * mappings are examined and only those portions of the destination rect for
+ * which the mapping changed are updated. This permits minor changes to a
+ * mapping (e.g. moving an edge) without having to redraw the entire region.
+ * Regions of the destination drawable which were previously covered by the
+ * mapping but which were exposed by modifying the mapping are redrawn, in
+ * effect erasing the mapping.
+ *
+ * SetMapping optimizes the mapping operation where possible. In particular,
+ * if the mapping is one-to-one and both the source and destination rasters
+ * are server rasters, a very fast memory copy in the server is used. Other
+ * cases, for example a dezoom involving antialising, can be expensive.
+ *
+ * The mapping number is arbitrary. Mapping numbers may be preallocated by
+ * some client defined logic, or dynamically allocated with nextMapping.
+ * Most applications will want to set the rasterop (ROP) argument to zero,
+ * which causes the mapping to copy the source to the destination. For further
+ * information on the significance of the bits in the rasterop refer to the
+ * gterm widget documentation.
+ *
+ * The source and destination rects are specifed with six fields each: the
+ * raster number, coordinate type, X,Y coordinates of the rect, and the
+ * X,Y size of the rect in pixels. The coordinate type may be either "Pixel"
+ * (raster pixel coordinates) or NDC. NDC coordinates are normalized device
+ * coordinates in the range 0.0 to 1.0 in either axis. The origin is in the
+ * upper left corner for Pixel coordinates, and in the lower left corner for
+ * NDC coordinates.
+ *
+ * The source and destination rects need not be the same size. The source
+ * will be scaled as necessary to fill the destination. Scaling options,
+ * e.g. the antialiasing technique used for a dezoom, are controlled by the
+ * rasterop. If the DNX or DNY field is negative the mapping will flip the
+ * image about the corresponding axis.
+ *
+ * The source and destination rects can be any two rasters, or even the
+ * same raster. A special case is raster zero, the display window. Mapping
+ * a source raster to dst=0 is equivalent to displaying the raster. By
+ * default data mapped to raster zero will also be saved in an off-screen
+ * pixmap in the server and used to autmatically refresh the window in
+ * response to window system expose events. This feature may be disabled
+ * by setting the transient flag in the rasterop.
+ *
+ * A raster can have multiple source or destination mappings defined on it.
+ * A region of a raster may be the source for more than one mapping in which
+ * case all mappings are updated when the source region is modified. Multiple
+ * sources may be mapped to (different regions) of a destination raster to
+ * implement special effects such as split screen or picture insets. Mappings
+ * may be chained to set up graphics pipelines, where the destination of one
+ * mapping is the source of the next. Care must be taken to avoid feedback or
+ * infinite loops can result.
+ */
+static int
+gtermSetMapping (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int mapping, rop, src, st, dst, dt, status;
+ int sx, sy, snx, sny, dx, dy, dnx, dny;
+
+ if (argc != 15)
+ return (TCL_ERROR);
+
+ mapping = atoi (argv[1]);
+ rop = atoi (argv[2]);
+ get_mapping (&argv[3],
+ &src, &st, &sx, &sy, &snx, &sny,
+ &dst, &dt, &dx, &dy, &dnx, &dny);
+
+ status = GtSetMapping (w, mapping, rop,
+ src, st, sx, sy, snx, sny,
+ dst, dt, dx, dy, dnx, dny);
+
+ return (status == ERR ? TCL_ERROR : TCL_OK);
+}
+
+
+/* getMapping -- Get a mapping.
+ *
+ * Usage: getMapping mapping rop
+ * src st sx sy snx sny
+ * dst dt dx dy dnx dny
+ *
+ * The given mapping is returned in the output variables. All arguments
+ * except MAPPING are output variables. It is an error if the mapping is
+ * not defined, but the mapping need not be enabled.
+ */
+static int
+gtermGetMapping (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int mapping, rop, src, st, dst, dt, status;
+ int sx, sy, snx, sny, dx, dy, dnx, dny;
+ char buf[SZ_NUMBER];
+
+ if (argc != 15)
+ return (TCL_ERROR);
+
+ mapping = atoi (argv[1]);
+ status = GtGetMapping (w, mapping, &rop,
+ &src, &st, &sx, &sy, &snx, &sny,
+ &dst, &dt, &dx, &dy, &dnx, &dny);
+ if (status == ERR)
+ return (TCL_ERROR);
+
+ sprintf (buf, "%d", rop);
+ Tcl_SetVar (obm->tcl, argv[2], buf, 0);
+ put_mapping (obm->tcl, &argv[3],
+ src, st, sx, sy, snx, sny,
+ dst, dt, dx, dy, dnx, dny);
+
+ return (TCL_OK);
+}
+
+
+/* SelectRaster -- Given the raw screen coordinates SX,SY (or coords in
+ * any destination raster), determine the mapping and source raster which are
+ * mapped to that pixel and return the raster and mapping numbers and the
+ * coordinates of the same pixel in the source raster.
+ *
+ * Usage: raster = selectRaster dras dt dx dy rt rx ry [map]
+ *
+ * where dras display raster
+ * dt,rt coordinate type - "pixel" or "ndc"
+ * dx,dy display raster coordinates (input)
+ * rx,ry source raster coordinates (output)
+ * map mapping selected (output)
+ *
+ * Note that the coordinates returned by selectRaster are measured (taking
+ * a line as an example) from zero at the left edge of the first pixel, to
+ * "width" at the right edge of the last pixel. This means that the floating
+ * point coordinates of the center of raster pixel N will be N + 0.5. For
+ * example, if we input screen coordinates (dras=0), x=117, and no mapping
+ * is in effect, the floating point raster coordinates returned will be 117.5.
+ * The difference occurs because the input coordinate is a pixel number
+ * (integer) while the output coordinate is a floating point coordinate
+ * measuring the continuously variable location a pixel. int(x) will convert
+ * this coordinate to a raster pixel number.
+ */
+static int
+gtermSelectRaster (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ int raster, dras, dt, dx, dy, rt, rx, ry, mp;
+ char *xout, *yout, *mpout;
+ float fx, fy;
+ char buf[64];
+
+ if (argc < 8)
+ return (TCL_ERROR);
+
+ /* Get arguments. */
+ dras = atoi (argv[1]);
+ if ((dt = coordType (argv[2])) < 0)
+ dt = GtPixel;
+ dx = (int) atof (argv[3]);
+ dy = (int) atof (argv[4]);
+ if (dt == GtNDC) {
+ dx *= MAXNDC;
+ dy *= MAXNDC;
+ }
+ if ((rt = coordType (argv[5])) < 0)
+ rt = GtPixel;
+ xout = argv[6];
+ yout = argv[7];
+ mpout = (argc > 8) ? argv[8] : NULL;
+
+ raster = GtSelectRaster (wp->w, dras, dt, dx, dy, GtNDC, &rx, &ry, &mp);
+
+ if (rt == GtNDC) {
+ /* Return coords scaled 0.0 - 1.0. */
+ fx = (float)rx / MAXNDC;
+ fy = (float)ry / MAXNDC;
+ } else {
+ /* Return raster pixel coordinates. */
+ ndcToPixel (wp->w, raster, rx, ry, &fx, &fy);
+ }
+
+ sprintf (buf, "%g", fx);
+ Tcl_SetVar (obm->tcl, xout, buf, 0);
+ sprintf (buf, "%g", fy);
+ Tcl_SetVar (obm->tcl, yout, buf, 0);
+ if (mpout) {
+ sprintf (buf, "%d", mp);
+ Tcl_SetVar (obm->tcl, mpout, buf, 0);
+ }
+
+ sprintf (buf, "%d", raster);
+ Tcl_SetResult (obm->tcl, buf, TCL_VOLATILE);
+ return (TCL_OK);
+}
+
+
+/* UnmapPixel -- unmapPixel is a simplified, less general version of
+ * selectRaster which will automatically follow graphics pipelines back to
+ * the original mapped raster. If desired the raster pixel value can be
+ * returned as well as the raster number and raster pixel coordinates
+ * corresponding to a screen (raster 0) pixel.
+ *
+ * Usage: unmapPixel sx sy raster rx ry [rz]
+ *
+ * where sx,sy "screen" (raster 0) coordinates
+ * raster original mapped raster (output)
+ * rx,ry source raster coordinates (output)
+ * rz source raster pixel value (output)
+ *
+ * By following graphics pipelines back to the original source raster we mean
+ * the following. If raster A is mapped to raster B which is mapped to C (the
+ * screen), given a screen coordinate in the mapped region unmapPixel will
+ * return the raster number and coordinates for raster A.
+ */
+static int
+gtermUnmapPixel (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ int dst, dx, dy, src, sx, sy, mapping;
+ char *raster_out, *x_out, *y_out, *z_out;
+ char buf[SZ_NUMBER];
+ float fx, fy;
+
+ if (argc < 6)
+ return (TCL_ERROR);
+
+ /* Get arguments. */
+ dx = (int) atof (argv[1]);
+ dy = (int) atof (argv[2]);
+ raster_out = argv[3];
+ x_out = argv[4];
+ y_out = argv[5];
+ z_out = (argc > 6) ? argv[6] : NULL;
+
+ /* Follow the pipeline back to the original mapped raster. */
+ fx = dx; fy = dy;
+ src = 0;
+
+ do {
+ src = GtSelectRaster (wp->w, dst=src,
+ GtPixel, dx, dy, GtNDC, &sx, &sy, &mapping);
+ if (src != dst) {
+ ndcToPixel (wp->w, src, sx, sy, &fx, &fy);
+ dx = (int) fx;
+ dy = (int) fy;
+ }
+ } while (dst != src);
+
+ sprintf (buf, "%d", src);
+ Tcl_SetVar (obm->tcl, raster_out, buf, 0);
+ sprintf (buf, "%g", fx);
+ Tcl_SetVar (obm->tcl, x_out, buf, 0);
+ sprintf (buf, "%g", fy);
+ Tcl_SetVar (obm->tcl, y_out, buf, 0);
+
+ if (z_out) {
+ uchar data[1];
+ GtReadPixels (wp->w, src, data, 8, dx, dy, 1, 1);
+ sprintf (buf, "%d", data[0]);
+ Tcl_SetVar (obm->tcl, z_out, buf, 0);
+ }
+
+ return (TCL_OK);
+}
+
+
+/* flip -- Edit a mapping to flip the mapped subimage in X and/or Y.
+ *
+ * Usage: flip mapping axis [axis]
+ *
+ * where axis is "x" or "y". This is a convenience routine for changing only
+ * the flip portion of a mapping.
+ */
+static int
+gtermFlip (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ WidgetPrivate wp = &obj->widget;
+ ObmContext obm = wp->obm;
+ register Widget w = wp->w;
+ int mapping, rop, flipX, flipY, i;
+ int src, st, sx, sy, snx, sny;
+ int dst, dt, dx, dy, dnx, dny;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ mapping = atoi (argv[1]);
+ flipX = flipY = 0;
+ for (i=2; i < argc; i++) {
+ if (argv[i][0] == 'x')
+ flipX = !flipX;
+ else if (argv[i][0] == 'y')
+ flipY = !flipY;
+ }
+
+ if (flipX || flipY) {
+ GtGetMapping (w, mapping,
+ &rop, &src,&st,&sx,&sy,&snx,&sny, &dst,&dt,&dx,&dy,&dnx,&dny);
+
+ if (flipX)
+ dnx = -dnx;
+ if (flipY)
+ dny = -dny;
+
+ GtSetMapping (w, mapping,
+ rop, src,st,sx,sy,snx,sny, dst,dt,dx,dy,dnx,dny);
+ }
+
+ return (TCL_OK);
+}
+
+
+/* gtermMarkerInit -- Initialize the Marker subsystem for a Gterm widget.
+ * This destroys all markers and initializes the marker subsystem.
+ *
+ * Usage: markerInit
+ */
+static int
+gtermMarkerInit (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+
+ GtMarkerInit (wp->w);
+ return (TCL_OK);
+}
+
+
+/* gtermCreateMarker -- Create a new marker.
+ *
+ * Usage: createMarker name attribute-list
+ * e.g. createMarker name {attribute value [attribute value ...]}
+ * or createMarker name attribute value [attribute value ...]
+ *
+ * Any marker attribute may be assigned a value when the marker is created.
+ * Refer to <ObmW/Gterm.h> for a list of marker attribute names. Often the
+ * the attributes "type" and "createMode" need to be specified at marker
+ * create time.
+ *
+ * type The marker type: text, rectangle, circle, etc.
+ *
+ * createMode A marker should be created with createMode=interactive
+ * if the user is expected to interactively drag out
+ * the marker using the pointer and either the default
+ * or an application specified translation table. A
+ * marker can also be created interactively using only
+ * the m_create (marker create) action, however m_create
+ * does not allow the marker attributes to be set.
+ *
+ * There are any number of ways to use a GUI to create a marker under the
+ * Object Manager, but an example might be using a translation to call a GUI
+ * procedure which issues the createMarker call. For example a pointer down
+ * event could translate as "call(newMarker,$name,$x,$y) m_create()" where
+ * newMarker is a GUI marker creation procedure which sends a createMarker
+ * message to the Gterm widget. The GUI procedure could set the marker
+ * attributes as desired, possibly using additional GUI components to define
+ * the marker attributes. The m_create action will notice that a
+ * createMarker has been executed and will merely activate the marker and
+ * give it the pointer focus (i.e. install the marker translations). The
+ * user will then use the pointer or keyboard to drag out the marker.
+ *
+ * If the marker is created noninteractive the application must set the marker
+ * position and size using marker attributes. If the marker is sensitive
+ * the user can then use the marker's translations to interactively modify
+ * the marker (resize it, move it, etc.). All markers which are visible and
+ * sensitive and which have the necessary translations can be interactively
+ * modified by the user; the reason for creating a marker in interactive mode
+ * is to allow the initial marker position and size to be specified
+ * interactively *when* the marker is created, instead of afterwards.
+ *
+ * Any number of attributes may be given when the marker is created. Most
+ * marker attributes can also be modified after a marker has been created
+ * by sending setAttribute messages to the marker.
+ */
+static int
+gtermCreateMarker (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ GtermObject obj = (GtermObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register ObmContext obm = wp->obm;
+ Arg args[MAX_ARGS];
+ int nargs, i;
+ char **items;
+ int nitems;
+ char *name;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ name = argv[1];
+
+ if (argc == 3) {
+ /* Attribute list passed as a list argument. */
+ if (Tcl_SplitList (tcl, argv[2], &nitems, &items) != TCL_OK)
+ return (TCL_ERROR);
+ } else if (argc > 3) {
+ /* Attribute list passed as separate arguments. */
+ nitems = argc - 2;
+ items = (char **) XtMalloc (nitems * sizeof(char *));
+ if (items == NULL)
+ return (TCL_ERROR);
+ for (i=0; i < nitems; i++)
+ items[i] = argv[i+2];
+ } else
+ return (TCL_ERROR);
+
+ if (argc > 2)
+ for (i=nargs=0; i < nitems && nargs < MAX_ARGS; i += 2) {
+ XtSetArg (args[nargs], items[i], items[i+1]);
+ nargs++;
+ }
+
+ obmNewObject (obm, name, "Marker", obj->core.name, args, nargs);
+
+ if (argc > 2)
+ free ((char *) items);
+
+ return (TCL_OK);
+}
+
+
+/*
+ * Gterm widget utility procedures.
+ * ------------------------------------------
+ */
+
+
+/* coordType -- Convert a coordinate type string "pixel" or "ndc" to an
+ * integer code.
+ */
+coordType (name)
+char *name;
+{
+ if (strcmp (name, "pixel") == 0 ||
+ strcmp (name, "Pixel") == 0 ||
+ strcmp (name, "PIXEL") == 0) {
+
+ return (GtPixel);
+
+ } else if (
+ strcmp (name, "ndc") == 0 ||
+ strcmp (name, "NDC") == 0) {
+
+ return (GtNDC);
+
+ } else
+ return (-1);
+}
+
+
+/* dataLevelType -- Convert a data level type string to an integer code.
+ */
+dataLevelType (name)
+char *name;
+{
+ if (strcmp (name, "set") == 0)
+ return (GtSet);
+ else if (strcmp (name, "clear") == 0)
+ return (GtClear);
+ else if (strcmp (name, "invert") == 0)
+ return (GtInvert);
+ else
+ return (-1);
+}
+
+
+/* lineStyle -- Convert a line style string to an integer code.
+ */
+lineStyle (name)
+char *name;
+{
+ if (strcmp (name, "solid") == 0)
+ return (GtSolid);
+ else if (strcmp (name, "dashed") == 0)
+ return (GtDashed);
+ else if (strcmp (name, "dotted") == 0)
+ return (GtDotted);
+ else if (strcmp (name, "dashDot") == 0)
+ return (GtDashDot);
+ else if (strcmp (name, "dash3Dot") == 0)
+ return (GtDash3Dot);
+ else
+ return (-1);
+}
+
+
+/* fillType -- Convert a fill type string to an integer code.
+ */
+fillType (name)
+char *name;
+{
+ if (strcmp (name, "solid") == 0)
+ return (GtSolid);
+ else if (strcmp (name, "outline") == 0)
+ return (GtOutline);
+ else
+ return (-1);
+}
+
+
+/* colorToIndex -- Convert a color name or number to a gterm widget color
+ * index.
+ */
+colorToIndex (name)
+char *name;
+{
+ if (isdigit (*name))
+ return (atoi (name));
+ else if (strcmp (name, "background") == 0)
+ return (0);
+ else if (strcmp (name, "foreground") == 0)
+ return (1);
+ else if (strcmp (name, "black") == 0)
+ return (0);
+ else if (strcmp (name, "white") == 0)
+ return (1);
+ else if (strcmp (name, "red") == 0)
+ return (2);
+ else if (strcmp (name, "green") == 0)
+ return (3);
+ else if (strcmp (name, "blue") == 0)
+ return (4);
+ else if (strcmp (name, "cyan") == 0)
+ return (5);
+ else if (strcmp (name, "magenta") == 0)
+ return (6);
+ else if (strcmp (name, "yellow") == 0)
+ return (7);
+ else if (strcmp (name, "user1") == 0)
+ return (8);
+ else if (strcmp (name, "user2") == 0)
+ return (9);
+ else
+ return (-1);
+}
+
+
+/* ncdToPixel -- Convert NDC (integer) to raster pixel (floating) coordinates.
+ */
+ndcToPixel (w, raster, nx, ny, rx, ry)
+Widget w;
+int raster;
+int nx, ny;
+float *rx, *ry;
+{
+ int rtype, width, height, depth;
+ int x2, y2;
+
+ GtQueryRaster (w, raster, &rtype, &width, &height, &depth);
+ x2 = width;
+ y2 = height;
+
+ *rx = (float)( nx) / MAXNDC * x2;
+ *ry = (float)(MAXNDC - ny) / MAXNDC * y2; /* NDC is flipped in Y */
+}
+
+static XPoint *
+get_points (points, npoints)
+char *points;
+int *npoints;
+{
+ register int i;
+ register char *ip;
+ register XPoint *pv;
+ char *ipp, *ip_save;
+ int maxpts, npts;
+
+ maxpts = MAX_POLYPTS;
+ if ((pv = (XPoint *) XtMalloc (maxpts * sizeof(XPoint))) == NULL)
+ return (NULL);
+
+ /* Get the points array. */
+ for (npts=0, ip=points; *ip; ) {
+ while (isspace(*ip) || *ip == '{')
+ ip++;
+
+ ip_save = ip;
+ pv[npts].x = (short) strtod (ip, &ipp); ip = ipp;
+ pv[npts].y = (short) strtod (ip, &ipp); ip = ipp;
+ if (ip == ip_save) {
+ XtFree ((char *) pv);
+ return (NULL);
+ }
+
+ while (isspace(*ip) || *ip == '}')
+ ip++;
+
+ if (++npts >= maxpts) {
+ maxpts *= 2;
+ if ((pv = (XPoint *) XtRealloc ((char *)pv,
+ maxpts * sizeof(XPoint))) == NULL)
+ return (NULL);
+ }
+ }
+
+ *npoints = npts;
+ return (pv);
+}
+
+
+/* get_mapping -- Read a mapping from an argument list into local variables.
+ */
+static void
+get_mapping (argv, src, st, sx,sy,snx,sny, dst, dt, dx,dy,dnx,dny)
+register char **argv; /* mapping values */
+int *src, *st;
+int *sx, *sy, *snx, *sny;
+int *dst, *dt;
+int *dx, *dy, *dnx, *dny;
+{
+ register int ndc;
+ register double v;
+
+ *src = atoi (argv[0]);
+ *st = (strcmp(argv[1],"pixel")==0 || strcmp(argv[1],"Pixel")==0) ?
+ GtPixel : GtNDC;
+ ndc = (*st == GtNDC);
+
+ v = atof(argv[2]);
+ *sx = ndc ? (v * MAXNDC) : v;
+ v = atof(argv[3]);
+ *sy = ndc ? ((1.0 - v) / 1.0 * MAXNDC) : v;
+ v = atof(argv[4]);
+ *snx = ndc ? (v * MAXNDC) : v;
+ v = atof(argv[5]);
+ *sny = ndc ? (v * MAXNDC) : v;
+
+ *dst = atoi (argv[6]);
+ *dt = (strcmp(argv[7],"pixel")==0 || strcmp(argv[7],"Pixel")==0) ?
+ GtPixel : GtNDC;
+ ndc = (*dt == GtNDC);
+
+ v = atof(argv[8]);
+ *dx = ndc ? (v * MAXNDC) : v;
+ v = atof(argv[9]);
+ *dy = ndc ? ((1.0 - v) / 1.0 * MAXNDC) : v;
+ v = atof(argv[10]);
+ *dnx = ndc ? (abs(v) * MAXNDC) : abs(v);
+ if (v < 0)
+ *dnx = -(*dnx);
+ v = atof(argv[11]);
+ *dny = ndc ? (abs(v) * MAXNDC) : abs(v);
+ if (v < 0)
+ *dny = -(*dny);
+}
+
+
+/* put_mapping -- Output a mapping from local variables to a list of output
+ * variables.
+ */
+static void
+put_mapping (tcl, argv, src, st, sx,sy,snx,sny, dst, dt, dx,dy,dnx,dny)
+register Tcl_Interp *tcl;
+register char **argv; /* mapping variables */
+int src, st;
+int sx, sy, snx, sny;
+int dst, dt;
+int dx, dy, dnx, dny;
+{
+ register int ndc;
+ char buf[SZ_NUMBER];
+
+ sprintf (buf, "%d", src);
+ Tcl_SetVar (tcl, argv[0], buf, 0);
+ Tcl_SetVar (tcl, argv[1], st == GtPixel ? "Pixel" : "NDC", 0);
+ ndc = (st == GtNDC);
+
+ sprintf (buf, "%g", ndc ? (float)sx / MAXNDC : (float)sx);
+ Tcl_SetVar (tcl, argv[2], buf, 0);
+ sprintf (buf, "%g",
+ ndc ? (1.0 - ((float)sy / MAXNDC)) : (float)sy);
+ Tcl_SetVar (tcl, argv[3], buf, 0);
+ sprintf (buf, "%g", ndc ? (float)snx / MAXNDC : (float)snx);
+ Tcl_SetVar (tcl, argv[4], buf, 0);
+ sprintf (buf, "%g", ndc ? (float)sny / MAXNDC : (float)sny);
+ Tcl_SetVar (tcl, argv[5], buf, 0);
+
+ sprintf (buf, "%d", src);
+ Tcl_SetVar (tcl, argv[6], buf, 0);
+ Tcl_SetVar (tcl, argv[7], st == GtPixel ? "Pixel" : "NDC", 0);
+ ndc = (st == GtNDC);
+
+ sprintf (buf, "%g", ndc ? (float)dx / MAXNDC : (float)dx);
+ Tcl_SetVar (tcl, argv[8], buf, 0);
+ sprintf (buf, "%g",
+ ndc ? (1.0 - ((float)dy / MAXNDC)) : (float)dy);
+ Tcl_SetVar (tcl, argv[9], buf, 0);
+ sprintf (buf, "%g", ndc ? (float)dnx / MAXNDC : (float)dnx);
+ Tcl_SetVar (tcl, argv[10], buf, 0);
+ sprintf (buf, "%g", ndc ? (float)dny / MAXNDC : (float)dny);
+ Tcl_SetVar (tcl, argv[11], buf, 0);
+}