summaryrefslogtreecommitdiffstats
path: root/tksao/widget
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2016-10-27 18:59:29 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2016-10-27 18:59:29 (GMT)
commitd4d595fa7fb12903db9227d33d48b2b00120dbd1 (patch)
tree7d18365de0d6d1b29399b6a17c7eb01c2eb3ed49 /tksao/widget
parent949f96e29bfe0bd8710d775ce220e597064e2589 (diff)
downloadblt-d4d595fa7fb12903db9227d33d48b2b00120dbd1.zip
blt-d4d595fa7fb12903db9227d33d48b2b00120dbd1.tar.gz
blt-d4d595fa7fb12903db9227d33d48b2b00120dbd1.tar.bz2
Initial commit
Diffstat (limited to 'tksao/widget')
-rw-r--r--tksao/widget/truecolor16.C148
-rw-r--r--tksao/widget/truecolor16.h42
-rw-r--r--tksao/widget/truecolor24.C292
-rw-r--r--tksao/widget/truecolor24.h47
-rw-r--r--tksao/widget/truecolor8.C71
-rw-r--r--tksao/widget/truecolor8.h42
-rw-r--r--tksao/widget/widget.C813
-rw-r--r--tksao/widget/widget.h203
8 files changed, 1658 insertions, 0 deletions
diff --git a/tksao/widget/truecolor16.C b/tksao/widget/truecolor16.C
new file mode 100644
index 0000000..ed0aa60
--- /dev/null
+++ b/tksao/widget/truecolor16.C
@@ -0,0 +1,148 @@
+// Copyright (C) 1999-2016
+// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+// For conditions of distribution and use, see copyright notice in "copyright"
+
+#include "truecolor16.h"
+#include "util.h"
+
+TrueColor16::TrueColor16(Visual* visual)
+{
+#if !(_WIN32)
+ rx_ = visual->red_mask;
+ gx_ = visual->green_mask;
+ bx_ = visual->blue_mask;
+#endif
+#if _WIN32
+ // windows masks are plain wrong
+ rx_ = 0x7C00;
+ gx_ = 0x03E0;
+ bx_ = 0x001F;
+#endif
+
+ rm_ = decodeMask((unsigned short)rx_, &rs_);
+ gm_ = decodeMask((unsigned short)gx_, &gs_);
+ bm_ = decodeMask((unsigned short)bx_, &bs_);
+}
+
+unsigned short TrueColor16::decodeMask(unsigned short mask, int* s)
+{
+ // first calc ffs for mask
+ unsigned short m1 = mask;
+ int m1s;
+ for (m1s=0; m1s<16; m1s++) {
+ if (m1 & 0x1)
+ break;
+ m1 >>= 1;
+ }
+
+ // then shift mask to mask a char
+ for (int i=0; i<16; i++) {
+ if (mask & 0x8000)
+ break;
+ mask <<= 1;
+ }
+ mask >>= 8;
+
+ // now calc ffs for new mask
+ unsigned short m2 = mask;
+ int m2s;
+ for (m2s=0; m2s<16; m2s++) {
+ if (m2 & 0x1)
+ break;
+ m2 >>= 1;
+ }
+
+ *s = m1s-m2s;
+ return mask;
+}
+
+void TrueColor16::encodeTrueColor(XColor* src, char* dest, XImage* ximage)
+{
+ if (!ximage)
+ return;
+
+ int msb = ximage->byte_order;
+
+ unsigned short r = (unsigned char)src->red;
+ unsigned short g = (unsigned char)src->green;
+ unsigned short b = (unsigned char)src->blue;
+ unsigned short v = 0;
+ v |= rs_>0 ? ((r & rm_) << rs_) : ((r & rm_) >> -rs_);
+ v |= gs_>0 ? ((g & gm_) << gs_) : ((g & gm_) >> -gs_);
+ v |= bs_>0 ? ((b & bm_) << bs_) : ((b & bm_) >> -bs_);
+
+ if ((!msb && lsb()) || (msb && !lsb()))
+ memcpy(dest, &v, 2);
+ else {
+ unsigned char* rr = (unsigned char*)(&v);
+ *(dest) = *(rr+1);
+ *(dest+1) = *(rr);
+ }
+}
+
+void TrueColor16::decodeTrueColor(char* src, XColor* dest, XImage* ximage)
+{
+ if (!ximage)
+ return;
+
+ int msb = ximage->byte_order;
+ unsigned short v = 0;
+
+ if ((!msb && lsb()) || (msb && !lsb()))
+ memcpy(dest, &v, 2);
+ else {
+ unsigned char* rr = (unsigned char*)(&v);
+ *(rr+1) = *(src+0);
+ *(rr+0) = *(src+1);
+ }
+
+ dest->red = (unsigned short)((v & rx_) >> rs_);
+ dest->green = (unsigned short)((v & gx_) >> gs_);
+ dest->blue = (unsigned short)((v & bx_) >> bs_);
+}
+
+void TrueColor16::encodeTrueColor(unsigned char* src, XImage* ximage)
+{
+ int& width = ximage->width;
+ int& height = ximage->height;
+ char* data = ximage->data;
+ int msb = ximage->byte_order;
+
+ const unsigned char* ptr = src;
+ if ((!msb && lsb()) || (msb && !lsb())) {
+ for (int jj=0; jj<height; jj++) {
+ char* dest = data + jj*ximage->bytes_per_line; // may be padded at the end
+
+ for (int ii=0; ii<width; ii++, dest+=2, ptr+=3) {
+ unsigned short r = ptr[0];
+ unsigned short g = ptr[1];
+ unsigned short b = ptr[2];
+ unsigned short v = 0;
+ v |= rs_>0 ? ((r & rm_) << rs_) : ((r & rm_) >> -rs_);
+ v |= gs_>0 ? ((g & gm_) << gs_) : ((g & gm_) >> -gs_);
+ v |= bs_>0 ? ((b & bm_) << bs_) : ((b & bm_) >> -bs_);
+
+ memcpy(dest, &v, 2);
+ }
+ }
+ }
+ else {
+ for (int jj=0; jj<height; jj++) {
+ char* dest = data + jj*ximage->bytes_per_line;
+
+ for (int ii=0; ii<width; ii++, dest+=2, ptr+=3) {
+ unsigned short r = ptr[0];
+ unsigned short g = ptr[1];
+ unsigned short b = ptr[2];
+ unsigned short v = 0;
+ v |= rs_>0 ? ((r & rm_) << rs_) : ((r & rm_) >> -rs_);
+ v |= gs_>0 ? ((g & gm_) << gs_) : ((g & gm_) >> -gs_);
+ v |= bs_>0 ? ((b & bm_) << bs_) : ((b & bm_) >> -bs_);
+
+ unsigned char* rr = (unsigned char*)(&v);
+ *(dest) = *(rr+1);
+ *(dest+1) = *(rr);
+ }
+ }
+ }
+}
diff --git a/tksao/widget/truecolor16.h b/tksao/widget/truecolor16.h
new file mode 100644
index 0000000..ba60c35
--- /dev/null
+++ b/tksao/widget/truecolor16.h
@@ -0,0 +1,42 @@
+// Copyright (C) 1999-2016
+// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+// For conditions of distribution and use, see copyright notice in "copyright"
+
+#ifndef __truecolor16_h__
+#define __truecolor16_h__
+
+#include <string.h>
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+using namespace std;
+
+#include <tk.h>
+
+class TrueColor16 {
+ protected:
+ unsigned long rx_;
+ unsigned long gx_;
+ unsigned long bx_;
+ unsigned short rm_;
+ unsigned short gm_;
+ unsigned short bm_;
+ int rs_;
+ int gs_;
+ int bs_;
+
+ private:
+ unsigned short decodeMask(unsigned short, int*);
+
+ protected:
+ void decodeTrueColor(char*, XColor*, XImage*);
+ void encodeTrueColor(XColor*, char*, XImage*);
+ void encodeTrueColor(unsigned char*, XImage*);
+
+ public:
+ TrueColor16(Visual*);
+};
+
+#endif
+
diff --git a/tksao/widget/truecolor24.C b/tksao/widget/truecolor24.C
new file mode 100644
index 0000000..a1d0673
--- /dev/null
+++ b/tksao/widget/truecolor24.C
@@ -0,0 +1,292 @@
+// Copyright (C) 1999-2016
+// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+// For conditions of distribution and use, see copyright notice in "copyright"
+
+#include "truecolor24.h"
+#include "util.h"
+
+TrueColor24::TrueColor24(Visual* visual)
+{
+#if !(_WIN32 || MAC_OSX_TK)
+ ax_ = 0;
+ rx_ = visual->red_mask;
+ gx_ = visual->green_mask;
+ bx_ = visual->blue_mask;
+#endif
+#if MAC_OSX_TK
+ ax_ = 0xFF000000;
+ rx_ = 0x00FF0000;
+ gx_ = 0x0000FF00;
+ bx_ = 0x000000FF;
+#endif
+#if _WIN32
+ // windows masks are plain wrong
+ ax_ = 0;
+ rx_ = 0x00FF0000;
+ gx_ = 0x0000FF00;
+ bx_ = 0x000000FF;
+#endif
+
+ rs_ = decodeMask((unsigned long)rx_);
+ gs_ = decodeMask((unsigned long)gx_);
+ bs_ = decodeMask((unsigned long)bx_);
+ as_ = decodeMask((unsigned long)ax_);
+}
+
+int TrueColor24::decodeMask(unsigned long mask)
+{
+ switch (mask) {
+ case 0:
+ return 0;
+ case 0xff:
+ return 0;
+ case 0xff00:
+ return 8;
+ case 0xff0000:
+ return 16;
+ case 0xff000000:
+ return 24;
+ }
+ return 0;
+}
+
+void TrueColor24::encodeTrueColor(XColor* src, char* dest, XImage* ximage)
+{
+ if (!ximage)
+ return;
+
+ switch (ximage->bits_per_pixel) {
+ case 24:
+ encodeTrueColor24(src, dest, ximage);
+ break;
+ case 32:
+ encodeTrueColor32(src, dest, ximage);
+ break;
+ }
+}
+
+void TrueColor24::decodeTrueColor(char* src, XColor* dest, XImage* ximage)
+{
+ if (!ximage)
+ return;
+
+ switch (ximage->bits_per_pixel) {
+ case 24:
+ decodeTrueColor24(src, dest, ximage);
+ break;
+ case 32:
+ decodeTrueColor32(src, dest, ximage);
+ break;
+ }
+}
+
+void TrueColor24::encodeTrueColor24(XColor* src, char* dest, XImage* ximage)
+{
+ int msb = ximage->byte_order;
+
+ unsigned int r = (unsigned char)src->red;
+ unsigned int g = (unsigned char)src->green;
+ unsigned int b = (unsigned char)src->blue;
+ unsigned int v = 0;
+ v |= r << rs_;
+ v |= g << gs_;
+ v |= b << bs_;
+
+ if ((!msb && lsb()) || (msb && !lsb()))
+ memcpy(dest, &v, 3);
+ else {
+ unsigned char* rr = (unsigned char*)(&v);
+ *(dest+0) = *(rr+3);
+ *(dest+1) = *(rr+2);
+ *(dest+2) = *(rr+1);
+ }
+}
+
+void TrueColor24::decodeTrueColor24(char* src, XColor* dest, XImage* ximage)
+{
+ int msb = ximage->byte_order;
+ unsigned int v = 0;
+
+ if ((!msb && lsb()) || (msb && !lsb()))
+ memcpy(&v, src, 3);
+ else {
+ unsigned char* rr = (unsigned char*)(&v);
+ *(rr+3) = *(src+0);
+ *(rr+2) = *(src+1);
+ *(rr+1) = *(src+2);
+ }
+
+ dest->red = (unsigned short)((v & rx_) >> rs_);
+ dest->green = (unsigned short)((v & gx_) >> gs_);
+ dest->blue = (unsigned short)((v & bx_) >> bs_);
+}
+
+void TrueColor24::encodeTrueColor32(XColor* src, char* dest, XImage* ximage)
+{
+ int msb = ximage->byte_order;
+
+ unsigned int r = (unsigned char)src->red;
+ unsigned int g = (unsigned char)src->green;
+ unsigned int b = (unsigned char)src->blue;
+ unsigned int v = 0;
+#ifdef MAC_OSX_TK
+ unsigned int a = 0xff;
+ v |= a << as_;
+#endif
+ v |= r << rs_;
+ v |= g << gs_;
+ v |= b << bs_;
+
+ if ((!msb && lsb()) || (msb && !lsb()))
+ memcpy(dest, &v, 4);
+ else {
+ unsigned char* rr = (unsigned char*)(&v);
+ *(dest+0) = *(rr+3);
+ *(dest+1) = *(rr+2);
+ *(dest+2) = *(rr+1);
+ *(dest+3) = *(rr+0);
+ }
+}
+
+void TrueColor24::decodeTrueColor32(char* src, XColor* dest, XImage* ximage)
+{
+ int msb = ximage->byte_order;
+ unsigned int v = 0;
+
+ if ((!msb && lsb()) || (msb && !lsb()))
+ memcpy(dest, &v, 4);
+ else {
+ unsigned char* rr = (unsigned char*)(&v);
+ *(rr+3) = *(src);
+ *(rr+2) = *(src+1);
+ *(rr+1) = *(src+2);
+ *(rr+0) = *(src+3);
+ }
+
+ dest->red = (unsigned short)((v & rx_) >> rs_);
+ dest->green = (unsigned short)((v & gx_) >> gs_);
+ dest->blue = (unsigned short)((v & bx_) >> bs_);
+}
+void TrueColor24::encodeTrueColor(unsigned char* src, XImage* ximage)
+{
+ if (!ximage)
+ return;
+
+ switch (ximage->bits_per_pixel) {
+ case 24:
+ encodeTrueColor24(src, ximage);
+ break;
+ case 32:
+ encodeTrueColor32(src, ximage);
+ break;
+ }
+}
+
+void TrueColor24::encodeTrueColor24(unsigned char* src, XImage* ximage)
+{
+ int& width = ximage->width;
+ int& height = ximage->height;
+ char* data = ximage->data;
+ int bytesPerPixel = ximage->bits_per_pixel/8;
+ int msb = ximage->byte_order;
+
+ const unsigned char* ptr = src;
+ if ((!msb && lsb()) || (msb && !lsb())) {
+ for (int jj=0; jj<height; jj++) {
+ char* dest = data + jj*ximage->bytes_per_line;
+
+ for (int ii=0; ii<width; ii++, dest+=bytesPerPixel, ptr+=3) {
+ unsigned int r = ptr[0];
+ unsigned int g = ptr[1];
+ unsigned int b = ptr[2];
+ unsigned int v = 0;
+ v |= r << rs_;
+ v |= g << gs_;
+ v |= b << bs_;
+
+ memcpy(dest, &v, 3);
+ }
+ }
+ }
+ else {
+ for (int jj=0; jj<height; jj++) {
+ char* dest = data + jj*ximage->bytes_per_line;
+
+ for (int ii=0; ii<width; ii++, dest+=bytesPerPixel, ptr+=3) {
+ unsigned int r = ptr[0];
+ unsigned int g = ptr[1];
+ unsigned int b = ptr[2];
+ unsigned int v = 0;
+ v |= r << rs_;
+ v |= g << gs_;
+ v |= b << bs_;
+
+ unsigned char* rr = (unsigned char*)(&v);
+ *(dest) = *(rr+3);
+ *(dest+1) = *(rr+2);
+ *(dest+2) = *(rr+1);
+ }
+ }
+ }
+}
+
+void TrueColor24::encodeTrueColor32(unsigned char* src, XImage* ximage)
+{
+ int& width = ximage->width;
+ int& height = ximage->height;
+ char* data = ximage->data;
+ int bytesPerPixel = ximage->bits_per_pixel/8;
+ int msb = ximage->byte_order;
+
+ const unsigned char* ptr = src;
+ if ((!msb && lsb()) || (msb && !lsb())) {
+ for (int jj=0; jj<height; jj++) {
+ // the line may be padded at the end
+ char* dest = data + jj*ximage->bytes_per_line;
+
+ for (int ii=0; ii<width; ii++, dest+=bytesPerPixel, ptr+=3) {
+ unsigned int r = ptr[0];
+ unsigned int g = ptr[1];
+ unsigned int b = ptr[2];
+ unsigned int v = 0;
+#ifdef MAC_OSX_TK
+ unsigned int a = 0xff;
+ v |= a << as_;
+#endif
+ v |= r << rs_;
+ v |= g << gs_;
+ v |= b << bs_;
+
+ memcpy(dest, &v, 4);
+ }
+ }
+ }
+ else {
+ for (int jj=0; jj<height; jj++) {
+ // the line may be padded at the end
+ char* dest = data + jj*ximage->bytes_per_line;
+
+ for (int ii=0; ii<width; ii++, dest+=bytesPerPixel, ptr+=3) {
+ unsigned int r = ptr[0];
+ unsigned int g = ptr[1];
+ unsigned int b = ptr[2];
+ unsigned int v = 0;
+#ifdef MAC_OSX_TK
+ unsigned int a = 0xff;
+ v |= a << as_;
+#endif
+ v |= r << rs_;
+ v |= g << gs_;
+ v |= b << bs_;
+
+ unsigned char* rr = (unsigned char*)(&v);
+ *(dest) = *(rr+3);
+ *(dest+1) = *(rr+2);
+ *(dest+2) = *(rr+1);
+ *(dest+3) = *(rr);
+ }
+ }
+ }
+}
+
+
diff --git a/tksao/widget/truecolor24.h b/tksao/widget/truecolor24.h
new file mode 100644
index 0000000..7d106bd
--- /dev/null
+++ b/tksao/widget/truecolor24.h
@@ -0,0 +1,47 @@
+// Copyright (C) 1999-2016
+// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+// For conditions of distribution and use, see copyright notice in "copyright"
+
+#ifndef __truecolor24_h__
+#define __truecolor24_h__
+
+#include <string.h>
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+using namespace std;
+
+#include <tk.h>
+
+class TrueColor24 {
+ protected:
+ unsigned long rx_;
+ unsigned long gx_;
+ unsigned long bx_;
+ unsigned long ax_;
+ int rs_;
+ int gs_;
+ int bs_;
+ int as_;
+
+ private:
+ int decodeMask(unsigned long);
+ void decodeTrueColor24(char*, XColor*, XImage*);
+ void decodeTrueColor32(char*, XColor*, XImage*);
+ void encodeTrueColor24(XColor*, char*, XImage*);
+ void encodeTrueColor24(unsigned char*, XImage*);
+ void encodeTrueColor32(XColor*, char*, XImage*);
+ void encodeTrueColor32(unsigned char*, XImage*);
+
+ protected:
+ void decodeTrueColor(char*, XColor*, XImage*);
+ void encodeTrueColor(XColor*, char*, XImage*);
+ void encodeTrueColor(unsigned char*, XImage*);
+
+ public:
+ TrueColor24(Visual*);
+};
+
+#endif
+
diff --git a/tksao/widget/truecolor8.C b/tksao/widget/truecolor8.C
new file mode 100644
index 0000000..98ef6bf
--- /dev/null
+++ b/tksao/widget/truecolor8.C
@@ -0,0 +1,71 @@
+// Copyright (C) 1999-2016
+// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+// For conditions of distribution and use, see copyright notice in "copyright"
+
+#include "truecolor8.h"
+#include "util.h"
+
+TrueColor8::TrueColor8(Visual* visual)
+{
+
+#if !(_WIN32)
+ rx_ = visual->red_mask;
+ gx_ = visual->green_mask;
+ bx_ = visual->blue_mask;
+#endif
+#if _WIN32
+ // windows masks are plain wrong
+ rx_ = 0xE0;
+ gx_ = 0x18;
+ bx_ = 0x07;
+#endif
+
+ rm_ = decodeMask((unsigned char)rx_, &rs_);
+ gm_ = decodeMask((unsigned char)rx_, &gs_);
+ bm_ = decodeMask((unsigned char)rx_, &bs_);
+}
+
+unsigned char TrueColor8::decodeMask(unsigned char mask, int* s)
+{
+ *s=0;
+ for (int i=0; i<8; i++, (*s)++) {
+ if (mask & 0x80)
+ break;
+ mask <<= 1;
+ }
+ return mask;
+}
+
+void TrueColor8::encodeTrueColor(XColor* src, char* dest, XImage* ximage)
+{
+ *dest =
+ ((((unsigned char)src->blue) & bm_) >> bs_) |
+ ((((unsigned char)src->green) & gm_) >> gs_) |
+ ((((unsigned char)src->red) & rm_) >> rs_);
+}
+
+void TrueColor8::decodeTrueColor(char* src, XColor* dest, XImage* ximage)
+{
+ dest->red = (unsigned short)((*src & rx_) >> rs_);
+ dest->green = (unsigned short)((*src & gx_) >> gs_);
+ dest->blue = (unsigned short)((*src & bx_) >> bs_);
+}
+
+void TrueColor8::encodeTrueColor(unsigned char* src, XImage* ximage)
+{
+ int& width = ximage->width;
+ int& height = ximage->height;
+ char* data = ximage->data;
+
+ const unsigned char* ptr = src;
+ for (int j=0; j<height; j++) {
+ char* dest = data + j*ximage->bytes_per_line;
+
+ for (int i=0; i<width; i++, dest++, ptr+=3)
+ *dest =
+ ((ptr[0] & rm_) >> rs_) |
+ ((ptr[1] & gm_) >> gs_) |
+ ((ptr[2] & bm_) >> bs_);
+ }
+}
+
diff --git a/tksao/widget/truecolor8.h b/tksao/widget/truecolor8.h
new file mode 100644
index 0000000..55d0fdc
--- /dev/null
+++ b/tksao/widget/truecolor8.h
@@ -0,0 +1,42 @@
+// Copyright (C) 1999-2016
+// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+// For conditions of distribution and use, see copyright notice in "copyright"
+
+#ifndef __truecolor8_h__
+#define __truecolor8_h__
+
+#include <string.h>
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+using namespace std;
+
+#include <tk.h>
+
+class TrueColor8 {
+ protected:
+ unsigned long rx_;
+ unsigned long gx_;
+ unsigned long bx_;
+ unsigned char rm_;
+ unsigned char gm_;
+ unsigned char bm_;
+ int rs_;
+ int gs_;
+ int bs_;
+
+ private:
+ unsigned char decodeMask(unsigned char, int*);
+
+ protected:
+ void decodeTrueColor(char*, XColor*, XImage*);
+ void encodeTrueColor(XColor*, char*, XImage*);
+ void encodeTrueColor(unsigned char*, XImage*);
+
+ public:
+ TrueColor8(Visual*);
+};
+
+#endif
+
diff --git a/tksao/widget/widget.C b/tksao/widget/widget.C
new file mode 100644
index 0000000..743ce7b
--- /dev/null
+++ b/tksao/widget/widget.C
@@ -0,0 +1,813 @@
+// Copyright (C) 1999-2016
+// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+// For conditions of distribution and use, see copyright notice in "copyright"
+
+#include <tkInt.h>
+
+#include "widget.h"
+#include "util.h"
+
+// Tk Canvas Widget Functions Declaration
+
+int WidgetConfigProc(Tcl_Interp* interp, Tk_Canvas canvas, Tk_Item* item,
+ int argc, Tcl_Obj *const argv[], int flags)
+{
+ return WIDGET(item).configure(argc, (const char**)argv, flags);
+}
+
+int WidgetCoordProc(Tcl_Interp* interp, Tk_Canvas canvas, Tk_Item* item,
+ int argc, Tcl_Obj *const argv[])
+{
+ return WIDGET(item).coordProc(argc, (char**)argv);
+}
+
+void WidgetDeleteProc(Tk_Canvas canvas, Tk_Item* item, Display* display)
+{
+ delete ((WidgetOptions*)item)->widget;
+}
+
+void WidgetDisplayProc(Tk_Canvas canvas, Tk_Item* item, Display* display,
+ Drawable draw, int x, int y, int width, int height)
+{
+ WIDGET(item).displayProc(draw, x, y, width, height);
+}
+
+double WidgetPointProc(Tk_Canvas canvas, Tk_Item* item, double* point)
+{
+ return WIDGET(item).pointProc(point);
+}
+
+int WidgetAreaProc(Tk_Canvas canvas, Tk_Item* item, double* bbox)
+{
+ return WIDGET(item).areaProc(bbox);
+}
+
+int WidgetPostscriptProc(Tcl_Interp* interp, Tk_Canvas canvas,
+ Tk_Item* item, int prepass)
+{
+ return WIDGET(item).postscriptProc(prepass);
+}
+
+void WidgetScaleProc(Tk_Canvas canvas, Tk_Item* item,
+ double Ox, double Oy , double Sx, double Sy)
+{
+ WIDGET(item).scaleProc(Ox, Oy, Sx, Sy);
+}
+
+void WidgetTranslateProc(Tk_Canvas canvas, Tk_Item* item, double x, double y)
+{
+ WIDGET(item).translateProc(x, y);
+}
+
+int WidgetIndexProc(Tcl_Interp* interp, Tk_Canvas canvas, Tk_Item* item,
+ char indexString, int* indexPtr)
+{
+ WIDGET(item).indexProc(indexString, indexPtr);
+ return 1;
+}
+
+void WidgetICursorProc(Tk_Canvas canvas, Tk_Item* item, int index)
+{
+ WIDGET(item).icursorProc(index);
+}
+
+int WidgetSelectionProc(Tk_Canvas canvas, Tk_Item* item,
+ int offset, char* buffer, int maxBytes)
+{
+ WIDGET(item).selectionProc(offset, buffer, maxBytes);
+ return 1;
+}
+
+void WidgetInsertProc(Tk_Canvas canvas, Tk_Item* item, int index, char* string)
+{
+ WIDGET(item).insertProc(index, string);
+}
+
+void WidgetDCharsProc(Tk_Canvas canvas, Tk_Item* item, int first, int last)
+{
+ WIDGET(item).dcharsProc(first, last);
+}
+
+int WidgetParse(ClientData widget, Tcl_Interp* interp, int argc,
+ const char** argv)
+{
+ int result;
+ Tcl_Preserve(widget);
+
+ if (argc >= 2 && !strncmp(argv[1],"config",6))
+ result = ((Widget*)widget)->configCmd(argc-2, argv+2);
+
+ else {
+ istringstream istr(ios::in|ios::out);
+ ostream ostr(istr.rdbuf());
+
+ for (int i=1; i<argc; i++)
+ ostr << argv[i] << " ";
+ ostr << ends;
+
+ result = ((Widget*)widget)->parse(istr);
+ }
+
+ Tcl_Release(widget);
+ return result;
+}
+
+// Member Functions
+
+Widget::Widget(Tcl_Interp* interp_, Tk_Canvas canvas_, Tk_Item* item) :
+ interp(interp_), canvas(canvas_)
+{
+ // initialize item ptr to this. This is the method the canvas widget procs
+ // know how to call member functions.
+ ((WidgetOptions*)item)->widget = this;
+
+ // init members
+ options = (WidgetOptions*)item;
+ configSpecs = NULL;
+ tkwin = Tk_CanvasTkwin(canvas);
+ display = Tk_Display(tkwin);
+ screenNumber = Tk_ScreenNumber(tkwin);
+ visual = Tk_Visual(tkwin);
+ depth = Tk_Depth(tkwin);
+
+ pixmap = 0;
+ widgetGC = NULL;
+ visible = True;
+
+ originX = 0;
+ originY = 0;
+
+ // this is needed because of a problem with Tk_ConfigureWidget
+ options->cmdName = NULL;
+ options->helvetica = NULL;
+ options->courier = NULL;
+ options->times = NULL;
+
+ cmd = NULL;
+ result = TCL_OK;
+
+ // postscript
+ psLevel = 2;
+ psResolution = 300;
+ psColorSpace = RGB;
+}
+
+Widget::~Widget()
+{
+ // free the options
+ Tk_FreeOptions(configSpecs, (char*)this->options, display, 0);
+
+ // clean up tcl command
+ if (cmd) {
+ Tcl_DeleteCommand(interp, cmd);
+ delete [] cmd;
+ }
+
+ // clean up pixmap resources
+ if (pixmap)
+ Tk_FreePixmap(display, pixmap);
+
+ if (widgetGC)
+ XFreeGC(display, widgetGC);
+}
+
+void Widget::error(const char* m)
+{
+ Tcl_AppendResult(interp, m, NULL);
+ result = TCL_ERROR;
+}
+
+void Widget::msg(const char* m)
+{
+ Tcl_AppendResult(interp, m, NULL);
+}
+
+int Widget::configure(int argc, const char** argv, int flags)
+{
+ if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, argv,
+ (char*)this->options, flags) != TCL_OK)
+ return TCL_ERROR;
+
+ if (flags != TK_CONFIG_ARGV_ONLY) {
+ // create command
+ createCommand();
+ updateBBox();
+ invalidPixmap();
+ }
+ else {
+ // configure command
+ if (configSpecs[CONFIGCOMMAND].specFlags & TK_CONFIG_OPTION_SPECIFIED)
+ createCommand();
+
+ if ((configSpecs[CONFIGX].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGY].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGWIDTH].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGHEIGHT].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGANCHOR].specFlags & TK_CONFIG_OPTION_SPECIFIED))
+ updateBBox();
+
+ if ((configSpecs[CONFIGWIDTH].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGHEIGHT].specFlags & TK_CONFIG_OPTION_SPECIFIED))
+ invalidPixmap();
+
+ if ((configSpecs[CONFIGX].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGY].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGWIDTH].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGHEIGHT].specFlags & TK_CONFIG_OPTION_SPECIFIED) ||
+ (configSpecs[CONFIGANCHOR].specFlags & TK_CONFIG_OPTION_SPECIFIED))
+ redraw();
+ }
+
+ return TCL_OK;
+}
+
+// Required Canvas Functions
+
+int Widget::coordProc(int argc, char** argv)
+{
+ char xStr[TCL_DOUBLE_SPACE], yStr[TCL_DOUBLE_SPACE];
+
+ switch (argc) {
+
+ // print the current values
+ case 0:
+ Tcl_PrintDouble(interp, options->x, xStr);
+ Tcl_PrintDouble(interp, options->y, yStr);
+ Tcl_AppendResult(interp, xStr, " ", yStr, NULL);
+ return TCL_OK;
+
+ // set current x&y to new values
+ case 2: {
+ double x0, y0;
+ if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &x0) != TCL_OK) ||
+ (Tk_CanvasGetCoord(interp, canvas, argv[1], &y0) != TCL_OK))
+ return TCL_ERROR;
+ options->x = (int)x0;
+ options->y = (int)y0;
+ updateBBox();
+ return TCL_OK;
+ }
+
+ // else, error message
+ default:
+ Tcl_AppendResult(interp, "wrong # coordinates: expected 0 or 2", NULL);
+ return TCL_ERROR;
+ }
+}
+
+// Widget Display Procedure. It takes the contents of the pixmap and
+// after clipping, copies it into the drawable.
+
+void Widget::displayProc(Drawable draw, int clipX, int clipY,
+ int clipWidth, int clipHeight)
+{
+ if (visible == False)
+ return;
+
+ // create bbox
+ BBox bb(clipX, clipY, clipX+clipWidth, clipY+clipHeight);
+
+ // update the pixmap from ximage/graphics
+ if (updatePixmap(bb) != TCL_OK)
+ return; // something is wrong, bail out
+
+ // define pixmap clip region
+ // NOTE: it appears that the canvas coord system is 1 to n, width/height = n
+ // with the original of value 1,1 located at upper left corner
+ int pmX, pmY, pmWidth, pmHeight;
+
+ if (clipX > options->item.x1) {
+ pmX = clipX - options->item.x1;
+ pmWidth = options->item.x2 - clipX;
+ }
+ else {
+ pmX = 0;
+ if ((clipX + clipWidth) < options->item.x2)
+ pmWidth = clipX + clipWidth - options->item.x1;
+ else
+ pmWidth = options->item.x2 - options->item.x1;
+ }
+
+ if (clipY > options->item.y1) {
+ pmY = clipY - options->item.y1;
+ pmHeight = options->item.y2 - clipY;
+ }
+ else {
+ pmY = 0;
+ if ((clipY + clipHeight) < options->item.y2)
+ pmHeight = clipY + clipHeight - options->item.y1;
+ else
+ pmHeight = options->item.y2 - options->item.y1;
+ }
+
+ // convert to canvas coords
+ short drawX, drawY;
+ Tk_CanvasDrawableCoords(canvas, (double)(options->item.x1 + pmX),
+ (double)(options->item.y1 + pmY), &drawX, &drawY);
+
+ // just in case
+ if (!widgetGC)
+ widgetGC = XCreateGC(display, Tk_WindowId(tkwin), 0, NULL);
+
+ // set the clip region and copy the pixmap into the drawable
+ XSetClipOrigin(display, widgetGC, drawX - pmX, drawY - pmY);
+ XCopyArea(display, pixmap, draw, widgetGC, pmX, pmY, (unsigned int) pmWidth,
+ (unsigned int) pmHeight, drawX, drawY);
+}
+
+double Widget::pointProc(double* point)
+{
+ double xdiff, ydiff;
+
+ if (point[0] < options->item.x1)
+ xdiff = options->item.x1 - point[0];
+ else if (point[0] > options->item.x2)
+ xdiff = point[0] - options->item.x2;
+ else
+ xdiff = 0;
+
+ if (point[1] < options->item.y1)
+ ydiff = options->item.y1 - point[1];
+ else if (point[1] > options->item.y2)
+ ydiff = point[1] - options->item.y2;
+ else
+ ydiff = 0;
+
+ return hypot(xdiff, ydiff);
+}
+
+int Widget::areaProc(double* bbox)
+{
+ if ((bbox[2] <= options->item.x1) || (bbox[0] >= options->item.x2) ||
+ (bbox[3] <= options->item.y1) || (bbox[1] >= options->item.y2))
+ return -1; // item is outside bbox
+
+ if ((bbox[0] <= options->item.x1) && (bbox[1] <= options->item.y1) &&
+ (bbox[2] >= options->item.x2) && (bbox[3] >= options->item.y2))
+ return 1; // item is inside bbox
+
+ return 0; // item overlaps bbox
+}
+
+int Widget::postscriptProc(int prepass)
+{
+ return TCL_OK;
+}
+
+void Widget::scaleProc(double Ox, double Oy, double Sx, double Sy)
+{
+ // translate to (Ox,Oy), scale by (Sx,Sy), translate back from (Ox,Oy)
+ options->x = (int)(Ox + (Sx * (options->x - Ox)));
+ options->y = (int)(Oy + (Sy * (options->y - Oy)));
+ options->width = (int)(options->width * Sx);
+ options->height = (int)(options->height * Sy);
+
+ updateBBox();
+ invalidPixmap(); // width and height have changed
+}
+
+void Widget::translateProc(double deltaX, double deltaY)
+{
+ options->x += (int)deltaX;
+ options->y += (int)deltaY;
+
+ updateBBox();
+}
+
+// Subcommand Functions
+
+int Widget::configCmd(int argc, const char** argv)
+{
+ switch (argc) {
+ case 0:
+ return Tk_ConfigureInfo(interp, tkwin, configSpecs, (char*)this->options, NULL, 0);
+ case 1:
+ return Tk_ConfigureInfo(interp, tkwin, configSpecs,
+ (char*)this->options, argv[0],0);
+ default:
+ return configure(argc, argv, TK_CONFIG_ARGV_ONLY);
+ }
+}
+
+void Widget::getHeightCmd()
+{
+ ostringstream str;
+ str << options->height << ends;
+ Tcl_AppendResult(interp, str.str().c_str(), NULL);
+}
+
+void Widget::getWidthCmd()
+{
+ ostringstream str;
+ str << options->width << ends;
+ Tcl_AppendResult(interp, str.str().c_str(), NULL);
+}
+
+void Widget::hideCmd()
+{
+ visible = False;
+ redraw();
+}
+
+void Widget::queryCursorCmd()
+{
+ Window root, child;
+ int rootx,rooty,winx,winy;
+ unsigned int msk;
+ XQueryPointer(display,Tk_WindowId(tkwin),&root,&child,
+ &rootx,&rooty,&winx,&winy,&msk);
+
+#ifdef MAC_OSX_TK
+ // XQueryPointer: Only a partial implementation
+ // only rootx,rooty are valid
+ int xx,yy;
+ Tk_GetRootCoords(tkwin,&xx,&yy);
+ winx = rootx-xx;
+ winy = rooty-yy;
+#endif
+
+#ifdef _WIN32
+ winx = rootx;
+ winy = rooty;
+#endif
+
+ ostringstream str;
+ str << winx << ' ' << winy << ends;
+ Tcl_AppendResult(interp, str.str().c_str(), NULL);
+}
+
+void Widget::resetCmd()
+{
+ reset();
+ invalidPixmap();
+ redraw();
+}
+
+void Widget::showCmd()
+{
+ visible = True;
+ redraw();
+}
+
+// Private Member Functions
+
+void Widget::createCommand()
+{
+ if (cmd) {
+ Tcl_DeleteCommand(interp, cmd);
+ if (cmd)
+ delete [] cmd;
+ }
+
+ cmd = new char[strlen(options->cmdName)+1];
+ strcpy(cmd, options->cmdName);
+ Tcl_CreateCommand(interp, cmd, WidgetParse, (ClientData)this, NULL);
+}
+
+int Widget::checkArgs(int should, int argc, char** argv)
+{
+ // if should is negative, don't check
+ if (should >= 0) {
+ if (should != argc) {
+ ostringstream str;
+ str << should << '\0';
+ Tcl_AppendResult(interp, "wrong # args: requires ", str.str().c_str(),
+ " args.", NULL);
+ return TCL_ERROR;
+ }
+ else
+ return TCL_OK;
+ }
+
+ return TCL_OK;
+}
+
+double Widget::getDisplayRatio()
+{
+#ifdef MAC_OSX_TK
+ return 1.416;
+#else
+ return 25.4/72 *
+ DisplayWidth(display, screenNumber) /
+ DisplayWidthMM(display, screenNumber);
+#endif
+}
+
+void Widget::invalidPixmap()
+{
+ if (pixmap)
+ Tk_FreePixmap(display, pixmap);
+ pixmap = 0;
+}
+
+void Widget::redraw()
+{
+ Tk_CanvasEventuallyRedraw(canvas, options->item.x1, options->item.y1,
+ options->item.x2, options->item.y2);
+}
+
+void Widget::redraw(BBox bb)
+{
+ // bb in canvas coords
+ // we need to expand by 1, i don't know why
+ Tk_CanvasEventuallyRedraw(canvas, (int)bb.ll[0], (int)bb.ll[1],
+ (int)bb.ur[0]+1, (int)bb.ur[1]+1);
+}
+
+void Widget::redrawNow()
+{
+ Tk_CanvasEventuallyRedraw(canvas, options->item.x1, options->item.y1,
+ options->item.x2, options->item.y2);
+ Tcl_DoOneEvent(TCL_IDLE_EVENTS);
+}
+
+void Widget::redrawNow(BBox bb)
+{
+ // bb in canvas coords
+ // we need to expand by 1, i don't know why
+ Tk_CanvasEventuallyRedraw(canvas, (int)bb.ll[0], (int)bb.ll[1],
+ (int)bb.ur[0]+1, (int)bb.ur[1]+1);
+ Tcl_DoOneEvent(TCL_IDLE_EVENTS);
+}
+
+void Widget::forceUpdate()
+{
+ Tcl_DoOneEvent(TCL_IDLE_EVENTS);
+}
+
+// Update Bounding Box. For image at (n,n) with size (m,m),
+// bbox is defined from (n,n) to (n+m,n+m)
+
+void Widget::updateBBox()
+{
+ originX = options->x;
+ originY = options->y;
+
+ int& ww = options->width;
+ int& hh = options->height;
+
+ // Modify position point using anchor information.
+ switch (options->anchor) {
+ case TK_ANCHOR_N:
+ originX -= ww/2;
+ break;
+ case TK_ANCHOR_NE:
+ originX -= ww;
+ break;
+ case TK_ANCHOR_E:
+ originX -= ww;
+ originY -= hh/2;
+ break;
+ case TK_ANCHOR_SE:
+ originX -= ww;
+ originY -= hh;
+ break;
+ case TK_ANCHOR_S:
+ originX -= ww/2;
+ originY -= hh;
+ break;
+ case TK_ANCHOR_SW:
+ originY -= hh;
+ break;
+ case TK_ANCHOR_W:
+ originY -= hh/2;
+ break;
+ case TK_ANCHOR_NW:
+ break;
+ case TK_ANCHOR_CENTER:
+ originX -= ww/2;
+ originY -= hh/2;
+ break;
+ }
+
+ // Update item item
+ options->item.x1 = originX;
+ options->item.y1 = originY;
+ options->item.x2 = originX + options->width;
+ options->item.y2 = originY + options->height;
+}
+
+int Widget::getColor(const char* str)
+{
+ XColor* cc= NULL;
+ // starting with tk8.6, colors are W3C based, not X11
+ if (!strncmp(str,"green",5) || !strncmp(str,"GREEN",5))
+ cc = Tk_GetColor(interp, tkwin, "lime");
+ else
+ cc = Tk_GetColor(interp, tkwin, str);
+
+ return cc ? cc->pixel : 0;
+}
+
+XColor* Widget::getXColor(const char* str)
+{
+ // note: Tk_GetColor can return an XColor without valid red,green,blue
+ // if common colorname is used. (uses XAllocNamedColor).
+ // force an hash string instead (uses XAllocColor).
+
+ XColor* cc=NULL;
+ if (!strncmp(str,"white",5))
+ cc = Tk_GetColor(interp, tkwin, "#ffffff");
+ else if (!strncmp(str,"black",5))
+ cc = Tk_GetColor(interp, tkwin, "#000000");
+ else if (!strncmp(str,"red",3))
+ cc = Tk_GetColor(interp, tkwin, "#ff0000");
+ else if (!strncmp(str,"green",5))
+ cc = Tk_GetColor(interp, tkwin, "#00ff00");
+ else if (!strncmp(str,"blue",4))
+ cc = Tk_GetColor(interp, tkwin, "#0000ff");
+ else if (!strncmp(str,"cyan",4))
+ cc = Tk_GetColor(interp, tkwin, "#00ffff");
+ else if (!strncmp(str,"magenta",7))
+ cc = Tk_GetColor(interp, tkwin, "#ff00ff");
+ else if (!strncmp(str,"yellow",6))
+ cc = Tk_GetColor(interp, tkwin, "#ffff00");
+ else
+ cc = Tk_GetColor(interp, tkwin, str);
+
+ return cc ? cc : Tk_GetColor(interp, tkwin, "white");
+}
+
+void Widget::warp(Vector& vv)
+{
+#if !(_WIN32 || MAC_OSX_TK)
+ XWarpPointer(display, None, None, 0, 0, 0, 0, vv[0], vv[1]);
+#endif
+
+#ifdef MAC_OSX_TK
+ XXWarpPointer(display, None, None, 0, 0, 0, 0, vv[0], vv[1]);
+#endif
+
+#ifdef _WIN32
+ Window root, child;
+ int rootx,rooty,winx,winy;
+ unsigned int msk;
+ XQueryPointer(display,Tk_WindowId(tkwin),&root,&child,
+ &rootx,&rooty,&winx,&winy,&msk);
+ XWarpPointer(display, None, Tk_WindowId(tkwin), 0, 0, 0, 0,
+ winx+vv[0], winy+vv[1]);
+#endif
+}
+
+void Widget::warpTo(Vector& vv)
+{
+#if !(MAC_OSX_TK)
+ XWarpPointer(display, None, Tk_WindowId(tkwin), 0, 0, 0, 0, vv[0], vv[1]);
+#endif
+
+#ifdef MAC_OSX_TK
+ XXWarpPointer(display, None, Tk_WindowId(tkwin), 0, 0, 0, 0, vv[0], vv[1]);
+#endif
+}
+
+void Widget::psHead1(ostream& str, int width, int height)
+{
+ switch (psColorSpace) {
+ case BW:
+ case GRAY:
+ str << "/picstr " << dec << width << " string def" << endl
+ << width << ' ' << height << " 8 matrix" << endl
+ << "{currentfile picstr readhexstring pop}" << endl
+ << "image" << endl;
+ break;
+ case RGB:
+ case CMYK:
+ str << "/picstr " << dec << width*3 << " string def" << endl
+ << width << ' ' << height << " 8 matrix" << endl
+ << "{currentfile picstr readhexstring pop}" << endl
+ << "false 3 colorimage" << endl;
+ break;
+ }
+}
+
+void Widget::psHead2(ostream& str, int width, int height, const char* compress,
+ const char* decode)
+{
+ switch (psColorSpace) {
+ case BW:
+ case GRAY:
+ str << "/DeviceGray setcolorspace" << endl;
+ break;
+ case RGB:
+ str << "/DeviceRGB setcolorspace" << endl;
+ break;
+ case CMYK:
+ str << "/DeviceCMYK setcolorspace" << endl;
+ break;
+ }
+
+ str << "<<" << endl
+ << "/ImageType 1" << endl
+ << "/Width " << dec << width << endl
+ << "/Height " << dec << height << endl
+ << "/BitsPerComponent 8" << endl;
+
+ switch (psColorSpace) {
+ case BW:
+ case GRAY:
+ str << "/Decode [0 1]" << endl;
+ break;
+ case RGB:
+ str << "/Decode [0 1 0 1 0 1]" << endl;
+ break;
+ case CMYK:
+ str << "/Decode [0 1 0 1 0 1 0 1]" << endl;
+ break;
+ }
+
+ str << "/ImageMatrix matrix" << endl
+ << "/DataSource currentfile" << endl;
+
+ if (decode)
+ str << "/" << decode << "Decode filter" << endl;
+
+ if (compress)
+ str << "/" << compress << "Decode filter" << endl;
+
+ str << ">>" << endl
+ << "image" << endl;
+}
+
+// compute coordinates of lower-left corner of the image
+// taking into account the anchor position for the image.
+// this mapping is different than in widget.c, due to postscript origin
+// (y is flipped)
+
+Vector Widget::psOrigin()
+{
+ double xx = options->x;
+ double yy = Tk_CanvasPsY(canvas, options->y);
+
+ double ww = options->width;
+ double hh = options->height;
+
+ switch (options->anchor) {
+ case TK_ANCHOR_N:
+ xx -= ww/2;
+ yy -= hh;
+ break;
+ case TK_ANCHOR_NE:
+ xx -= ww;
+ yy -= hh;
+ break;
+ case TK_ANCHOR_E:
+ xx -= ww;
+ yy -= hh/2;
+ break;
+ case TK_ANCHOR_SE:
+ xx -= ww;
+ break;
+ case TK_ANCHOR_S:
+ xx -= ww/2;
+ break;
+ case TK_ANCHOR_SW:
+ break;
+ case TK_ANCHOR_W:
+ yy -= hh/2;
+ break;
+ case TK_ANCHOR_NW:
+ yy -= hh;
+ break;
+ case TK_ANCHOR_CENTER:
+ xx -= ww/2;
+ yy -= hh/2;
+ break;
+ }
+
+ return Vector(xx,yy);
+}
+
+// this routine attemps a work around for a problems with level 2 postscript
+// and other software such as dvips and assemble
+
+/*
+void Widget::psFix(ostringstream& ostr)
+{
+ string str = ostr.str();
+ const char* buf = str.c_str();
+ int size = str.length();
+ char* a = (char*)buf;
+
+ while (*a && a<buf+size) {
+ // dvips version 5.55. Basically, we can't have %% at the start of a line
+ if (*a=='\n' && *(a+1)=='%' && *(a+2)=='%') {
+ // reverse the order so that we don't have a %% at the begining of a line
+ *a++ = '%';
+ *a++ = '%';
+ *a++ = '\n';
+ }
+
+ // no one uses this anymore
+ // assemble. Basically, we can't have % at the start of a line
+ else if (*a=='\n' && *(a+1)=='%') {
+ // reverse the order so that we don't have a % at the begining of a line
+ *a++ = '%';
+ *a++ = '\n';
+ }
+
+ a++;
+ }
+
+ ostr.str(str);
+}
+*/
diff --git a/tksao/widget/widget.h b/tksao/widget/widget.h
new file mode 100644
index 0000000..af06e4b
--- /dev/null
+++ b/tksao/widget/widget.h
@@ -0,0 +1,203 @@
+// Copyright (C) 1999-2016
+// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+// For conditions of distribution and use, see copyright notice in "copyright"
+
+#ifndef __widget_h__
+#define __widget_h__
+
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <float.h>
+#include <math.h>
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+using namespace std;
+
+#include <tcl.h>
+#include <tk.h>
+
+#include "vector.h"
+
+class Attribute;
+
+extern float psScale;
+
+// General Defines
+
+#define WIDGET(x) (*(((WidgetOptions*)(x))->widget))
+
+// Widget ConfigSpecs Defines
+
+#define CONFIGX 1
+#define CONFIGY 2
+#define CONFIGWIDTH 3
+#define CONFIGHEIGHT 4
+#define CONFIGANCHOR 5
+#define CONFIGCOMMAND 6
+#define CONFIGHELVETICA 7
+#define CONFIGCOURIER 8
+#define CONFIGTIMES 9
+
+// Tk Canvas Widget Function Declarations
+
+extern int WidgetConfigProc(Tcl_Interp*, Tk_Canvas, Tk_Item*, int,
+ Tcl_Obj *const [],int);
+extern int WidgetCoordProc(Tcl_Interp*, Tk_Canvas, Tk_Item*, int, Tcl_Obj *const []);
+extern void WidgetDeleteProc(Tk_Canvas, Tk_Item*, Display*);
+extern void WidgetDisplayProc(Tk_Canvas, Tk_Item*, Display*, Drawable,
+ int, int, int, int);
+extern double WidgetPointProc(Tk_Canvas, Tk_Item*, double*);
+extern int WidgetAreaProc(Tk_Canvas, Tk_Item*, double*);
+extern int WidgetPostscriptProc(Tcl_Interp*, Tk_Canvas, Tk_Item*, int);
+extern void WidgetScaleProc(Tk_Canvas, Tk_Item*, double, double,
+ double, double);
+extern void WidgetTranslateProc(Tk_Canvas, Tk_Item*, double, double);
+extern int WidgetIndexProc(Tcl_Interp*, Tk_Canvas, Tk_Item*, char, int*);
+extern void WidgetICursorProc(Tk_Canvas, Tk_Item*, int);
+extern int WidgetSelectionProc(Tk_Canvas, Tk_Item*, int, char*, int);
+extern void WidgetInsertProc(Tk_Canvas, Tk_Item*, int, char*);
+extern void WidgetDCharsProc(Tk_Canvas, Tk_Item*, int, int);
+
+extern int WidgetParse(ClientData, Tcl_Interp*, int, char**);
+
+class Widget;
+
+// this structure is returned by each Canvas Function Proc
+
+struct WidgetOptions {
+ Tk_Item item; // required by tk
+ int x, y; // Coordinates of positioning point on canvas
+ int width; // widget width
+ int height; // widget height
+ Tk_Anchor anchor; // Where to anchor widget relative to x,y
+ char* cmdName; // Suggested Tcl command name
+
+ char* helvetica; // name of X11 font
+ char* courier; // name of X11 font
+ char* times; // name of X11 font
+
+ Widget* widget; // pointer to widget class
+};
+
+// Widget Class
+
+class Widget {
+ friend class Attribute;
+
+ public:
+ enum PSColorSpace {BW, GRAY, RGB, CMYK};
+ Tcl_Interp* interp; // Tcl interp
+
+ protected:
+ WidgetOptions* options; // Pointer to Tk Options
+ Tk_ConfigSpec* configSpecs; // configure specs
+ Tk_Canvas canvas; // handle to canvas
+ Tk_Window tkwin; // Tk window id
+
+ Display* display; // display of canvas
+ Visual* visual; // visual of canvas
+ int depth; // depth of canvas
+ int screenNumber; // screen number of canvas
+
+ Pixmap pixmap; // size of canvas item
+ GC widgetGC; // gc for pixmap XCopyArea
+ int visible; // redraw when true
+
+ int originX; // widget upper left origin
+ int originY; // widget upper left origin
+
+ char* cmd; // actual command name used
+ int result; // result of TCL command
+
+ int psResolution; // postscript resolution
+ int psLevel; // postscript level
+ PSColorSpace psColorSpace; // postscript color space
+
+ protected:
+ virtual int updatePixmap(const BBox&) =0; // render into pixmap
+ virtual void invalidPixmap(); // pixmap is invalid
+ virtual void reset() {}; // reset widget
+
+ void createCommand(); // create tcl command
+ void updateBBox(); // update item bounding box
+
+ int checkArgs(int, int, char**); // check args utility
+
+ void psHead1(ostream&, int, int);
+ void psHead2(ostream&, int, int, const char*, const char*);
+ Vector psOrigin();
+ // void psFix(ostringstream& ostr);
+
+ public:
+ Widget(Tcl_Interp*, Tk_Canvas, Tk_Item*);
+ virtual ~Widget();
+
+ Tcl_Interp* getInterp() {return interp;}
+
+ void redraw(); // ping tk to redraw this widget
+ void redraw(BBox); // ping tk to redraw this bbox
+ void redrawNow(); // force update now this widget
+ void redrawNow(BBox); // force update now this bbox
+ void forceUpdate(); // only force update
+
+ virtual int parse(istringstream&) =0; // parse subcommands
+
+ virtual int configure(int, const char**, int); // parse config options
+ void error(const char*); // parse error function
+ void msg(const char*); // parse msg function
+
+ Tk_Window getTkwin() {return tkwin;}
+ Display* getDisplay() {return display;}
+ double getDisplayRatio();
+ Visual* getVisual() {return visual;}
+ int getWidth() {return options->width;}
+ int getHeight() {return options->height;}
+ int getDepth() {return depth;}
+ int getScreenNumber() {return screenNumber;}
+ Tk_Canvas getCanvas() {return canvas;}
+
+ int getColor(const char* str);
+ XColor* getXColor(const char*);
+
+ void warp(Vector&);
+ void warpTo(Vector&);
+
+ // Required Canvas Functions
+ int coordProc(int, char**);
+ void displayProc(Drawable, int, int, int, int);
+ double pointProc(double*);
+ int areaProc(double*);
+ virtual int postscriptProc(int);
+ void scaleProc(double, double, double, double);
+ void translateProc(double, double);
+ virtual int indexProc(char indexString, int* indexPtr) {return TCL_OK;}
+ virtual void icursorProc(int index) {}
+ virtual int selectionProc(int offset, char* buffer, int maxBytes)
+ {return maxBytes;}
+ virtual void insertProc(int index, char* string) {}
+ virtual void dcharsProc(int first, int last) {}
+
+ // Subcommand Functions
+ int configCmd(int, const char**); // configure command
+ void getHeightCmd(); // return height of widget
+ void getWidthCmd(); // return width of widget
+ void hideCmd(); // hide item command
+ void queryCursorCmd(); // get cursor coords
+ void resetCmd(); // reset item command
+ void showCmd(); // show item command
+
+ // Postscript Commands
+ void psLevelCmd(int l) {psLevel = l;}
+ void psResolutionCmd(int r) {psResolution = r;}
+ void psColorSpaceCmd(PSColorSpace c) {psColorSpace = c;}
+
+#ifdef MAC_OSX_TK
+ virtual void macsosxPrintCmd() {}
+#endif
+};
+
+#endif
+