// Copyright (C) 1999-2013 // Smithsonian Astrophysical Observatory, Cambridge, MA, USA // For conditions of distribution and use, see copyright notice in "copyright" #include <ctype.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <sstream> using namespace std; #include <tcl.h> #include "iistcl.h" extern "C" { #include "iis.h" #include "xim.h" int Tcliis_Init(Tcl_Interp* interp); int TcliisCmd(ClientData data, Tcl_Interp *interp, int argc, const char* argv[]); } IIS* iis=NULL; // Debug int IISDebug= 0; static char* dupstr(const char* str) { char* copy; if (str) { copy=new char[strlen(str)+1]; strcpy(copy,str); } else copy=NULL; return copy; } int Tcliis_Init(Tcl_Interp* interp) { if (IISDebug) cerr << "Iis_Init()" << endl; if (Tcl_InitStubs(interp, TCL_PATCH_LEVEL, 0) == NULL) return TCL_ERROR; Tcl_CreateCommand(interp, "iis", TcliisCmd, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); if (Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_VERSION) != TCL_OK) return TCL_ERROR; iis = new IIS(interp); if (iis) return TCL_OK; else return TCL_ERROR; } int TcliisCmd(ClientData data, Tcl_Interp *interp, int argc, const char* argv[]) { if (argc>=2) { if (!strncmp(argv[1], "open", 4)) return iis->open(argc, argv); else if (!strncmp(argv[1], "close", 4)) return iis->close(); else if (!strncmp(argv[1], "retcur", 4)) return iis->retcur(argc, argv); else if (!strncmp(argv[1], "debug", 4)) return iis->debug(argc, argv); else { Tcl_AppendResult(interp, "iis: unknown command: ", argv[1], NULL); return TCL_ERROR; } } else { Tcl_AppendResult(interp, "usage: iis ?open?close?retcur?", NULL); return TCL_ERROR; } } IIS::IIS(Tcl_Interp* intp) { interp = intp; { for (int i=0; i<MAXCHANNEL; i++) { chan[i] = NULL; func[i] = NULL; } } // Resources xim.def_config = 1; // default FB config xim.def_nframes = 0; // default number of frames xim.ncolors = DEF_NCOLORS; // number of image pixel colors xim.tileBorder = DEF_TILE_BORDER; // image border when tiling frames xim.borderColor = dupstr(DEF_BORDER_COLOR); // border color for tileFrames xim.autoscale = 0; // is XY autoscaling enabled xim.antialias = 0; // apply antialiasing when dezooming xim.antialiasType = (char*)DEF_ANTIALIASTYPE; // type of antialiasing xim.invert = 0; // use inverted colormap xim.tileFrames = 0; // tile rather than overlay frames xim.highlightFrames = 0; // highlight tiled frames xim.gui = dupstr("default"); // GUI file name // xim.imtoolrc = dupstr(FBCONFIG_2); // imtoolrc file name xim.memModel = dupstr("fast"); // *FB memory model xim.userCMap1 = dupstr("none"); // user colormap file xim.userCMap2 = dupstr("none"); // user colormap file xim.userCMapDir1 = dupstr("none"); // user colormap directory xim.userCMapDir2 = dupstr(CMAPCONFIG); // user colormap directory xim.printConfig = dupstr(PRINTCONFIG); // printer configuration file xim.input_fifo = dupstr(O_DEVNAME); // *client's output, e.g. /dev/imt1o xim.output_fifo = dupstr(I_DEVNAME); // *client's input, e.g. /dev/imt1i xim.unixaddr = dupstr(DEF_UNIXADDR); // *format for unix socket path xim.ism_addr = dupstr("none"); xim.port = DEF_PORT; // *port for INET socket xim.ism_task = dupstr(DEF_ISM_TASK); // items that require 'c' style memory allocation xim.imtoolrc = (char *) calloc(strlen(FBCONFIG_2)+1, sizeof(char)); strncpy (xim.imtoolrc, FBCONFIG_2, strlen(FBCONFIG_2)); /* Internal state. */ xim.obm = NULL; // object manager { for (int i=0; i<MAX_CLIENTS; i++) { xim.chan[i].xim = NULL; // backpointer to xim descriptor xim.chan[i].id = 0; // input callback id xim.chan[i].type = 0; // channel type xim.chan[i].datain = 0; // input channel xim.chan[i].dataout = 0; // output channel xim.chan[i].keepalive = 0; // used to keep input fifo ready xim.chan[i].path[0] = '\0'; // for unix sockets xim.chan[i].reference_frame = 0;// reference (cmd i/o) frame xim.chan[i].rf_p = NULL; // reference frame descriptor } } xim.cursor_chan = NULL; // *cursor mode channel { xim.ism_chan.xim = (XtPointer)NULL; xim.ism_chan.id = 0; xim.ism_chan.datain = 0; xim.ism_chan.dataout = 0; xim.ism_chan.connected = 0; xim.ism_chan.name[0] = '\0'; xim.ism_chan.path[0] = '\0'; xim.ism_chan.msgbuf[0] = '\0'; } { for (int i=0; i<MAX_ISM; i++) { xim.ism_client[i].xim = (XtPointer)NULL; xim.ism_client[i].id = 0; xim.ism_client[i].datain = 0; xim.ism_client[i].dataout = 0; xim.ism_client[i].connected = 0; xim.ism_client[i].name[0] = '\0'; xim.ism_client[i].path[0] = '\0'; xim.ism_client[i].msgbuf[0] = '\0'; } } xim.toplevel = NULL; // dummy toplevel app shell xim.gt = NULL; // *imagewin gterm-image widget xim.cb = NULL; // colorbar gterm-image widget xim.gm_border = NULL; // border marker for tileFrames xim.tileFramesList = 0; // frames to be tiled (bitmask) xim.nTileFrames = 0; // number of frames to be tiled xim.tileRows = 1; xim.tileCols = 1; xim.tileByRows = 1; xim.tileTopDown = 1; xim.tileLabels = 0; xim.rop = 0; // rasterop for mappings xim.display_frame = 0; // currently displayed frame xim.df_p = NULL; // *display frame descriptor { for (int i=0; i<MAX_FRAMES; i++) { xim.frames[i].frameno = 0; xim.frames[i].raster = 0; xim.frames[i].zoomras = 0; xim.frames[i].zoommap = 0; xim.frames[i].dispmap = 0; xim.frames[i].colormap = DEF_COLORMAP; xim.frames[i].offset = 0.5; xim.frames[i].scale = 1.0; xim.frames[i].xscale = xim.frames[i].yscale = 1.0; xim.frames[i].xmag = xim.frames[i].ymag = 1.0; xim.frames[i].xcen = xim.frames[i].ycen = 0.0; xim.frames[i].xoff = xim.frames[i].yoff = 0.0; xim.frames[i].xflip = xim.frames[i].yflip = 0; xim.frames[i].label[0] = '\0'; xim.frames[i].ctran.valid = 0; xim.frames[i].ctran.a = xim.frames[i].ctran.b = 0; xim.frames[i].ctran.c = xim.frames[i].ctran.d = 0; xim.frames[i].ctran.tx = xim.frames[i].ctran.ty = 0; xim.frames[i].ctran.z1 = xim.frames[i].ctran.z2 = 0; xim.frames[i].ctran.zt = 0; xim.frames[i].ctran.format[0] = '\0'; xim.frames[i].ctran.imtitle[0] = '\0'; xim.frames[i].wcsbuf[0] = '\0'; xim.frames[i].nmaps = 0; } } xim.fb_configno = 0; // *current config number xim.nframes = 0; // *current number of frame bufs xim.width = 0; xim.height = 0; // *current width, height //xim.fb_config[MAX_FBCONFIG]; // *fb config table xim.clientPrivate = NULL; // used by imtool client code xim.psim = NULL; // EPS image struct pointer xim.pcp = NULL; // printer config pointer xim.flp = NULL; // load disk file pointer xim.fsp = NULL; // save disk file pointer } IIS::~IIS() { if (xim.borderColor) delete [] xim.borderColor; if (xim.gui) delete [] xim.gui; // if (xim.imtoolrc) // delete xim.imtoolrc; if (xim.memModel) delete [] xim.memModel; if (xim.userCMap1) delete [] xim.userCMap1; if (xim.userCMap2) delete [] xim.userCMap2; if (xim.userCMapDir1) delete [] xim.userCMapDir1; if (xim.userCMapDir2) delete [] xim.userCMapDir2; if (xim.antialiasType) delete xim.antialiasType; if (xim.printConfig) delete [] xim.printConfig; if (xim.input_fifo) delete [] xim.input_fifo; if (xim.output_fifo) delete [] xim.output_fifo; if (xim.unixaddr) delete [] xim.unixaddr; if (xim.ism_addr) delete [] xim.ism_addr; if (xim.ism_task) delete [] xim.ism_task; // items that require 'c' style memory allocation if (xim.imtoolrc) free(xim.imtoolrc); } void IIS::eval(char* cmd) { if (Tcl_Eval(interp, cmd) == TCL_ERROR) cerr << Tcl_GetStringResult(interp) << endl; } const char *IIS::evalstr(char* cmd) { if (Tcl_Eval(interp, cmd) == TCL_ERROR) cerr << Tcl_GetStringResult(interp) << endl; return Tcl_GetStringResult(interp); } const char *IIS::result() { return Tcl_GetStringResult(interp); } int IIS::open(int argc, const char* argv[]) { if (IISDebug) cerr << "IIS:open()" << endl; if (argc==6) { delete [] xim.input_fifo; xim.input_fifo = dupstr(argv[2]); // *client's output, e.g. /dev/imt1i delete [] xim.output_fifo; xim.output_fifo = dupstr(argv[3]); // *client's input, e.g. /dev/imt1o string x(argv[4]); istringstream str(x); str >> xim.port; // *port for INET socket delete [] xim.unixaddr; xim.unixaddr = dupstr(argv[5]); // *format for unix socket path } xim_initialize(&xim, xim.def_config, xim.def_nframes, 1); xim_iisOpen(&xim); return TCL_OK; } int IIS::close() { if (IISDebug) cerr << "IIS::close()" << endl; xim_iisClose(&xim); return TCL_OK; } int IIS::retcur(int argc, const char* argv[]) { if (IISDebug) cerr << "IIS::retcur()" << endl; if (argc==6) { if (xim.cursor_chan == NULL) { Tcl_AppendResult(interp, "iis retcur: no cursor channel", NULL); return TCL_ERROR; } float xx,yy; { string x(argv[2]); istringstream str(x); str >> xx; } { string x(argv[3]); istringstream str(x); str >> yy; } int key = argv[4][0]; int frame; { string x(argv[5]); istringstream str(x); str >> frame; } xim_retCursorVal(&xim, xx, yy, frame, 0, key, (char*)""); return TCL_OK; } else { Tcl_AppendResult(interp, "iis retcur: wrong number of args", NULL); return TCL_ERROR; } } int IIS::encodewcs(int argc, const char* argv[]) { if (IISDebug) cerr << "IIS::encodewcs()" << endl; if (argc==4 || argc==5) { float sx,sy; { string x(argv[2]); istringstream str(x); str >> sx; } { string x(argv[3]); istringstream str(x); str >> sy; } int sz = 0; { string x(argv[4]); istringstream str(x); str >> sz; } char buf[SZ_LINE]; xim_encodewcs(&xim, sx, sy, sz, buf); Tcl_SetResult (interp, buf, TCL_VOLATILE); return TCL_OK; } else { Tcl_AppendResult(interp, "iis encodewcs: wrong number of args", NULL); return TCL_ERROR; } } int IIS::debug(int argc, const char* argv[]) { IISDebug = !strncmp(argv[2],"1",1); return TCL_OK; }