Logo Search packages:      
Sourcecode: saods9 version File versions

frmarker.C

// Copyright (C) 1999-2004
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"

#include <stdlib.h>
#include <time.h>

#if __GNUC__ >= 3
#include <fstream>
#include "fdstream.hpp"
#else
#include <fstream.h>
#endif

#include "framebase.h"
#include "fitsimage.h"
#include "util.h"
#include "mmap.h"
#include "contour.h"

#include "marker.h"
#include "basemarker.h"
#include "basecircle.h"
#include "annulus.h"
#include "panda.h"
#include "circle.h"
#include "compass.h"
#include "ellipse.h"
#include "ellipseannulus.h"
#include "box.h"
#include "boxannulus.h"
#include "polygon.h"
#include "line.h"
#include "text.h"
#include "ruler.h"
#include "projection.h"
#include "point.h"

#define LISTBUFSIZE 8192

// NOTE: all marker traversal routines use a local ptr as opposed to the
// list current() because marker call backs may invoke another traversal 
// routine or the event loop, which may process pending events

// DS9/Funtools Marker Parser Stuff
extern FrameBase* fr;              // used by mkerror,ciaoerror,otherror

#undef yyFlexLexer
#define yyFlexLexer mkFlexLexer
#include <FlexLexer.h>

mkFlexLexer* mklexx = NULL;    // used by mklex
extern int mkparse(void*);

int mklex()
{
  return (mklexx ? mklexx->yylex() : 0);
}

void mkerror(const char* m)
{
  if (fr) {
    fr->error(m);
    const char* cmd = mklexx ? mklexx->YYText() : (const char*)NULL;
    if (cmd && cmd[0] != '\n') {
      fr->error(": ");
      fr->error(cmd);
    }
  }
}

// CIAO Marker Parser Stuff

#undef yyFlexLexer
#define yyFlexLexer ciaoFlexLexer
#include <FlexLexer.h>

ciaoFlexLexer* ciaolexx = NULL;    // used by ciaolex
extern int ciaoparse(void*);

int ciaolex()
{
  return (ciaolexx ? ciaolexx->yylex() : 0);
}

void ciaoerror(const char* m)
{
  if (fr) {
    fr->error(m);
    const char* cmd = ciaolexx ? ciaolexx->YYText() : (const char*)NULL;
    if (cmd && cmd[0] != '\n') {
      fr->error(": ");
      fr->error(cmd);
    }
  }
}

// Pros Marker Parser Stuff

#undef yyFlexLexer
#define yyFlexLexer prosFlexLexer
#include <FlexLexer.h>

prosFlexLexer* proslexx = NULL;    // used by proslex
extern int prosparse(void*);

int proslex()
{
  return (proslexx ? proslexx->yylex() : 0);
}

void proserror(const char* m)
{
  if (fr) {
    fr->error(m);
    const char* cmd = proslexx ? proslexx->YYText() : (const char*)NULL;
    if (cmd && cmd[0] != '\n') {
      fr->error(": ");
      fr->error(cmd);
    }
  }
}

// SAOtng Marker Parser Stuff

#undef yyFlexLexer
#define yyFlexLexer tngFlexLexer
#include <FlexLexer.h>

tngFlexLexer* tnglexx = NULL;    // used by tnglex
extern int tngparse(void*);

int tnglex()
{
  return (tnglexx ? tnglexx->yylex() : 0);
}

void tngerror(const char* m)
{
  if (fr) {
    fr->error(m);
    const char* cmd = tnglexx ? tnglexx->YYText() : (const char*)NULL;
    if (cmd && cmd[0] != '\n') {
      fr->error(": ");
      fr->error(cmd);
    }
  }
}

// SAOimage Marker Parser Stuff

#undef yyFlexLexer
#define yyFlexLexer saoFlexLexer
#include <FlexLexer.h>

saoFlexLexer* saolexx = NULL;    // used by saolex
extern int saoparse(void*);

int saolex()
{
  return (saolexx ? saolexx->yylex() : 0);
}

void saoerror(const char* m)
{
  if (fr) {
    fr->error(m);
    const char* cmd = saolexx ? saolexx->YYText() : (const char*)NULL;
    if (cmd && cmd[0] != '\n') {
      fr->error(": ");
      fr->error(cmd);
    }
  }
}

// XY Marker Parser Stuff

#undef yyFlexLexer
#define yyFlexLexer xyFlexLexer
#include <FlexLexer.h>

xyFlexLexer* xylexx = NULL;    // used by xylex
extern int xyparse(void*);

int xylex()
{
  return (xylexx ? xylexx->yylex() : 0);
}

void xyerror(const char* m)
{
  if (fr) {
    fr->error(m);
    const char* cmd = xylexx ? xylexx->YYText() : (const char*)NULL;
    if (cmd && cmd[0] != '\n') {
      fr->error(": ");
      fr->error(cmd);
    }
  }
}

// Marker Commands

void FrameBase::createCircleCmd(const Vector& center, double radius,
                      const char* color, int width, const char* font,
                      const char* text, unsigned short prop, 
                      const char* comment, const List<Tag>& tag)
{
  createMarker(new Circle(this, center, radius, 
                    color, width, font, text, prop, comment, tag));
}

void FrameBase::createAnnulusCmd(const Vector& center,
                       double start, double stop, int num,
                       const char* color, int width, const char* font,
                       const char* text, unsigned short prop,
                       const char* comment, const List<Tag>& tag)
{
  createMarker(new Annulus(this, center, start, stop, num, 
                     color, width, font, text, prop, comment, tag));
}

void FrameBase::createAnnulusCmd(const Vector& center,
                       double* radii, int num,
                       const char* color, int width, const char* font,
                       const char* text, unsigned short prop,
                       const char* comment, const List<Tag>& tag)
{
  createMarker(new Annulus(this, center, radii, num, 
                     color, width, font, text, prop, comment, tag));
}

void FrameBase::createBoxCmd(const Vector& center, const Vector& size, 
                   double angle,
                   const char* color, int width, const char* font,
                   const char* text, unsigned short prop,
                   const char* comment, const List<Tag>& tag)
{
  createMarker(new Box(this, center, size, angle, 
                   color, width, font, text, prop, comment, tag));
}

void FrameBase::createBoxAnnulusCmd(const Vector& center,
                        const Vector& inner, const Vector& outer,
                        int num,
                        double angle,
                        const char* color, int width,
                        const char* font, 
                        const char* text, unsigned short prop,
                        const char* comment, const List<Tag>& tag)
{
  createMarker(new BoxAnnulus(this, center, inner, outer, num, angle, 
                        color, width, font, text, prop, comment, tag));
}

void FrameBase::createBoxAnnulusCmd(const Vector& center, double angle, int num,
                        Vector* size,
                        const char* color, int width, 
                        const char* font, 
                        const char* text, unsigned short prop,
                        const char* comment, const List<Tag>& tag)
{
  createMarker(new BoxAnnulus(this, center, angle, num, size, 
                        color, width, font, text, prop, comment, tag));
}

void FrameBase::createEllipseCmd(const Vector& center, const Vector& radius,
                       double angle,
                       const char* color, int width, const char* font,
                       const char* text, unsigned short prop,
                       const char* comment, const List<Tag>& tag)

{
  createMarker(new Ellipse(this,center, radius, angle, 
                     color, width, font, text, prop, comment, tag));
}

void FrameBase::createEllipseAnnulusCmd(const Vector& center,
                            const Vector& inner, const Vector& outer,
                            int num, double angle,
                            const char* color, int width,
                            const char* font, 
                            const char* text, unsigned short prop,
                            const char* comment, const List<Tag>& tag)
{
  createMarker(new EllipseAnnulus(this, center, inner, outer, num, angle, 
                         color, width, font, text, prop, comment,tag));
}

void FrameBase::createEllipseAnnulusCmd(const Vector& center, double angle,
                            int num, Vector* radii,
                            const char* color, int width,
                            const char* font, 
                            const char* text, unsigned short prop,
                            const char* comment, const List<Tag>& tag)
{
  createMarker(new EllipseAnnulus(this, center, angle, num, radii, 
                         color, width, font, text, prop, comment,tag));
}

void FrameBase::createPandaCmd(const Vector& center,
                     double ang1, double ang2, int an,
                     double rad1, double rad2, int rn,
                     const char* color, int width, const char* font,
                     const char* text, unsigned short prop,
                     const char* comment, const List<Tag>& tag)
{
  createMarker(new Panda(this, center, ang1, ang2, an, rad1, rad2, rn, 
                   color, width, font, text, prop, comment, tag));
}

void FrameBase::createPandaCmd(const Vector& center,
                     double* a, int an,
                     double* r, int rn,
                     const char* color, int width, const char* font,
                     const char* text, unsigned short prop,
                     const char* comment, const List<Tag>& tag)
{
  createMarker(new Panda(this, center, a, an, r, rn,
                   color, width, font, text, prop, comment, tag));
}

void FrameBase::createPolygonCmd(const Vector& center, const Vector& bb,
                       const char* color, int width, const char* font,
                       const char* text, unsigned short prop,
                       const char* comment, const List<Tag>& tag)
{
  createMarker(new Polygon(this, center, bb, color, width, font, 
                     text, prop, comment, tag));
}

void FrameBase::createPolygonCmd(const List<Vertex>& list,
                       const char* color, int width, const char* font,
                       const char* text, unsigned short prop,
                       const char* comment, const List<Tag>& tag)
{
  createMarker(new Polygon(this, list, color, width, font, 
                     text, prop, comment, tag));
}

void FrameBase::createContourPolygonCmd(const char* color, int width, 
                            const char* font,
                            const char* text, unsigned short prop,
                            const char* comment, const List<Tag>& tag)
{
  // main contour
  if (hasContour()) {
    List<Vertex>& c = (List<Vertex>&)((*currentcontour)->contours());

    // build from back to front
    if (c.tail()) {
      List<Vertex> list;
      while (c.previous()) {
      if (c.current()->vector[0] != DBL_MAX)
        list.append(new Vertex(c.current()->vector));
      else {
        createMarker(new Polygon(this, list, 
                           color, width, font, text, prop, NULL, tag));
        list.deleteAll();
      }
      }
      createMarker(new Polygon(this, list, color, width, font, 
                         text, prop, comment, tag));
    }
  }

  // aux contours
  Contour* cptr = auxcontours.head();
  while (cptr) {
    List<Vertex>& c = (List<Vertex>&)(cptr->contours());

    // build from back to front
    if (c.tail()) {
      List<Vertex> list;
      while (c.previous()) {
      if (c.current()->vector[0] != DBL_MAX)
        list.append(new Vertex(c.current()->vector));
      else {
        createMarker(new Polygon(this, list, 
                           color, width, font, text, prop, NULL, tag));
        list.deleteAll();
      }
      }
      createMarker(new Polygon(this, list, color, width, font, 
                         text, prop, comment, tag));
    }

    cptr = cptr->next();
  }
}

void FrameBase::createLineCmd(const Vector& center, const Vector& p2, 
                    int arrow1, int arrow2,
                    const char* color, int width, const char* font,
                    const char* text, unsigned short prop,
                    const char* comment, const List<Tag>& tag)
{
  createMarker(new Line(this, center, p2, arrow1, arrow2,
                   color, width, font, text, prop, comment, tag));
}

void FrameBase::createTextCmd(const Vector& center, double angle,
                    const char* color, int width, const char* font,
                    const char* text, unsigned short prop,
                    const char* comment, const List<Tag>& tag)
{
  createMarker(new Text(this, center, angle, 
                  color, width, font, text, prop, comment, tag));
}

void FrameBase::createRulerCmd(const Vector& center, const Vector& p2,
                     CoordSystem sys, SkyFrame sky,
                     CoordSystem distsys, SkyFormat distformat,
                     const char* color, int width, const char* font,
                     const char* text, unsigned short prop,
                     const char* comment, const List<Tag>& tag)
{
  createMarker(new Ruler(this, center, p2, 
                   sys, sky, distsys, distformat, 
                   color, width, font, text, prop, comment, tag));
}

void FrameBase::createCompassCmd(const Vector& center, double r,
                       const char* north, const char* east, 
                       int na, int ea,
                       CoordSystem sys, SkyFrame sky,
                       const char* color, int width, const char* font,
                       const char* text, unsigned short prop,
                       const char* comment, const List<Tag>& tag)
{
  createMarker(new Compass(this, center, r, north, east, na, ea, sys, sky, 
                     color, width, font, text, prop, comment, tag));
}

void FrameBase::createProjectionCmd(const Vector& center, const Vector& p2, 
                        double w, const char* mvcb, const char* delcb,
                        const char* color, int width, const char* font,
                        const char* text, unsigned short prop,
                        const char* comment, const List<Tag>& tag)
{
  createMarker(new Projection(this, center, p2, w, mvcb, delcb,
                        color, width, font, text, prop, comment, tag));
}

void FrameBase::createCirclePointCmd(const Vector& center,
                         const char* color, int width,
                         const char* font,
                         const char* text, unsigned short prop,
                         const char* comment, const List<Tag>& tag)
{
  createMarker(new CirclePoint(this, center, color, width, font, 
                         text, prop, comment, tag));
}

void FrameBase::createBoxPointCmd(const Vector& center,
                        const char* color, int width, const char* font,
                        const char* text, unsigned short prop,
                        const char* comment, const List<Tag>& tag)
{
  createMarker(new BoxPoint(this, center, color, width, font, 
                      text, prop, comment, tag));
}

void FrameBase::createDiamondPointCmd(const Vector& center,
                          const char* color, int width,
                          const char* font,
                          const char* text, unsigned short prop,
                          const char* comment, const List<Tag>& tag)
{
  createMarker(new DiamondPoint(this, center, color, width, font, 
                        text, prop, comment, tag));
}

void FrameBase::createCrossPointCmd(const Vector& center,
                        const char* color, int width, const char* font,
                        const char* text, unsigned short prop,
                        const char* comment, const List<Tag>& tag)
{
  createMarker(new CrossPoint(this, center, color, width, font, 
                        text, prop, comment, tag));
}

void FrameBase::createExPointCmd(const Vector& center,
                       const char* color, int width, const char* font,
                       const char* text, unsigned short prop,
                       const char* comment, const List<Tag>& tag)
{
  createMarker(new ExPoint(this, center, color, width, font, 
                     text, prop, comment, tag));
}

void FrameBase::createArrowPointCmd(const Vector& center,
                        const char* color, int width, const char* font,
                        const char* text, unsigned short prop,
                        const char* comment, const List<Tag>& tag)
{
  createMarker(new ArrowPoint(this, center, color, width, font, 
                        text, prop, comment, tag));
}

void FrameBase::createBoxCirclePointCmd(const Vector& center,
                            const char* color, int width,
                            const char* font,
                            const char* text, unsigned short prop,
                            const char* comment, const List<Tag>& tag)
{
  createMarker(new BoxCirclePoint(this, center, color, width, font, 
                          text, prop, comment, tag));
}

void FrameBase::createMarker(Marker* m)
{
  markers->append(m);

  // now update new marker

  update(markerUpdate, m->getAllBBox());

  // and return id

  printInteger(m->getId());
}

void FrameBase::getMarkerAngleCmd(int id, CoordSystem sys)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      printDouble(radToDeg(mapAngleFromRef(m->getAngle(), sys)), DEFAULT);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerAnnulusRadiusCmd(int id, CoordSystem sys,SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      const double* r = ((Annulus*)m)->getRadii();
      int cnt = ((Annulus*)m)->getAnnuliCount();
      for (int i=0; i<cnt; i++) {
      markerPrintDouble(m->getCenter(), r[i], sys, format);
      Tcl_AppendResult(interp, "\n", NULL);
      }
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerBoxAnnulusSizeCmd(int id, CoordSystem sys, 
                               SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      const Vector* r = ((BoxAnnulus*)m)->getSize();
      int cnt = ((BoxAnnulus*)m)->getAnnuliCount();
      for (int i=0; i<cnt; i++) {
      markerPrintVector(m->getCenter(), r[i], sys, format);
      Tcl_AppendResult(interp, "\n", NULL);
      }
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerBoxSizeCmd(int id, InternalSystem sys)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      markerPrintVector(((Box*)m)->getSize(), sys);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerBoxSizeCmd(int id, CoordSystem sys, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      markerPrintVector(m->getCenter(), ((Box*)m)->getSize(), sys, format);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerCenterCmd(int id, InternalSystem sys)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      markerPrintCoord(m->getCenter(), sys);
      return;
    }
    m=m->next();
  }
}

void FrameBase::getMarkerCenterCmd(int id, CoordSystem sys, SkyFrame sky, 
                         SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      markerPrintCoord(m->getCenter(), m->getCenter(), sys, sky, format);
      return;
    }
    m=m->next();
  }
}

void FrameBase::getMarkerCircleRadiusCmd(int id, InternalSystem sys)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      markerPrintDouble(((Circle*)m)->getRadius(), sys);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerCircleRadiusCmd(int id, CoordSystem sys, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      markerPrintDouble(m->getCenter(),((Circle*)m)->getRadius(), sys, format);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerColorCmd()
{
  // return first found

  Marker* m=markers->head();
  while (m) {
    if (m->isSelected()) {
      Tcl_AppendResult(interp,  m->getColorName(), NULL);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerColorCmd(const char* tag)
{
  // return first found

  Marker* m=markers->head();
  while (m) {
    if (m->hasTag(tag)) {
      Tcl_AppendResult(interp,  m->getColorName(), NULL);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerColorCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      Tcl_AppendResult(interp,  m->getColorName(), NULL);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerCompassArrowCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (((Compass*)m)->getNorthArrow())
      Tcl_AppendResult(interp, "1", NULL);
      else
      Tcl_AppendResult(interp, "0", NULL);

      if (((Compass*)m)->getEastArrow())
      Tcl_AppendResult(interp, " 1", NULL);
      else
      Tcl_AppendResult(interp, " 0", NULL);

      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerCompassLabelCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      Tcl_AppendElement(interp, ((Compass*)m)->getNorthText());
      Tcl_AppendElement(interp, ((Compass*)m)->getEastText());
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerCompassRadiusCmd(int id, InternalSystem sys)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      markerPrintDouble(((Compass*)m)->getRadius(), sys);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerCompassRadiusCmd(int id, 
                                CoordSystem sys, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      markerPrintDouble(m->getCenter(),((Compass*)m)->getRadius(), sys,format);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerEllipseRadiusCmd(int id,
                                CoordSystem sys, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      markerPrintVector(m->getCenter(),((Ellipse*)m)->getRadius(),sys,format);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerEllipseAnnulusRadiusCmd(int id, CoordSystem sys, 
                                   SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      const Vector* r = ((EllipseAnnulus*)m)->getRadii();
      int cnt = ((EllipseAnnulus*)m)->getAnnuliCount();
      for (int i=0; i<cnt; i++) {
      markerPrintVector(m->getCenter(), r[i], sys, format);
      Tcl_AppendResult(interp, "\n", NULL);
      }
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerFontCmd()
{
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected()) {
      Tcl_AppendResult(interp, m->getFont(), NULL);
      return;
    }
    m=m->next();
  }
}

void FrameBase::getMarkerFontCmd(const char* tag)
{
  Marker* m=markers->head();
  while (m) {
    if (m->hasTag(tag)) {
      Tcl_AppendResult(interp, m->getFont(), NULL);
      return;
    }
    m=m->next();
  }
}

void FrameBase::getMarkerFontCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      Tcl_AppendResult(interp, m->getFont(), NULL);
      return;
    }
    m=m->next();
  }
}

#if __GNUC__ >= 3
void FrameBase::getMarkerHandleCmd(const Vector& v)
{
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected()) {
      int h = m->onHandle(v);
      if (h) {
      ostringstream str;
      str << m->getId() << ' ' << h << ends;
      Tcl_AppendResult(interp, str.str().c_str(), NULL);
      return;
      }
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "0 0", NULL);
}
#else
void FrameBase::getMarkerHandleCmd(const Vector& v)
{
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected()) {
      int h = m->onHandle(v);
      if (h) {
      char buf [16];
      ostrstream str(buf,16);
      str << m->getId() << ' ' << h << ends;
      Tcl_AppendResult(interp, buf, NULL);
      return;
      }
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "0 0", NULL);
}
#endif

void FrameBase::getMarkerIdCmd(const Vector& v)
{
  // v is in canvas coords

  Marker* m=markers->head();
  while (m) {
    if (m->isIn(v)) {
      printInteger(m->getId());
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "0", NULL);
}

#if __GNUC__ >= 3
void FrameBase::getMarkerIdAllCmd()
{
  Marker* m=markers->head();
  while (m) {
    ostringstream str;
    str << m->getId() << ' ' << ends;
    Tcl_AppendResult(interp, str.str().c_str(), NULL);
    m=m->next();
  }
}
#else
void FrameBase::getMarkerIdAllCmd()
{
  char buf[8];
  Marker* m=markers->head();
  while (m) {
    ostrstream str(buf,8);
    str << m->getId() << ' ' << ends;
    Tcl_AppendResult(interp, buf, NULL);
    m=m->next();
  }
}
#endif

void FrameBase::getMarkerLineCmd(int id, CoordSystem sys, SkyFrame sky, 
                       SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      markerPrintCoord(m->getCenter(), ((Line*)m)->getP1(), sys, sky, format);
      markerPrintCoord(m->getCenter(), ((Line*)m)->getP2(), sys, sky, format);
      return;
    }
    m=m->next();
  }
}

void FrameBase::getMarkerLineArrowCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (((Line*)m)->getP1Arrow())
      Tcl_AppendResult(interp, "1", NULL);
      else
      Tcl_AppendResult(interp, "0", NULL);

      if (((Line*)m)->getP2Arrow())
      Tcl_AppendResult(interp, " 1", NULL);
      else
      Tcl_AppendResult(interp, " 0", NULL);

      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerLineDistanceCmd(int id, CoordSystem sys, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      markerPrintDouble(m->getCenter(),((Line*)m)->getP2(),((Line*)m)->getP1(),
                  sys, format);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

#if __GNUC__ >= 3
void FrameBase::getMarkerLineWidthCmd()
{
  // return first found
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected()) {
      ostringstream str;
      str << m->getLineWidth() << ends;
      Tcl_AppendResult(interp, str.str().c_str(), NULL);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}
#else
void FrameBase::getMarkerLineWidthCmd()
{
  // return first found
  char buf[8];
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected()) {
      ostrstream str(buf,8);
      str << m->getLineWidth() << ends;
      Tcl_AppendResult(interp,  buf, NULL);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}
#endif

#if __GNUC__ >= 3
void FrameBase::getMarkerLineWidthCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      ostringstream str;
      str << m->getLineWidth() << ends;
      Tcl_AppendResult(interp, str.str().c_str(), NULL);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}
#else
void FrameBase::getMarkerLineWidthCmd(int id)
{
  char buf[8];
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      ostrstream str(buf,8);
      str << m->getLineWidth() << ends;
      Tcl_AppendResult(interp,  buf, NULL);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}
#endif

void FrameBase::getMarkerMapLenFromRefCmd(int id, double d, CoordSystem sys, 
                                SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      printDouble(m->mapLenFromRef(d,sys,format), DEFAULT);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerPandaAnglesCmd(int id, CoordSystem sys)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      const double* a = ((Panda*)m)->getAngles();
      int cnt = ((Panda*)m)->getAnglesCount();
      for (int i=0; i<cnt; i++) {
      // use panda version of radToDeg
      printDouble(((Panda*)m)->radToDeg(mapAngleFromReff(a[i],sys)),DEFAULT);
      Tcl_AppendResult(interp, "\n", NULL);
      }
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerPandaRadiusCmd(int id, CoordSystem sys, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      const double* r = ((Panda*)m)->getRadii();
      int cnt = ((Panda*)m)->getAnnuliCount();
      for (int i=0; i<cnt; i++) {
      markerPrintDouble(m->getCenter(), r[i], sys, format);
      Tcl_AppendResult(interp, "\n", NULL);
      }
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

#if __GNUC__ >= 3
void FrameBase::getMarkerPolygonSegmentCmd(const Vector& v)
{
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected() && m->isPolygon()) {
      int s = ((Polygon*)(m))->getSegment(v);
      if (s) {
      ostringstream str;
      str << m->getId() << ' ' << s << ends;
      Tcl_AppendResult(interp, str.str().c_str(), NULL);
      return;
      }
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "0 0", NULL);
}
#else
void FrameBase::getMarkerPolygonSegmentCmd(const Vector& v)
{
  char buf [16];
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected() && m->isPolygon()) {
      int s = ((Polygon*)(m))->getSegment(v);
      if (s) {
      ostrstream str(buf,16);
      str << m->getId() << ' ' << s << ends;
      Tcl_AppendResult(interp, buf, NULL);
      return;
      }
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "0 0", NULL);
}
#endif

void FrameBase::getMarkerPreserveCmd()
{
  if (preserveMarkers)
      Tcl_AppendResult(interp, "1", NULL);
  else
      Tcl_AppendResult(interp, "0", NULL);
}

void FrameBase::getMarkerProjectionCmd(int id, 
                               char* xName, char* yName,
                               char* xcName, char* ycName)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      Projection* p = (Projection*)m;
      bltProjection(xName, yName, xcName, ycName, 
                p->getSystem(), p->getSkyFrame(),
                p->getP1(), p->getP2(), p->getWidth(), p->getMethod());
      return;
    }
    m=m->next();
  }
}

void FrameBase::getMarkerProjectionPointsCmd(int id, CoordSystem sys, 
                                   SkyFrame sky, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      markerPrintCoord(m->getCenter(), ((Projection*)m)->getP1(), sys, 
                   sky, format);
      markerPrintCoord(m->getCenter(), ((Projection*)m)->getP2(), sys, 
                   sky, format);
      return;
    }
    m=m->next();
  }
}

void FrameBase::getMarkerProjectionDistanceCmd(int id, CoordSystem sys,
                                 SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      markerPrintDouble(m->getCenter(), ((Projection*)m)->getP2(),
                  ((Projection*)m)->getP1(), sys, format);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerProjectionMethodCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      printInteger(((Projection*)m)->getMethod());
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerProjectionWidthCmd(int id, CoordSystem sys, 
                              SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      markerPrintDouble(m->getCenter(), ((Projection*)m)->getWidth(),
                  sys, format);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerProjectionSystemCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      printCoordSystem(((Projection*)m)->getSystem());
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerProjectionSkyFrameCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      printSkyFrame(((Projection*)m)->getSkyFrame());
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerPropertyCmd(unsigned short which)
{
  // return first selected found

  Marker* m=markers->head();
  while (m) {
    if (m->isSelected()) {
      m->getProperty(which) ?
      Tcl_AppendResult(interp, "1", NULL): 
      Tcl_AppendResult(interp, "0", NULL);
      return;
    }
    m=m->next();
  }

  // else, return 'off'

  Tcl_AppendResult(interp, "0", NULL);
}

void FrameBase::getMarkerPropertyCmd(const char* tag, unsigned short which)
{
  // return first selected found

  Marker* m=markers->head();
  while (m) {
    if (m->hasTag(tag)) {
      m->getProperty(which) ?
      Tcl_AppendResult(interp, "1", NULL): 
      Tcl_AppendResult(interp, "0", NULL);
      return;
    }
    m=m->next();
  }

  // else, return 'off'

  Tcl_AppendResult(interp, "0", NULL);
}

void FrameBase::getMarkerPropertyCmd(int id, unsigned short which)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      m->getProperty(which) ?
      Tcl_AppendResult(interp, "1", NULL):
      Tcl_AppendResult(interp, "0", NULL);
      return;
    }
    m=m->next();
  }

  // else, return 'off'

  Tcl_AppendResult(interp, "0", NULL);
}

void FrameBase::getMarkerRulerDistanceCmd(int id, CoordSystem sys, 
                              SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      printDouble(radToDeg(((Ruler*)m)->getAngle()), DEFAULT);

      Tcl_AppendResult(interp, " ", NULL);
      markerPrintDouble(m->getCenter(), 
                  ((Ruler*)m)->getP2(), ((Ruler*)m)->getP1(),
                  sys, format);
      Tcl_AppendResult(interp, " ", NULL);
      markerPrintDouble(m->getCenter(), 
                  ((Ruler*)m)->getP3(), ((Ruler*)m)->getP1(),
                  sys, format);
      Tcl_AppendResult(interp, " ", NULL);
      markerPrintDouble(m->getCenter(), 
                  ((Ruler*)m)->getP3(), ((Ruler*)m)->getP2(),
                  sys, format);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerRulerPointCmd(int id, CoordSystem sys, SkyFrame sky,
                           SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      markerPrintCoord(m->getCenter(), ((Ruler*)m)->getP1(), sys, sky, format);
      markerPrintCoord(m->getCenter(), ((Ruler*)m)->getP2(), sys, sky, format);
      return;
    }
    m=m->next();
  }
}

#if __GNUC__ >= 3
void FrameBase::getMarkerSelectedCmd()
{
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected()) {
      ostringstream str;
      str << m->getId() << ' ' << ends;
      Tcl_AppendResult(interp, str.str().c_str(), NULL);
    }
    m=m->next();
  }
}
#else
void FrameBase::getMarkerSelectedCmd()
{
  char buf[8];
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected()) {
      ostrstream str(buf,8);
      str << m->getId() << ' ' << ends;
      Tcl_AppendResult(interp, buf, NULL);
    }
    m=m->next();
  }
}
#endif

#if __GNUC__ >= 3
void FrameBase::getMarkerSelectedCmd(const Vector& v)
{
  Marker* m=markers->head();
  while (m) {
    if (m->isIn(v) && m->isSelected()) {
      ostringstream str;
      str << m->getId() << ' ' << ends;
      Tcl_AppendResult(interp, str.str().c_str(), NULL);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "0", NULL);
}
#else
void FrameBase::getMarkerSelectedCmd(const Vector& v)
{
  char buf[8];
  Marker* m=markers->head();
  while (m) {
    if (m->isIn(v) && m->isSelected()) {
      ostrstream str(buf,8);
      str << m->getId() << ' ' << ends;
      Tcl_AppendResult(interp, buf, NULL);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "0", NULL);
}
#endif

void FrameBase::getMarkerSelectedNumberCmd()
{
  int count=0;
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected())
      count++;
    m=m->next();
  }

  printInteger(count);
}

void FrameBase::getMarkerShowCmd()
{
  if (*showMarkers)
    Tcl_AppendResult(interp, "1", NULL);
  else
    Tcl_AppendResult(interp, "0", NULL);
}

#if __GNUC__ >= 3
void FrameBase::getMarkerTagCmd(const char* tag)
{
  Marker* m=markers->head();
  while (m) {
    if (m->hasTag(tag)) {
      ostringstream str;
      str << m->getId() << ' ' << ends;
      Tcl_AppendResult(interp, str.str().c_str(), NULL);
    }
    m=m->next();
  }
}
#else
void FrameBase::getMarkerTagCmd(const char* tag)
{
  char buf[8];
  Marker* m=markers->head();
  while (m) {
    if (m->hasTag(tag)) {
      ostrstream str(buf,8);
      str << m->getId() << ' ' << ends;
      Tcl_AppendResult(interp, buf, NULL);
    }
    m=m->next();
  }
}
#endif

void FrameBase::getMarkerTagCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      const char* r = m->getTag();
      while (r) {
      Tcl_AppendElement(interp, r);
      r = m->getNextTag();
      }
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::getMarkerTagCmd(int id, int num)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      Tcl_AppendResult(interp,  m->getTag(num), NULL);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "", NULL);
}

#if __GNUC__ >= 3
void FrameBase::getMarkerTagDefaultNameCmd()
{
  int cnt = 1;

 again:
  ostringstream str;
  str << "Group " << cnt << ends;
  Marker* m = markers->head();
  while (m) {
    if (m->hasTag(str.str().c_str())) {
      cnt++;
      goto again;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, str.str().c_str(), NULL);
}
#else
void FrameBase::getMarkerTagDefaultNameCmd()
{
  char buf[16];
  int cnt = 1;

 again:
  ostrstream str(buf,16);
  str << "Group " << cnt << ends;
  Marker* m = markers->head();
  while (m) {
    if (m->hasTag(buf)) {
      cnt++;
      goto again;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, buf, NULL);
}
#endif

void FrameBase::getMarkerTagNumberCmd(const char* tag)
{
  // return number of markers with tag
  int count=0;
  Marker* m=markers->head();
  while (m) {
    if (m->hasTag(tag))
      count++;
    m=m->next();
  }

  printInteger(count);
}

void FrameBase::getMarkerTagsCmd()
{
  // return all tags
  List<Tag> tags;

  // loop thru all markers
  Marker* m=markers->head();
  while (m) {

    // loop thru all tags in markers
    const char* t = m->getTag();
    while (t) {
      // loop thru our current list
      int found = 0;
      Tag* tt = tags.head();
      while (tt) {
      if (!strcmp(tt->tag(), t)) {
        found =1;
        break;
      }
      tt = tt->next();
      }
      // didn't find it, add it to the list
      if (!found) {
      tags.append(new Tag(t));
      }

      t=m->getNextTag();
    }
    m=m->next();
  }

  // now sort

  // ok, dump the tags
  Tag* tt = tags.head();
  while (tt) {
    Tcl_AppendElement(interp, tt->tag());
    tt=tt->next();
  }
}

void FrameBase::getMarkerTextCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      Tcl_AppendResult(interp, m->getText(), NULL);
      return;
    }
    m=m->next();
  }
}

void FrameBase::getMarkerTypeCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      Tcl_AppendResult(interp, m->getType(), NULL);
      return;
    }
    m=m->next();
  }
}

void FrameBase::hasMarkerSelectedCmd()
{
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected()) {
      Tcl_AppendResult(interp, "1", NULL);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "0", NULL);
}

void FrameBase::hasMarkerPasteCmd()
{
  if (!pasteMarkers->isEmpty())
    Tcl_AppendResult(interp, "1", NULL);
  else
    Tcl_AppendResult(interp, "0", NULL);
}

void FrameBase::hasMarkerUndoCmd()
{
  if (!undoMarkers->isEmpty()) 
    switch (undoMarkerType) {
    case MOVE:
      Tcl_AppendResult(interp, "move", NULL);
      return;
    case EDIT:
      Tcl_AppendResult(interp, "edit", NULL);
      return;
    case DELETE:
      Tcl_AppendResult(interp, "delete", NULL);
      return;
    default:
      Tcl_AppendResult(interp, "", NULL);
      return;
    }
  else
    Tcl_AppendResult(interp, "", NULL);
}

void FrameBase::markerAngleCmd(int id, double angle)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canRotate()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      m->setAngle(angle);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerAngleCmd(int id, double angle, CoordSystem sys)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canRotate()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      m->setAngle(mapAngleToRef(angle,sys));
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerAnnulusCreateRadiusCmd(int id, const Vector& v)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      printInteger(((Annulus*)m)->addRadii(v*canvasToRef));
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerAnnulusDeleteRadiusCmd(int id, int h)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      ((Annulus*)m)->deleteRadii(h);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerAnnulusRadiusCmd(int id, double inner, double outer,
                               int num,
                               CoordSystem sys, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      FitsImage* ptr = findFits(m->getCenter());
      double r1 = ptr->mapLenToRef(inner, sys, format);
      double r2 = ptr->mapLenToRef(outer, sys, format);
      ((Annulus*)m)->setRadii(r1,r2,num);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerAnnulusRadiusCmd(int id, const char* lev, 
                               CoordSystem sys, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());

      int cnt = 0;
      double radii[MAXANNULI];
#if __GNUC__ >= 3
      string x(lev);
      istringstream str(x);
#else
      istrstream str(lev);
#endif
      while ((cnt<MAXANNULI) && (str >> radii[cnt]))
        ++cnt;
      
      FitsImage* ptr = findFits(m->getCenter());
      for (int i=0; i<cnt; i++)
        radii[i] = ptr->mapLenToRef(radii[i], sys, format);

      ((Annulus*)m)->setRadii(radii,cnt);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerBackCmd()
{
  Marker* m = markers->tail();
  while (m) {
    if (m->isSelected()) {
      Marker* prev = markers->extractPrev(m);
      markers->append(m);
      update(markerUpdate, m->getAllBBox());
      m = prev;
    }
    else
      m=m->previous();
  }
}

void FrameBase::markerBackCmd(const char* tag)
{
  Marker* m = markers->tail();
  while (m) {
    if (m->hasTag(tag)) {
      Marker* prev = markers->extractPrev(m);
      markers->append(m);
      update(markerUpdate, m->getAllBBox());
      m = prev;
    }
    else
      m=m->previous();
  }
}

void FrameBase::markerBackCmd(int id)
{
  Marker* m = markers->tail();
  while (m) {
    if (m->getId() == id) {
      markers->extractPrev(m);
      markers->append(m);
      update(markerUpdate, m->getAllBBox());
      return;
    }
    else
      m=m->previous();
  }
}

void FrameBase::markerBoxAnnulusSizeCmd(int id, const Vector& inner,
                              const Vector& outer, int num,
                              CoordSystem sys, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      FitsImage* ptr = findFits(m->getCenter());
      Vector s1 = ptr->mapLenToRef(inner, sys, format);
      Vector s2 = ptr->mapLenToRef(outer, sys, format);
      ((BoxAnnulus*)(m))->setSize(s1,s2,num);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerBoxAnnulusSizeCmd(int id,const char* lev, 
                              CoordSystem sys, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());

      int cnt = 0;
      Vector size[MAXANNULI];
#if __GNUC__ >= 3
      string x(lev);
      istringstream str(x);
#else
      istrstream str(lev);
#endif
      while ((cnt<MAXANNULI) && (str >> size[cnt][0]))
        str >> size[cnt++][1];
      
      // verify proper ratios
      {
        for (int i=0; i<cnt; i++)
          size[i][1] = size[i][0]*size[cnt-1][1]/size[cnt-1][0];
      }

      // map to ref coord sys
      {
        FitsImage* ptr = findFits(m->getCenter());
        for (int i=0; i<cnt; i++)
          size[i] = ptr->mapLenToRef(size[i], sys, format);
      }

      ((BoxAnnulus*)m)->setSize(size,cnt);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerBoxAnnulusCreateSizeCmd(int id, const Vector& v)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      printInteger(((BoxAnnulus*)m)->addSize(v*canvasToRef));
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerBoxAnnulusDeleteSizeCmd(int id, int h)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      ((BoxAnnulus*)m)->deleteSize(h);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerBoxSizeCmd(int id, const Vector& size, 
                         CoordSystem sys, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      FitsImage* ptr = findFits(m->getCenter());
      ((Box*)(m))->setSize(ptr->mapLenToRef(size, sys, format));
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerCallBackCmd(int id, Marker::Callback cb, const char* p, 
                        const char* a)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      result = m->setCallBack(cb, p, a);
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerCircleRadiusCmd(int id, double r, CoordSystem sys, 
                          SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      FitsImage* ptr = findFits(m->getCenter());
      double rr = ptr->mapLenToRef(r, sys, format);
      ((Circle*)m)->setRadius(rr);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerColorCmd(const char* clr)
{
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected()) {
      m->setColor(clr);
      update(markerUpdate, m->getAllBBox());
    }
    m=m->next();
  }
}

void FrameBase::markerColorCmd(const char* tag, const char* clr)
{
  Marker* m=markers->head();
  while (m) {
    if (m->hasTag(tag)) {
      m->setColor(clr);
      update(markerUpdate, m->getAllBBox());
    }
    m=m->next();
  }
}

void FrameBase::markerColorCmd(int id, const char* clr)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      m->setColor(clr);
      update(markerUpdate, m->getAllBBox());
      return;
    }
    m=m->next();
  }
}

#if __GNUC__ >= 3
void FrameBase::markerCommandCmd(MarkerFormat fm, const char* ccmd)
{
  // only make command string as long as needed
  // or the rest will be processed as garbage
  int len = strlen(ccmd)+2;
  char* buf = new char[len];
  memcpy(buf, ccmd, len);

  // add terminator to make parser happy
  buf[len-2] = '\n';
  buf[len-1] = NULL;

  string x(buf);
  istringstream istr(x);
  parseMarker(fm, istr);
  delete [] buf;
}
#else
void FrameBase::markerCommandCmd(MarkerFormat fm, const char* ccmd)
{
  // only make command string as long as needed
  // or the rest will be processed as garbage
  int len = strlen(ccmd)+2;
  char* buf = new char[len];
  memcpy(buf, ccmd, len);

  // add terminator to make parser happy
  buf[len-2] = '\n';
  buf[len-1] = NULL;

  istrstream istr(buf,len);
  parseMarker(fm, istr);
  delete [] buf;
}
#endif
 
#if __GNUC__ >= 3
void FrameBase::markerCommandVarCmd(MarkerFormat fm, const char* var)
{
  const char* ccmd = Tcl_GetVar(interp, var,
                        TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG);
  if (!ccmd) {
    result = TCL_ERROR;
    return;
  }

  // only make command string as long as needed
  // or the rest will be processed as garbage
  int len = strlen(ccmd)+2;
  char* buf = new char[len];
  memcpy(buf, ccmd, len);

  // add terminator to make parser happy
  buf[len-2] = '\n';
  buf[len-1] = NULL;

  string x(buf);
  istringstream istr(x);
  parseMarker(fm, istr);
  delete [] buf;
}
#else
void FrameBase::markerCommandVarCmd(MarkerFormat fm, const char* var)
{
  const char* ccmd = Tcl_GetVar(interp, var,
                        TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG);
  if (!ccmd) {
    result = TCL_ERROR;
    return;
  }

  // only make command string as long as needed
  // or the rest will be processed as garbage
  int len = strlen(ccmd)+2;
  char* buf = new char[len];
  memcpy(buf, ccmd, len);

  // add terminator to make parser happy
  buf[len-2] = '\n';
  buf[len-1] = NULL;

  istrstream istr(buf,len);
  parseMarker(fm, istr);
  delete [] buf;
}
#endif
 
void FrameBase::markerCompassArrowCmd(int id, int n, int e)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      ((Compass*)(m))->setArrows(n, e);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerCompassLabelCmd(int id, const char* n, const char* e)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      // it may shrink
      update(markerUpdate, m->getAllBBox());
      ((Compass*)(m))->setLabels(n, e);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerCompassRadiusCmd(int id, double r, CoordSystem sys, 
                           SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      FitsImage* ptr = findFits(m->getCenter());
      double rr = ptr->mapLenToRef(r, sys, format);
      ((Compass*)m)->setRadius(rr);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerCompassSystemCmd(int id, CoordSystem sys, SkyFrame sky)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      // it may shrink
      update(markerUpdate, m->getAllBBox());
      ((Compass*)(m))->setCoordSystem(sys, sky);
      update(markerUpdate, m->getAllBBox());
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerDeleteCallBackCmd(int id, Marker::Callback cb, const char* p)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      result = m->deleteCallBack(cb, p);
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerDeleteCmd()
{
  undoMarkers->deleteAll();
  Marker* m = markers->head();
  while (m) {
    if (m->isSelected() && m->canDelete()) {
      Marker* next = markers->extractNext(m);
      update(markerUpdate, m->getAllBBox());
      undoMarkers->append(m);
      m->doCallBack(Marker::DELETECB);
      m->clearCB();
      undoMarkerType = DELETE;
      m = next;
    }
    else
      m=m->next();
  }}

void FrameBase::markerDeleteCmd(const char* tag)
{
  undoMarkers->deleteAll();
  Marker* m = markers->head();
  while (m) {
    if (m->canDelete() && m->hasTag(tag)) {
      Marker* next = markers->extractNext(m);
      update(markerUpdate, m->getAllBBox());
      undoMarkers->append(m);
      m->doCallBack(Marker::DELETECB);
      m->clearCB();
      undoMarkerType = DELETE;
      m = next;
    }
    else
      m=m->next();
  }
}

void FrameBase::markerDeleteCmd(int id)
{
  undoMarkers->deleteAll();
  Marker* m = markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canDelete()) {
      markers->extractNext(m);
      update(markerUpdate, m->getAllBBox());
      undoMarkers->append(m);
      m->doCallBack(Marker::DELETECB);
      m->clearCB();
      undoMarkerType = DELETE;
      }
      return;
    }
    else
      m=m->next();
  }
}

void FrameBase::markerDeleteAllCmd()
{
  undoMarkers->deleteAll();
  Marker* m = markers->head();
  while (m) {
    if (m->canDelete()) {
      update(markerUpdate, m->getAllBBox());
      Marker* next = markers->extractNext(m);
      undoMarkers->append(m);
      m->doCallBack(Marker::DELETECB);
      m->clearCB();
      undoMarkerType = DELETE;
      m = next;
    }
    else
      m=m->next();
  }
}

void FrameBase::markerDeleteLastCmd()
{
  undoMarkers->deleteAll();
  Marker* m=markers->tail();
  if (m && m->canDelete()) {
    markers->extractNext(m);
    update(markerUpdate, m->getAllBBox());
    undoMarkers->append(m);
    m->doCallBack(Marker::DELETECB);
    m->clearCB();
    undoMarkerType = DELETE;
    return;
  }
}

void FrameBase::markerDeleteTagCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canDelete())
      m->deleteTags();
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerDeleteTagCmd(int id, const char* tag)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canDelete()) 
      m->deleteTag(tag);
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerDeleteTagCmd(int id, int which)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canDelete())
      m->deleteTag(which);
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerEditBeginCmd(int id, int h)
{
  // remember which marker is being edited
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id && m->canEdit()) {
      markerUndo(m, EDIT);

      editMarker = m;
      editMarker->editBegin(h);
      return;
    }
    m=m->next();
  }

  editMarker = NULL;
}

void FrameBase::markerEditBeginCmd(const Vector& v, int h)
{
  // remember which marker is being edited
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected() && m->canEdit()) {
      markerUndo(m, EDIT);

      editMarker = m;
      editMarker->editBegin(h);
      return;
    }
    m=m->next();
  }

  editMarker = NULL;
}

void FrameBase::markerEditMotionCmd(const Vector& v, int h)
{
  if (editMarker) {

    // erase current marker now
    redraw(editMarker->getAllBBox());
    forceUpdate();

    editMarker->edit(v*canvasToRef, h);
    editMarker->drawXOR();
  }
}

void FrameBase::markerEditEndCmd()
{
  if (editMarker)
    editMarker->editEnd();
  editMarker = NULL;

  update(markerUpdate);
}

void FrameBase::markerEllipseRadiusCmd(int id, const Vector& radius, 
                           CoordSystem sys, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      FitsImage* ptr = findFits(m->getCenter());
      ((Ellipse*)m)->setRadius(ptr->mapLenToRef(radius, sys, format));
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerEllipseAnnulusRadiusCmd(int id, const Vector& inner,
                                const Vector& outer,
                                int num,
                                CoordSystem sys, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      FitsImage* ptr = findFits(m->getCenter());
      Vector r1 = ptr->mapLenToRef(inner, sys, format);
      Vector r2 = ptr->mapLenToRef(outer, sys, format);
      ((EllipseAnnulus*)(m))->setRadii(r1,r2,num);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerEllipseAnnulusRadiusCmd(int id, const char* lev,
                                CoordSystem sys, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());

      int cnt = 0;
      Vector radii[MAXANNULI];
#if __GNUC__ >= 3
      string x(lev);
      istringstream str(x);
#else
      istrstream str(lev);
#endif
      while ((cnt<MAXANNULI) && (str >> radii[cnt][0]))
        str >> radii[cnt++][1];
      
      // verify proper ratios
      {
        for (int i=0; i<cnt; i++)
          radii[i][1] = radii[i][0]*radii[cnt-1][1]/radii[cnt-1][0];
      }

      // map to ref coord sys
      {
        FitsImage* ptr = findFits(m->getCenter());
        for (int i=0; i<cnt; i++)
          radii[i] = ptr->mapLenToRef(radii[i], sys, format);
      }

      ((EllipseAnnulus*)(m))->setRadii(radii,cnt);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerEllipseAnnulusCreateRadiusCmd(int id, const Vector& v)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      printInteger(((EllipseAnnulus*)m)->addRadii(v*canvasToRef));
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerEllipseAnnulusDeleteRadiusCmd(int id, int h)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      ((EllipseAnnulus*)m)->deleteRadii(h);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerFontCmd(const char* f)
{
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected()) {
      // things can shrink, so do before and after
      update(markerUpdate, m->getAllBBox());
      m->setFont(f);
      update(markerUpdate, m->getAllBBox());
    }
    m=m->next();
  }
}

void FrameBase::markerFontCmd(const char* tag, const char* f)
{
  Marker* m=markers->head();
  while (m) {
    if (m->hasTag(tag)) {
      // things can shrink, so do before and after
      update(markerUpdate, m->getAllBBox());
      m->setFont(f);
      update(markerUpdate, m->getAllBBox());
    }
    m=m->next();
  }
}

void FrameBase::markerFontCmd(int id, const char* f)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      // things can shrink, so do before and after
      update(markerUpdate, m->getAllBBox());
      m->setFont(f);
      update(markerUpdate, m->getAllBBox());
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerFrontCmd()
{
  Marker* m = markers->head();
  while (m) {
    if (m->isSelected()) {
      Marker* next = markers->extractNext(m);
      markers->insertHead(m);
      update(markerUpdate, m->getAllBBox());
      m = next;
    }
    else
      m=m->next();
  }
}

void FrameBase::markerFrontCmd(const char* tag)
{
  Marker* m = markers->head();
  while (m) {
    if (m->hasTag(tag)) {
      Marker* next = markers->extractNext(m);
      markers->insertHead(m);
      update(markerUpdate, m->getAllBBox());
      m = next;
    }
    else
      m=m->next();
  }
}

void FrameBase::markerFrontCmd(int id)
{
  Marker* m = markers->head();
  while (m) {
    if (m->getId() == id) {
      markers->extractNext(m);
      markers->insertHead(m);
      update(markerUpdate, m->getAllBBox());
      return;
    }
    else
      m=m->next();
  }
}

void FrameBase::markerLineCmd(int id, const Vector& p1, const Vector& p2, 
                    CoordSystem sys, SkyFrame sky)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      FitsImage* ptr = findFits(m->getCenter());
      ((Line*)(m))->setPoints(ptr->mapToRef(p1,sys,sky),
                        ptr->mapToRef(p2,sys,sky));
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerLineArrowCmd(int id, int p1, int p2)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      ((Line*)(m))->setArrows(p1, p2);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerLineWidthCmd(int w)
{
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected()) {
      m->setLineWidth(w);
      update(markerUpdate, m->getAllBBox());
    }
    m=m->next();
  }
}

void FrameBase::markerLineWidthCmd(int id, int w)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      m->setLineWidth(w);
      update(markerUpdate, m->getAllBBox());
      return;
    }
    m=m->next();
  }
}

#if __GNUC__ >= 3
void FrameBase::markerListCmd(MarkerFormat type, 
                    CoordSystem sys, SkyFrame sky, SkyFormat format,
                    int strip, int listwcs, int select, 
                    unsigned short mask, unsigned short value, 
                    List<Tag>& tags)
{
  char buf[LISTBUFSIZE];

  char delim;
  if (strip)
    delim = ';';
  else
    delim = '\n';

  void (FrameBase::*hproc)(ostream&, CoordSystem, SkyFrame, SkyFormat, 
                     char, int);
  void (Marker::*mproc)(ostream&, CoordSystem, SkyFrame, SkyFormat, char);

  switch (type) {
  case DS9:
    hproc = &FrameBase::markerListHeader;
    mproc = &Marker::list;
    break;
  case CIAO:
    hproc = &FrameBase::markerListCiaoHeader;
    mproc = &Marker::listCiao;
    break;
  case SAOTNG:
    hproc = &FrameBase::markerListSAOtngHeader;
    mproc = &Marker::listSAOtng;
    break;
  case SAOIMAGE:
    hproc = NULL;
    mproc = &Marker::listSAOimage;
    break;
  case PROS:
    hproc = NULL;
    mproc = &Marker::listPros;
    break;
  case RAWXY:
    hproc = NULL;
    mproc = &Marker::listXY;
    break;
  }

  if (hproc) {
    ostringstream str;
    (this->*hproc)(str, sys, sky, format, delim, listwcs);
    str << ends;
    Tcl_AppendResult(interp, str.str().c_str(), NULL);
  }

  Marker* m=markers->head();
  while (m) {
    ostringstream str;
    Tag* t;

    // selected
    if (select) {
      if (!m->isSelected())
      goto next;
    }

    // properties
    if (mask) {
      if (!((m->getProperty() & mask)  == value))
      goto next;
    }

    // tags
    if (t=tags.head()) {
      while (t) {
      if (!m->hasTag(t->tag()))
        goto next;
      t=t->next();
      }
    }

    // ok, its passed the tests!
    (m->*mproc)(str, sys, sky, format, delim);
    str << ends;
    Tcl_AppendResult(interp, str.str().c_str(), NULL);

  next:
    m=m->next();
  }
}
#else
void FrameBase::markerListCmd(MarkerFormat type, 
                    CoordSystem sys, SkyFrame sky, SkyFormat format,
                    int strip, int listwcs, int select, 
                    unsigned short mask, unsigned short value, 
                    List<Tag>& tags)
{
  char buf[LISTBUFSIZE];

  char delim;
  if (strip)
    delim = ';';
  else
    delim = '\n';

  void (FrameBase::*hproc)(ostream&, CoordSystem, SkyFrame, SkyFormat, 
                     char, int);
  void (Marker::*mproc)(ostream&, CoordSystem, SkyFrame, SkyFormat, char);

  switch (type) {
  case DS9:
    hproc = &FrameBase::markerListHeader;
    mproc = &Marker::list;
    break;
  case CIAO:
    hproc = &FrameBase::markerListCiaoHeader;
    mproc = &Marker::listCiao;
    break;
  case SAOTNG:
    hproc = &FrameBase::markerListSAOtngHeader;
    mproc = &Marker::listSAOtng;
    break;
  case SAOIMAGE:
    hproc = NULL;
    mproc = &Marker::listSAOimage;
    break;
  case PROS:
    hproc = NULL;
    mproc = &Marker::listPros;
    break;
  case RAWXY:
    hproc = NULL;
    mproc = &Marker::listXY;
    break;
  }

  if (hproc) {
    ostrstream str(buf,LISTBUFSIZE);
    (this->*hproc)(str, sys, sky, format, delim, listwcs);
    str << ends;
    Tcl_AppendResult(interp, buf, NULL);
  }

  Marker* m=markers->head();
  while (m) {
    ostrstream str(buf,LISTBUFSIZE);
    Tag* t;

    // selected
    if (select) {
      if (!m->isSelected())
      goto next;
    }

    // properties
    if (mask) {
      if (!((m->getProperty() & mask)  == value))
      goto next;
    }

    // tags
    if (t=tags.head()) {
      while (t) {
      if (!m->hasTag(t->tag()))
        goto next;
      t=t->next();
      }
    }

    // ok, its passed the tests!
    (m->*mproc)(str, sys, sky, format, delim);
    str << ends;
    Tcl_AppendResult(interp, buf, NULL);

  next:
    m=m->next();
  }
}
#endif

void FrameBase::markerLoadCmd(MarkerFormat fm, const char* fn)
{
  ifstream str(fn);
  if (!str) {
    result = TCL_ERROR;
    return;
  }  
  parseMarker(fm, str);
}

void FrameBase::markerLoadCmd(MarkerFormat fm, const char* fn, 
                        CoordSystem sys, SkyFrame sky)
{
  markerDefaultSystem = sys;
  markerDefaultSky = sky;

  ifstream str(fn);
  if (!str) {
    result = TCL_ERROR;
    return;
  }  
  parseMarker(fm, str);
}

#if __GNUC__ >= 3
void FrameBase::markerLoadCmd(MarkerFormat fm, int fd)
{
  boost::fdistream str(fd);
  if (!str) {
    result = TCL_ERROR;
    return;
  }  
  parseMarker(fm, str);
}
#else
void FrameBase::markerLoadCmd(MarkerFormat fm, int fd)
{
  ifstream str(fd);
  if (!str) {
    result = TCL_ERROR;
    return;
  }  
  parseMarker(fm, str);
}
#endif

#if __GNUC__ >= 3
void FrameBase::markerLoadCmd(MarkerFormat fm, int fd, 
                        CoordSystem sys, SkyFrame sky)
{
  markerDefaultSystem = sys;
  markerDefaultSky = sky;

  boost::fdistream str(fd);
  if (!str) {
    result = TCL_ERROR;
    return;
  }  
  parseMarker(fm, str);
}
#else
void FrameBase::markerLoadCmd(MarkerFormat fm, int fd, 
                        CoordSystem sys, SkyFrame sky)
{
  markerDefaultSystem = sys;
  markerDefaultSky = sky;

  ifstream str(fd);
  if (!str) {
    result = TCL_ERROR;
    return;
  }  
  parseMarker(fm, str);
}
#endif

void FrameBase::markerLoadFitsCmd(const char* fn, const char* color,
                          int width, const char* font)
{
  if (!currentFits)
    return;

  // verify that we have an ext specified
  if (fn && (fn[strlen(fn)-1] != ']')) {
    result = TCL_ERROR;
    return;
  }

  FitsFile* mk = new FitsFitsMMap(fn, FitsFile::EXACT);
  if (!mk->isValid() || !mk->isTable()) {
    delete mk;
    result = TCL_ERROR;
    return;
  }

  FitsHead* mkh = mk->head();
  if (mkh->naxes() != 2) {
    delete mk;
    result = TCL_ERROR;
    return;
  }
  FitsTableHDU* mkhdu = (FitsTableHDU*)mkh->hdu();

  // determine x and y column names
  // if image, hard code 'x' and 'y'
  // however, if table, find out the columns used to bin
  FitsColumn* x;
  FitsColumn* y;
  if (*channelFits) {
    FitsImage* ptr = *channelFits;
    if (ptr->isImage()) {
      x = mkhdu->find("x");
      y = mkhdu->find("y");
    }
    else {
      x = mkhdu->find(ptr->getHistX());
      y = mkhdu->find(ptr->getHistY());
    }
  }
  else {
    x = mkhdu->find("x");
    y = mkhdu->find("y");
  }

  FitsColumn* shape = mkhdu->find("shape");
  FitsColumn* r = mkhdu->find("r");
  FitsColumn* ang = mkhdu->find("rotang");
  
  // manatory columns
  if (!x || !y) {
    delete mk;
    result = TCL_ERROR;
    return;
  }

  char* ptr = (char*)mk->data();
  int rows = mkhdu->rows();
  int rowlen = mkhdu->width();

  char text[] = "";
  List<Tag> taglist;

  for (int i=0; i<rows; i++, ptr+=rowlen) {
    char* s1;
    if (shape)
      s1 = toUpper(shape->str(ptr));
    else {
      s1 = new char[7];
      strcpy(s1,"POINT ");
    }

    // look for '!', which sets include/exclude
    char* s2 = s1;
    unsigned short props = Marker::SELECT | Marker::EDIT | Marker::MOVE |
      Marker::ROTATE | Marker::DELETE | Marker::HIGHLITE | Marker::SOURCE;
    if (s2[0]=='!')
      s2++;
    else
      props |= Marker::INCLUDE;

    if (!strncmp(s2, "CIRCLE", 6) && r)
      createCircleCmd(
      currentFits->mapToRef(Vector(x->value(ptr,0),y->value(ptr,0)),
                        PHYSICAL),
      currentFits->mapLenToRef(r->value(ptr), PHYSICAL), 
      color, width, font, text, props, NULL, taglist);

    else if (!strncmp(s2, "ANNULU", 6) && r)
      createAnnulusCmd(
      currentFits->mapToRef(Vector(x->value(ptr,0),y->value(ptr,0)),PHYSICAL),
      currentFits->mapLenToRef(r->value(ptr,1),PHYSICAL),
      currentFits->mapLenToRef(r->value(ptr,0),PHYSICAL), 1,
      color, width, font, text, props, NULL, taglist);

    else if (!strncmp(s2, "BOX   ", 6) && r)
      createBoxCmd(
      currentFits->mapToRef(Vector(x->value(ptr,0),y->value(ptr,0)),PHYSICAL),
      currentFits->mapLenToRef(Vector(r->value(ptr,0),r->value(ptr,1)),
                         PHYSICAL), 0,
      color, width, font, text, props, NULL, taglist);

    else if (!strncmp(s2, "ROTBOX", 6) && r && ang)
      createBoxCmd(
      currentFits->mapToRef(Vector(x->value(ptr,0), y->value(ptr,0)),
                   PHYSICAL),
      currentFits->mapLenToRef(Vector(r->value(ptr,0),r->value(ptr,1)),
                         PHYSICAL), 
      degToRad(ang->value(ptr)),
      color, width, font, text, props, NULL, taglist);

    else if (!strncmp(s2, "RECTAN", 6)) {
      Vector v1(x->value(ptr,0), y->value(ptr,0));
      Vector v2(x->value(ptr,1), y->value(ptr,1));
      Vector d = v2-v1;
      Vector c = d/2 + v1;

      createBoxCmd(currentFits->mapToRef(c,PHYSICAL), 
      currentFits->mapLenToRef(d,PHYSICAL), 
      0,
      color, width, font, text, props, NULL, taglist);
    }

    else if (!strncmp(s2, "ROTREC", 6) && ang) {
      Vector v1(x->value(ptr,0), y->value(ptr,0));
      Vector v2(x->value(ptr,1), y->value(ptr,1));
      Vector d = v2-v1;
      Vector c = d/2 + v1;

      createBoxCmd(currentFits->mapToRef(c,PHYSICAL), 
      currentFits->mapLenToRef(d,PHYSICAL), 
      degToRad(ang->value(ptr)),
      color, width, font, text, props, NULL, taglist);
    }

    else if (!strncmp(s2, "ELLIPS", 6) && r && ang)
      createEllipseCmd(
      currentFits->mapToRef(Vector(x->value(ptr,0),y->value(ptr,0)),PHYSICAL),
        currentFits->mapLenToRef(Vector(r->value(ptr,0),r->value(ptr,1)),
                         PHYSICAL),degToRad(ang->value(ptr)),
      color, width, font, text, props, NULL, taglist);

    else if (!strncmp(s2, "PIE   ", 6) && r && ang)
      createPandaCmd(
      currentFits->mapToRef(Vector(x->value(ptr,0),y->value(ptr,0)),PHYSICAL),
      degToRad(ang->value(ptr,0)-90), degToRad(ang->value(ptr,1)-90), 1,
      currentFits->mapLenToRef(r->value(ptr,1),PHYSICAL),
      currentFits->mapLenToRef(r->value(ptr,0),PHYSICAL), 1,
      color, width, font, text, props, NULL, taglist);

    else if (!strncmp(s2, "POINT ", 6))
      createBoxCirclePointCmd(
      currentFits->mapToRef(Vector(x->value(ptr,0),y->value(ptr,0)),PHYSICAL),
      color, width, font, text, props, NULL, taglist);

    else if (!strncmp(s2, "POLYGO", 6)) {
      List<Vertex> list;
      Vertex* first = new Vertex(
      currentFits->mapToRef(Vector(x->value(ptr,0), y->value(ptr,0)),
                   PHYSICAL));
      list.append(first);

      // this could be a problem, if the end points are not the same

      int i=1;
      while (1) {
      Vertex* n = new Vertex(
        currentFits->mapToRef(Vector(x->value(ptr,i), y->value(ptr,i)),
                        PHYSICAL));
      if (n->vector[0] != first->vector[0] || 
          n->vector[1] != first->vector[1])
        list.append(n);
      else {
        delete n;
        break;
      }

      i++;
      }

      createPolygonCmd(list, color, width, font, text, props, NULL, 
                   taglist);
    }

    delete [] s1;
  }

  delete mk;
}

void FrameBase::markerMoveCmd(const Vector& v)
{
  undoMarkers->deleteAll();
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected() && m->canMove()) {
      undoMarkers->append(m->dup());
      undoMarkerType = MOVE;

      Vector c = m->getCenter() * refToCanvas;
      update(markerUpdate, m->getAllBBox());
      m->moveTo((c + v) * canvasToRef);
      update(markerUpdate, m->getAllBBox());
    }
    m=m->next();
  }
}

void FrameBase::markerMoveCmd(const char* tag, const Vector& v)
{
  undoMarkers->deleteAll();
  Marker* m=markers->head();
  while (m) {
    if (m->canMove() && m->hasTag(tag)) {
      undoMarkers->append(m->dup());
      undoMarkerType = MOVE;

      Vector c = m->getCenter() * refToCanvas;
      update(markerUpdate, m->getAllBBox());
      m->moveTo((c + v) * canvasToRef);
      update(markerUpdate, m->getAllBBox());
    }
    m=m->next();
  }
}

void FrameBase::markerMoveCmd(int id, const Vector& v)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canMove()) {
      markerUndo(m, MOVE);

      Vector c = m->getCenter() * refToCanvas;
      update(markerUpdate, m->getAllBBox());
      m->moveTo((c + v) * canvasToRef);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerMoveBeginCmd(const Vector& v)
{
  markerBegin = v * canvasToRef;
  undoMarkers->deleteAll();
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected() && m->canMove()) {
      undoMarkers->append(m->dup());
      undoMarkerType = MOVE;
      m->moveBegin();
    }
    m=m->next();
  }
}

void FrameBase::markerMoveBeginCmd(int id, const Vector& v)
{
  markerBegin = v * canvasToRef;
  undoMarkers->deleteAll();
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canMove()) {
      undoMarkers->append(m->dup());
      undoMarkerType = MOVE;
      m->moveBegin();
      }
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerMoveMotionCmd(const Vector& v)
{
  // first, accumulate erase markers

  Marker* m=markers->head();
  if (m) {
    while (m) {
      if (m->isSelected() && m->canMove())
      redraw(m->getAllBBox());
      m=m->next();
    }

    // and erase now

    forceUpdate();

    // ok, now draw selected markers in new location

    Vector markerEnd = v * canvasToRef;
    Vector diff = markerEnd - markerBegin;
    markerBegin = markerEnd;

    m=markers->head();
    while (m) {
      if (m->isSelected() && m->canMove()) {
      m->move(diff);
      m->drawXOR();
      }
      m=m->next();
    }
  }
}

void FrameBase::markerMoveMotionCmd(int id, const Vector& v)
{
  // first, accumulate erase markers

  Marker* m=markers->head(); 
  if (m) {
    while (m) {
      if (m->getId() && m->canMove()) {
      redraw(m->getAllBBox());
      break;
      }
      m=m->next();
    }

    if (!m)
      return; // can't find it

    Marker *ptr = m;

    // and erase now

    forceUpdate();

    // ok, now draw selected markers in new location

    Vector markerEnd = v * canvasToRef;
    Vector diff = markerEnd - markerBegin;
    markerBegin = markerEnd;

    ptr->move(diff);
    ptr->drawXOR();
  }
}

void FrameBase::markerMoveEndCmd()
{
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected() && m->canMove())
      m->moveEnd();
    m=m->next();
  }

  // update widget since we don't know where the selected markers came from
  update(markerUpdate);
}

void FrameBase::markerMoveEndCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canMove())
      m->moveEnd();
      return;
    }
    m=m->next();
  }

  // update widget since we don't know where the selected markers came from
  update(markerUpdate);
}

void FrameBase::markerMoveToCmd(const Vector& v, CoordSystem sys, SkyFrame sky)
{
  undoMarkers->deleteAll();
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected() && m->canMove()) {
      undoMarkers->append(m->dup());
      undoMarkerType = MOVE;

      update(markerUpdate, m->getAllBBox());
      FitsImage* ptr = findFits(m->getCenter());
      m->moveTo(ptr->mapToRef(v,sys,sky));
      update(markerUpdate, m->getAllBBox());
    }
    m=m->next();
  }
}

void FrameBase::markerMoveToCmd(const char* tag, const Vector& v, 
                      CoordSystem sys, SkyFrame sky)
{
  undoMarkers->deleteAll();
  Marker* m=markers->head();
  while (m) {
    if (m->canMove() && m->hasTag(tag)) {
      undoMarkers->append(m->dup());
      undoMarkerType = MOVE;

      update(markerUpdate, m->getAllBBox());
      FitsImage* ptr = findFits(m->getCenter());
      m->moveTo(ptr->mapToRef(v,sys,sky));
      update(markerUpdate, m->getAllBBox());
    }
    m=m->next();
  }
}

void FrameBase::markerMoveToCmd(int id, const Vector& v, InternalSystem sys)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canMove()) {
      markerUndo(m, MOVE);

      update(markerUpdate, m->getAllBBox());
      m->moveTo(mapToRef(v, sys));
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerMoveToCmd(int id, const Vector& v, 
                      CoordSystem sys, SkyFrame sky)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canMove()) {
      markerUndo(m, MOVE);

      update(markerUpdate, m->getAllBBox());
      FitsImage* ptr = findFits(m->getCenter());
      m->moveTo(ptr->mapToRef(v,sys,sky));
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerPandaCreateAnglesCmd(int id, const Vector& v)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      printInteger(((Panda*)m)->addAngles(v*canvasToRef));
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerPandaCreateRadiusCmd(int id, const Vector& v)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      printInteger(((Panda*)m)->addRadii(v*canvasToRef));
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerPandaDeleteCmd(int id, int h)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      ((Panda*)m)->deleteAnglesRadii(h);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerPandaEditCmd(int id, double a1, double a2, int an, 
                         double r1, double r2, int rn, 
                         CoordSystem sys, SkyFormat format)

{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());

      ((Panda*)m)->setAnglesRadii(mapAngleToRef(a1,sys),
                            mapAngleToRef(a2,sys),
                            an,r1,r2,rn);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerPandaEditCmd(int id, const char* a, const char* r,
                         CoordSystem sys,
                         CoordSystem rsys, SkyFormat rformat)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());

      int acnt = 0;
      double angles[MAXANGLES];
      {
#if __GNUC__ >= 3
        string x(a);
        istringstream astr(x);
#else
        istrstream astr(a);
#endif
        while ((acnt<MAXANGLES) && (astr >> angles[acnt]))
          ++acnt;
      }     
      {
        for (int i=0; i<acnt; i++)
          angles[i] = mapAngleToRef(degToRad(angles[i]),sys);
      }
      int rcnt = 0;
      double radii[MAXANNULI];
      {
#if __GNUC__ >= 3
        string x(r);
        istringstream rstr(x);
#else
        istrstream rstr(r);
#endif
        while ((rcnt<MAXANNULI) && (rstr >> radii[rcnt]))
          ++rcnt;
      }     
      {
        FitsImage* ptr = findFits(m->getCenter());
        for (int i=0; i<rcnt; i++)
          radii[i] = ptr->mapLenToRef(radii[i], rsys, rformat);
      }

      ((Panda*)m)->setAnglesRadii(angles,acnt,radii,rcnt);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerPolygonCreateVertexCmd(int id, int seg, const Vector& v)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      ((Polygon*)(m))->createVertex(seg, v * canvasToRef);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerPolygonDeleteVertexCmd(int id, int h)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      ((Polygon*)(m))->deleteVertex(h);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerPolygonResetCmd(int id, const Vector& size, 
                              CoordSystem sys, SkyFormat format)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      FitsImage* ptr = findFits(m->getCenter());
      ((Polygon*)(m))->reset(ptr->mapLenToRef(size, sys, format));
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerProjectionCmd(int id, 
                            const Vector& p1, const Vector& p2, 
                            CoordSystem sys, SkyFrame sky,
                            double width, int method,
                            CoordSystem wdsys, SkyFormat wdformat)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      FitsImage* ptr = findFits(m->getCenter());
      ((Projection*)(m))->set(ptr->mapToRef(p1,sys,sky),
                        ptr->mapToRef(p2,sys,sky), 
                        ptr->mapLenToRef(width, wdsys, wdformat),
                        method);
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerProjectionSystemCmd(int id, CoordSystem sys,SkyFrame sky)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      ((Projection*)m)->setSystem(sys,sky);
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerPropertyCmd(unsigned short prop, int value)
{
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected()) {
      if (prop == Marker::FIXED || 
        prop == Marker::INCLUDE || 
        prop == Marker::SOURCE) {
      // marker will change bbox, so get before and after
      update(markerUpdate, m->getAllBBox());
      m->setProperty(prop, value);
      update(markerUpdate, m->getAllBBox());
      }
      else
      m->setProperty(prop, value);
    }
    m=m->next();
  }
}

void FrameBase::markerPropertyCmd(const char* tag, unsigned short prop, int value)
{
  Marker* m=markers->head();
  while (m) {
    if (m->hasTag(tag)) {
      if (prop == Marker::FIXED || 
        prop == Marker::INCLUDE || 
        prop == Marker::SOURCE) {
      // marker will change bbox, so get before and after
      update(markerUpdate, m->getAllBBox());
      m->setProperty(prop, value);
      update(markerUpdate, m->getAllBBox());
      }
      else
      m->setProperty(prop, value);
    }
    m=m->next();
  }
}

void FrameBase::markerPropertyCmd(unsigned short prop, int value, const Vector& v)
{
  // v is in canvas coords

  Marker* m=markers->head();
  while (m) {
    if (m->isIn(v)) {
      if (prop == Marker::FIXED || 
        prop == Marker::INCLUDE || 
        prop == Marker::SOURCE) {
      // marker will change bbox, so get before and after
      update(markerUpdate, m->getAllBBox());
      m->setProperty(prop, value);
      update(markerUpdate, m->getAllBBox());
      }
      else
      m->setProperty(prop, value);
    }
    m=m->next();
  }
}

void FrameBase::markerPropertyCmd(int id, unsigned short prop, int value)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (prop == Marker::FIXED || 
        prop == Marker::INCLUDE ||
        prop == Marker::SOURCE) {
      // marker will change bbox, so get before and after
      update(markerUpdate, m->getAllBBox());
      m->setProperty(prop, value);
      update(markerUpdate, m->getAllBBox());
      }
      else
      m->setProperty(prop, value);

      return;
    }
    m=m->next();
  }
}

void FrameBase::markerRotateBeginCmd(int id)
{
  // remember which marker is being edited
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canRotate()) {
      markerUndo(m, EDIT);
      rotateMarker = m;
      rotateMarker->rotateBegin();
      }
      return;
    }
    m=m->next();
  }

  rotateMarker = NULL;
}

void FrameBase::markerRotateBeginCmd(const Vector& v)
{
  // remember which marker is being edited
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected() && m->canRotate()) {
      markerUndo(m, EDIT);
      rotateMarker = m;
      rotateMarker->rotateBegin();
      return;
    }
    m=m->next();
  }

  rotateMarker = NULL;
}

void FrameBase::markerRotateMotionCmd(const Vector& v, int h)
{
  if (rotateMarker) {

    // erase current marker now
    redraw(rotateMarker->getAllBBox());
    forceUpdate();

    rotateMarker->rotate(v*canvasToRef, h);
    rotateMarker->drawXOR();
  }
}

void FrameBase::markerRotateEndCmd()
{
  if (rotateMarker)
    rotateMarker->rotateEnd();
  rotateMarker = NULL;
  update(markerUpdate);
}

void FrameBase::markerRulerPointCmd(int id, const Vector& p1, const Vector& p2,
                        CoordSystem sys, SkyFrame sky)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canEdit()) {
      markerUndo(m, EDIT);

      // it may shrink
      update(markerUpdate, m->getAllBBox());
      FitsImage* ptr = findFits(m->getCenter());
      ((Ruler*)(m))->setPoints(ptr->mapToRef(p1,sys,sky),
                         ptr->mapToRef(p2,sys,sky));
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerRulerSystemCmd(int id, CoordSystem sys, SkyFrame sky,
                         CoordSystem distsys, SkyFormat distformat)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      // it may shrink
      update(markerUpdate, m->getAllBBox());
      ((Ruler*)(m))->setCoordSystem(sys, sky, distsys, distformat);
      update(markerUpdate, m->getAllBBox());
      return;
    }
    m=m->next();
  }

  result = TCL_ERROR;
}

void FrameBase::markerSaveCmd(const char* fileName, MarkerFormat type, 
                        CoordSystem sys, SkyFrame sky, SkyFormat format,
                        int listwcs)
{
  char delim = '\n';

  ofstream fn(fileName);
  if (fn) {

    void (FrameBase::*hproc)(ostream&, CoordSystem, SkyFrame, SkyFormat, 
                       char, int);
    void (Marker::*mproc)(ostream&, CoordSystem, SkyFrame, SkyFormat, char);

    switch (type) {
    case DS9:
      hproc = &FrameBase::markerListHeader;
      mproc = &Marker::list;
      break;
    case CIAO:
      hproc = &FrameBase::markerListCiaoHeader;
      mproc = &Marker::listCiao;
      break;
    case SAOTNG:
      hproc = &FrameBase::markerListSAOtngHeader;
      mproc = &Marker::listSAOtng;
      break;
    case SAOIMAGE:
      hproc = NULL;
      mproc = &Marker::listSAOimage;
      break;
    case PROS:
      hproc = NULL;
      mproc = &Marker::listPros;
      break;
    case RAWXY:
      hproc = NULL;
      mproc = &Marker::listXY;
      break;
    }

    if (hproc)
      (this->*hproc)(fn, sys, sky, format, delim, listwcs);

    Marker* m=markers->head();
    while (m) {
      (m->*mproc)(fn, sys, sky, format, delim);
      m=m->next();
    }
  }
  else {
    Tcl_AppendResult(interp, "Unable to open file ", fileName, NULL);
    result = TCL_ERROR;
  }
}

void FrameBase::markerSelectCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      if (m->canSelect()) {
      m->select();
      update(markerUpdate, m->getAllBBox());
      }
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerSelectCmd(const Vector& v)
{
  // first, check to see if we clicked on an already selected marker

  Marker* m=markers->head();
  while (m) {
    if (m->isIn(v) && m->isSelected()) {
      Tcl_AppendResult(interp, "1", NULL);
      return;
    }
    m=m->next();
  }

  // ok, now select the first found, and unselect the rest

  int found = 0;

  m=markers->head();
  while (m) {
    if (m->isIn(v) && m->canSelect() && !found) {
      if (!m->isSelected()) {
      m->select();
      update(markerUpdate, m->getBBox());
      }
      found = 1;
    }
    else {
      if (m->isSelected()) {
      m->unselect();
      update(markerUpdate, m->getBBox());
      }
    }
    m=m->next();
  } 

  if (found)
    Tcl_AppendResult(interp, "1", NULL);
  else
    Tcl_AppendResult(interp, "0", NULL);
}

void FrameBase::markerSelectCmd()
{
  Marker* m=markers->head();
  while (m) {
    if (m->canSelect()) {
      m->select();
      update(markerUpdate, m->getBBox());
    }
    m=m->next();
  }
}

void FrameBase::markerSelectCmd(const char* tag)
{
  Marker* m=markers->head();
  while (m) {
    if (m->canSelect() && m->hasTag(tag)) {
      m->select();
      update(markerUpdate, m->getBBox());
    }
    m=m->next();
  }
}

void FrameBase::markerSelectToggleCmd(const Vector& v)
{
  // toggle the select of the first found

  Marker* m=markers->head();
  while (m) {
    if (m->isIn(v) && m->canSelect()) {
      m->toggleSelect();
      update(markerUpdate, m->getBBox());
      Tcl_AppendResult(interp, "1", NULL);
      return;
    }
    m=m->next();
  }

  Tcl_AppendResult(interp, "0", NULL);
}

void FrameBase::markerShowCmd(int which)
{
  *showMarkers = which;
  update(markerUpdate);
}

void FrameBase::markerTagCmd(const char* tag)
{
  Marker* m=markers->head();
  while (m) {
    if (m->isSelected())
      m->addTag(tag);
    m=m->next();
  }
}

void FrameBase::markerTagCmd(int id, const char* tag)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      m->addTag(tag);
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerTagEditCmd(const char* from, const char* to)
{
  Marker* m=markers->head();
  while (m) {
    m->editTag(from, to);
    m=m->next();
  }
}

void FrameBase::markerTagDeleteCmd(const char* t)
{
  Marker* m=markers->head();
  while (m) {
    m->deleteTag(t);
    m=m->next();
  }
}

void FrameBase::markerTagDeleteAllCmd()
{
  Marker* m=markers->head();
  while (m) {
    m->deleteTags();
    m=m->next();
  }
}

void FrameBase::markerTagSelectCmd(const char* tag)
{
  Marker* m=markers->head();
  while (m) {
    if (m->hasTag(tag))
      m->select();
    else
      m->unselect();
    update(markerUpdate, m->getBBox());
    m=m->next();
  }
}

void FrameBase::markerTagUpdateCmd(const char* t)
{
  markerTagDeleteCmd(t);
  markerTagCmd(t);
}

void FrameBase::markerTextCmd(int id, const char* text)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      // things can shrink, so do before and after
      update(markerUpdate,m->getAllBBox());
      m->setText(text);
      update(markerUpdate,m->getAllBBox());
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerCopyCmd()
{
  undoMarkers->deleteAll();
  pasteMarkers->deleteAll();
  Marker* m = markers->head();
  while (m) {
    if (m->isSelected())
      pasteMarkers->append(m->dup());
    m=m->next();
  }
}

void FrameBase::markerCopyCmd(const char* tag)
{
  undoMarkers->deleteAll();
  pasteMarkers->deleteAll();
  Marker* m = markers->head();
  while (m) {
    if (m->hasTag(tag))
      pasteMarkers->append(m->dup());
    m=m->next();
  }
}

void FrameBase::markerCutCmd()
{
  undoMarkers->deleteAll();
  pasteMarkers->deleteAll();
  Marker* m = markers->head();
  while (m) {
    if (m->isSelected() && m->canDelete()) {
      Marker* next = markers->extractNext(m);
      update(markerUpdate, m->getAllBBox());
      pasteMarkers->append(m);
      m->doCallBack(Marker::DELETECB);
      m->disableCB();
      m = next;
    }
    else
      m=m->next();
  }
}

void FrameBase::markerCutCmd(const char* tag)
{
  undoMarkers->deleteAll();
  pasteMarkers->deleteAll();
  Marker* m = markers->head();
  while (m) {
    if (m->canDelete() && m->hasTag(tag)) {
      Marker* next = markers->extractNext(m);
      update(markerUpdate, m->getAllBBox());
      pasteMarkers->append(m);
      m->doCallBack(Marker::DELETECB);
      m->disableCB();
      m = next;
    }
    else
      m=m->next();
  }
}

void FrameBase::markerPasteCmd()
{
  unselectMarkers();

  undoMarkers->deleteAll();
  Marker* m=pasteMarkers->head();
  while (m) {
    Marker* n = m->dup();
    n->newIdentity();
    markers->append(n);

    m = m->next();
  }

  update(markerUpdate);
}

#if __GNUC__ >= 3
void FrameBase::markerPasteCmd(CoordSystem sys, SkyFrame sky)
{
  char buf[LISTBUFSIZE];

  MarkerFormat type = DS9;
  SkyFormat format = DEGREES;
  char delim = '\n';

  {
    ostringstream str;
    markerListHeader(str, sys, sky, format, delim, 0);
    str << ends;
    Tcl_AppendResult(interp, str.str().c_str(), NULL);
  }

  Marker* m=pasteMarkers->head();
  while (m) {
    ostringstream str;
    m->list(str, sys, sky, format, delim);
    str << ends;
    Tcl_AppendResult(interp, str.str().c_str(), NULL);
    m=m->next();
  }
}
#else
void FrameBase::markerPasteCmd(CoordSystem sys, SkyFrame sky)
{
  char buf[LISTBUFSIZE];

  MarkerFormat type = DS9;
  SkyFormat format = DEGREES;
  char delim = '\n';

  {
    ostrstream str(buf,LISTBUFSIZE);
    markerListHeader(str, sys, sky, format, delim, 0);
    str << ends;
    Tcl_AppendResult(interp, buf, NULL);
  }

  Marker* m=pasteMarkers->head();
  while (m) {
    ostrstream str(buf,LISTBUFSIZE);
    m->list(str, sys, sky, format, delim);
    str << ends;
    Tcl_AppendResult(interp, buf, NULL);
    m=m->next();
  }
}
#endif

void FrameBase::markerUndoCmd()
{
  Marker* n=undoMarkers->head();
  while (n) {
    Marker* next = n->next();
    undoMarkers->extractPrev(n);
    
    switch (undoMarkerType) {
    case NONE:
      break;
    case DELETE:
      markers->append(n);
      n->updateBBox();
      update(markerUpdate,n->getAllBBox());
      break;
    case EDIT:
    case MOVE:
      {
      Marker* m=markers->head();
      while (m) {
        if (m->getId() == n->getId()) {
          n->enableCB();
          m->updateBBox();
          update(markerUpdate,m->getAllBBox());

          markers->insertNext(m,n);
          markers->extractNext(m);

          n->updateBBox();
          update(markerUpdate,n->getAllBBox());
          switch (undoMarkerType) {
          case EDIT:
            n->doCallBack(Marker::EDITCB);
            break;
          case MOVE:
            n->doCallBack(Marker::MOVECB);
            break;
          }

          m->disableCB();
          delete m;
          break;
        }
        m=m->next();
      }
      }
      break;
    }

    n=next;
  }

  undoMarkerType = NONE;
}

void FrameBase::markerUnselectCmd(int id)
{
  Marker* m=markers->head();
  while (m) {
    if (m->getId() == id) {
      m->unselect();
      update(markerUpdate, m->getBBox());
      return;
    }
    m=m->next();
  }
}

void FrameBase::markerUnselectAllCmd()
{
  Marker* m=markers->head();
  while (m) {
    m->unselect();
    update(markerUpdate, m->getBBox());
    m=m->next();
  } 
}

void FrameBase::regionSelectBeginCmd(const Vector& v)
{
  regionBegin = v;
  regionEnd = v;
}

void FrameBase::regionSelectMotionCmd(const Vector& v)
{
  if (visible) {

    // erase 

    redrawNow((BBox(regionBegin, regionEnd)).expand(2));

    // and draw to window

    regionEnd = v;
    BBox cc = BBox(regionBegin, regionEnd) * canvasToWindow;
    Vector size = cc.size();

    XDRAWRECTANGLE(display, Tk_WindowId(tkwin), selectGCXOR,
               (int)cc.ll[0], (int)cc.ll[1], (int)size[0], (int)size[1]);
  }
}

void FrameBase::regionSelectEndCmd()
{
  BBox bb(regionBegin, regionEnd);

  Marker* m=markers->head();
  while (m) {
    if (bb.isIn(m->getBBox())==4 && m->canSelect())
      m->select();
    else
      m->unselect();
    m=m->next();
  } 

  update(markerUpdate, bb.expand(2));
}

void FrameBase::regionSelectShiftEndCmd()
{
  BBox bb(regionBegin, regionEnd);

  Marker* m=markers->head();
  while (m) {
    if (bb.isIn(m->getBBox())==4)
      m->select();
    m=m->next();
  }

  update(markerUpdate, bb.expand(2));
}

// Marker Support

void FrameBase::markerUndo(Marker* m, UndoMarkerType t)
{
  undoMarkers->deleteAll();
  undoMarkers->append(m->dup());
  undoMarkerType = t;
}

void FrameBase::parseMarker(MarkerFormat fm, istream& str)
{
  switch (fm) {
  case DS9:
    mklexx = new mkFlexLexer(&str);
    mkparse(this);
    delete mklexx;
    mklexx = NULL;
    break;

  case CIAO:
    ciaolexx = new ciaoFlexLexer(&str);
    ciaoparse(this);
    delete ciaolexx;
    ciaolexx = NULL;
    break;

  case PROS:
    proslexx = new prosFlexLexer(&str);
    prosparse(this);
    delete proslexx;
    proslexx = NULL;
    break;

  case SAOTNG:
    tnglexx = new tngFlexLexer(&str);
    tngparse(this);
    delete tnglexx;
    tnglexx = NULL;
    break;

  case SAOIMAGE:
    saolexx = new saoFlexLexer(&str);
    saoparse(this);
    delete saolexx;
    saolexx = NULL;
    break;

  case RAWXY:
    xylexx = new xyFlexLexer(&str);
    xyparse(this);
    delete xylexx;
    xylexx = NULL;
    break;
  }
}

void FrameBase::psMarkers(int mode)
{
  // render from back to front
  // bbox is in canvas coords

  const BBox bb = BBox(0, 0, options->width-1, options->height-1) * 
    widgetToCanvas;

  Marker* m=markers->tail();
  while (m) {
    if (m->isVisible(bb))
      m->ps(mode);
    m=m->previous();
  }
}

void FrameBase::renderfgMarkers(const BBox& bb)
{
  // render from back to front
  // bbox is in canvas coords

  Marker* m=fgMarkers.tail();
  while (m) {
    if (m->isVisible(bb))
      m->draw(pixmap);
    m=m->previous();
  }
}

void FrameBase::renderbgMarkers(const BBox& bb)
{
  // render from back to front
  // bbox is in canvas coords

  Marker* m=bgMarkers.tail();
  while (m) {
    if (m->isVisible(bb))
      m->draw(basePixmap);
    m=m->previous();
  }
}

void FrameBase::renderMagnifierMarkers(const Matrix& matrix, const BBox& bb)
{
  // render from back to front
  // bbox is in canvas coords

  Marker* m=markers->tail();
  while (m) {
    if (m->isVisible(bb))
      m->drawMagnifier(matrix);
    m=m->previous();
  }
}

void FrameBase::unselectMarkers()
{
  Marker* m=markers->head();
  while (m) {
    m->unselect();
    m=m->next();
  }
}

void FrameBase::updateCBMarkers()
{
  Marker* m=markers->head();
  while (m) {
    m->doCallBack(Marker::UPDATECB);
    m=m->next();
  }
}

void FrameBase::updateMarkers()
{
  Marker* m=markers->head();
  while (m) {
    m->updateBBox();
    m=m->next();
  }
}

void FrameBase::updateMarkerCoords(const Matrix& mm)
{
  Marker* m=markers->head();
  while (m) {
    m->updateCoords(mm);

    // do any callbacks
    m->doCallBack(Marker::MOVECB);
    m->doCallBack(Marker::EDITCB);
    m->doCallBack(Marker::ROTATECB);

    m=m->next();
  }
}

void FrameBase::markerPrintCoord(const Vector& v, InternalSystem sys)
{
  printVector(mapFromRef(v, sys), DEFAULT);
}

void FrameBase::markerPrintCoord(const Vector& c, const Vector& v,
                       CoordSystem sys, SkyFrame sky, SkyFormat format)
{
  switch (*currentMode) {
  case SINGLE:
    if (currentFits)
      printFromRef(currentFits, v, sys, sky, format, DEFAULT);
    break;
  case MOSAIC:
    if (*channelFits) {
      FitsImage* ptr = *channelFits;
      while (ptr) {
      Vector img = c * ptr->getRefToData();
      int* params = ptr->getDataParams(currentScale->scanMode());
      int& xmin = params[1];
      int& xmax = params[2];
      int& ymin = params[3];
      int& ymax = params[4];

      if (img[0]>=xmin && img[0]<xmax && img[1]>=ymin && img[1]<ymax) {
        printFromRef(ptr, v, sys, sky, format, DEFAULT);
        return;
      }

      ptr = ptr->next();
      }
    }

    // use default coordinate frame
    switch (sys) {
    case AMPLIFIER:
    case PHYSICAL:
    case IMAGE:
      break;
    default:
      if (currentFits)
      printFromRef(currentFits, v, sys, sky, format, DEFAULT);
      break;
    }

    break;
  }
}

void FrameBase::markerPrintDouble(double d, InternalSystem sys)
{
  printDouble(mapLenFromRef(d, sys), DEFAULT);
}

void FrameBase::markerPrintDouble(const Vector& c, double d, 
                        CoordSystem sys, SkyFormat format)
{
  switch (*currentMode) {
  case SINGLE:
    if (currentFits)
      printDouble(currentFits->mapLenFromRef(d, sys, format), DEFAULT);
    break;
  case MOSAIC:
    if (*channelFits) {
      FitsImage* ptr = *channelFits;
      while (ptr) {
      Vector img = c * ptr->getRefToData();
      int* params = ptr->getDataParams(currentScale->scanMode());
      int& xmin = params[1];
      int& xmax = params[2];
      int& ymin = params[3];
      int& ymax = params[4];

      if (img[0]>=xmin && img[0]<xmax && img[1]>=ymin && img[1]<ymax) {
        printDouble(ptr->mapLenFromRef(d, sys, format), DEFAULT);
        return;
      }

      ptr = ptr->next();
      }
    }

    // use default coordinate frame
    switch (sys) {
    case IMAGE:
    case PHYSICAL:
    case AMPLIFIER:
      break;
    default:
      if (currentFits)
      printDouble(currentFits->mapLenFromRef(d, sys, format), DEFAULT);
      break;
    }

    break;
  }
}

void FrameBase::markerPrintDouble(const Vector& c,
                        const Vector& p1, const Vector& p2,
                        CoordSystem sys, SkyFormat format)
{
  switch (*currentMode) {
  case SINGLE:
    if (currentFits)
      printDouble(currentFits->mapDistFromRef(p1,p2,sys,format), DEFAULT);
    break;
  case MOSAIC:
    if (*channelFits) {
      FitsImage* ptr = *channelFits;
      while (ptr) {
      Vector img = c * ptr->getRefToData();
      int* params = ptr->getDataParams(currentScale->scanMode());
      int& xmin = params[1];
      int& xmax = params[2];
      int& ymin = params[3];
      int& ymax = params[4];

      if (img[0]>=xmin && img[0]<xmax && img[1]>=ymin && img[1]<ymax) {
        printDouble(ptr->mapDistFromRef(p1, p2, sys, format), DEFAULT);
        return;
      }

      ptr = ptr->next();
      }
    }

    // use default coordinate frame
    switch (sys) {
    case IMAGE:
    case PHYSICAL:
    case AMPLIFIER:
      break;
    default:
      if (currentFits)
      printDouble(currentFits->mapDistFromRef(p1,p2,sys,format), DEFAULT);
      break;
    }

    break;
  }
}

void FrameBase::markerPrintVector(const Vector& v, InternalSystem sys)
{
  printVector(mapLenFromRef(v,sys), DEFAULT);
}

void FrameBase::markerPrintVector(const Vector& c, const Vector& v,
                        CoordSystem sys, SkyFormat format)
{
  switch (*currentMode) {
  case SINGLE:
    if (currentFits)
      printVector(currentFits->mapLenFromRef(v, sys, format), DEFAULT);
    break;
  case MOSAIC:
    if (*channelFits) {
      FitsImage* ptr = *channelFits;
      while (ptr) {
      Vector img = c * ptr->getRefToData();
      int* params = ptr->getDataParams(currentScale->scanMode());
      int& xmin = params[1];
      int& xmax = params[2];
      int& ymin = params[3];
      int& ymax = params[4];

      if (img[0]>=xmin && img[0]<xmax && img[1]>=ymin && img[1]<ymax) {
        printVector(ptr->mapLenFromRef(v, sys, format), DEFAULT);
        return;
      }

      ptr = ptr->next();
      }
    }

    // use default coordinate frame
    switch (sys) {
    case IMAGE:
    case PHYSICAL:
    case AMPLIFIER:
      break;
    default:
      if (currentFits)
      printVector(currentFits->mapLenFromRef(v, sys, format), DEFAULT);
      break;
    }

    break;
  }
}

void FrameBase::markerListHeader(ostream& str, CoordSystem sys, SkyFrame sky,
                       SkyFormat format, char delim, int listwcs)
{
  // no comments for semicolons
  if (delim != ';') {
    // header
    str << "# Region file format: DS9 version 3.0" << delim;
    if (currentFits)
      str << "# Filename: " <<  currentFits->getFullBaseFileName() << delim;

    if (listwcs)
      if (sys > WCS)
      currentFits->listWCS(str, sys, delim);
      else
      currentFits->listWCS(str, WCS, delim);

    str << "global color=green font=\"helvetica 10 normal\" "
      << "select=1 edit=1 move=1 delete=1 include=1 fixed=0 source" 
      << delim;

    // wcs
    if (sys > WCS)
      str << "global wcs = wcs" << (char)(sys-WCS+'`') << delim;
  }
}

void FrameBase::markerListCiaoHeader(ostream& str, CoordSystem sys, 
                             SkyFrame sky, SkyFormat format, 
                             char delim, int listwcs)
{
  // no comments for semicolons
  if (delim != ';')
    str << "# Region file format: CIAO version 1.0" << delim;
}

void FrameBase::markerListSAOtngHeader(ostream& str, CoordSystem sys,
                               SkyFrame sky, SkyFormat format, 
                               char delim, int listwcs)
{
  // no comments for semicolons
  if (delim == ';')
    return;

  if (currentFits)
    str << "# filename: " << currentFits->getRootFileName() << delim;

  switch (sys) {
  case IMAGE:
  case PHYSICAL:
  case AMPLIFIER:
  case DETECTOR:
    str << "# format: pixels (physical)" << delim;
    break;

  default:
    str << "# format: ";
    switch (sky) {
    case FK4:
    case FK5:
    case ICRS:
    case ECLIPTIC:
    case GALACTIC:
      switch (format) {
      case DEGREES:
      str << "degrees (";
      break;
      case SEXAGESIMAL:
      case HMS:
      str << "hms (";
      break;
      }

      switch (sky) {
      case FK4:
      str << "fk4";
      break;
      case FK5:
      str << "fk5";
      break;
      case ICRS:
      str << "icrs";
      break;
      case GALACTIC:
      str << "galactic";
      break;
      case ECLIPTIC:
      str << "ecliptic";
      break;
      }

      str << ')' << delim;
      break;

    default:
      str << "linear";
    }
  }
}



Generated by  Doxygen 1.6.0   Back to index