diff options
Diffstat (limited to 'vendor/x11iraf/ximtool/ximclient.c')
-rw-r--r-- | vendor/x11iraf/ximtool/ximclient.c | 2576 |
1 files changed, 2576 insertions, 0 deletions
diff --git a/vendor/x11iraf/ximtool/ximclient.c b/vendor/x11iraf/ximtool/ximclient.c new file mode 100644 index 00000000..2d67f25d --- /dev/null +++ b/vendor/x11iraf/ximtool/ximclient.c @@ -0,0 +1,2576 @@ +#include <stdio.h> +#include <ctype.h> +#include <math.h> +#include <sys/stat.h> +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <Tcl/tcl.h> +#include <Obm.h> +#include <ObmW/Gterm.h> +#include "ximtool.h" + +/* + * XIMCLIENT.C -- The Ximtool "client" object. This code implements an OBM + * client and responds to messages sent to the client object by the GUI code + * executing under the object manager. + * + * xim_clientOpen (xim) + * xim_clientClose (xim) + * xim_clientExecute (xim, objname, key, cmd) + * + * The clientExecute callback is called by the GUI code in the object manager + * to execute ximtool client commands. + * + * Client commands: + * + * setFrame frameno + * frameno = getFrame [raster] + * raster = getRaster [frameno] + * frame = getSource [raster [sx sy snx sny]] + * nextFrame + * prevFrame + * matchFrames [frames [reference_frame]] + * registerFrames [frames [reference_frame]] + * offfsetRegister [frames [reference_frame]] + * fitFrame + * clearFrame [frame] + * + * setOption option value [args] + * setColormap colormap + * setOffset xoff yoff + * windowColormap offset scale + * windowRGB color offset scale save_flag + * zoom [mag | xmag ymag [ xcen ycen ]] + * zoomAbs [mag | xmag ymag [ xcen ycen ]] + * center = centroid xcen ycen size [type] + * pix = getPixels x0 y0 nx ny [format] + * pan xcen ycen + * flip axis [axis ...] + * + * setPrintOption option value [args] + * print [x0 y0 nx ny] + * setSaveOption option value [args] + * save [x0 y0 nx ny] + * setLoadOption option value [args] + * load + * help + * info option + * + * wcsstr = encodewcs sx sy sz + * retCursorVal sx sy [frame [wcs [key [strval]]]] + * + * ism_start task + * ism_stop task + * ism_cmd task [args] + * + * initialize + * Reset + * Quit + */ + + +/* Client callback struct. */ +typedef struct { + XimDataPtr xim; + Tcl_Interp *tcl; + Tcl_Interp *server; +} XimClient, *XimClientPtr; + + + +static int initialize(), Reset(), Quit(); +static int setColormap(), updateColormap(), windowColormap(); +static int zoom(), pan(), getSource(); +static int setFrame(), getFrame(), getRaster(), nextFrame(), prevFrame(); +static int fitFrame(), matchFrames(), registerFrames(), retCursorVal(); +static int encodewcs(), flip(), clearFrame(), setOption(), setOffset(); +static int setPrintOption(), setSaveOption(), setLoadOption(); +static int print(), save(), load(), help(), windowRGB(); +static int centroid(), getPixels(); +static int ism_start(), ism_stop(), ism_cmd(); + +extern int ism_evaluate(), info(); +extern IsmModule ismNameToPtr(); +extern double atof(); + + +/* xim_clientOpen -- Initialize the ximtool client code. + */ +void +xim_clientOpen (xim) +XimDataPtr xim; +{ + register XimClientPtr xc; + register Tcl_Interp *tcl; + + xc = (XimClientPtr) XtCalloc (1, sizeof(XimClient)); + xim->clientPrivate = (int *)xc; + + xc->xim = xim; + xc->tcl = tcl = Tcl_CreateInterp(); + ObmAddCallback (xim->obm, OBMCB_clientOutput|OBMCB_preserve, + xim_clientExecute, (XtPointer)xc); + + Tcl_CreateCommand (tcl, + "Quit", Quit, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "Reset", Reset, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "initialize", initialize, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "setFrame", setFrame, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "getFrame", getFrame, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "getRaster", getRaster, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "getSource", getSource, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "nextFrame", nextFrame, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "prevFrame", prevFrame, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "fitFrame", fitFrame, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "matchFrames", matchFrames, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "registerFrames", registerFrames, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "offsetRegister", registerFrames, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "clearFrame", clearFrame, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "setOption", setOption, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "setColormap", setColormap, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "setOffset", setOffset, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "windowColormap", windowColormap, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "updateColormap", updateColormap, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "zoom", zoom, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "zoomAbs", zoom, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "centroid", centroid, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "getPixels", getPixels, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "pan", pan, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "flip", flip, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "retCursorVal", retCursorVal, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "encodewcs", encodewcs, (ClientData)xc, NULL); + + Tcl_CreateCommand (tcl, + "setPrintOption", setPrintOption, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "print", print, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "setSaveOption", setSaveOption, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "save", save, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "setLoadOption", setLoadOption, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "load", load, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "help", help, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "info", info, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "windowRGB", windowRGB, (ClientData)xc, NULL); + + /* ISM module callbacks. */ + Tcl_CreateCommand (tcl, + "ism_start", ism_start, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "ism_stop", ism_stop, (ClientData)xc, NULL); + Tcl_CreateCommand (tcl, + "ism_cmd", ism_cmd, (ClientData)xc, NULL); +} + + +/* xim_clientClose -- Shutdown the ximtool client code. + */ +void +xim_clientClose (xim) +XimDataPtr xim; +{ + register XimClientPtr xc = (XimClientPtr) xim->clientPrivate; + Tcl_DeleteInterp (xc->tcl); +} + + +/* xim_clientExecute -- Called by the GUI code to send a message to the + * "client", which from the object manager's point of view is ximtool itself. + */ +xim_clientExecute (xc, tcl, objname, key, command) +register XimClientPtr xc; +Tcl_Interp *tcl; /* caller's Tcl */ +char *objname; /* object name */ +int key; /* notused */ +char *command; +{ + register XimDataPtr xim = xc->xim; + + xc->server = tcl; + if (strcmp (objname, "client") == 0) + Tcl_Eval (xc->tcl, command); + else + ism_evaluate (xim, objname, command); + + return (0); +} + + +/* + * XIMTOOL CLIENT commands. + * ---------------------------- + */ + +/* Quit -- Exit ximtool. + * + * Usage: Quit + */ +static int +Quit (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + xim_shutdown (xim); +} + + +/* Reset -- Reset ximtool. + * + * Usage: Reset + * + * Reset does a full power-on reset of ximtool. + */ +static int +Reset (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + xim_initialize (xim, xim->fb_configno, xim->nframes, 1); +} + + +/* initialize -- Reinitialize ximtool. + * + * Usage: initialize + * + * Initialize does a partial reinitialization of ximtool, preserving the + * current frame buffers and view. + */ +static int +initialize (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + xim_initialize (xim, xim->fb_configno, xim->nframes, 0); +} + + +/* setFrame -- Set the frame to be displayed. + * + * Usage: setFrame <frameno> + */ +static int +setFrame (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + if (argc == 2) + xim_setFrame (xc->xim, atoi(argv[1])); + return (TCL_OK); +} + + +/* getFrame -- Get the frame number. + * + * Usage: frameno = getFrame [raster] + * + * This routine has two forms. When called with no argument getFrame returns + * the current display frame. When called with a raster number getFrame + * returns the frame number with which the raster is associated. + */ +static int +getFrame (xc, tcl, argc, argv) +XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb; + char frameno[SZ_NAME]; + register int i; + int raster; + + if (argc == 1) + sprintf (frameno, "%d", xc->xim->display_frame); + else { + raster = atoi (argv[1]); + strcpy (frameno, "0"); + + for (i=1; i <= xim->nframes; i++) { + fb = &xim->frames[i-1]; + if (fb->raster == raster || fb->zoomras == raster) { + sprintf (frameno, "%d", fb->frameno); + break; + } + } + } + + Tcl_SetResult (xc->server, frameno, TCL_VOLATILE); + return (TCL_OK); +} + + +/* getRaster -- Get the image raster number of the given frame. + * + * Usage: raster = getRaster [frameno] + * + * This routine has two forms. When called with no argument getRaster returns + * the raster number of the current display frame. When called with a frame + * number getRaster returns the raster number of the given frame. + */ +static int +getRaster (xc, tcl, argc, argv) +XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb; + char buf[SZ_NAME]; + register int i; + int frameno; + + if (argc == 1) + sprintf (buf, "%d", xim->df_p->raster); + else { + frameno = atoi (argv[1]); + strcpy (buf, "0"); + + for (i=1; i < xim->nframes; i++) { + fb = &xim->frames[i-1]; + if (fb->frameno == frameno) { + sprintf (buf, "%d", fb->raster); + break; + } + } + } + + Tcl_SetResult (xc->server, buf, TCL_VOLATILE); + return (TCL_OK); +} + + +/* getSource -- Get the source of the currently displayed image. + * + * Usage: frame = getSource [raster [sx sy snx sny]] + * + * getSource returns the frame number of the currently displayed frame as + * the function value, and the raster number and source rect within that + * raster are returned as function arguments. + */ +static int +getSource (xc, tcl, argc, argv) +XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register int i; + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb = xim->df_p; + int src, st, sx, sy, snx, sny; + int dst, dt, dx, dy, dnx, dny; + char buf[SZ_NAME]; + int frameno, rop; + + GtGetMapping (xim->gt, fb->zoommap, &rop, + &src,&st,&sx,&sy,&snx,&sny, &dst,&dt,&dx,&dy,&dnx,&dny); + + if (argc > 1) { + sprintf (buf, "%d", fb->raster); + Tcl_SetVar (xc->server, argv[1], buf, 0); + } + if (argc > 2) { + sprintf (buf, "%d", sx); + Tcl_SetVar (xc->server, argv[2], buf, 0); + sprintf (buf, "%d", sy); + Tcl_SetVar (xc->server, argv[3], buf, 0); + sprintf (buf, "%d", snx); + Tcl_SetVar (xc->server, argv[4], buf, 0); + sprintf (buf, "%d", sny); + Tcl_SetVar (xc->server, argv[5], buf, 0); + } + + sprintf (buf, "%d", fb->frameno); + Tcl_SetResult (xc->server, buf, TCL_VOLATILE); + + return (TCL_OK); +} + + +/* nextFrame -- Display the next frame in sequence. + * + * Usage: nextFrame + */ +static int +nextFrame (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + int frame; + + if (xim->display_frame < xim->nframes) + frame = xim->display_frame + 1; + else + frame = 1; + + xim_setFrame (xc->xim, frame); + return (TCL_OK); +} + + +/* prevFrame -- Display the previous frame in sequence. + * + * Usage: prevFrame + */ +static int +prevFrame (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + int frame; + + if (xim->display_frame > 1) + frame = xim->display_frame - 1; + else + frame = xim->nframes; + + xim_setFrame (xc->xim, frame); + return (TCL_OK); +} + + +/* matchFrames -- Set the enhancement of the listed frames to match that of + * the given reference frame. If no reference frame is given the current + * display frame is used. If no frames are listed all frames are matched + * to the current display frame. + * + * Usage: matchFrames [frames [reference_frame]] + */ +static int +matchFrames (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + int *frames, frame_list[32], reference_frame; + int nitems, i; + char **items; + + /* Get reference frame. */ + if (argc > 2) + reference_frame = atoi (argv[2]); + else + reference_frame = xim->display_frame; + + /* Get frame list. */ + if (argc > 1) { + if (Tcl_SplitList (tcl, argv[1], &nitems, &items) != TCL_OK) + goto nolist; + for (i=0, frames=frame_list; i < nitems; i++) + frames[i] = atoi (items[i]); + frames[i] = (int) NULL; + XtFree ((char *)items); + } else +nolist: frames = NULL; + + xim_matchFrames (xc->xim, frames, reference_frame); + return (TCL_OK); +} + + +/* registerFrames -- Register the listed frames with the given reference + * frame. If no reference frame is given the current display frame is used. + * If no frames are listed all frames are registered with the current + * display frame. + * + * Usage: registerFrames [frames [reference_frame]] + * offsetRegister [frames [reference_frame]] + */ +static int +registerFrames (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + int *frames, frame_list[32], reference_frame; + int nitems, i, offsets; + char **items; + + /* Get reference frame. */ + if (argc > 2) + reference_frame = atoi (argv[2]); + else + reference_frame = xim->display_frame; + + /* Get frame list. */ + if (argc > 1) { + if (Tcl_SplitList (tcl, argv[1], &nitems, &items) != TCL_OK) + goto nolist; + for (i=0, frames=frame_list; i < nitems; i++) + frames[i] = atoi (items[i]); + frames[i] = (int) NULL; + XtFree ((char *)items); + } else +nolist: frames = NULL; + + offsets = (strcmp (argv[0], "offsetRegister") == 0); + xim_registerFrames (xc->xim, frames, reference_frame, offsets); + return (TCL_OK); +} + + +/* setOffset -- Set the offset for the current display frame buffer. + * + * Usage: setOffset xoff yoff + */ +static int +setOffset (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb = xim->df_p; + float xcen, ycen; + float xmag, ymag; + float xoff, yoff; + Boolean absolute = False; + int frame = xim->display_frame - 1; + + + if (argc < 3) + return (TCL_ERROR); + + xcen = fb->xcen; + ycen = fb->ycen; + xmag = fb->xmag; + ymag = fb->ymag; + + /* Get offset values for the frame. */ + xoff = atof (argv[1]); + yoff = atof (argv[2]); + + /* Set frame offset. */ + xim_setZoom (xim, fb, fb->frameno, fb->zoommap, + fb->raster, fb->zoomras, xcen, ycen, xmag, ymag, xoff, yoff, + absolute); + + /* Now set he frame values independent of the display frame. */ + fb = &xim->frames[frame]; + fb->xoff = xoff; + fb->yoff = yoff; + + return (TCL_OK); +} + + + +/* clearFrame -- Clear the given frame, or the current frame in no frame + * number is given. + * + * Usage: clearFrame [frame] + */ +static int +clearFrame (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + int frame; + + if (argc > 1) + frame = atoi (argv[1]); + else + frame = xim->display_frame; + + xim_eraseFrame (xc->xim, frame); + return (TCL_OK); +} + + +/* fitFrame -- Attempt to make the display window the same size as the frame + * buffer. + * + * Usage: fitFrame + */ +static int +fitFrame (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + + xim_fitFrame (xc->xim); + return (TCL_OK); +} + + +/* setOption -- Set an ximtool client option. + * + * Usage: setOption option value [args] + * + * Options: + * autoscale true|false + * antialias true|false [type] + * tileFrames true|false [frames] + * tileByRow true|false + * tileTopDown true|false + * tileGeom type|geom [frames] + * cmfocus size + */ +char *h_orient[] = { + "1x1","2x1","3x1","2x2", "3x2","3x2","4x2","4x2", "3x3","5x2","4x3","4x3" +}; +char *v_orient[] = { + "1x1","1x2","1x3","2x2", "2x3","2x3","2x4","2x4", "3x3","2x5","3x4","3x4" +}; + +static int +setOption (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb = xim->df_p; + char *option, *strval, **items; + char buf[SZ_LINE]; + int ch, value, nx, ny, nitems, i, frame_list=0; + + + if (argc < 3) + return (TCL_ERROR); + else { + option = argv[1]; + strval = argv[2]; + + if (strcmp (option, "tileGeom") != 0) { + ch = strval[0]; + if (isdigit (ch)) + value = atoi (strval); + else if (ch == 'T' || ch == 't') + value = 1; + else if (ch == 'F' || ch == 'f') + value = 0; + } + } + + if (strcmp (option, "autoscale") == 0) { + if (xim->autoscale != value) { + xim->autoscale = value; + xim_resize (xim, xim->gt); + sprintf (buf, "%s", value ? "True" : "False"); + xim_message (xim, "autoscale", buf); + } + } else if (strcmp (option, "antialias") == 0) { + if (xim->antialias != value) { + xim->antialias = value; + if (value) { + if (argc > 3) + xim->rop = xim_getAntialias (xim, argv[3]); + else + xim->rop = xim_getAntialias (xim, xim->antialiasType); + } else + xim->rop = 0; + xim_setRop (xim, fb, xim->rop); + sprintf (buf, "%s", value ? "True" : "False"); + xim_message (xim, "antialias", buf); + } + + } else if (strcmp (option, "cmfocus") == 0) { + if (xim->cm_focus != value) { + int box_size = value; + xim->cm_focus = box_size; + GtSetColormapFocus (box_size); + } + + } else if (strcmp (option, "tileFrames") == 0) { + if (xim->tileFrames != value) { + /* Get list of frames to be tiled. */ + if (argc > 3) { + if (Tcl_SplitList (tcl, argv[3], &nitems, &items) != TCL_OK) + goto nolist1; + for (i=0; i < nitems; i++) + frame_list |= (1 << (atoi(items[i]) - 1)); + XtFree ((char *)items); + } else { +nolist1: for (i=0; i < xim->nframes; i++) + frame_list |= (1 << i); + nitems = xim->nframes; + } + + /* Set or clear tile frame mode. */ + xim_tileFrames (xim, value ? frame_list : 0); + } + + } else if (strcmp (option, "tileByRows") == 0) { + xim->tileByRows = value; + xim_tileFrames (xim, xim->tileFramesList); + + } else if (strcmp (option, "tileTopDown") == 0) { + xim->tileTopDown = value; + xim_tileFrames (xim, xim->tileFramesList); + + } else if (strcmp (option, "tileLabels") == 0) { + xim->tileLabels = value; + xim_tileFrames (xim, xim->tileFramesList); + + } else if (strcmp (option, "tileGeom") == 0) { + /* Get list of frames to be tiled. */ + if (argc > 3) { + if (Tcl_SplitList (tcl, argv[3], &nitems, &items) != TCL_OK) + goto nolist2; + for (i=0; i < nitems; i++) + frame_list |= (1 << (atoi(items[i]) - 1)); + XtFree ((char *)items); + } else { +nolist2: for (i=0; i < xim->nframes; i++) + frame_list |= (1 << i); + nitems = xim->nframes; + } + nitems = max (nitems, 1); + + + /* Get the option or tile geometry. */ + if (strcmp (strval, "Best") == 0) { + if (xim->width < xim->height) + goto horient; + else + goto vorient; + } else if (strcmp (strval, "Square") == 0) { + for (i=0; (i*i) < nitems; i++) + ; + nx = ny = i; + } else if (strcmp (strval, "Horizontal") == 0) { +horient: if (nitems >= 13) + nx = ny = 4; + else + sscanf (h_orient[nitems-1], "%dx%d", &nx, &ny); + } else if (strcmp (strval, "Vertical") == 0) { +vorient: if (nitems >= 13) + nx = ny = 4; + else + sscanf (v_orient[nitems-1], "%dx%d", &nx, &ny); + } else if (strcmp (strval, "Row") == 0) { + nx = nitems; + ny = 1; + } else if (strcmp (strval, "Column") == 0) { + nx = 1; + ny = nitems; + } else { + sscanf (strval, "%dx%d", &nx, &ny); + } + + /* Set or clear tile frame mode. */ + xim->tileRows = ny; + xim->tileCols = nx; + xim->tileFramesList = frame_list; + sprintf (buf, "%d %d", nx, ny); + xim_message (xim, "tileOptions", buf); + + xim_tileFrames (xim, xim->tileFramesList); + } + + return (TCL_OK); +} + + +/* setColormap -- Set the colormap for the current display frame. + * + * Usage: setColormap <colormap> + * + * The colormap may be specified either by number or by name. + */ +static int +setColormap (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb = xim->df_p; + unsigned short m_red[MAX_COLORS]; + unsigned short m_green[MAX_COLORS]; + unsigned short m_blue[MAX_COLORS]; + char buf[SZ_LINE]; + ColorMapPtr cm; + int i; + + + if (argc == 2) { + if (isdigit (*argv[1])) + i = atoi(argv[1]); + else { + for (i=1; i <= ncolormaps; i++) + if (strcmp (colormaps[i-1].name, argv[1]) == 0) + break; + } + + if (i >= 1 && i <= ncolormaps) { + cm = &colormaps[i-1]; + if (strncmp (cm->name, "Random", 6) == 0) { + xim_setColormap (cm->name, NULL, + m_red, m_green, m_blue, xim->ncolors); + GtWriteColormap (xim->gt, cm->mapno, + first_color, xim->ncolors, m_red, m_green, m_blue); + } + + fb->colormap = i; + GtSetColormapFocus (-1); /* force full update */ + GtLoadColormap (xim->gt, cm->mapno, fb->offset, fb->scale); + GtSetColormapFocus (xim->cm_focus); + xim_enhancement (xim, fb); + } + } + + return (TCL_OK); +} + + +/* windowColormap -- Set the colormap for the current display frame. + * + * Usage: windowColormap <offset> <scale> + */ +static int +windowColormap (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb = xim->df_p; + register ColorMapPtr cm; + char buf[SZ_LINE]; + + if (argc > 1) { + cm = &colormaps[fb->colormap-1]; + fb->offset = atof(argv[1]); + fb->scale = (argc > 2) ? (float)atof(argv[2]) : fb->scale; + GtLoadColormap (xim->gt, cm->mapno, fb->offset, fb->scale); + xim_enhancement (xim, fb); + } + + return (TCL_OK); +} + + +/* updateColormap -- Update the colormap for the entire display frame. + * + * Usage: updateColormap <offset> <scale> + */ +static int +updateColormap (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb = xim->df_p; + register ColorMapPtr cm; + char buf[SZ_LINE]; + + if (argc > 1) { + cm = &colormaps[fb->colormap-1]; + fb->offset = atof(argv[1]); + fb->scale = (argc > 2) ? (float)atof(argv[2]) : fb->scale; + GtSetColormapFocus (-1); /* force full update */ + GtLoadColormap (xim->gt, cm->mapno, fb->offset, fb->scale); + GtSetColormapFocus (xim->cm_focus); + xim_enhancement (xim, fb); + } + + return (TCL_OK); +} + + +/* zoom -- Set the zoom factors for the current frame to the given values. + * A zoom factor > 1 enlarges the image, < 1 shrinks the image, 1.0 maps + * one source pixel to one destination pixel. + * + * Usage: zoom <xymag> 1 argument + * zoom <xmag> <ymag> 2 arguments + * zoom <xmag> <ymag> <xcen> <ycen> 4 arguments + * + * When called as "zoom" the magnification is relative to the fixed scaling, + * if any, used to scale the frame to fit the display window at mag=1.0. + * When called as zoomAbs" the magnification given is the actual scale factor + * used to map raster pixels to display pixels. + */ +static int +zoom (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb = xim->df_p; + float xmag, ymag; + float xcen, ycen; + float xoff, yoff; + Boolean absolute; + + xmag = fb->xmag; + ymag = fb->ymag; + xcen = fb->xcen; + ycen = fb->ycen; + xoff = fb->xoff; + yoff = fb->yoff; + + switch (argc) { + case 7: + xoff = atof (argv[5]); + yoff = atof (argv[6]); + /* fall through */ + case 5: + xcen = atof (argv[3]); + ycen = atof (argv[4]); + /* fall through */ + case 3: + xmag = atof (argv[1]); + ymag = atof (argv[2]); + break; + case 2: + xmag = ymag = atof (argv[1]); + break; + } + + absolute = (strcmp (argv[0], "zoomAbs") == 0); + xim_setZoom (xim, fb, fb->frameno, fb->zoommap, + fb->raster, fb->zoomras, xcen, ycen, xmag, ymag, xoff, yoff, + absolute); + + return (TCL_OK); +} + + +/* pan -- Pan the current frame, i.e., change the view center. + * + * Usage: pan <xcen> <ycen> + */ +static int +pan (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb = xim->df_p; + Boolean absolute = False; + float xmag, ymag; + float xcen, ycen; + float xoff, yoff; + double atof(); + + xmag = fb->xmag; + ymag = fb->ymag; + xoff = fb->xoff; + yoff = fb->yoff; + + if (argc == 3) { + xcen = atof (argv[1]); + ycen = atof (argv[2]); + + xim_setZoom (xim, fb, fb->frameno, fb->zoommap, + fb->raster, fb->zoomras, xcen, ycen, xmag, ymag, xoff, yoff, + absolute); + } + + return (TCL_OK); +} + + +/* centroid -- Center the cursor on the feature given an initial position + * and box size. Return a correction to the center. + * + * Usage: centroid <xcen> <ycen> <size> [ <type> ] + */ +static int +centroid (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb = xim->df_p; + register CtranPtr ct = (CtranPtr) &fb->ctran; + unsigned char junk[MAX_COLORS]; + unsigned char *pix = NULL; + float *data=NULL, *xm=NULL, *ym=NULL; + float xsum, ysum, xsumx, ysumx; + float cx, cy, lo, hi, px, xcen, ycen, size; + float xmin=999999.0, xmax=-999999.0; + int w, h, ncolors, i, j; + int dist=0, mind=99999, maxd=99999, imin=0, imax=0; + int x0, y0, nx, npix, min_max=-1; + char buf[SZ_LINE]; + double atof(); + + + if (argc < 4) + return (TCL_ERROR); + + xcen = atof (argv[1]); + ycen = atof (argv[2]); + size = atof (argv[3]); + if (argc == 5) + min_max = strcmp (argv[4],"max"); + + x0 = xcen - size; + y0 = ycen - size; + nx = size * 2 + 1; + npix = nx * nx; + + /* Read the display raster. */ + pix = xim_readDisplay (xim, x0,y0,nx,nx, &w,&h, junk,junk,junk, + &ncolors); + + /* Scale the data to the WCS pixel values for centroiding. */ + data = (float *) XtMalloc (npix * sizeof(float)); + for (i=0; i < npix; i++) { + if (pix[i] == 0) { + data[i] = 0.0; + } else { + if (ct->zt == W_LINEAR) { + data[i] = ((pix[i]-1) * (ct->z2 - ct->z1) / 199) + ct->z1; + data[i] = max (ct->z1, min (ct->z2, data[i])); + } else + data[i] = (float) pix[i]; + } + cx = (nx / 2) - (i % nx); + cy = (nx / 2) - (i / nx); + dist = (int) (sqrt (cx*cx + cy*cy) + 0.5); + + if (data[i] > xmax) + xmax = data[i], maxd = dist, imax = i; + else if (data[i] == xmax && dist < maxd) + maxd = dist, imax = i; + + if (data[i] < xmin) + xmin = data[i], mind = dist, imin = i; + else if (data[i] == xmin && dist < mind) + mind = dist, imin = i; + } + XtFree ((char *)pix); + + if (min_max >= 0) { + if (min_max == 0) { + if (data[npix/2] == xmax) + sprintf (buf, "0 0"); + else + sprintf (buf, "%g %g", (imax%nx)-size, (imax/nx)-size); + } else { + if (data[npix/2] == xmin) + sprintf (buf, "0 0"); + else + sprintf (buf, "%g %g", (imin%nx)-size, (imin/nx)-size); + } + + /* Return the correction to the position. */ + Tcl_SetResult (xc->server, buf, TCL_VOLATILE); + return (TCL_OK); + } + + + /* Find the low threshold for the subraster (i.e. the mean). */ + lo = hi = xsum = data[0]; + for (i=1; i < npix ; i++) { + xsum += data[i]; + lo = (data[i] < lo ? data[i] : lo); + hi = (data[i] > hi ? data[i] : hi); + } + + /* Check for a raster with all the same pixels, in which case + * just return a zero offset. + */ + if (lo == hi) { + sprintf (buf, "0 0"); + Tcl_SetResult (xc->server, buf, TCL_VOLATILE); + return (TCL_OK); + + } else + lo = xsum / (float)npix; + + /* Accumulate the x and y marginals. */ + xm = (float *) XtMalloc (nx * sizeof(float)); + ym = (float *) XtMalloc (nx * sizeof(float)); + for (i=0; i < nx; i++) { + xsum = xm[i] = 0.0, ysum = ym[i] = 0.0; + for (j=0; j < nx; j++) { + px = data[(j*nx)+i]; /* column sum */ + if (lo <= px) + xsum += px - lo; + + px = data[(i*nx)+j]; /* row sum */ + if (lo <= px) + ysum += px - lo; + } + xm[i] = xsum; + ym[i] = ysum; + } + XtFree ((char *)data); + + /* Now calculate the centroids as the first moment. If all the + * marginals are zero (i.e. all pixels the same) then return a + * zero correction. + */ + xsum = xsumx = 0.0, ysum = ysumx = 0.0; + px = (float) nx; + for (i=0; i < nx; i++) { + xsum += (xm[i] / px); + xsumx += (xm[i] / px) * i; + + ysum += (ym[i] / px); + ysumx += (ym[i] / px) * i; + } + cx = (xsum == 0.0) ? size : xsumx / xsum; + cy = (ysum == 0.0) ? size : ysumx / ysum; + + XtFree ((char *)xm); /* clean up */ + XtFree ((char *)ym); + + /* Return the correction to the position. */ + sprintf (buf, "%d %d", nint(cx-size), nint(cy-size)); + Tcl_SetResult (xc->server, buf, TCL_VOLATILE); + + return (TCL_OK); +} + + +/* getPixels -- Get an array of pixels around the given center position. + * + * Usage: getPixels <x0> <y0> <nx> <ny> [format [scale]] + */ + +#define PF_NONE 0 /* don't format the output pixels */ +#define PF_PIXTAB 1 /* format for pixel table */ +#define PF_HCUT 2 /* format for horizontal cut-plot */ +#define PF_VCUT 3 /* format for vertical cut-plot */ + +static int +getPixels (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb = xim->df_p; + register CtranPtr ct = (CtranPtr) &fb->ctran; + register int i, j, k, l; + unsigned char *pix = NULL; + char *buf = NULL, ch, val[32]; + float *data = NULL; + float z1 = ct->z1, z2 = ct->z2; + float scale=1.0, yscale = 128.0 / (z2 - z1); + int x0, y0, nx, ny, format=0, npix, sample=1, raster=0; + double atof(); + + + if (argc < 5) + return (TCL_ERROR); + + x0 = atof (argv[1]); + y0 = atof (argv[2]); + nx = atof (argv[3]); + ny = atof (argv[4]); + if (argc >= 6) { + if (isdigit ((ch = *argv[5]))) + format = atoi (argv[5]); + else if (ch == 'T' || ch == 't') + format = 1; + else + format = 0; + } + if (argc >= 7) + sample = (isdigit(*argv[6]) ? atoi (argv[6]) : 1); + if (argc == 8) + scale = atof (argv[7]); + + npix = nx * ny; + + + /* Read the display raster. */ + pix = (unsigned char *) XtMalloc (npix); + if (GtReadPixels (xim->gt, raster, pix, 8, x0, y0, nx, ny) < 0) + return (TCL_ERROR); + + /* Scale the data to the WCS pixel values for display. We don't + * get here if an ISM is running that provides access to the real + * pixel values. + */ + data = (float *) XtCalloc (npix, sizeof(float)); + for (i=0; i < npix; i+=sample) { + if (pix[i] == 0) { + data[i] = 0.0; + } else { + if (ct->zt == W_LINEAR) { + data[i] = ((pix[i]-1) * (z2 - z1) / 199) + z1; + data[i] = max (z1, min (z2, data[i])); + } else + data[i] = (float) pix[i]; + } + if (format > 1) { data[i] = (z2 - data[i]) * yscale; } + } + XtFree ((char *)pix); + + /* Get a text buffer large enough to hold the encoded data. */ + if (!(buf = (char *) XtMalloc ((npix + 4) * 30))) { + XtFree ((char *)data); + return (TCL_ERROR); + } + + /* Encode the data as {ddd} {ddd} {ddd}...{ddd}. The first four + * elements are the zscale values and the array min/max. + */ + strcpy (buf, ""); + sprintf (val, "{%10.1f} ", z1); strcat (buf, val); + sprintf (val, "{%10.1f} ", z2); strcat (buf, val); + + if (format == PF_PIXTAB) { + for (i=0; i < npix; i++) { + sprintf (val, "{%10.1f%c} ", data[i], + (data[i] <= z1 ? '-' : (data[i] >= z2 ? '+' : ' ')) ); + strcat (buf, val); + } + } else if (format == PF_HCUT) { + for (i=0; i < npix; i+=sample) { + sprintf (val, "{%g %g} ", i * scale, data[i]); + strcat (buf, val); + } + } else if (format == PF_VCUT) { + for (i=0; i < npix; i+=sample) { + sprintf (val, "{%g %g} ", data[i], i * scale); + strcat (buf, val); + } + } else { + for (i=0; i < npix; i++) { + sprintf (val, "{%f} ", data[i]); + strcat (buf, val); + } + } + + Tcl_SetResult (xc->server, buf, TCL_VOLATILE); + XtFree ((char *)data); + XtFree ((char *)buf); + + return (TCL_OK); +} + + +/* flip -- Flip the current display frame in the indicated axis or axes. + * + * Usage: flip [axis [axis ...]] + */ +static int +flip (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb = xim->df_p; + int flip_x = 0, flip_y = 0; + int ch, i; + + for (i=1; i < argc; i++) { + ch = argv[i][0]; + if (ch == 'x' || ch == 'X') + flip_x = !flip_x; + else if (ch == 'y' || ch == 'Y') + flip_y = !flip_y; + } + + xim_setFlip (xim, fb, flip_x, flip_y); + return (TCL_OK); +} + + +/* retCursorVal -- Return a cursor value to the ximtool client process. This + * should be executed by the GUI to terminate a cursor read. + * + * Usage: retCursorVal sx sy [frame [wcs [key [strval]]]] + */ +static int +retCursorVal (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + int frame, wcs, key; + float sx, sy; + char *s, *strval; + + if (argc < 3) + return (TCL_ERROR); + + sx = atof (argv[1]); + sy = atof (argv[2]); + frame = (argc > 3) ? atoi (argv[3]) : xim->display_frame; + wcs = (argc > 4) ? atoi (argv[4]) : 1; + + if (argc > 5) { + s = argv[5]; + if (s[0] == '^') + key = s[1] - 'A' + 1; + else + key = s[0]; + } else + key = 0; + + strval = (argc > 6) ? argv[6] : ""; + + xim_retCursorVal (xim, sx, sy, frame, wcs, key, strval); + + return (TCL_OK); +} + + +/* encodewcs -- Convert raw screen coordinates x,y,z (z=pixel value) to + * world coordinates using the WCS passed to ximtool by the client application + * when the frame was loaded. The encoded description of the current position + * and pixel value is returned to the GUI as a string value. + * + * Usage: string = encodewcs sx sy sz + */ +static int +encodewcs (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + char buf[SZ_LINE]; + float sx, sy; + int sz; + + if (argc < 3) + return (TCL_ERROR); + + sx = atof (argv[1]); + sy = atof (argv[2]); + sz = (argc > 3) ? atoi (argv[3]) : 0; + + xim_encodewcs (xc->xim, sx, sy, sz, buf); + Tcl_SetResult (xc->server, buf, TCL_VOLATILE); + + return (TCL_OK); +} + + +/* setPrintOption -- Set an ximtool client hardcopy option. + * + * Usage: setPrintOption option value [args] + * + * Options: + * autoscale true|false + * autorotate true|false + * maxaspect true|false + * annotate true|false + * compress true|false + * + * orientation portrait|landscape + * papersize letter|legal|A4|B5 + * imscale value + * + * colortype gray|pseudo|rgb + * printername strval + * devicetype printer|file + * + * printcmd command + * printfile filename + * + * dotitle true|false + * doborders true|false + * docolorbars true|false + * title string + * + * corners llx lly urx ury + */ +static int +setPrintOption (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb = xim->df_p; + register PSImagePtr psim = xim->psim; + register PrintCfgPtr pcp = xim->pcp; + register PrinterPtr prp; + register int i; + int llx, lly, urx, ury; + char *option, strval[SZ_LINE]; + char buf[SZ_LINE]; + int pnum, ch, value, psflags = psim->page.flags; + + if (argc < 3) + return (TCL_ERROR); + else { + option = argv[1]; + strcpy (strval, argv[2]); + for (i=3; i < argc; i++) { + strcat (strval, " "); + strcat (strval, argv[i]); + } + + ch = strval[0]; + if (isdigit (ch)) + value = atoi (strval); + else if (ch == 'T' || ch == 't') + value = 1; + else if (ch == 'F' || ch == 'f') + value = 0; + } + + if (strcmp (option, "autoscale") == 0) { /* AUTOSCALE */ + psflags = value ? psflags | EPS_AUTOSCALE : + psflags & ~EPS_AUTOSCALE ; + psim->page.flags = psflags; + sprintf (buf, "%s %s", option, value ? "True" : "False"); + xim_message (xim, "printOptions", buf); + + } else if (strcmp (option, "autorotate") == 0) { /* AUTOROTATE */ + psflags = value ? psflags | EPS_AUTOROTATE : + psflags & ~EPS_AUTOROTATE ; + psim->page.flags = psflags; + sprintf (buf, "%s %s", option, value ? "True" : "False"); + xim_message (xim, "printOptions", buf); + + } else if (strcmp (option, "maxaspect") == 0) { /* MAXASPECT */ + psflags = value ? psflags | EPS_MAXASPECT : + psflags & ~EPS_MAXASPECT ; + psim->page.flags = psflags; + sprintf (buf, "%s %s", option, value ? "True" : "False"); + xim_message (xim, "printOptions", buf); + + } else if (strcmp (option, "dotitle") == 0) { /* TITLE */ + psflags = value ? psflags | EPS_DOTITLE : + psflags & ~EPS_DOTITLE ; + psim->page.flags = psflags; + sprintf (buf, "%s %s", option, value ? "True" : "False"); + xim_message (xim, "printOptions", buf); + + } else if (strcmp (option, "doborders") == 0) { /* BORDERS */ + psflags = value ? psflags | EPS_DOBORDERS : + psflags & ~EPS_DOBORDERS ; + psim->page.flags = psflags; + sprintf (buf, "%s %s", option, value ? "True" : "False"); + xim_message (xim, "printOptions", buf); + + } else if (strcmp (option, "docolorbar") == 0) { /* COLORBAR */ + psflags = value ? psflags | EPS_DOCOLORBAR : + psflags & ~EPS_DOCOLORBAR ; + psim->page.flags = psflags; + sprintf (buf, "%s %s", option, value ? "True" : "False"); + xim_message (xim, "printOptions", buf); + + } else if (strcmp (option, "title") == 0) { /* TITLE STR */ + if (strcmp ("imtitle", strval) != 0) { + strcpy (psim->label, strval); + sprintf (buf, "title %s", strval); + xim_message (xim, "printOptions", buf); + } + + } else if (strcmp (option, "annotate") == 0) { /* ANNOTATE */ + if (value) { + if (!psim->label) + psim->label = (char *) calloc (SZ_LINE, sizeof (char)); + sprintf (psim->label, "[Frame %d] %s", + fb->frameno, fb->ctran.imtitle); + psim->annotate = 1; + } else { + if (psim->label) { + XtFree ((char *)psim->label); + psim->label = NULL; + } + psim->annotate = 0; + } + sprintf (buf, "%s %s", option, value ? "True" : "False"); + xim_message (xim, "printOptions", buf); + + } else if (strcmp (option, "compress") == 0) { /* COMPRESS */ + if (value) + psim->compression = RLECompression; + else + psim->compression = NoCompression; + sprintf (buf, "%s %s", option, value ? "True" : "False"); + xim_message (xim, "printOptions", buf); + + } else if (strcmp (option, "orientation") == 0) { /* ORIENTATION */ + if (ch == 'P' || ch == 'p') + psim->page.orientation = EPS_PORTRAIT; + else if (ch == 'L' || ch == 'l') + psim->page.orientation = EPS_LANDSCAPE; + sprintf (buf, "%s %s", option, strval); + xim_message (xim, "printOptions", buf); + + } else if (strcmp (option, "papersize") == 0) { /* PAPER SIZE */ + if (strval[2] == 'T' || strval[2] == 't') + psim->page.page_type = EPS_LETTER; + else if (strval[2] == 'G' || strval[2] == 'g') + psim->page.page_type = EPS_LEGAL; + else if (strval[0] == 'A' || strval[0] == 'a') + psim->page.page_type = EPS_A4; + else if (strval[0] == 'B' || strval[0] == 'b') + psim->page.page_type = EPS_B5; + sprintf (buf, "%s %s", option, strval); + xim_message (xim, "printOptions", buf); + + } else if (strcmp (option, "imscale") == 0) { /* IMAGE SCALE */ + if (value >= 10) { + if ((int)(psim->page.scale*100.0) != value) + psim->page.scale = (float) value / 100.0; + sprintf (buf, "%s %d", option, value); + xim_message (xim, "printOptions", buf); + } + + } else if (strcmp (option, "colortype") == 0) { /* COLORTYPE */ + if (ch == 'G' || ch == 'g') + psim->colorClass = EPS_GRAYSCALE; + else if (ch == 'P' || ch == 'p') + psim->colorClass = EPS_PSEUDOCOLOR; + else if (ch == 'R' || ch == 'r') + psim->colorClass = EPS_TRUECOLOR; + sprintf (buf, "%s %s", option, strval); + xim_message (xim, "printOptions", buf); + + } else if (strcmp (option, "devicetype") == 0) { /* DEVICETYPE */ + + if (strval[0] == 'p' || strval[0] == 'P') { + pcp->diskfile = 0; + sprintf (buf, "deviceType Printer"); + xim_message (xim, "printOptions", buf); + sprintf (buf, "printCmd %s", pcp->printCmd); + xim_message (xim, "printOptions", buf); + sprintf (buf, "printerName %d", pcp->printno); + xim_message (xim, "printOptions", buf); + + } else if (strval[0] == 'f' || strval[0] == 'F') { + pcp->diskfile = 1; + sprintf (buf, "deviceType File"); + xim_message (xim, "printOptions", buf); + sprintf (buf, "printFile %s", pcp->printFile); + xim_message (xim, "printOptions", buf); + } + + } else if (strcmp (option, "printername") == 0) { /* PRINTER NAME */ + /* Set to printer mode if called in file mode. */ + if (pcp->diskfile) { + pcp->diskfile = 0; + sprintf (buf, "deviceType Printer"); + xim_message (xim, "printOptions", buf); + } + pnum = xim_getPrinterInfo (xim, strval); + sprintf (buf, "printerName %s", strval); + xim_message (xim, "printOptions", buf); + strcpy (pcp->printCmd, printer_list[pnum].printCmd); + sprintf (buf, "printCmd %s", pcp->printCmd); + xim_message (xim, "printOptions", buf); + + } else if (strcmp (option, "printcmd") == 0) { /* PRINT COMMAND */ + strcpy (pcp->printCmd, strval); + sprintf (buf, "printCmd %s", strval); + xim_message (xim, "printOptions", buf); + + } else if (strcmp (option, "printfile") == 0) { /* PRINT FILENAME */ + strcpy (pcp->printFile, strval); + sprintf (buf, "printFile %s", strval); + xim_message (xim, "printOptions", buf); + + } else if (strcmp (option, "corners") == 0) { /* IMAGE CORNERS */ + /* Set the corners of the image being printed. */ + sscanf (strval, "%d %d %d %d", &llx, &lly, &urx, &ury); + eps_setCorners (psim, llx, lly, urx, ury); + } + + /* Reload the page parameters in case anything's changed. */ + eps_setPage (psim, psim->page.orientation, psim->page.page_type, + (int)(psim->page.scale*100), psim->page.flags); + + return (TCL_OK); +} + + +/* setSaveOption -- Set an ximtool client disk file option. + * + * Usage: setSaveOption option value [args] + * + * Options: + * + * format fmt + * color gray|pseudo|rgb + * fname strval + */ +static int +setSaveOption (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb = xim->df_p; + register fileSavePtr fsp = xim->fsp; + register int i; + char *option, strval[SZ_LINE]; + char buf[SZ_LINE]; + int ch, value; + + if (argc < 3) + return (TCL_ERROR); + else { + option = argv[1]; + strcpy (strval, argv[2]); + for (i=3; i < argc; i++) { + strcat (strval, " "); + strcat (strval, argv[i]); + } + + + ch = strval[0]; + if (isdigit (ch)) + value = atoi (strval); + else if (ch == 'T' || ch == 't') + value = 1; + else if (ch == 'F' || ch == 'f') + value = 0; + } + + if (strcmp (option, "format") == 0) { /* FORMAT */ + switch (strval[0]) { + case 'r': + if (strval[2] == 's') { + fsp->format = XIM_RAS; + strcpy (fsp->fname, "frame%d.ras"); + } else if (strval[2] == 'w') { + fsp->format = XIM_RAW; + strcpy (fsp->fname, "frame%d.raw"); + } + break; + case 'g': + fsp->format = XIM_GIF; + strcpy (fsp->fname, "frame%d.gif"); + break; + case 'j': + fsp->format = XIM_JPEG; + strcpy (fsp->fname, "frame%d.jpg"); + break; + case 't': + fsp->format = XIM_TIFF; + strcpy (fsp->fname, "frame%d.tiff"); + break; + case 'f': + fsp->format = XIM_FITS; + strcpy (fsp->fname, "frame%d.fits"); + break; + case 'e': + fsp->format = XIM_EPS; + strcpy (fsp->fname, "frame%d.eps"); + break; + case 'x': + fsp->format = XIM_X11; + strcpy (fsp->fname, "frame%d.xwd"); + break; + } + sprintf (buf, "%s %s", option, strval); + xim_message (xim, "saveOptions", buf); + sprintf (buf, "fname %s", fsp->fname); + xim_message (xim, "saveOptions", buf); + + } else if (strcmp (option, "color") == 0) { /* COLOR */ + if (ch == 'G' || ch == 'g') + fsp->colorType = XIM_GRAYSCALE; + else if (ch == 'P' || ch == 'p') + fsp->colorType = XIM_PSEUDOCOLOR; + else if (ch == 'R' || ch == 'r') + fsp->colorType = XIM_RGB; + sprintf (buf, "%s %s", option, strval); + xim_message (xim, "saveOptions", buf); + + } else if (strcmp (option, "fname") == 0) { /* FILENAME */ + strcpy (fsp->fname, strval); + sprintf (buf, "%s %s", option, strval); + xim_message (xim, "saveOptions", buf); + } + + return (TCL_OK); +} + + +/* setLoadOption -- Set an ximtool client disk file option. + * + * Usage: setLoadOption option value [args] + * + * Options: + * up + * root + * home + * rescan + * headers + * pattern patstr + * gray 0|1 + * zscale 0|1 + * zrange 0|1 + * z1 value + * z2 value + * nsample value + * + */ +static int +setLoadOption (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register int i; + register XimDataPtr xim = xc->xim; + register fileLoadPtr flp = xim->flp; + char *ip, *op, *option, *strval; + char buf[SZ_LINE]; + + if (argc < 2) + return (TCL_ERROR); + else { + option = argv[1]; + strval = (argc == 3 ? argv[2] : "" ); + } + + if (strcmp (option, "up") == 0) { /* UP */ + if (strcmp("/", flp->curdir) != 0) { + for (i=strlen(flp->curdir); i > 1; i--) { + if (flp->curdir[i] == '/') + break; + } + flp->curdir[i] = '\0'; + sprintf (buf, "curdir %s", flp->curdir); + xim_message (xim, "loadOptions", buf); + xim_dirRescan (xim); + } + + } else if (strcmp (option, "root") == 0) { /* ROOT */ + strcpy (flp->curdir, "/"); + sprintf (buf, "curdir %s", flp->curdir); + xim_message (xim, "loadOptions", buf); + xim_dirRescan (xim); + + } else if (strcmp (option, "home") == 0) { /* HOME */ + strcpy (flp->curdir, flp->homedir); + sprintf (buf, "curdir %s", flp->curdir); + xim_message (xim, "loadOptions", buf); + xim_dirRescan (xim); + + } else if (strcmp (option, "pattern") == 0) { /* PATTERN */ + if (strcmp(strval, flp->pattern) != 0) { + strcpy (flp->pattern, strval); + sprintf (buf, "pattern %s", flp->pattern); + xim_message (xim, "loadOptions", buf); + xim_dirRescan (xim); + } + + } else if (strcmp (option, "rescan") == 0) { /* RESCAN */ + xim_dirRescan (xim); + + } else if (strcmp (option, "headers") == 0) { /* HEADERS */ + xim_scanHeaders (xim); + + } else if (strcmp (option, "gray") == 0) { /* GRAY */ + flp->gray = (strval[0] == '0' ? 0 : 1); + sprintf (buf, "gray %s", strval[0] == '0' ? "off" : "on"); + xim_message (xim, "loadOptions", buf); + + } else if (strcmp (option, "zscale") == 0) { /* ZSCALE */ + flp->zscale = (strval[0] == '0' ? 0 : 1); + sprintf (buf, "zscale %s", strval[0] == '0' ? "off" : "on"); + xim_message (xim, "loadOptions", buf); + + } else if (strcmp (option, "zrange") == 0) { /* ZRANGE */ + flp->zrange = (strval[0] == '0' ? 0 : 1); + sprintf (buf, "zrange %s", strval[0] == '0' ? "off" : "on"); + xim_message (xim, "loadOptions", buf); + + } else if (strcmp (option, "z1") == 0) { /* Z1 */ + sscanf (argv[2], "%g", &(flp->z1)); + sprintf (buf, "z1 %s", argv[2]); + xim_message (xim, "loadOptions", buf); + + } else if (strcmp (option, "z2") == 0) { /* Z2 */ + sscanf (argv[2], "%g", &(flp->z2)); + sprintf (buf, "z2 %s", argv[2]); + xim_message (xim, "loadOptions", buf); + + } else if (strcmp (option, "nsample") == 0) { /* NSAMPLE */ + sscanf (argv[2], "%d", &(flp->nsample)); + sprintf (buf, "nsample %s", argv[2]); + xim_message (xim, "loadOptions", buf); + } + + return (TCL_OK); +} + + +/* Print -- Print the current display frame to a printer or to a file (EPS). + * + * Usage: print [x0 y0 nx ny] + * + * print rename old new + * print cancel fname + * + * If a subregion is given the indicated region is printed, otherwise the + * full display frame is printed. + * + * The forms "print rename" and "print cancel" are actions for print alerts. + */ +static int +print (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + int x0, y0, nx, ny; + + /* Handle the special cases first. */ + if (argc == 4 && strcmp (argv[1], "rename") == 0) { + ximp_rename (xim, argv[2], argv[3]); + return (TCL_OK); + } else if (argc == 3 && strcmp (argv[1], "cancel") == 0) { + ximp_cancel (xim, argv[2]); + return (TCL_OK); + } + + /* Normal case of a print. */ + if (argc == 5) { + x0 = atoi (argv[1]); + y0 = atoi (argv[2]); + nx = atoi (argv[3]); + ny = atoi (argv[4]); + } else + x0 = y0 = nx = ny = 0; + + if (xim_print (xim, x0,y0, nx,ny) < 0) + return (TCL_ERROR); + else + return (TCL_OK); +} + + +/* Save -- Save the current display frame to a disk file. + * + * Usage: save [x0 y0 nx ny] + * + * save rename old new + * save cancel fname + * + * If a subregion is given the indicated region is saved, otherwise the + * full display frame is saved. + * + * The forms "save rename" and "save cancel" are actions for save alerts. + */ +static int +save (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register fileSavePtr fsp = xim->fsp; + int x0, y0, nx, ny; + + /* Handle the special cases first. */ + if (argc == 4 && strcmp (argv[1], "rename") == 0) { + xims_rename (xim, argv[2], argv[3]); + return (TCL_OK); + } else if (argc == 3 && strcmp (argv[1], "cancel") == 0) { + xims_cancel (xim, argv[2]); + return (TCL_OK); + } + + if (argc == 5) { + x0 = atoi (argv[1]); + y0 = atoi (argv[2]); + nx = atoi (argv[3]); + ny = atoi (argv[4]); + } else + x0 = y0 = nx = ny = 0; + + /* Pass off to the file save routines. */ + if (xim_saveFile (xim, fsp->fname, fsp->format, x0,y0, nx,ny) < 0) + return (TCL_ERROR); + else + return (TCL_OK); +} + + +/* Load -- Load a frame from a disk file. + * + * Usage: load filename [frame] + * + * Options: frame display frame to be loaded + */ +static int +load (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register int i; + register XimDataPtr xim = xc->xim; + register fileLoadPtr flp = xim->flp; + char *ip, *op, *fname; + char *flist, buf[SZ_LINE]; + struct stat file_info; + int frame; + + if (argc < 2) + return (TCL_ERROR); + + fname = argv[1]; + frame = (argc >= 3) ? atoi(argv[2]) : xim->display_frame; + + /* If given a directory change the directory browser current reference + * directory and get a listing. + */ + if (fname[strlen(fname)-1] == '/') { + fname[strlen(fname)-1] = '\0'; + if (fname[0] == '/') { + sprintf (flp->curdir, "%s", fname); + } else { + strcat (flp->curdir, "/"); + strcat (flp->curdir, fname); + } + sprintf (buf, "curdir %s", flp->curdir); + xim_message (xim, "loadOptions", buf); + + xim_dirRescan (xim); + + } else { + /* Otherwise it may be some kind of image to be loaded, but first + * check to see if it's not some other directory first. + */ + (void) stat (fname, &file_info); + if (S_ISDIR(file_info.st_mode)) { + sprintf (flp->curdir, "%s", fname); + sprintf (buf, "curdir %s", flp->curdir); + xim_message (xim, "loadOptions", buf); + xim_dirRescan (xim); + return (TCL_OK); + } + + /* It's not a directory, so try loading the file. */ + if (xim_loadFile (xim, fname, frame) != 0) + return (TCL_ERROR); + } + + return (TCL_OK); +} + + +/* Help -- Send the default help text (HTML) to the GUI. + * + * Usage: help + */ + +/* The builtin default help text. */ +static char *help_text[] = { + "setValue {", +# include "ximtool.html.h" + "}", + NULL +}; + +static int +help (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register char *ip, *op, *helptxt; + register int i; + + helptxt = (char *) XtMalloc (1024000); + for (i=0, op=helptxt; ip = help_text[i]; i++) { + while (*ip) + *op++ = *ip++; + *op++ = '\n'; + } + *op++ = '\0'; + + ObmDeliverMsg (xim->obm, "help", helptxt); + XtFree ((char *)helptxt); + + return (TCL_OK); +} + + +/* Info -- Send various kinds of information to the GUI. The 'args' option + * allows us to pass in information from the GUI that cannot be easily + * obtained otherwise, e.g. private information inthe Gterm widget such as + * the basePixel resource. + * + * Usage: info option [ args ... ] + */ + +info (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + char line[SZ_LINE], path[80], *option, *message; + + if (argc < 2) + return (TCL_ERROR); + else + option = argv[1]; + + message = (char *) XtCalloc (8182, sizeof(char)); + + if (strcmp (option, "server") == 0) { + info_server (xim, argc, argv, message); + + } else if (strcmp (option, "wcs") == 0) { + info_wcs (xim, message); + + } else if (strcmp (option, "clients") == 0) { + info_clients (xim, message); + + } else if (strcmp (option, "imtoolrc") == 0) { + info_imtoolrc (xim, message); + + } else { + XtFree ((char *)message); + return (TCL_ERROR); + } + + strcat (message, "\n\0"); + + if (*message) + xim_message (xim, "info", message); + XtFree ((char *)message); + + return (TCL_OK); +} + + +/* INFO_SERVER -- Helper routine to report server state information. + */ +info_server (xim, argc, argv, text) +register XimDataPtr xim; +int argc; +char **argv; +char *text; +{ + extern char *ximtool_version[]; + extern int ncolormaps, first_color; + char cmapname[80], line[SZ_LINE]; + ColorMapPtr cm; + + sprintf (text, "\t%s\n\n", ximtool_version[0]); + + sprintf (line, "%20s: %s\n", "Base Pixel", + (argc >= 3 ? argv[2] :"")); + strcat (text, line); + sprintf (line, "%20s: %s\n", "Max Colors", + (argc >= 4 ? argv[3] :"")); + strcat (text, line); + sprintf (line, "%20s: %s\n", "Memory Model", xim->memModel); + strcat (text, line); + sprintf (line, "%20s: %s\n", "Antialias Type", xim->antialiasType); + strcat (text, line); + strcat (text, "\n"); + + cm = &colormaps[DEF_COLORMAP-1]; + strcpy (cmapname, cm->name); + sprintf (line, "%20s: %s\n", "Current Colormap", cmapname); + strcat (text, line); + sprintf (line, "%20s: %d\n", "Colormaps Available", ncolormaps); + strcat (text, line); + sprintf (line, "%20s: %s\n", "User Cmap 1", xim->userCMap1); + strcat (text, line); + sprintf (line, "%20s: %s\n", "User Cmap 2", xim->userCMap1); + strcat (text, line); + sprintf (line, "%20s: %s\n", "Cmap Dir 1", xim->userCMapDir1); + strcat (text, line); + sprintf (line, "%20s: %s\n", "Cmap Dir 2", xim->userCMapDir2); + strcat (text, line); + strcat (text, "\n"); + sprintf (line, "%20s: %s\n", "Printer Config", xim->printConfig); + strcat (text, line); + sprintf (line, "%20s: %s\n", "Printer File", xim->pcp->printFile); + strcat (text, line); + sprintf (line, "%20s: %s\n", "Printer Cmd", xim->pcp->printCmd); + strcat (text, line); +} + + +/* INFO_CLIENTS -- Helper routine to report client (display or ISM) state. + */ +info_clients (xim, text) +register XimDataPtr xim; +char *text; +{ + register IsmModule ism; + register int i; + char line[SZ_LINE], path[80]; + extern ismModule ism_modules[]; + extern int ism_nmodules; + + strcpy (text, "\t\tClient Communications Channels\n\n"); + + strcat (text, " Display Client Connections\t "); + strcat (text, "ISM Client Connections\n"); + strcat (text, " --------------------------\t "); + strcat (text, "----------------------\n"); + + if (xim->port) + sprintf (line, " inet: %d\t\t\t ", xim->port); + else + sprintf (line, " inet: Disabled\t\t"); + strcat (text, line); + + sprintf (path, xim->ism_addr, getuid()); + sprintf (line, "unix: %s\n", path); + strcat (text, line); + + if (strcmp(xim->unixaddr, "none") != 0) { + sprintf (path, xim->unixaddr, getuid()); + sprintf (line, " unix: %s\n", path); + } else + sprintf (line, " unix: Disabled\n"); + strcat (text, line); + + if (strcmp(xim->input_fifo,"") != 0 && + strcmp(xim->input_fifo,"none") != 0) + sprintf (line, " fifo: %s\n\t %s\n\n", + xim->input_fifo, xim->output_fifo); + else + sprintf (line, " fifo: Disabled\n\n"); + strcat (text, line); + + strcat (text, "\n"); + strcat (text, "\t\t Available ISM Components\n\n"); + strcat (text, " Name Channel Command\n"); + strcat (text, " ---- ------- -------\n"); + for (i=0; i < ism_nmodules; i++) { + ism = &ism_modules[i]; + sprintf (line, " %-9.9s %-15.15s '%s'\n", + ism->name, + (ism->connected ? ism->chan->path : "Disabled"), + ism->command); + strcat (text, line); + } +} + + +/* INFO_WCS -- Helper routine to report WCS and mapping information for + * each frame in the display. + */ +info_wcs (xim, text) +register XimDataPtr xim; +char *text; +{ + register FrameBufPtr fr = xim->df_p; + register CtranPtr ct = &fr->ctran; + register int i; + MappingPtr mp = (MappingPtr) NULL; + char line[SZ_LINE]; + + /* Write the current frame WCS. */ + sprintf (line, + "\t\tFrame %d WCS & Mappings\n\t\t------------------------\n\n", + fr->frameno); + strcat (text, line); + + strcat (text, "Frame WCS:\n"); + sprintf (line, " a = %9.3f\t b = %9.3f %s\n", + ct->a, ct->b, "# Scale factors"); + strcat (text, line); + + sprintf (line, " c = %9.3f\t d = %9.3f %s\n", + ct->c, ct->d, "# Cross factors"); + strcat (text, line); + + sprintf (line, " tx = %9.3f\tty = %9.3f %s\n", + ct->tx, ct->ty, "# Translation"); + strcat (text, line); + sprintf (line, " z1 = %9.3f\tz2 = %9.3f %s\n", + ct->z1, ct->z2, "# z-scale range"); + strcat (text, line); + + sprintf (line, " zt = %9s\t%30s\n", + (ct->zt == W_UNITARY ? "unitary" : + (ct->zt == W_LINEAR ? "linear" : + (ct->zt == W_LOG ? "log" : "unknown"))), + "# z-scale type\n"); + strcat (text, line); + + + fr = (FrameBufPtr) NULL; + for (i=0; i < xim->nframes; i++) { + fr = &xim->frames[i]; + if (xim->display_frame == fr->frameno) + break; + } + + if (!fr) { + strcat (text, " \n \n"); + return; + } + + for (i=0; i < fr->nmaps; i++) { + mp = &(fr->mapping[i]); + ct = &(mp->ctran); + + sprintf (line, "\nMapping %d: \n", mp->id); + strcat (text, line); + + sprintf (line, " a = %7.3f b = %7.3f\n", ct->a, ct->b); + strcat (text, line); + sprintf (line, " c = %7.3f d = %7.3f\n", ct->c, ct->d); + strcat (text, line); + sprintf (line, " tx = %7.3f ty = %7.3f\n", ct->tx, ct->ty); + strcat (text, line); + sprintf (line, " z1 = %7.3f z2 = %7.3f\tzt: %s\n", + ct->z1, ct->z2, + (ct->zt == W_UNITARY ? "unitary" : + (ct->zt == W_LINEAR ? "linear" : + (ct->zt == W_LOG ? "log" : "unknown"))) ); + strcat (text, line); + + sprintf (line, " region %d: %s\n", mp->regid, mp->region); + strcat (text, line); + sprintf (line, " src: x=%9f y=%9f nx=%d ny=%d\n", + mp->sx, mp->sy, mp->snx, mp->sny); + strcat (text, line); + sprintf (line, " dest: x=%9d y=%9d nx=%d ny=%d\n", + mp->dx, mp->dy, mp->dnx, mp->dny); + + strcat (text, line); + sprintf (line, " ref: %s\n", mp->ref); + strcat (text, line); + } + strcat (text, " \n \n"); +} + + +/* INFO_IMTOOLRC -- Helper routine to report the frame buffer configuration + * table. + */ +info_imtoolrc (xim, text) +register XimDataPtr xim; +char *text; +{ + register int last_fb_used = MAX_FBCONFIG; + register int i, w, h, nf, fb_config = xim->fb_configno; + char line[SZ_LINE]; + + strcpy (text, " Frame Buffer Configuration Table\n"); + strcat (text, " --------------------------------\n\n"); + + sprintf (line, " Imtoolrc File: %s\n", xim->imtoolrc); + strcat (text, line); + strcat (text, "\n Config NFrames\tWidth\tHeight\n"); + strcat (text, " ------ -------\t-----\t------\n"); + + /* Find the index of the last FB defined. */ + for (i=MAX_FBCONFIG; i > 1; i--) + if (xim->fb_config[i-1].width != DEF_FRAME_WIDTH || + xim->fb_config[i-1].height != DEF_FRAME_HEIGHT) { + last_fb_used = i; + break; + } + + /* Print out the frame buffer configurations. */ + for (i=1; i <= last_fb_used; i++) { + w = xim->fb_config[i-1].width; + h = xim->fb_config[i-1].height; + nf = xim->fb_config[i-1].nframes; + if (i > 1 && (w == DEF_FRAME_WIDTH && h == DEF_FRAME_HEIGHT)) { + sprintf (line, " %4d\t\t 0\t n/a\t n/a\n", i); + } else { + sprintf (line, " %4d\t\t%2d\t%5d\t%5d\t %s\n", + i, nf, w, h, ((i==fb_config) ? "<--- current" : " ")); + } + strcat (text, line); + } + strcat (text, " \n \n"); +} + + +/* windowRGB -- Window an individual component of an RGB colormap. We start + * with the currently defined cmap and scale it's component by the given + * offset and slope. A 'save' flag is set when the button is released meaning + * the user is done with that component and the loaded colormap is updated, + * otherwise continue changing that color from the previous call allowing us + * to window the color progressively. The GUI's 'initialize' option should + * restore the original colormap. [This is still test code.] + * + * Usage: windowRGB <color> <offset> <scale> <save> + * + * Options: color color to manipulate (1=Red,2=Green,3=Blue) + * offset offset of transformation + * scale slope of transformation + * save save to loaded colormap when complete? + */ + +static int +windowRGB (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register FrameBufPtr fb = xim->df_p; + register ColorMapPtr cm; + int color, first, nelem, maxelem, save = 0; + unsigned short r[MAX_COLORS]; + unsigned short g[MAX_COLORS]; + unsigned short b[MAX_COLORS]; + char buf[SZ_LINE]; + + + if (argc > 1) { + cm = &colormaps[fb->colormap-1]; + color = atoi(argv[1]); + fb->offset = atof(argv[2]); + fb->scale = (argc > 2) ? (float)atof(argv[3]) : fb->scale; + save = atoi(argv[4]); + + /* Query and read the current colormap. */ + GtQueryColormap (xim->gt, cm->mapno, &first, &nelem, &maxelem); + GtReadColormap (xim->gt, cm->mapno, first, nelem, r,g,b); + + /* compute the scaled colormap, scaling only the color we're + * interested in. + */ + switch (color) { + case 1: + cmapScale (r, nelem, first, fb->offset, fb->scale); + break; + case 2: + cmapScale (g, nelem, first, fb->offset, fb->scale); + break; + case 3: + cmapScale (b, nelem, first, fb->offset, fb->scale); + break; + } + + /* Lastly, write it back to the widget. */ + GtWriteColormap (xim->gt, 0, first, nelem, r, g, b); + if (save) + GtWriteColormap (xim->gt, cm->mapno, first, nelem, r, g, b); + } + + return (TCL_OK); +} + + +/* cmapScale -- Given a single-color cmap scale it with the given offset and + * slope, the scaling is done in place. + */ + +cmapScale (map, ncells, first, offset, slope) +unsigned short map[MAX_COLORS]; +int ncells, first; +float offset, slope; +{ + register int i, c1, c2; + register float x, y, z, frac; + unsigned short val, out[MAX_COLORS]; + + for (i=0; i < ncells; i++) { + x = (float)i / (float)(ncells - 1); + y = (x - offset) * slope + 0.5; + + if (y <= 0.0) { + val = map[first]; + } else if (y >= 1.0) { + val = map[ncells-1]; + } else { + z = y * (ncells - 1); + c1 = (int)z; + c2 = min (ncells-1, c1 + 1); + frac = z - c1; + val = map[c1] * (1.0 - frac) + map[c2] * frac; + } + + out[i] = val; + } + + for (i=0; i < MAX_COLORS; i++) + map[i] = out[i]; +} + + + +/* ISM_START -- Start the ISM task. The named task must be listed in + * the array of ISM modules. + * + * Usage: ism_start task + */ +static int +ism_start (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register IsmModule ism; + + if (argc < 2) + return (TCL_ERROR); + + /* Lookup the command for the task and start it. + */ + if ((ism = ismNameToPtr (argv[1]))) { + system (ism->command); + return (TCL_OK); + } + + /* Task not found, return an error. */ + return (TCL_ERROR); +} + + +/* ISM_STOP -- Stop the ISM task. The named task is told to shut itself + * down by executing the registered shutdown callback. We return OK if + * the shutdown can be executed, an ERR is returned if the named task is + * not currently running. + * + * Usage: ism_stop task + */ +static int +ism_stop (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register IsmModule ism; + + if (argc < 2) + return (TCL_ERROR); + + /* Lookup the command for the task and stop it. */ + if ((ism = ismNameToPtr (argv[1]))) { + (*ism->shutdownCB) (xim, ism); + ism->connected = 0; + return (TCL_OK); + } + + /* Task not found, return an error. */ + return (TCL_ERROR); +} + + +/* ISM_CMD -- Send a command to the named ISM command callback. Return + * values are sent as messages to the GUI 'ism_msg' parameter object, we + * simply pass the argv to the appropriate function. + * + * Usage: ism_cmd task <args> + */ +static int +ism_cmd (xc, tcl, argc, argv) +register XimClientPtr xc; +Tcl_Interp *tcl; +int argc; +char **argv; +{ + register XimDataPtr xim = xc->xim; + register IsmModule ism; + char **cmd_argv; + int cmd_argc; + + if (argc < 2) + return (TCL_ERROR); + + /* Lookup the command callback for the task and run it. */ + if ((ism = ismNameToPtr (argv[1]))) { + + /* Get local copy of argc and argv containing only the commands + * for the ISM callback. + */ + if ((cmd_argc = (argc - 2) > 0)) { + cmd_argv = (char **) XtMalloc (cmd_argc * sizeof(char *)); + memmove (cmd_argv, &argv[2], cmd_argc * sizeof(char *)); + } + + /* Process the command. */ + (*ism->commandCB) (xim, ism, cmd_argc, cmd_argv); + return (TCL_OK); + } + + /* Task not found, return an error. */ + return (TCL_ERROR); +} |