[rlplot] 03/23: Imported Upstream version 1.0
Andreas Tille
tille at debian.org
Wed Jun 29 09:50:54 UTC 2016
This is an automated email from the git hooks/post-receive script.
tille pushed a commit to branch master
in repository rlplot.
commit b7e8971c25f8988042da0b93106bf4f84a0a41fa
Author: Andreas Tille <tille at debian.org>
Date: Wed Jun 29 11:43:54 2016 +0200
Imported Upstream version 1.0
---
Axes.cpp | 49 +-
Export.cpp | 27 +-
Fileio.cpp | 296 ++++++++---
ODbuttons.cpp | 157 ++++--
PlotObs.cpp | 1228 +++++++++++++++++++++++++++++++++----------
PropertyDlg.cpp | 1260 ++++++++++++++++++++++++++++++--------------
QT_Spec.cpp | 585 +++++++++++++++------
QT_Spec.h | 5 +
RLPLOT.ICO | Bin 766 -> 4286 bytes
RLPLOT.RC | 79 +--
RLPlot-Icons.zip | Bin 0 -> 38437 bytes
RLPlot.bmp | Bin 630 -> 3126 bytes
RLPlot.xpm | 254 +++++++--
TheDialog.cpp | 280 +++++-----
TheDialog.h | 19 +-
UtilObj.cpp | 613 ++++++++++++++-------
Utils.cpp | 79 +++
Version.h | 3 +-
WinSpec.cpp | 154 ++++--
WinSpec.h | 1 +
exprlp.cpp | 47 +-
mfcalc.cpp | 1548 ++++++++++++++++++++++++++++++++++++++++--------------
mfcalc.y | 1077 +++++++++++++++++++++++++++++--------
rlp_math.cpp | 516 +++++++++++++++++-
rlplot.cpp | 406 ++++++++++----
rlplot.h | 244 ++++++---
rlplot.spec | 6 +-
spreadwi.cpp | 1092 ++++++++++++++++++++++++++++----------
28 files changed, 7503 insertions(+), 2522 deletions(-)
diff --git a/Axes.cpp b/Axes.cpp
index 320ff5b..bc5a4a0 100755
--- a/Axes.cpp
+++ b/Axes.cpp
@@ -544,8 +544,14 @@ Tick::Command(int cmd, void *tmpl, anyOutput *o)
MouseEvent *mev;
TextDEF *LabelDef;
GraphObj **tmpPlots;
+ AxisDEF *axis;
switch(cmd){
+ case CMD_SET_AXDEF:
+ if(axis = (AxisDEF*)tmpl) {
+ flags = (flags & AXIS_MINORTICK) | axis->flags;
+ }
+ break;
case CMD_FLUSH:
if(Grid) DeleteGO(Grid); Grid = 0L;
if(label) DeleteGO(label); label = 0L;
@@ -620,11 +626,7 @@ Tick::Command(int cmd, void *tmpl, anyOutput *o)
case MOUSE_LBUP:
if(IsInRect(&rDims, mev->x, mev->y) && !CurrGO &&
IsCloseToLine(&pts[0], &pts[1], mev->x, mev->y)) {
- if(pts[0].x == pts[1].x || pts[0].y == pts[1].y) {
- o->ShowMark(&rDims, MRK_INVERT);
- CurrGO = this;
- }
- else o->ShowMark(this, MRK_GODRAW);
+ o->ShowMark(this, MRK_GODRAW);
return true;
}
break;
@@ -1262,11 +1264,7 @@ Axis::Command(int cmd, void *tmpl, anyOutput *o)
}
else if(IsInRect(&rDims, mev->x, mev->y) && !CurrGO &&
IsCloseToLine(&pts[0], &pts[1], mev->x, mev->y)) {
- if(pts[0].x == pts[1].x || pts[0].y == pts[1].y){
- o->ShowMark(&rDims, MRK_INVERT);
- CurrGO = this;
- }
- else o->ShowMark(this, MRK_GODRAW);
+ o->ShowMark(this, MRK_GODRAW);
return true;
}
break;
@@ -1276,14 +1274,25 @@ Axis::Command(int cmd, void *tmpl, anyOutput *o)
if(Ticks[i] && Ticks[i]->Command(cmd, tmpl, o)) return true;
return false;
case CMD_SET_AXDEF:
- if(tmpl) {
+ if(axis = (AxisDEF*)tmpl) {
if(axis && axis->owner == (void*)this) {
if(axis->breaks) free(axis->breaks);
free(axis);
}
+ if(Ticks) for(i = 0; i < NumTicks; i++)
+ if(Ticks[i]) {
+ Ticks[i]->Command(cmd, tmpl, o);
+ Ticks[i]->Command(CMD_SET_GRIDTYPE, (void*) &gl_type, 0L);
+ Ticks[i]->Command(CMD_TLB_TXTDEF, &tlbdef, 0L);
+ if(axis->flags & AXIS_GRIDLINE) Ticks[i]->Command(CMD_SET_GRIDLINE, &GridLine, 0L);
+ Ticks[i]->SetSize(SIZE_TICK_ANGLE, tick_angle);
+ Ticks[i]->SetSize(SIZE_AXIS_TICKS, sizAxTick);
+ Ticks[i]->SetSize(SIZE_LB_XDIST, tlbdist.fx);
+ Ticks[i]->SetSize(SIZE_LB_YDIST, tlbdist.fy);
+ Ticks[i]->Command(CMD_TICK_TYPE, &tick_type, 0L);
+ }
+ return true;
}
- axis = (AxisDEF*)tmpl;
- if(axis) return true;
return false;
case CMD_CAN_DELETE:
if(axis->owner == (void*)this) return true;
@@ -1297,18 +1306,16 @@ Axis::Command(int cmd, void *tmpl, anyOutput *o)
case CMD_DELOBJ:
o->HideMark();
if(!tmpl || !parent) return false;
- if(Ticks && NumTicks) for(i = 0; i < NumTicks; i++){
- if(Ticks[i] == tmpl) {
- Undo.DeleteGO((GraphObj**)(&Ticks[i]), 0L, o);
- return parent->Command(CMD_REDRAW, 0L, o);
- }
- else if(Ticks[i] && Ticks[i]->Command(cmd, tmpl, o))
- return parent->Command(CMD_REDRAW, 0L, o);
- }
+ if(DeleteGOL((GraphObj***) &Ticks, NumTicks, (GraphObj *)tmpl, o))
+ return parent->Command(CMD_REDRAW, 0L, o);
if(tmpl == (void*)axisLabel) {
Undo.DeleteGO((GraphObj**)(&axisLabel), 0L, o);
return parent->Command(CMD_REDRAW, 0L, o);
}
+ if(Ticks && NumTicks) for(i = 0; i < NumTicks; i++){
+ if(Ticks[i] && Ticks[i]->Command(cmd, tmpl, o))
+ return parent->Command(CMD_REDRAW, 0L, o);
+ }
break;
case CMD_MUTATE:
if(!parent || !(tmpPlots = (GraphObj **)tmpl) || !tmpPlots[0] || !tmpPlots[1]) return false;
diff --git a/Export.cpp b/Export.cpp
index 4470367..7b4b7f5 100755
--- a/Export.cpp
+++ b/Export.cpp
@@ -799,14 +799,26 @@ ExportSVG::oSolidLine(POINT *p)
bool
ExportSVG::oTextOut(int x, int y, char *txt, int cb)
{
- int h, ix, iy;
+ int i, h, ix, iy;
char tmptxt[140], *nt;
- h = TxtSet.iSize;
+ if(!txt || !txt[0]) return false;
+ else h = TxtSet.iSize;
if(TxtSet.Align & TXA_VCENTER) iy = y + h/3;
else if(TxtSet.Align & TXA_VBOTTOM) iy = y;
- else iy = y + iround(h*.8f);
+ else iy = y + iround(h * 0.8);
ix = x;
+ if((TxtSet.Style & TXS_SUB) || (TxtSet.Style & TXS_SUPER)) h = iround((double)TxtSet.iSize * 0.8);
+ if(TxtSet.Style & TXS_SUB) {
+ if((TxtSet.Align & TXA_VCENTER) == TXA_VCENTER) iy +=un2iy(TxtSet.fSize*0.4);
+ else if((TxtSet.Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy += un2iy(TxtSet.fSize*0.2);
+ else if((TxtSet.Align & TXA_VTOP) == TXA_VTOP) iy += un2iy(TxtSet.fSize*.6);
+ }
+ else if(TxtSet.Style & TXS_SUPER) {
+ if((TxtSet.Align & TXA_VCENTER) == TXA_VCENTER) iy -= un2iy(TxtSet.fSize*0.4);
+ else if((TxtSet.Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy -= un2iy(TxtSet.fSize*0.6);
+ else if((TxtSet.Align & TXA_VTOP) == TXA_VTOP) iy -= un2iy(TxtSet.fSize*0.2);
+ }
sprintf(output, "<text x=\"%d\" y=\"%d\" ", ix, iy);
if(fabs(TxtSet.RotBL) >.01 || fabs(TxtSet.RotCHAR) >.01) {
sprintf(tmptxt,"transform=\"rotate(%.0f,%d,%d)\" ", -TxtSet.RotBL, ix, iy);
@@ -825,10 +837,17 @@ ExportSVG::oTextOut(int x, int y, char *txt, int cb)
sprintf(tmptxt, " fill:%s; stroke:%s; ", ColName(TxtSet.ColTxt),
ColName(TxtSet.ColTxt));
AddToOutput(tmptxt);
- sprintf(tmptxt, "font-size:%d; text-anchor:%s \">", TxtSet.iSize,
+ sprintf(tmptxt, "font-size:%d; text-anchor:%s \">", h,
(TxtSet.Align & TXA_HRIGHT) ? "end" : (TxtSet.Align & TXA_HCENTER) ? "middle":"start");
AddToOutput(tmptxt);
nt = str2xml(txt);
+ if((TxtSet.Style & TXS_SUB) || (TxtSet.Style & TXS_SUPER)) {
+ for(i = strlen(nt)+6, nt[i+1]=0; i > 5; i--) {
+ nt[i] = nt[i-6];
+ }
+ nt[0] = '&'; nt[1] = 'n'; nt[2] = 'b';
+ nt[3] = 's'; nt[4] = 'p'; nt[5] = ';';
+ }
if((strlen(indent)+strlen(nt)+strlen(output)) <110) strcat(output, nt);
else {
fprintf(oFile, "%s%s\n", indent, output);
diff --git a/Fileio.cpp b/Fileio.cpp
index 50c52e2..e022eb8 100755
--- a/Fileio.cpp
+++ b/Fileio.cpp
@@ -38,6 +38,7 @@ extern GraphObj *CurrGO; //Selected Graphic Objects
extern Default defs;
extern int dlgtxtheight;
extern char TmpTxt[];
+extern int cPlots;
static notary *Notary = 0L;
static ReadCache *Cache = 0L;
@@ -81,8 +82,14 @@ int OpenOutputFile(char *file)
if(!ptr) goto openerr;
ti = time(0L);
cbOut = sprintf(ptr,";RLP 1.0\n;File \"%s\" created by RLPlot version "
- ""SZ_VERSION"\n;Date/Time: %s",
- file, ctime(&ti));
+ ""SZ_VERSION" for %s \n;Date/Time: %s ",
+ file,
+#ifdef _WINDOWS
+ "Windows",
+#else
+ "Qt",
+#endif
+ ctime(&ti));
}
return iFile;
openerr:
@@ -194,6 +201,32 @@ void WriteTypFpLst3D(fPOINT3D *ptr, long count)
else if(n < count) c += sprintf(tmp+c, "\n");
AddStringToOutput(tmp, c);
}
+}
+
+static char * esc_str = 0L;
+static int esc_str_size = 0;
+int WriteEscString(char *txt, char *buff, int cb)
+{
+ int i, j, l, lim = 60;
+
+ if(!txt || !txt[0]) return 0;
+ l = strlen(txt);
+ if((l+10) > esc_str_size) esc_str = (char*)realloc(esc_str, esc_str_size = (l+10));
+ j = 0; esc_str[j++] = '"';
+ for(i = 0; txt[i]; i++) {
+ switch(txt[i]) {
+ case '\\': j += sprintf(esc_str+j, "\\\\"); break;
+ case '\n': j += sprintf(esc_str+j, "\\n"); break;
+ default: esc_str[j++] = txt[i];
+ }
+ if(j > esc_str_size -2) esc_str = (char*)realloc(esc_str, (esc_str_size += 20));
+ if(j > lim) {
+ j += sprintf(esc_str+j, "\"\n \"");
+ lim += 60;
+ }
+ }
+ j += sprintf(esc_str+j, "\"\n");
+ return sprintf(buff+cb, "%s", esc_str);
}
bool ExecOutput(long id, char *Class, descIO *Desc)
@@ -222,7 +255,7 @@ bool ExecOutput(long id, char *Class, descIO *Desc)
cb += sprintf(buff+cb," %d\n", *(int*)Desc[i].ptr);
break;
case typNZLFLOAT:
- if(*((double*)Desc[i].ptr) < 0.0001) {
+ if(fabs(*((double*)Desc[i].ptr)) < 1.0e-7) {
cb = last;
break;
}
@@ -351,7 +384,7 @@ bool ExecOutput(long id, char *Class, descIO *Desc)
break;
case typTEXT:
if(!*(char**)(Desc[i].ptr)) cb = last;
- else cb += sprintf(buff+cb, "\"%s\"\n", *(char**)(Desc[i].ptr));
+ else cb += WriteEscString(*(char**)(Desc[i].ptr), buff, cb);
break;
case typTXTDEF:
case typPTRTXTDEF:
@@ -581,7 +614,8 @@ bool ExecInput(descIO *Desc)
if(!*(GraphObj***)(Desc[j].ptr)){
*(GraphObj***)(Desc[j].ptr) = (GraphObj**)calloc(il, sizeof(GraphObj*));
}
- if((gobs = *(GraphObj***)(Desc[j].ptr))){
+ if((gobs = *(GraphObj***)(Desc[j].ptr))){
+ i += 4;
while(tmp[i-1] != '{') i++; while(tmp[i-1] < 33) i++;
strcat(tmp, " ");
for( ;il >0; il--) {
@@ -641,7 +675,7 @@ bool ExecInput(descIO *Desc)
}
break;
case typTEXT:
- for(i = strlen(tmp); i > 0 &&(tmp[i-1] < 33 || (tmp[i-1] ==
+ for(i = strlen(tmp); i > 0 &&(tmp[i-1] < 32 || (tmp[i-1] ==
'"' && tmp[i-2] != '\\') || (tmp[i-1] == '\\' &&
(mlines = true))); tmp[--i] = 0);
for(i = 0; tmp[i] && (tmp[i] < 33 || tmp[i] == '"'); i++);
@@ -694,7 +728,8 @@ bool ExecInput(descIO *Desc)
bool SaveGraphAs(GraphObj *g)
{
char *name = 0L;
- int i;
+ int i;
+ bool bRet = true;
if(Notary || !g) {
ErrorBox("Output pending or\nno graph.");
@@ -722,9 +757,10 @@ bool SaveGraphAs(GraphObj *g)
}
else ErrorBox("Open failed for\noutput file.");
CloseOutputFile();
- }
+ }
+ else bRet = false;
if(Notary) delete Notary; Notary = 0L;
- return true;
+ return bRet;
}
char *GraphToMem(GraphObj *g, long *size)
@@ -821,10 +857,10 @@ bool OpenGraph(GraphObj *root, char *name, unsigned char *mem)
hv = HashValue(tmp);
switch(hv) {
case 3895: go = new Axis(FILE_READ); break;
- case 886: go = new Bar(FILE_READ); break;
+ case 7496002: go = new Bar(FILE_READ); break;
case 81384: go = new Symbol(FILE_READ); break;
case 62229: go = new Bubble(FILE_READ); break;
- case 948: go = new Box(FILE_READ); break;
+ case 7892802: go = new Box(FILE_READ); break;
case 15411: go = new Arrow(FILE_READ); break;
case 1052406: go = new ErrorBar(FILE_READ); break;
case 324566: go = new Whisker(FILE_READ); break;
@@ -845,6 +881,7 @@ bool OpenGraph(GraphObj *root, char *name, unsigned char *mem)
case 386257: go = new ellipse(FILE_READ); break;
case 95680: go = new mLabel(FILE_READ); break;
case 4819316: go = new PlotScatt(FILE_READ); break;
+ case 117848: go = new xyStat(FILE_READ); break;
case 15935312: go = new BubblePlot(FILE_READ); break;
case 247376: go = new BoxPlot(FILE_READ); break;
case 317384: go = new StackBar(FILE_READ); break;
@@ -873,7 +910,8 @@ bool OpenGraph(GraphObj *root, char *name, unsigned char *mem)
case 1053744: go = new FreqDist(FILE_READ); break;
case 68748: go = new Legend(FILE_READ); break;
case 66800: go = new Grid3D(FILE_READ); break;
- case 967843: go = new DefsRW(FILE_READ); break;
+ case 967843: go = new DefsRW(FILE_READ); break;
+ case 66848: go = new Func3D(FILE_READ); break;
default:
sprintf(debug, "Object %ld in file\n(Class = \"%s\")\nhash #%d\nis unknown.",
id, tmp, hv);
@@ -891,6 +929,7 @@ bool OpenGraph(GraphObj *root, char *name, unsigned char *mem)
Cache->Close();
if((go = Notary->PopGO(lid))) {
go->Command(CMD_SET_DATAOBJ, 0L, 0L);
+ delete Notary; Notary = 0L;
if(root->Id == GO_PAGE) {
if(go->Id == GO_PAGE){
if(!(root->parent->Command(CMD_DROP_GRAPH,(void *)go, 0L))) DeleteGO(go);
@@ -902,10 +941,8 @@ bool OpenGraph(GraphObj *root, char *name, unsigned char *mem)
}
if(go) go->Command(CMD_FILENAME, name, 0L);
}
- delete Notary;
- Notary = 0L;
- delete Cache;
- Cache = 0L;
+ if(Notary) delete Notary; Notary = 0L;
+ delete Cache; Cache = 0L;
return true;
ReadErr:
@@ -1241,7 +1278,9 @@ Bar::FileIO(int rw)
if(BarFill.hatch) memcpy(&HatchLine, BarFill.hatch, sizeof(LineDEF));
BarFill.hatch = &HatchLine;
memcpy(&BarLine, defs.GetOutLine(), sizeof(LineDEF));
- size = parent ? parent->GetSize(SIZE_BAR): defs.GetSize(SIZE_BAR);
+ size = parent ? parent->GetSize(SIZE_BAR): defs.GetSize(SIZE_BAR);
+ mo = 0L;
+ mrc.left = mrc.right = mrc.top = mrc.bottom = 0;
return true;
case FILE_READ:
ExecInput(Desc);
@@ -1331,13 +1370,13 @@ DataLine::FileIO(int rw)
BgColor = defs.Color(COL_BG);
pts = 0L; dirty = true; mo = 0L;
mrc.left = mrc.right = mrc.top = mrc.bottom = 0;
- min.fx = min.fy = max.fx = max.fy = 0.0f;
+ min.fx = min.fy = max.fx = max.fy = 0.0;
return true;
case FILE_READ:
ExecInput(Desc);
nPnt = i;
nPntSet = i-1;
- if(file2)FileValues(file2, 1, 0.0f, 1.0f);
+ if(file2)FileValues(file2, 1, 0.0, 1.0);
else if(file1)FileValues(file1, 2, Start, fabs(Step) > defs.min4log ? Step : 1.0);
if(file1) free(file1);
if(file2) free(file2);
@@ -1776,6 +1815,7 @@ Line3D::FileIO(int rw)
{"ssRefX", typTEXT, &x_range, 0L},
{"ssRefY", typTEXT, &y_range, 0L},
{"ssRefZ", typTEXT, &z_range, 0L},
+ {"ssRef", typIPLST, &ssRef, &cssRef},
{"values", typLAST | typFPLST3D, &values, &nPts}};
switch(rw) {
@@ -1855,7 +1895,8 @@ mLabel::FileIO(int rw)
descIO Desc[] = {
{"moveable", typNZINT, &moveable, 0L},
{"Pos", typNZLFPOINT, &fPos, 0L},
- {"Dist", typNZLFPOINT, &fDist, 0L},
+ {"Dist", typNZLFPOINT, &fDist, 0L},
+ {"lspc", typLFLOAT, &lspc, 0L},
{"Flags", typDWORD, &flags, 0L},
{"TxtDef", typTXTDEF, &TextDef, 0L},
{"Lines", typLAST | typOBJLST, &Lines, &nLines}};
@@ -1878,7 +1919,7 @@ mLabel::FileIO(int rw)
TextDef.Style = TXS_NORMAL;
TextDef.Font = FONT_HELVETICA;
TextDef.text = 0L;
- undo_flags = 0L;
+ undo_flags = 0L; lspc = 1.0;
curr_z = 0.0; is3D = false;
return true;
case FILE_READ:
@@ -2115,7 +2156,8 @@ PlotScatt::RegGO(void *n)
bool
PlotScatt::FileIO(int rw)
{
- descIO Desc[] = {
+ descIO Desc[] = {
+ {"hide", typNZINT, &hidden, 0L},
{"Bounds", typFRECT, &Bounds, 0L},
{"DefSym", typNZINT, &DefSym, 0L},
{"baDist", typLFPOINT, &BarDist, 0L},
@@ -2163,6 +2205,51 @@ PlotScatt::FileIO(int rw)
return false;
}
+bool
+xyStat::FileIO(int rw)
+{
+ descIO Desc[] = {
+ {"Type", typNZINT, &type, 0L},
+ {"hide", typNZINT, &hidden, 0L},
+ {"Bounds", typFRECT, &Bounds, 0L},
+ {"DefSym", typNZINT, &DefSym, 0L},
+ {"baDist", typLFPOINT, &BarDist, 0L},
+ {"confi", typLFLOAT, &ci, 0L},
+ {"xRange", typTEXT, &xRange, 0L},
+ {"yRange", typTEXT, &yRange, 0L},
+ {"prefix", typTEXT, &case_prefix, 0L},
+ {"x_axis", typNZINT, &use_xaxis, 0L},
+ {"y_axis", typNZINT, &use_yaxis, 0L},
+ {"Bars", typOBJLST, &Bars, &nPoints},
+ {"Symbols", typOBJLST, &Symbols, &nPoints},
+ {"PL", typGOBJ, &TheLine, 0L},
+ {"ErrBars", typOBJLST, &Errors, &nPoints},
+ {"Labels", typLAST | typOBJLST, &Labels, &nPoints}};
+ int i;
+
+ switch(rw) {
+ case INIT_VARS:
+ //most initialistion is done by PlotScatt::FileIO
+ curr_data = 0L;
+ case_prefix = 0L;
+ ci = 95.0;
+ return true;
+ case FILE_READ:
+ nPoints = 0L;
+ ExecInput(Desc);
+ ForEach(FE_PARENT, 0L, 0L);
+ return true;
+ case FILE_WRITE:
+ if(TheLine) TheLine->FileIO(rw);
+ if(Symbols) for(i = 0; i < nPoints; i++) if(Symbols[i]) Symbols[i]->FileIO(rw);
+ if(Errors) for(i = 0; i < nPoints; i++) if(Errors[i]) Errors[i]->FileIO(rw);
+ if(Labels) for(i = 0; i < nPoints; i++) if(Labels[i]) Labels[i]->FileIO(rw);
+ if(Bars) for(i = 0; i < nPoints; i++) if(Bars[i]) Bars[i]->FileIO(rw);
+ return ExecOutput(Notary->RegisterGO(this), "xyStat", Desc);
+ }
+ return false;
+}
+
void
FreqDist::RegGO(void *n)
{
@@ -2179,6 +2266,7 @@ FreqDist::FileIO(int rw)
{
descIO Desc[] = {
{"Type", typNZINT, &type, 0L},
+ {"hide", typNZINT, &hidden, 0L},
{"ssRef", typTEXT, &ssRef, 0L},
{"x_axis", typNZINT, &use_xaxis, 0L},
{"y_axis", typNZINT, &use_yaxis, 0L},
@@ -2234,6 +2322,7 @@ Regression::FileIO(int rw)
{
descIO Desc[] = {
{"Type", typNZINT, &type, 0L},
+ {"hide", typNZINT, &hidden, 0L},
{"Bounds", typFRECT, &Bounds, 0L},
{"xRange", typTEXT, &xRange, 0L},
{"yRange", typTEXT, &yRange, 0L},
@@ -2280,6 +2369,7 @@ bool
BubblePlot::FileIO(int rw)
{
descIO Desc[] = {
+ {"hide", typNZINT, &hidden, 0L},
{"Bounds", typFRECT, &Bounds, 0L},
{"x_axis", typNZINT, &use_xaxis, 0L},
{"y_axis", typNZINT, &use_yaxis, 0L},
@@ -2330,6 +2420,7 @@ PolarPlot::FileIO(int rw)
{
descIO Desc[] = {
{"Type", typNZINT, &type, 0L},
+ {"hide", typNZINT, &hidden, 0L},
{"Bounds", typFRECT, &Bounds, 0L},
{"ang_offs", typLFLOAT, &offs, 0L},
{"Plots", typOBJLST, &Plots, (long*)&nPlots},
@@ -2366,6 +2457,7 @@ BoxPlot::RegGO(void *n)
if(Boxes) for(i = 0; i < nPoints; i++) if(Boxes[i]) Boxes[i]->RegGO(n);
if(Whiskers) for(i = 0; i < nPoints; i++) if(Whiskers[i]) Whiskers[i]->RegGO(n);
if(Symbols) for(i = 0; i < nPoints; i++) if(Symbols[i]) Symbols[i]->RegGO(n);
+ if(Labels) for(i = 0; i < nPoints; i++) if(Labels[i]) Labels[i]->RegGO(n);
if(TheLine) TheLine->RegGO(n);
((notary*)n)->AddRegGO(this);
}
@@ -2374,14 +2466,22 @@ BoxPlot::RegGO(void *n)
bool
BoxPlot::FileIO(int rw)
{
- descIO Desc[] = {
+ descIO Desc[] = {
+ {"Type", typNZINT, &type, 0L},
+ {"hide", typNZINT, &hidden, 0L},
{"Bounds", typFRECT, &Bounds, 0L},
- {"boDist", typLFPOINT, &BoxDist, 0L},
+ {"xRange", typTEXT, &xRange, 0L},
+ {"yRange", typTEXT, &yRange, 0L},
+ {"prefix", typTEXT, &case_prefix, 0L},
+ {"boDist", typLFPOINT, &BoxDist, 0L},
+ {"ci_box", typNZLFLOAT, &ci_box, 0L},
+ {"ci_err", typNZLFLOAT, &ci_err, 0L},
{"x_axis", typNZINT, &use_xaxis, 0L},
{"y_axis", typNZINT, &use_yaxis, 0L},
{"Boxes", typOBJLST, &Boxes, &nPoints},
{"Whiskers", typOBJLST, &Whiskers, &nPoints},
{"Symbols", typOBJLST, &Symbols, &nPoints},
+ {"Labels", typOBJLST, &Labels, &nPoints},
{"Line", typLAST | typGOBJ, &TheLine, 0L}};
int i;
@@ -2393,6 +2493,7 @@ BoxPlot::FileIO(int rw)
sprintf(TmpTxt, "boxes (%s)", name);
free(name); name=strdup(TmpTxt);
}
+ curr_data = 0L;
return true;
case FILE_READ:
return ExecInput(Desc);
@@ -2403,6 +2504,8 @@ BoxPlot::FileIO(int rw)
if(Whiskers[i]) Whiskers[i]->FileIO(rw);
if(Symbols) for(i = 0; i < nPoints; i++)
if(Symbols[i]) Symbols[i]->FileIO(rw);
+ if(Labels) for(i = 0; i < nPoints; i++)
+ if(Labels[i]) Labels[i]->FileIO(rw);
if(TheLine) TheLine->FileIO(rw);
return ExecOutput(Notary->RegisterGO(this), "BoxPlot", Desc);
}
@@ -2703,6 +2806,7 @@ Grid3D::RegGO(void *n)
if(n) {
if(lines) for(i = 0; i < nLines; i++) if(lines[i]) lines[i]->RegGO(n);
+ if(planes) for(i = 0; i < nPlanes; i++) if(planes[i]) planes[i]->RegGO(n);
((notary*)n)->AddRegGO(this);
}
}
@@ -2715,7 +2819,9 @@ Grid3D::FileIO(int rw)
{"Start", typPOINT3D, &start, 0L},
{"Step", typPOINT3D, &step, 0L},
{"Line", typLINEDEF, &Line, 0L},
- {"lines", typLAST | typOBJLST, &lines, &nLines}};
+ {"Fill", typFILLDEF, &Fill, 0L},
+ {"lines", typOBJLST, &lines, &nLines},
+ {"planes", typLAST | typOBJLST, &planes, &nPlanes}};
int i;
switch(rw) {
@@ -2734,9 +2840,11 @@ Grid3D::FileIO(int rw)
ExecInput(Desc);
//now set parent in all children
if(lines) for(i = 0; i < nLines; i++) if(lines[i]) lines[i]->parent = this;
+ if(planes) for(i = 0; i < nPlanes; i++) if(planes[i]) planes[i]->parent = this;
return true;
case FILE_WRITE:
if(lines) for(i = 0; i < nLines; i++) if(lines[i]) lines[i]->FileIO(rw);
+ if(planes) for(i = 0; i < nPlanes; i++) if(planes[i]) planes[i]->FileIO(rw);
return ExecOutput(Notary->RegisterGO(this), "Grid3D", Desc);
}
return false;
@@ -2775,17 +2883,15 @@ Function::RegGO(void *n)
bool
Function::FileIO(int rw)
{
- char *tmp_cmdxy = 0L, *tmp_param = 0L;
descIO Desc[] = {
{"x1", typNZLFLOAT, &x1, 0L},
{"x2", typNZLFLOAT, &x2, 0L},
{"xstep", typNZLFLOAT, &xstep, 0L},
{"Line", typLINEDEF, &Line, 0L},
- {"f_xy", typTEXT, &tmp_cmdxy, 0L},
- {"param", typTEXT, &tmp_param, 0L},
+ {"f_xy", typTEXT, &cmdxy, 0L},
+ {"param", typTEXT, ¶m, 0L},
{"DataLine", typLAST | typGOBJ, &dl, 0L}};
- int i, j;
-
+
switch(rw) {
case SAVE_VARS:
return SaveVarGO(Desc);
@@ -2800,31 +2906,11 @@ Function::FileIO(int rw)
return true;
case FILE_READ:
ExecInput(Desc);
- if(tmp_cmdxy && tmp_cmdxy[0]) cmdxy = tmp_cmdxy;
- if(tmp_param && tmp_param[0]) param = tmp_param;
if(dl) dl->parent = this;
return true;
case FILE_WRITE:
if(dl) dl->FileIO(rw);
- if(cmdxy) {
- for(i = j = 0; cmdxy[i]; i++) {
- if(cmdxy[i] == '\n') j += sprintf(TmpTxt+j, "\\n");
- else TmpTxt[j++] = cmdxy[i];
- }
- TmpTxt[j] = 0;
- if(i) tmp_cmdxy = strdup(TmpTxt);
- }
- if(param) {
- for(i = j = 0; param[i]; i++) {
- if(param[i] == '\n') j += sprintf(TmpTxt+j, "\\n");
- else TmpTxt[j++] = param[i];
- }
- TmpTxt[j] = 0;
- if(i) tmp_param = strdup(TmpTxt);
- }
ExecOutput(Notary->RegisterGO(this), "Function", Desc);
- if(tmp_cmdxy) free(tmp_cmdxy);
- if(tmp_param) free(tmp_param);
}
return false;
}
@@ -2843,7 +2929,6 @@ FitFunc::RegGO(void *n)
bool
FitFunc::FileIO(int rw)
{
- char *tmp_cmdxy = 0L, *tmp_parxy = 0L;
descIO Desc[] = {
{"ssXref", typTEXT, &ssXref, 0L},
{"ssYref", typTEXT, &ssYref, 0L},
@@ -2854,10 +2939,10 @@ FitFunc::FileIO(int rw)
{"chi2", typNZLFLOAT, &chi2, 0L},
{"maxiter", typNZINT, &maxiter, 0L},
{"Line", typLINEDEF, &Line, 0L},
- {"f_xy", typTEXT, &tmp_cmdxy, 0L},
- {"p_xy", typTEXT, &tmp_parxy, 0L},
+ {"f_xy", typTEXT, &cmdxy, 0L},
+ {"p_xy", typTEXT, &parxy, 0L},
{"Symbols", typLAST | typOBJLST, &Symbols, &nPoints}};
- int i, j;
+ int i;
switch(rw) {
case SAVE_VARS:
@@ -2875,28 +2960,10 @@ FitFunc::FileIO(int rw)
return true;
case FILE_READ:
ExecInput(Desc);
- if(tmp_cmdxy && tmp_cmdxy[0]) cmdxy = tmp_cmdxy;
- if(tmp_parxy && tmp_parxy[0]) parxy = tmp_parxy;
if(Symbols) for(i = 0; i < nPoints; i++)
if(Symbols[i]) Symbols[i]->parent = this;
return true;
case FILE_WRITE:
- if(cmdxy) {
- for(i = j = 0; cmdxy[i]; i++) {
- if(cmdxy[i] == '\n') j += sprintf(TmpTxt+j, "\\n");
- else TmpTxt[j++] = cmdxy[i];
- }
- TmpTxt[j] = 0;
- if(i) tmp_cmdxy = strdup(TmpTxt);
- }
- if(parxy) {
- for(i = j = 0; parxy[i]; i++) {
- if(parxy[i] == '\n') j += sprintf(TmpTxt+j, "\\n");
- else TmpTxt[j++] = parxy[i];
- }
- TmpTxt[j] = 0;
- if(i) tmp_parxy = strdup(TmpTxt);
- }
if(Symbols) for(i = 0; i < nPoints; i++) if(Symbols[i]) Symbols[i]->FileIO(rw);
return ExecOutput(Notary->RegisterGO(this), "FitFunc", Desc);
}
@@ -3105,7 +3172,7 @@ Axis::FileIO(int rw)
}
if(axis) axis->owner = this;
if(axisLabel)axisLabel->parent = this;
- if(Ticks && NumTicks) for(i = 0; i < NumTicks; i++) if(Ticks[i]) Ticks[i]->parent = this;
+ if(Ticks) for(i = 0; i < NumTicks; i++) if(Ticks[i]) Ticks[i]->parent = this;
return true;
case FILE_WRITE:
//do all ticks
@@ -3187,6 +3254,78 @@ Plot3D::FileIO(int rw)
}
return false;
}
+
+void
+Func3D::RegGO(void *n)
+{
+}
+
+bool
+Func3D::FileIO(int rw)
+{
+ fPOINT3D rot_vec, rot_ang;
+ //DEBUG: must initialize rot_vec, rot_ang in case they are not present in file
+ descIO Desc[] = {
+ {"Type", typNZINT, &type, 0L},
+ {"xBounds", typLFPOINT, &xBounds, 0L},
+ {"yBounds", typLFPOINT, &yBounds, 0L},
+ {"zBounds", typLFPOINT, &zBounds, 0L},
+ {"Corner1", typPOINT3D, &cub1, 0L},
+ {"Corner2", typPOINT3D, &cub2, 0L},
+ {"Center", typPOINT3D, &rotC, 0L},
+ {"rot_vec", typPOINT3D, &rot_vec, 0L},
+ {"rot_ang", typPOINT3D, &rot_ang, 0L},
+ {"Axes", typOBJLST, &Axes, (long*)&nAxes},
+ {"Plots", typOBJLST, &plots, (long*)&nPlots},
+ {"x1", typNZLFLOAT, &x1, 0L},
+ {"x2", typNZLFLOAT, &x2, 0L},
+ {"xstep", typNZLFLOAT, &xstep, 0L},
+ {"z1", typNZLFLOAT, &x1, 0L},
+ {"z2", typNZLFLOAT, &x2, 0L},
+ {"zstep", typNZLFLOAT, &xstep, 0L},
+ {"g_idx", typNZINT, &g_idx, 0L},
+ {"Line", typLINEDEF, &Line, 0L},
+ {"Fill", typFILLDEF, &Fill, 0L},
+ {"f_xz", typTEXT, &cmdxy, 0L},
+ {"param", typLAST | typTEXT, ¶m, 0L}};
+ int i;
+
+ switch(rw) {
+ case SAVE_VARS:
+ return SaveVarGO(Desc);
+ case INIT_VARS:
+ x1 = -20.0; x2 = 20.0; xstep = 2.0;
+ z1 = -20.0; z2 = 20.0; zstep = 2.0;
+ gda = 0L; gob = 0L;
+ g_idx = 0; param = cmdxy = 0L;
+ Line.width = defs.GetSize(SIZE_HAIRLINE);
+ Line.patlength = defs.GetSize(SIZE_PATLENGTH);
+ Line.color = Line.pattern = 0x0L;
+ Fill.color = 0x00c0c0c0;
+ Fill.color2 = 0x00ffffff;
+ Fill.hatch = 0L;
+ Fill.type = FILL_LIGHT3D;
+ if(name) {
+ sprintf(TmpTxt, "3D function (Plot %d)", cPlots);
+ free(name); name=strdup(TmpTxt);
+ }
+ return true;
+ case FILE_READ:
+ ExecInput(Desc);
+ RotDef[0] = rot_vec.fx; RotDef[1] = rot_vec.fy; RotDef[2] = rot_vec.fz;
+ RotDef[3] = rot_ang.fx; RotDef[4] = rot_ang.fy; RotDef[5] = rot_ang.fz;
+ return true;
+ case FILE_WRITE:
+ rot_vec.fx = RotDef[0]; rot_vec.fy = RotDef[1]; rot_vec.fz = RotDef[2];
+ rot_ang.fx = RotDef[3]; rot_ang.fy = RotDef[4]; rot_ang.fz = RotDef[5];
+ //do all plots
+ for(i = 0; plots && i< nPlots; i++) if(plots[i]) plots[i]->FileIO(rw);
+ //do all axes
+ if(Axes) for(i = 0; i< nAxes; i++) if(Axes[i]) Axes[i]->FileIO(rw);
+ ExecOutput(Notary->RegisterGO(this), "Func3D", Desc);
+ }
+ return false;
+}
void
Graph::RegGO(void *n)
@@ -3265,7 +3404,7 @@ Graph::FileIO(int rw)
if(Axes[i] && Axes[i]->GetAxis() == &x_axis) ixax = i;
else if(Axes[i] && Axes[i]->GetAxis() == &y_axis) iyax = i;
}
- if(Id == GO_GRAPH && parent && parent->Id != GO_PAGE)RegGO(Notary);
+ if(Id == GO_GRAPH)RegGO(Notary);
//do all plots
if(Plots) for(i = 0; i< NumPlots; i++) if(Plots[i]) Plots[i]->FileIO(rw);
//do all axes
@@ -3281,7 +3420,8 @@ Page::RegGO(void *n)
int i;
if(n) {
- if(Plots) for(i = 0; i< NumPlots; i++) if(Plots[i]) Plots[i]->RegGO(n);
+ if(Plots) for(i = 0; i< NumPlots; i++)
+ if(Plots[i] && Plots[i]->Id != GO_GRAPH) Plots[i]->RegGO(n);
((notary*)n)->AddRegGO(this);
}
}
@@ -3314,7 +3454,8 @@ Page::FileIO(int rw)
return true;
case FILE_WRITE:
//do all plots
- bModified = false;
+ bModified = false;
+ if(Id == GO_PAGE)RegGO(Notary);
if(Plots) for(i = 0; i< NumPlots; i++) if(Plots[i]) Plots[i]->FileIO(rw);
return ExecOutput(Notary->RegisterGO(this), "Page", Desc);
}
@@ -3327,7 +3468,8 @@ DefsRW::FileIO(int rw)
descIO Desc[] = {
{"dUnits", typINT, &defs.dUnits, 0L},
{"cUnits", typINT, &defs.dUnits, 0L},
- {"dtHeight", typINT, &dlgtxtheight, 0L},
+ {"dtHeight", typINT, &dlgtxtheight, 0L},
+ {"ss_txt", typLFLOAT, &defs.ss_txt, 0L},
{"File1", typTEXT, &defs.File1, 0L},
{"File2", typTEXT, &defs.File2, 0L},
{"File3", typTEXT, &defs.File3, 0L},
diff --git a/ODbuttons.cpp b/ODbuttons.cpp
index f4d94c4..7a22b70 100755
--- a/ODbuttons.cpp
+++ b/ODbuttons.cpp
@@ -117,14 +117,15 @@ void OD_LineStyleTempl(int cmd, void *par, RECT *rec, anyOutput *o,
{
LineDEF Line = {.1f, 1.0f, 0x0L, 0x0L};
FillDEF Fill = {FILL_NONE, 0x00ffffffL, 1.0, 0L};
- POINT pts[10];
- int ix, iy, np;
+ POINT *pts;
+ int i, ix, iy, np;
+ if(!(pts=(POINT*)malloc(sizeof(POINT)*(rec->right-rec->left)))) return;
switch(cmd) {
case OD_DRAWNORMAL:
case OD_DRAWSELECTED:
- Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00d0d0d0L;
- Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00d0d0d0L;
+ Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00e8e8e8L;
+ Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00e8e8e8L;
ix = (rec->left + rec->right)/2;
iy = (rec->top +rec->bottom)/2;
o->SetLine(&Line);
@@ -189,17 +190,49 @@ void OD_LineStyleTempl(int cmd, void *par, RECT *rec, anyOutput *o,
pts[np].x = pts[np-1].x; pts[np++].y = rec->top+15;
if(id == 209) pts[np-1].y -= 7;
break;
+ case 210:
+ pts[0].x = rec->left +9; pts[0].y = iy+4; pts[1].x = pts[0].x+1;
+ for(i = 0; i < (rec->right - rec->left - 18); i++) {
+ pts[1].y = 4 + iy + iround(pow(20.0, 1.0+((double)-i)/30.0) * -sin(((double)i)/4.0));
+ o->oSolidLine(pts);
+ pts[0].x++; pts[1].x++; pts[0].y = pts[1].y;
+ }
+ o->oCircle(rec->left+7, iy+4, rec->left+12, iy +9);
+ o->oCircle(rec->left+12, iy-10, rec->left+17, iy -5);
+ o->oCircle(rec->right-19, iy+5, rec->right-24, iy +10);
+ o->oCircle(rec->right-9, iy, rec->right-14, iy+5);
+ break;
+ case 211:
+ pts[0].y = rec->top +9; pts[0].x = ix; pts[1].y = pts[0].y+1;
+ for(i = 0; i < (rec->bottom - rec->top - 18); i++) {
+ pts[1].x = ix + iround(pow(20.0, 1.0+((double)-i)/50.0) * -sin(((double)i)/4.0));
+ o->oSolidLine(pts);
+ pts[0].y++; pts[1].y++; pts[0].x = pts[1].x;
+ }
+ o->oCircle(ix-3, rec->top + 7, ix+2, rec->top + 12);
+ o->oCircle(rec->left+11, iy-10, rec->left+16, iy -5);
+ o->oCircle(ix+3, rec->top + 27, ix+8, rec->top + 32);
+ o->oCircle(ix-5, iy+12, ix, iy + 17);
+ break;
}
if(np) o->oPolyline(pts, np);
- o->oCircle(ix-2, iy-2, ix+2, iy+2);
+ switch(id) {
+ case 201: case 202: case 203: case 204: case 205:
+ case 206: case 207: case 208: case 209:
+ o->oCircle(ix-2, iy-2, ix+2, iy+2);
#ifdef _WINDOWS
- o->oCircle(rec->left+13, rec->bottom-13, rec->left+17, rec->bottom-17);
- o->oCircle(rec->right-13, rec->top+13, rec->right-17, rec->top+17);
+ o->oCircle(rec->left+13, rec->bottom-13, rec->left+17, rec->bottom-17);
+ o->oCircle(rec->right-13, rec->top+13, rec->right-17, rec->top+17);
#else
- o->oCircle(rec->left+13, rec->bottom-14, rec->left+17, rec->bottom-16);
- o->oCircle(rec->right-14, rec->top+13, rec->right-16, rec->top+17);
+ o->oCircle(rec->left+13, rec->bottom-14, rec->left+17, rec->bottom-16);
+ o->oCircle(rec->right-14, rec->top+13, rec->right-16, rec->top+17);
#endif
+ break;
+ case 210: case 211:
+ break;
+ }
o->UpdateRect(rec, false);
+ free(pts);
break;
}
}
@@ -219,8 +252,8 @@ void OD_ErrBarTempl(int cmd, void *par, RECT *rec, anyOutput *o,
switch(cmd) {
case OD_DRAWNORMAL:
case OD_DRAWSELECTED:
- Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00d0d0d0L;
- Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00d0d0d0L;
+ Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00e8e8e8L;
+ Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00e8e8e8L;
ix = (rec->left + rec->right)/2;
iy = (rec->top +rec->bottom)/2;
o->SetLine(&Line);
@@ -283,8 +316,8 @@ void OD_WhiskerTempl(int cmd, void *par, RECT *rec, anyOutput *o,
switch(cmd) {
case OD_DRAWNORMAL:
case OD_DRAWSELECTED:
- Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00d0d0d0L;
- Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00d0d0d0L;
+ Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00e8e8e8L;
+ Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00e8e8e8L;
ix = (rec->left + rec->right)/2;
iy = (rec->top +rec->bottom)/2;
o->SetLine(&Line);
@@ -344,8 +377,8 @@ void OD_PolarTempl(int cmd, void *par, RECT *rec, anyOutput *o,
switch(cmd) {
case OD_DRAWNORMAL:
case OD_DRAWSELECTED:
- Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00d0d0d0L;
- Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00d0d0d0L;
+ Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00e8e8e8L;
+ Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00e8e8e8L;
ix = (rec->left + rec->right)/2;
iy = (rec->top +rec->bottom)/2;
o->SetLine(&Line);
@@ -388,7 +421,7 @@ void OD_PolarTempl(int cmd, void *par, RECT *rec, anyOutput *o,
o->oPolygon(pts, 5);
break;
case 204:
- if(cmd == OD_DRAWNORMAL) FillG.color = 0x00d0d0d0L;
+ if(cmd == OD_DRAWNORMAL) FillG.color = 0x00e8e8e8L;
o->SetFill(&FillG);
o->oCircle(ix-6, rec->top+5, ix+6, iy+6);
memcpy(&td, &o->TxtSet, sizeof(TextDEF));
@@ -429,8 +462,8 @@ void OD_PieTempl(int cmd, void *par, RECT *rec, anyOutput *o,
switch(cmd) {
case OD_DRAWNORMAL:
case OD_DRAWSELECTED:
- Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00d0d0d0L;
- Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00d0d0d0L;
+ Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00e8e8e8L;
+ Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00e8e8e8L;
ix = (rec->left + rec->right)/2;
iy = (rec->top +rec->bottom)/2;
o->SetLine(&Line);
@@ -525,8 +558,8 @@ void OD_BreakTempl(int cmd, void *par, RECT *rec, anyOutput *o,
switch(cmd) {
case OD_DRAWNORMAL:
case OD_DRAWSELECTED:
- Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00d0d0d0L;
- Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00d0d0d0L;
+ Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00e8e8e8L;
+ Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00e8e8e8L;
ix = (rec->left + rec->right)>>1;
iy = (rec->top +rec->bottom)>>1;
o->SetLine(&Line);
@@ -617,11 +650,12 @@ void OD_PlotTempl(int cmd, void *par, RECT *rec, anyOutput *o,
iy = (rec->top +rec->bottom)>>1;
switch(id) {
case 560: case 561: case 562: case 563: case 564: //3D axes
+ case 565:
OD_AxisTempl3D(cmd, par, rec, o, data, 410+AxisTempl3D);
break;
default:
- Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00d0d0d0L;
- Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00d0d0d0L;
+ Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00e8e8e8L;
+ Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00e8e8e8L;
o->SetLine(&Line);
pts[0].x = pts[3].x = pts[4].x = rec->left;
pts[0].y = pts[1].y = pts[4].y = rec->top;
@@ -844,6 +878,41 @@ void OD_PlotTempl(int cmd, void *par, RECT *rec, anyOutput *o,
pts[0].y += 9; pts[1].y += 10; pts[2].y = pts[1].y;
o->oPolyline(pts, 3, 0L);
break;
+ case 532:
+ pts[0].x = rec->left +13; pts[0].y = rec->top+8;
+ pts[1].x = rec->left +13; pts[1].y = iy;
+ o->oSolidLine(pts);
+ pts[0].x -= 3; pts[1].x += 3;
+ pts[0].y = pts[1].y = rec->top+8;
+ o->oSolidLine(pts);
+ pts[0].y = pts[1].y = iy;
+ o->oSolidLine(pts);
+ pts[0].x = ix; pts[0].y = iy-8;
+ pts[1].x = ix; pts[1].y = rec->bottom-13;
+ o->oSolidLine(pts);
+ pts[0].x -= 3; pts[1].x += 3;
+ pts[0].y = pts[1].y = iy-8;
+ o->oSolidLine(pts);
+ pts[0].y = pts[1].y = rec->bottom-13;
+ o->oSolidLine(pts);
+ pts[0].x = rec->right -13; pts[0].y = rec->top+10;
+ pts[1].x = rec->right -13; pts[1].y = iy-6;
+ o->oSolidLine(pts);
+ pts[0].x -= 3; pts[1].x += 3;
+ pts[0].y = pts[1].y = rec->top+10;
+ o->oSolidLine(pts);
+ pts[0].y = pts[1].y = iy-6;
+ o->oSolidLine(pts);
+ pts[0].x = rec->left+13; pts[1].x = ix; pts[2].x = rec->right-13;
+ pts[0].y = (rec->top+8+iy)>>1;
+ pts[1].y = (rec->bottom-13 + iy -8)>>1;
+ pts[2].y = (rec->top+10+iy-6)>>1;
+ o->oPolyline(pts, 3, 0L);
+ o->SetFill(&FillY);
+ o->oCircle(pts[0].x-3, pts[0].y-3, pts[0].x+3, pts[0].y+3);
+ o->oCircle(pts[1].x-3, pts[1].y-3, pts[1].x+3, pts[1].y+3);
+ o->oCircle(pts[2].x-3, pts[2].y-3, pts[2].x+3, pts[2].y+3);
+ break;
case 540:
o->SetFill(&FillR);
o->oRectangle(rec->left+8, rec->bottom-8, rec->left+16, rec->bottom-3);
@@ -1012,6 +1081,32 @@ void OD_PlotTempl(int cmd, void *par, RECT *rec, anyOutput *o,
pts[4].x = pts[0].x; pts[4].y = pts[0].y;
o->oPolygon(pts, 5, 0L);
break;
+ case 565:
+ o->SetLine(&rLine);
+ pts[0].x = ix-16; pts[0].y = iy-2;
+ pts[1].x = ix+4; pts[1].y = iy+6;
+ for(i = 0; i < 4; i++) {
+ o->oSolidLine(pts);
+ pts[0].x += 4; pts[1].x += 4;
+ pts[0].y -= 4; pts[1].y -= 4;
+ }
+ pts[0].x = ix+4; pts[0].y = iy+6;
+ pts[1].x -= 2; pts[1].y += 4;
+ for(i = 0; i < 5; i++) {
+ o->oSolidLine(pts);
+ pts[0].x -= 5; pts[1].x -= 5;
+ pts[0].y -= 2; pts[1].y -= 2;
+ }
+ memcpy(&td, &o->TxtSet, sizeof(TextDEF));
+ memcpy(&otd, &o->TxtSet, sizeof(TextDEF));
+ td.Align = TXA_HCENTER | TXA_VTOP;
+ td.Style = TXS_NORMAL;
+ td.Mode = TXM_TRANSPARENT;
+ td.ColTxt = 0x00c00000L;
+ o->SetTextSpec(&td);
+ o->oTextOut(ix, iy+4, "f(x,z)", 0);
+ o->SetTextSpec(&otd);
+ break;
}
o->UpdateRect(rec, false);
break;
@@ -1033,8 +1128,8 @@ void OD_AxisTempl(int cmd, void *par, RECT *rec, anyOutput *o,
switch(cmd) {
case OD_DRAWNORMAL:
case OD_DRAWSELECTED:
- Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00d0d0d0L;
- Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00d0d0d0L;
+ Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00e8e8e8L;
+ Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00e8e8e8L;
o->SetLine(&Line);
pts[0].x = pts[3].x = pts[4].x = rec->left;
pts[0].y = pts[1].y = pts[4].y = rec->top;
@@ -1152,8 +1247,8 @@ void OD_AxisTempl3D(int cmd, void *par, RECT *rec, anyOutput *o,
switch(cmd) {
case OD_DRAWNORMAL:
case OD_DRAWSELECTED:
- Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00d0d0d0L;
- Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00d0d0d0L;
+ Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00e8e8e8L;
+ Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00e8e8e8L;
o->SetLine(&Line);
pts[0].x = pts[3].x = pts[4].x = rec->left;
pts[0].y = pts[1].y = pts[4].y = rec->top;
@@ -1161,9 +1256,10 @@ void OD_AxisTempl3D(int cmd, void *par, RECT *rec, anyOutput *o,
pts[2].y = pts[3].y = rec->bottom-1;
o->oPolyline(pts, 5);
Line.color = 0x00000000L;
- o->SetLine(&Line);
- o->SetFill(&Fill);
+ o->SetLine(&Line); o->SetFill(&Fill);
o->oRectangle(rec->left+3, rec->top+3, rec->right-3, rec->bottom-3);
+ Line.color = cmd == OD_DRAWSELECTED ? 0x00c0c0c0L : 0x0L;
+ o->SetLine(&Line); o->SetFill(&Fill);
switch(id) {
case 410: case 411:
pts[0].x = rec->left+20; pts[0].y = rec->bottom-14;
@@ -1199,6 +1295,7 @@ void OD_AxisTempl3D(int cmd, void *par, RECT *rec, anyOutput *o,
o->oSolidLine(pts);
}
o->UpdateRect(rec, false);
+ Line.color = 0x00000000L; o->SetLine(&Line);
break;
}
}
@@ -1217,8 +1314,8 @@ void OD_NewAxisTempl(int cmd, void *par, RECT *rec, anyOutput *o,
switch(cmd) {
case OD_DRAWNORMAL:
case OD_DRAWSELECTED:
- Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00d0d0d0L;
- Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00d0d0d0L;
+ Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00e8e8e8L;
+ Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00e8e8e8L;
o->SetLine(&Line);
ix = (rec->right + rec->left)>>1;
iy = (rec->bottom + rec->top)>>1;
diff --git a/PlotObs.cpp b/PlotObs.cpp
index 30c873a..2af0276 100755
--- a/PlotObs.cpp
+++ b/PlotObs.cpp
@@ -279,6 +279,7 @@ PlotScatt::PlotScatt(int src):Plot(0L, 0L)
PlotScatt::~PlotScatt()
{
ForEach(FE_FLUSH, 0L, 0L);
+ if(name) free(name); name=0L;
Undo.InvalidGO(this);
}
@@ -286,31 +287,35 @@ double
PlotScatt::GetSize(int select)
{
int i;
- double ft1, ft2;
+ double ft1, ft2, d;
switch(select){
case SIZE_BARMINX:
if(BarDist.fx >= 0.0001) return BarDist.fx;
- if((!Bars) | (nPoints < 2)) return 1.0f;
- ft1 = fabs(Bars[1]->GetSize(SIZE_XPOS) - Bars[0]->GetSize(SIZE_XPOS));
- for(i = 2; i < nPoints; i++) {
- if(Bars[i] && Bars[i-1]) {
- ft2 = fabs(Bars[i]->GetSize(SIZE_XPOS) - Bars[i-1]->GetSize(SIZE_XPOS));
- if(ft2 < ft1 || ft1 < 0.0001f) ft1 = ft2;
+ if((!Bars) || (nPoints < 2)) return BarDist.fx = 1.0;
+ ft1 = -HUGE_VAL; ft2 = HUGE_VAL; BarDist.fx= HUGE_VAL;
+ for(i = 0; i < nPoints; i++) {
+ if(Bars[i]) {
+ ft2 = Bars[i]->GetSize(SIZE_XPOS);
+ d = fabs(ft2-ft1);
+ if(d != 0.0 && d < BarDist.fx) BarDist.fx = d;
}
+ ft1 = ft2;
}
- return BarDist.fx = ft1 > 0.0001 ? ft1 : 1.0;
+ return BarDist.fx = BarDist.fx > 0.0001 && BarDist.fx != HUGE_VAL ? BarDist.fx : 1.0;
case SIZE_BARMINY:
if(BarDist.fy >= 0.0001) return BarDist.fy;
- if((!Bars) | (nPoints < 2)) return 1.0f;
- ft1 = fabs(Bars[1]->GetSize(SIZE_YPOS) - Bars[0]->GetSize(SIZE_YPOS));
- for(i = 2; i < nPoints; i++) {
- if(Bars[i] && Bars[i-1]) {
- ft2 = fabs(Bars[i]->GetSize(SIZE_YPOS) - Bars[i-1]->GetSize(SIZE_YPOS));
- if(ft2 < ft1 || ft1 < 0.0001f) ft1 = ft2;
+ if((!Bars) || (nPoints < 2)) return BarDist.fy = 1.0;
+ ft1 = -HUGE_VAL; ft2 = HUGE_VAL; BarDist.fy= HUGE_VAL;
+ for(i = 0; i < nPoints; i++) {
+ if(Bars[i]) {
+ ft2 = Bars[i]->GetSize(SIZE_YPOS);
+ d = fabs(ft2-ft1);
+ if(d != 0.0 && d < BarDist.fy) BarDist.fy = d;
}
+ ft1 = ft2;
}
- return BarDist.fy = ft1 > 0.0001 ? ft1 : 1.0;
+ return BarDist.fy = BarDist.fy > 0.0001 && BarDist.fy != HUGE_VAL ? BarDist.fy : 1.0;
default:
return Plot::GetSize(select);
}
@@ -332,6 +337,7 @@ PlotScatt::SetSize(int select, double value)
if(Symbols) for(i = 0; i < nPoints; i++)
if(Symbols[i]) Symbols[i]->SetSize(select, value);
return true;
+ case SIZE_WHISKER: case SIZE_WHISKER_LINE:
case SIZE_ERRBAR: case SIZE_ERRBAR_LINE:
if(Errors) for(i = 0; i < nPoints; i++)
if(Errors[i]) Errors[i]->SetSize(select, value);
@@ -340,6 +346,10 @@ PlotScatt::SetSize(int select, double value)
if(Bars) for(i = 0; i < nPoints; i++)
if(Bars[i]) Bars[i]->SetSize(select, value);
return true;
+ case SIZE_LB_XDIST: case SIZE_LB_YDIST:
+ if(Labels) for(i = 0; i < nPoints; i++)
+ if(Labels[i]) Labels[i]->SetSize(select, value);
+ return true;
case SIZE_ARROW_LINE: case SIZE_ARROW_CAPWIDTH: case SIZE_ARROW_CAPLENGTH:
if(Arrows) for(i = 0; i < nPoints; i++)
if(Arrows[i]) Arrows[i]->SetSize(select, value);
@@ -357,6 +367,7 @@ PlotScatt::SetColor(int select, DWORD col)
switch(select) {
case COL_SYM_LINE:
case COL_SYM_FILL: go = (GraphObj**)Symbols; break;
+ case COL_WHISKER:
case COL_ERROR_LINE: go = (GraphObj**)Errors; break;
case COL_BAR_LINE:
case COL_BAR_FILL: go = (GraphObj**)Bars; break;
@@ -438,12 +449,18 @@ PlotScatt::Command(int cmd, void *tmpl, anyOutput *o)
dirty = false;
case CMD_UPDATE:
if(cmd == CMD_UPDATE){
- Undo.ObjConf(this, UNDO_CONTINUE);
+ if (Symbols) SavVarObs((GraphObj **)Symbols, nPoints, UNDO_CONTINUE);
+ if (Bars) SavVarObs((GraphObj **)Bars, nPoints, UNDO_CONTINUE);
+ if (Errors) SavVarObs((GraphObj **)Errors, nPoints, UNDO_CONTINUE);
+ if (Arrows) SavVarObs((GraphObj **)Arrows, nPoints, UNDO_CONTINUE);
+ if (DropLines) SavVarObs((GraphObj **)DropLines, nPoints, UNDO_CONTINUE);
+ if (Labels) SavVarObs((GraphObj **)Labels, nPoints, UNDO_CONTINUE);
dirty = true;
}
case CMD_SET_DATAOBJ:
if(cmd == CMD_SET_DATAOBJ) {
Id = GO_PLOTSCATT;
+ if(data && data == (DataObj *) tmpl) return true;
data = (DataObj *)tmpl;
}
ForEach(cmd, tmpl, o);
@@ -463,14 +480,18 @@ PlotScatt::Command(int cmd, void *tmpl, anyOutput *o)
if(Symbols) for(i = 0; i < nPoints; i++)
if(Symbols[i]) Symbols[i]->Command(cmd, tmpl, o);
return true;
+ case CMD_SETTEXTDEF:
+ if(Labels) for(i = 0; i < nPoints; i++)
+ if(Labels[i]) Labels[i]->Command(cmd, tmpl, o);
+ return true;
case CMD_DL_LINE: case CMD_DL_TYPE:
if(DropLines) for(i = 0; i < nPoints; i++)
if(DropLines[i]) DropLines[i]->Command(cmd, tmpl, o);
return true;
- case CMD_ERR_TYPE:
- if(Errors) for(i = 0; i < nPoints; i++)
- if(Errors[i]) Errors[i]->type = *((int*)tmpl);
- return true;
+ case CMD_ERR_TYPE: case CMD_WHISKER_STYLE:
+ if(Errors) for(i = 0; i < nPoints; i++) {
+ if(Errors[i]) Errors[i]->Command(cmd, tmpl, o);
+ }
case CMD_BAR_TYPE: case CMD_BAR_FILL:
if(Bars) for(i = 0; i < nPoints; i++) {
if(Bars[i]) Bars[i]->Command(cmd, tmpl, o);
@@ -495,6 +516,8 @@ PlotScatt::Command(int cmd, void *tmpl, anyOutput *o)
return SavVarObs((GraphObj **)Arrows, nPoints, 0L);
case CMD_SAVE_DROPLINES:
return SavVarObs((GraphObj **)DropLines, nPoints, 0L);
+ case CMD_SAVE_LABELS:
+ return SavVarObs((GraphObj **)Labels, nPoints, 0L);
}
return false;
}
@@ -631,6 +654,206 @@ PlotScatt::ForEach(int cmd, void *tmp, anyOutput *o)
return false;
}
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// xyStat is based on scatterplot
+xyStat::xyStat(GraphObj *par, DataObj *d):PlotScatt(par, d, 0L)
+{
+ FileIO(INIT_VARS);
+ Id = GO_XYSTAT;
+}
+
+xyStat::xyStat(int src):PlotScatt(0)
+{
+ FileIO(INIT_VARS);
+ if(src == FILE_READ) {
+ FileIO(FILE_READ);
+ }
+}
+
+xyStat::~xyStat()
+{
+ ForEach(FE_FLUSH, 0L, 0L);
+ if(curr_data) delete curr_data; curr_data = 0L;
+ if(case_prefix) free(case_prefix); case_prefix = 0L;
+ if(yRange) free(yRange); yRange = 0L;
+ if(xRange) free(xRange); xRange = 0L;
+ if(name) free(name); name=0L;
+ Undo.InvalidGO(this);
+}
+
+bool
+xyStat::Command(int cmd, void *tmpl, anyOutput *o)
+{
+ switch (cmd) {
+ case CMD_UPDATE:
+ if (Symbols) SavVarObs((GraphObj **)Symbols, nPoints, UNDO_CONTINUE);
+ if (Bars) SavVarObs((GraphObj **)Bars, nPoints, UNDO_CONTINUE);
+ if (Errors) SavVarObs((GraphObj **)Errors, nPoints, UNDO_CONTINUE);
+ if (Labels) SavVarObs((GraphObj **)Labels, nPoints, UNDO_CONTINUE);
+ CreateData();
+ ForEach(CMD_SET_DATAOBJ, curr_data, o);
+ ForEach(CMD_UPDATE, tmpl, o);
+ return dirty = true;
+ case CMD_SET_DATAOBJ:
+ if(cmd == CMD_SET_DATAOBJ) {
+ Id = GO_XYSTAT;
+ if(data && data == (DataObj *) tmpl) return true;
+ if(curr_data) delete curr_data; curr_data = 0L;
+ data = (DataObj *)tmpl;
+ if(data && !curr_data) CreateData();
+ tmpl = curr_data;
+ }
+ ForEach(cmd, tmpl, o);
+ return true;
+ default:
+ return PlotScatt::Command(cmd, tmpl, o);
+ }
+ return false;
+}
+
+void
+xyStat::CreateData()
+{
+ int i, j, k, l, m, n, *ny;
+ double x, y, ss, d, lo, hi, **ay, *ax, *tay, *q1, *q2, *q3;
+ lfPOINT *xy;
+ AccRange *rX, *rY;
+
+ if(curr_data) delete curr_data; curr_data = 0L;
+ if(!data || !xRange || !yRange || !xRange[0] || !yRange[0]) return;
+ if(!(rX = new AccRange(xRange)) || !(rY = new AccRange(yRange))) return;
+ m = rX->CountItems(); n = 0;
+ if(m < 2 || !(xy = (lfPOINT*) malloc(m * sizeof(lfPOINT)))) {
+ delete rX; delete rY;
+ return;
+ }
+ ny = (int*) calloc(m, sizeof(int));
+ ay = (double**) calloc(m, sizeof(double*));
+ ax = (double*) calloc(m, sizeof(double));
+ tay = (double*)malloc(m * sizeof(double));
+ if(!ny || !ay || !ax || !tay) {
+ if(ny) free(ny); if(ay) free(ay);
+ if(ax) free(ax); if(tay) free(tay);
+ delete rX; delete rY;
+ return;
+ }
+ rX->GetFirst(&i, &j); rY->GetFirst(&k, &l);
+ rX->GetNext(&i, &j); rY->GetNext(&k, &l); n=0;
+ do {
+ if(data->GetValue(j, i, &x) && data->GetValue(l, k, &y)){
+ xy[n].fx = x; xy[n].fy = y;
+ n++;
+ }
+ }while(rX->GetNext(&i, &j) && rY->GetNext(&k, &l));
+ delete rX; delete rY;
+ if(!n) {
+ if(ny) free(ny); if(ay) free(ay);
+ if(ax) free(ax); if(tay) free(tay);
+ return;
+ }
+ SortFpArray(n, xy);
+ for(i = j = 0; i < (n-1); i++, j++) {
+ ax[j] = xy[i].fx; tay[0] = xy[i].fy;
+ ny[j] = 1;
+ for(k = 1; xy[i+1].fx == xy[i].fx; k++) {
+ tay[k] = xy[i+1].fy;
+ i++; ny[j]++;
+ }
+ ay[j] = (double*)memdup(tay, k * sizeof(double), 0);
+ }
+ if(xy[i].fx > xy[i-1].fx) {
+ ax[j] = xy[i].fx; tay[0] = xy[i].fy;
+ ny[j] = 1;
+ ay[j++] = (double*)memdup(tay, sizeof(double), 0);
+ }
+ if(type & 0x0480) { //medians and/or percentiles required
+ q1 = (double *)malloc(j * sizeof(double));
+ q2 = (double *)malloc(j * sizeof(double));
+ q3 = (double *)malloc(j * sizeof(double));
+ if(q1 && q2 && q3) {
+ for(i = 0; i < j; i++) {
+ if(ny[i] > 1) d_quartile(ny[i], ay[i], q1+i, q2+i, q3+i);
+ else q1[i] = q2[i] = q3[i] = *ay[i];
+ }
+ }
+ else type &= (~0x0480);
+ }
+ else q1 = q2 = q3 = 0L;
+ if((curr_data = new DataObj()) && curr_data->Init(j, 6)) {
+ for(i = 0; i < j; i++) curr_data->SetValue(i,0,ax[i]); // set x-values
+ for(i = 0; i < j; i++) { // set y-values
+ if(ny[i] > 1) switch(type & 0x00f0) {
+ case 0x0010: default:
+ curr_data->SetValue(i, 1, y=d_amean(ny[i], ay[i]));
+ break;
+ case 0x0020:
+ curr_data->SetValue(i, 1, y=d_gmean(ny[i], ay[i]));
+ break;
+ case 0x0040:
+ curr_data->SetValue(i, 1, y=d_hmean(ny[i], ay[i]));
+ break;
+ case 0x0080:
+ curr_data->SetValue(i, 1, y=q2[i]);
+ break;
+ }
+ else curr_data->SetValue(i, 1, y= *ay[i]);
+ curr_data->SetValue(i, 4, y);
+ }
+ for(i = 0; i < j; i++) { // set errors
+ switch(type & 0x1f00) {
+ case 0x0100: case 0x0200: case 0x1000: //SD, SEM, conf. int.
+ if(ny[i] > 1) {
+ y = d_amean(ny[i], ay[i]);
+ for(k = 0, ss = 0.0; k < (ny[i]); k++) {
+ ss += ((d=ay[i][k]-y)*d);
+ ny[i] = ny[i];
+ }
+ ss = ss/(double)(ny[i]-1);
+ switch(type & 0x1f00) {
+ case 0x0100:
+ curr_data->SetValue(i, 2, sqrt(ss));
+ break;
+ case 0x0200:
+ curr_data->SetValue(i, 2, sqrt(ss)/sqrt(ny[i]));
+ break;
+ case 0x1000:
+ d = distinv(t_dist, ny[i]-1, 1, 1.0-(ci/100.0), 2.0);
+ curr_data->SetValue(i, 2, d * sqrt(ss)/sqrt(ny[i]));
+ break;
+ }
+ }
+ else curr_data->SetValue(i, 2, 0.0);
+ if(curr_data->GetValue(i, 1, &y) && curr_data->GetValue(i, 2, &hi))
+ curr_data->SetValue(i, 4, hi+y);
+ break;
+ case 0x0400: //percentiles
+ curr_data->SetValue(i, 2, q1[i]); curr_data->SetValue(i, 3, q3[i]);
+ curr_data->SetValue(i, 4, q3[i]);
+ break;
+ case 0x0800: //min-max
+ lo = hi = *ay[i];
+ for(k = 1; k < ny[i]; k++) {
+ if(ay[i][k] < lo) lo = ay[i][k];
+ if(ay[i][k] > hi) hi = ay[i][k];
+ }
+ curr_data->SetValue(i, 2, lo); curr_data->SetValue(i, 3, hi);
+ curr_data->SetValue(i, 4, hi);
+ break;
+ }
+ }
+ if(type & 0x6000) for(i = 0; i < j; i++) { // number of cases
+ sprintf(TmpTxt, "%s%d", case_prefix ? case_prefix : "", ny[i]);
+ curr_data->SetText(i, 5, TmpTxt);
+ }
+ }
+ else {
+ if(curr_data) delete curr_data;
+ curr_data = 0L;
+ }
+ if(q1) free(q1); if(q2) free(q2); if(q3) free(q3);
+ for(i = 0; i < m; i++) if(ay[i]) free(ay[i]);
+ free(tay); free(ay); free(ax); free(ny); free(xy);
+}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// BarChart is based on scatterplot
@@ -665,6 +888,8 @@ FreqDist::~FreqDist()
for(i = 0; i < nPlots; i++) if(plots[i]) DeleteGO(plots[i]);
free(plots); plots=0L;
}
+ if(name) free(name); name=0L;
+
}
void
@@ -854,11 +1079,9 @@ FreqDist::ProcData(int sel)
cb += sprintf(fo+cb,"x2= %g\n", max);
cb += sprintf(fo+cb,"xstep= %g\n", (max-min)/100.0);
cb += sprintf(fo+cb,"Line= 0.4 6 0x000000ff 0x0\n");
-
cb += sprintf(fo+cb,"f_xy=\"A=%g; SD=%g; M=%g\\n", nv*step, sd, mean);
cb += sprintf(fo+cb,"ex=(x-M)/SD; ex=-0.5*ex*ex\\n");
cb += sprintf(fo+cb,"y=(A/(SD*2.5066283))*exp(ex)\\n\"\n");
-
OpenGraph(this, 0L, (unsigned char *)fo);
free(fo);
}
@@ -891,6 +1114,7 @@ Regression::Regression(int src):Plot(0L, 0L)
Regression::~Regression()
{
Command(CMD_FLUSH, 0L, 0L);
+ if(name) free(name); name=0L;
Undo.InvalidGO(this);
}
@@ -1035,7 +1259,7 @@ Regression::Command(int cmd, void *tmpl, anyOutput *o)
return SavVarObs((GraphObj **)Symbols, nPoints, 0L);
case CMD_UPDATE:
if(Symbols) {
- Undo.ObjConf(this, UNDO_CONTINUE);
+ SavVarObs((GraphObj**)Symbols, nPoints, UNDO_CONTINUE);
for(i = 0; i < nPoints; i++)
if(Symbols[i]) Symbols[i]->Command(cmd, tmpl, o);
if(rLine || sde) Recalc();
@@ -1158,6 +1382,7 @@ BubblePlot::~BubblePlot()
for(i = 0; i < nPoints; i++) if(Bubbles[i]) DeleteGO(Bubbles[i]);
free (Bubbles);
}
+ if(name) free(name); name=0L;
Undo.InvalidGO(this);
}
@@ -1218,10 +1443,14 @@ BubblePlot::Command(int cmd, void *tmpl, anyOutput *o)
}
}
return false;
+ case CMD_LEGEND:
+ if(((GraphObj*)tmpl)->Id != GO_LEGEND) return false;
+ if(Bubbles) for (i = 0; i < nPoints; i++)
+ if(Bubbles[i]) Bubbles[i]->Command(cmd, tmpl, o);
+ return true;
case CMD_MRK_DIRTY:
dirty = true;
- case CMD_SETSCROLL:
- case CMD_REDRAW:
+ case CMD_SETSCROLL: case CMD_REDRAW:
if(parent) return parent->Command(cmd, tmpl, o);
return false;
case CMD_USEAXIS:
@@ -1231,10 +1460,12 @@ BubblePlot::Command(int cmd, void *tmpl, anyOutput *o)
Id = GO_BUBBLEPLOT;
data = (DataObj *)tmpl;
case CMD_UPDATE:
- if(cmd == CMD_UPDATE) Undo.ObjConf(this, UNDO_CONTINUE);
- case CMD_BUBBLE_ATTRIB:
- case CMD_BUBBLE_TYPE:
- case CMD_BUBBLE_FILL:
+ if(cmd == CMD_UPDATE && Bubbles) SavVarObs((GraphObj **)Bubbles, nPoints, UNDO_CONTINUE);
+ case CMD_AUTOSCALE:
+ if(cmd == CMD_AUTOSCALE && Bubbles) {
+ Bounds.Xmax = Bounds.Ymax = -HUGE_VAL; Bounds.Xmin = Bounds.Ymin = HUGE_VAL;
+ }
+ case CMD_BUBBLE_ATTRIB: case CMD_BUBBLE_TYPE: case CMD_BUBBLE_FILL:
case CMD_BUBBLE_LINE:
if(Bubbles) for(i = 0; i < nPoints; i++)
if(Bubbles[i]) Bubbles[i]->Command(cmd, tmpl, o);
@@ -1292,6 +1523,7 @@ PolarPlot::~PolarPlot()
for(i = 0; i < nAxes; i++) if(Axes[i]) DeleteGO(Axes[i]);
free(Axes); Axes = 0L;
}
+ if(name) free(name); name=0L;
Undo.InvalidGO(this);
}
@@ -1486,6 +1718,8 @@ BoxPlot::BoxPlot(int src):Plot(0L, 0L)
for(i = 0; i < nPoints; i++) if(Whiskers[i]) Whiskers[i]->parent = this;
if(Symbols)
for(i = 0; i < nPoints; i++) if(Symbols[i]) Symbols[i]->parent = this;
+ if(Labels)
+ for(i = 0; i < nPoints; i++) if(Labels[i]) Labels[i]->parent = this;
if(TheLine) TheLine->parent = this;
}
}
@@ -1514,18 +1748,27 @@ BoxPlot::~BoxPlot()
int i;
if(Whiskers) {
- for(i = 0; i < nPoints; i++) if(Whiskers[i]) delete(Whiskers[i]);
+ for(i = 0; i < nPoints; i++) if(Whiskers[i]) DeleteGO(Whiskers[i]);
free (Whiskers);
}
if(Boxes) {
- for(i = 0; i < nPoints; i++) if(Boxes[i]) delete(Boxes[i]);
+ for(i = 0; i < nPoints; i++) if(Boxes[i]) DeleteGO(Boxes[i]);
free (Boxes);
}
if(Symbols) {
- for(i = 0; i < nPoints; i++) if(Symbols[i]) delete(Symbols[i]);
+ for(i = 0; i < nPoints; i++) if(Symbols[i]) DeleteGO(Symbols[i]);
free (Symbols);
}
- if(TheLine) delete(TheLine);
+ if(Labels) {
+ for(i = 0; i < nPoints; i++) if(Labels[i]) DeleteGO(Labels[i]);
+ free (Labels);
+ }
+ if(TheLine) DeleteGO(TheLine);
+ if(curr_data) delete curr_data; curr_data = 0L;
+ if(xRange) free(xRange); xRange = 0L;
+ if(yRange) free(yRange); yRange = 0L;
+ if(case_prefix) free(case_prefix); case_prefix = 0L;
+ if(name) free(name); name=0L;
Undo.InvalidGO(this);
}
@@ -1533,35 +1776,35 @@ double
BoxPlot::GetSize(int select)
{
int i;
- double ft1, ft2;
+ double ft1, ft2, d;
switch(select){
case SIZE_BOXMINX:
if(BoxDist.fx >= 0.0001) return BoxDist.fx;
- if((!Boxes) | (nPoints < 2)) return 1.0;
- ft1 = ft2 = 1.0;
- if(Boxes[0] && Boxes[1]) ft1 = fabs(Boxes[1]->GetSize(SIZE_XPOS) -
- Boxes[0]->GetSize(SIZE_XPOS));
- else return 1.0;
- for(i = 2; i < nPoints; i++) {
- if(Boxes[i] && Boxes[i-1]) ft2 = fabs(Boxes[i]->
- GetSize(SIZE_XPOS) - Boxes[i-1]->GetSize(SIZE_XPOS));
- if(ft2 < ft1 || ft1 < 0.0001) ft1 = ft2;
- }
- return BoxDist.fx = ft1 > 0.0001 ? ft1 : 1.0;
+ if((!Boxes) || (nPoints < 2)) return BoxDist.fx = 1.0;
+ ft1 = -HUGE_VAL; ft2 = HUGE_VAL; BoxDist.fx= HUGE_VAL;
+ for(i = 0; i < nPoints; i++) {
+ if(Boxes[i]) {
+ ft2 = Boxes[i]->GetSize(SIZE_XPOS);
+ d = fabs(ft2-ft1);
+ if(d != 0.0 && d < BoxDist.fx) BoxDist.fx = d;
+ }
+ ft1 = ft2;
+ }
+ return BoxDist.fx = BoxDist.fx > 0.0001 && BoxDist.fx != HUGE_VAL ? BoxDist.fx : 1.0;
case SIZE_BOXMINY:
if(BoxDist.fy >= 0.0001) return BoxDist.fy;
- if((!Boxes) | (nPoints < 2)) return 1.0f;
- ft1 = ft2 = 1.0f;
- if(Boxes[0] && Boxes[1]) ft1 = fabs(Boxes[1]->GetSize(SIZE_YPOS) -
- Boxes[0]->GetSize(SIZE_YPOS));
- else return 1.0f;
- for(i = 2; i < nPoints; i++) {
- if(Boxes[i] && Boxes[i-1]) ft2 = fabs(Boxes[i]->
- GetSize(SIZE_YPOS) - Boxes[i-1]->GetSize(SIZE_YPOS));
- if(ft2 < ft1 || ft1 < 0.0001f) ft1 = ft2;
- }
- return BoxDist.fy = ft1 > 0.0001 ? ft1 : 1.0f;
+ if((!Boxes) || (nPoints < 2)) return BoxDist.fy = 1.0;
+ ft1 = -HUGE_VAL; ft2 = HUGE_VAL; BoxDist.fy= HUGE_VAL;
+ for(i = 0; i < nPoints; i++) {
+ if(Boxes[i]) {
+ ft2 = Boxes[i]->GetSize(SIZE_YPOS);
+ d = fabs(ft2-ft1);
+ if(d != 0.0 && d < BoxDist.fy) BoxDist.fy = d;
+ }
+ ft1 = ft2;
+ }
+ return BoxDist.fy = BoxDist.fy > 0.0001 && BoxDist.fy != HUGE_VAL ? BoxDist.fy : 1.0;
default:
return Plot::GetSize(select);
}
@@ -1573,21 +1816,22 @@ BoxPlot::SetSize(int select, double value)
int i;
switch(select & 0xfff){
- case SIZE_SYMBOL:
- case SIZE_SYM_LINE:
+ case SIZE_SYMBOL: case SIZE_SYM_LINE:
if(Symbols) for(i = 0; i < nPoints; i++)
if(Symbols[i]) Symbols[i]->SetSize(select, value);
return true;
- case SIZE_WHISKER:
- case SIZE_WHISKER_LINE:
+ case SIZE_WHISKER: case SIZE_WHISKER_LINE:
if(Whiskers) for(i = 0; i < nPoints; i++)
if(Whiskers[i]) Whiskers[i]->SetSize(select, value);
return true;
- case SIZE_BOX:
- case SIZE_BOX_LINE:
+ case SIZE_BOX: case SIZE_BOX_LINE:
if(Boxes) for(i = 0; i < nPoints; i++)
if(Boxes[i]) Boxes[i]->SetSize(select, value);
return true;
+ case SIZE_LB_XDIST: case SIZE_LB_YDIST:
+ if(Labels) for(i = 0; i < nPoints; i++)
+ if(Labels[i]) Labels[i]->SetSize(select, value);
+ return true;
}
return false;
}
@@ -1598,8 +1842,7 @@ BoxPlot::SetColor(int select, DWORD col)
int i;
switch(select) {
- case COL_SYM_LINE:
- case COL_SYM_FILL:
+ case COL_SYM_LINE: case COL_SYM_FILL:
if(Symbols) for(i = 0; i < nPoints; i++)
if(Symbols[i]) Symbols[i]->SetColor(select, col);
return true;
@@ -1619,18 +1862,10 @@ BoxPlot::SetColor(int select, DWORD col)
void
BoxPlot::DoPlot(anyOutput *o)
{
- int i;
-
- if(!parent) return;
+ if(!parent || !o) return;
parent->Command(CMD_REG_AXISPLOT, (void*)this, o);
if(use_xaxis || use_yaxis) ApplyAxes(o);
- if(TheLine) TheLine->DoPlot(o);
- if(Whiskers)
- for(i = 0; i < nPoints; i++) if(Whiskers[i]) Whiskers[i]->DoPlot(o);
- if(Boxes)
- for(i = 0; i < nPoints; i++) if(Boxes[i]) Boxes[i]->DoPlot(o);
- if(Symbols)
- for(i = 0; i < nPoints; i++) if(Symbols[i]) Symbols[i]->DoPlot(o);
+ ForEach(FE_PLOT, 0L, o);
dirty = false;
if(use_xaxis || use_yaxis)parent->Command(CMD_AXIS, 0L, o);
}
@@ -1638,102 +1873,89 @@ BoxPlot::DoPlot(anyOutput *o)
bool
BoxPlot::Command(int cmd, void *tmpl, anyOutput *o)
{
- int i, j;
- bool bRedraw;
- MouseEvent *mev;
- GraphObj **obs[] = {(GraphObj**)Boxes, (GraphObj**)Whiskers, (GraphObj**)Symbols};
- GraphObj ***go;
+ int i;
switch (cmd) {
case CMD_MOUSE_EVENT:
if(hidden) return false;
- mev = (MouseEvent *) tmpl;
- switch(mev->Action) {
- case MOUSE_LBUP:
- for(j = 2; j >= 0 && !CurrGO; j--) { //invers to plot order
- if(obs[j]) for (i = nPoints-1; i >= 0; i--)
- if(obs[j][i]) if(obs[j][i]->Command(cmd, tmpl, o))break;
+ if(!CurrGO && ((MouseEvent*)tmpl)->Action == MOUSE_LBUP) return ForEach(cmd, tmpl, o);
+ return false;
+ case CMD_LEGEND:
+ if(((GraphObj*)tmpl)->Id != GO_LEGEND) return false;
+ if(Boxes) for (i = 0; i < nPoints; i++) if(Boxes[i]) Boxes[i]->Command(cmd, tmpl, o);
+ if(Symbols) {
+ if(TheLine && TheLine->Id == GO_DATALINE) {
+ for (i = 0; i < nPoints && i < 100; i++)
+ if(Symbols[i]) ((Legend*)tmpl)->HasSym(&TheLine->LineDef, Symbols[i]);
}
- if(TheLine && !CurrGO) TheLine->Command(cmd, tmpl, o);
- break;
+ else {
+ for (i = 0; i < nPoints && i < 100; i++)
+ if(Symbols[i]) ((Legend*)tmpl)->HasSym(0L, Symbols[i]);
+ }
+ if(TheLine && TheLine->Id == GO_DATAPOLYGON) TheLine->Command(cmd, tmpl, o);
}
- break;
- case CMD_LEGEND:
- if(Boxes) for (i = 0; i < nPoints; i++)
- if(Boxes[i]) Boxes[i]->Command(cmd, tmpl, o);
+ else if(TheLine) TheLine->Command(cmd, tmpl, o);
break;
case CMD_SET_DATAOBJ:
Id = GO_BOXPLOT; data = (DataObj *)tmpl; dirty = true;
+ if(type && xRange && yRange && data) { //Stat. - Plot ?
+ CreateData();
+ return ForEach(CMD_SET_DATAOBJ, curr_data, o);
+ }
+ return ForEach(cmd, tmpl, o);
case CMD_AUTOSCALE:
- if(cmd == CMD_AUTOSCALE){
- if(hidden) return false;
- if(dirty) {
- Bounds.Xmin = Bounds.Ymin = HUGE_VAL;
- Bounds.Xmax = Bounds.Ymax = -HUGE_VAL;
- }
- else{
- if(parent && parent->Id >= GO_PLOT && parent->Id < GO_GRAPH &&
- Bounds.Xmax > Bounds.Xmin && Bounds.Ymax > Bounds.Ymin) {
- ((Plot*)parent)->CheckBounds(Bounds.Xmin, Bounds.Ymin);
- ((Plot*)parent)->CheckBounds(Bounds.Xmax, Bounds.Ymax);
- return true;
- }
- }
- dirty = false;
+ if(hidden) return false;
+ if(dirty) {
+ Bounds.Xmin = Bounds.Ymin = HUGE_VAL;
+ Bounds.Xmax = Bounds.Ymax = -HUGE_VAL;
}
- case CMD_UPDATE:
- if(cmd == CMD_UPDATE) Undo.ObjConf(this, UNDO_CONTINUE);
- for(j = 0; j < 3; j++) {
- if(obs[j]) for (i = 0; i < nPoints; i++)
- if(obs[j][i]) obs[j][i]->Command(cmd, tmpl, o);
+ else{
+ if(parent && parent->Id >= GO_PLOT && parent->Id < GO_GRAPH &&
+ Bounds.Xmax > Bounds.Xmin && Bounds.Ymax > Bounds.Ymin) {
+ ((Plot*)parent)->CheckBounds(Bounds.Xmin, Bounds.Ymin);
+ ((Plot*)parent)->CheckBounds(Bounds.Xmax, Bounds.Ymax);
+ return true;
+ }
}
- if(TheLine) TheLine->Command(cmd, tmpl, o);
- if(cmd == CMD_AUTOSCALE && parent && parent->Id > GO_PLOT && parent->Id < GO_GRAPH
+ dirty = false;
+ ForEach(cmd, tmpl, o);
+ if(parent && parent->Id > GO_PLOT && parent->Id < GO_GRAPH
&& Bounds.Xmax > Bounds.Xmin && Bounds.Ymax > Bounds.Ymin){
((Plot*)parent)->CheckBounds(Bounds.Xmin, Bounds.Ymin);
((Plot*)parent)->CheckBounds(Bounds.Xmax, Bounds.Ymax);
}
return true;
+ case CMD_UPDATE:
+ if(Boxes) SavVarObs((GraphObj **)Boxes, nPoints, UNDO_CONTINUE);
+ if(Whiskers) SavVarObs((GraphObj **)Whiskers, nPoints, UNDO_CONTINUE);
+ if(Symbols) SavVarObs((GraphObj **)Symbols, nPoints, UNDO_CONTINUE);
+ if(Labels) SavVarObs((GraphObj **)Labels, nPoints, UNDO_CONTINUE);
+ if(type && xRange && yRange) { //Stat. - Plot ?
+ CreateData();
+ ForEach(CMD_SET_DATAOBJ, curr_data, o);
+ }
+ ForEach(cmd, tmpl, o);
+ return dirty = true;
case CMD_USEAXIS:
UseAxis(*((int*)tmpl));
return true;
case CMD_MRK_DIRTY:
dirty = true;
- case CMD_SETSCROLL:
- case CMD_REDRAW:
- if(parent)return parent->Command(cmd, tmpl, o);
+ case CMD_SETSCROLL: case CMD_REDRAW:
+ if(parent) return parent->Command(cmd, tmpl, o);
return false;
+ case CMD_SETTEXTDEF:
+ if(Labels) for(i = 0; i < nPoints; i++)
+ if(Labels[i]) Labels[i]->Command(cmd, tmpl, o);
+ return true;
case CMD_DELOBJ:
- if(!parent || !o) return false;
- for(j = 0, bRedraw = false, go = 0L; j < 3 && !bRedraw; j++) {
- if(obs[j]) for(i = 0; i < nPoints; i++)
- if(obs[j][i] && tmpl == (void*)obs[j][i]) {
- o->HideMark();
- Undo.DeleteGO(&obs[j][i], 0L, o);
- switch(j) {
- case 0: go = (GraphObj***)&Boxes; break;
- case 1: go = (GraphObj***)&Whiskers; break;
- case 2: go = (GraphObj***)&Symbols; break;
- }
- bRedraw = true;
- break;
- }
- }
- if(!bRedraw && TheLine && tmpl == (void *) TheLine) {
- o->HideMark();
- Undo.DeleteGO((GraphObj**)(&TheLine), 0L, o);
- bRedraw = true;
+ if(ForEach(FE_DELOBJ, tmpl, o)) {
+ parent->Command(CMD_REDRAW, 0L, o);
+ return true;
}
- if(bRedraw && go) for(i = j = 0; i < nPoints; i++) if(go[0][i]) j++;
- if(!j) Undo.DropMemory(this, (void**)go, UNDO_CONTINUE);
- if(!Boxes && !Whiskers && !Symbols && !TheLine)
- parent->Command(CMD_DELOBJ_CONT, this, o);
- else if(bRedraw) parent->Command(CMD_REDRAW, NULL, o);
- return bRedraw;
- case CMD_SYMTEXT:
- case CMD_SYM_RANGETEXT:
- case CMD_SYMTEXTDEF:
- case CMD_SYM_TYPE:
+ return false;
+ case CMD_SYMTEXT: case CMD_SYM_RANGETEXT:
+ case CMD_SYMTEXTDEF: case CMD_SYM_TYPE:
if(Symbols) for(i = 0; i < nPoints; i++)
if(Symbols[i]) Symbols[i]->Command(cmd, tmpl, o);
return true;
@@ -1745,6 +1967,8 @@ BoxPlot::Command(int cmd, void *tmpl, anyOutput *o)
return SavVarObs((GraphObj **)Boxes, nPoints, UNDO_CONTINUE);
case CMD_SAVE_ERRS:
return SavVarObs((GraphObj **)Whiskers, nPoints, 0L);
+ case CMD_SAVE_LABELS:
+ return SavVarObs((GraphObj **)Labels, nPoints, 0L);
case CMD_BOX_TYPE:
BoxDist.fy = BoxDist.fx = 0.0;
case CMD_BOX_FILL:
@@ -1759,6 +1983,230 @@ BoxPlot::Command(int cmd, void *tmpl, anyOutput *o)
return false;
}
+bool
+BoxPlot::ForEach(int cmd, void *tmpl, anyOutput *o)
+{
+ GraphObj ***pobs[] = {(GraphObj***)&Boxes, (GraphObj***)&Whiskers,
+ (GraphObj***)&Symbols, (GraphObj***)&Labels};
+ GraphObj **p;
+ int i, j;
+ bool bRet;
+
+ switch(cmd) {
+ case FE_DELOBJ:
+ if(!o || !parent || !tmpl) return false;
+ for(i = 0; i < 4; i++) {
+ if(DeleteGOL(pobs[i], nPoints, (GraphObj*) tmpl, o)) return true;
+ }
+ if(TheLine && tmpl == (void *) TheLine) {
+ Undo.DeleteGO((GraphObj**)(&TheLine), 0L, o);
+ return true;
+ }
+ break;
+ case FE_PLOT:
+ if(TheLine) TheLine->DoPlot(o);
+ for(i = 0; i < 4; i++){
+ if(p= *pobs[i]) for(j = 0; j < nPoints; j++) {
+ if(p[j]) p[j]->DoPlot(o);
+ }
+ }
+ return true;
+ case CMD_MOUSE_EVENT: //invers to plot order
+ for(i = 3; i >= 0; i--){
+ if(p= *pobs[i]) for(j = nPoints-1; j >= 0; j--) {
+ if(p[j]) {
+ bRet = p[j]->Command(cmd, tmpl, o);
+ if(bRet && cmd == CMD_MOUSE_EVENT) return true;
+ }
+ }
+ }
+ if(TheLine) return TheLine->Command(cmd, tmpl, o);
+ return false;
+ default: //pass command to all objects
+ for(i = 0; i < 4; i++){
+ if(p= *pobs[i]) for(j = 0; j < nPoints; j++) {
+ if(p[j]) {
+ bRet = p[j]->Command(cmd, tmpl, o);
+ }
+ }
+ }
+ if(TheLine) return TheLine->Command(cmd, tmpl, o);
+ return false;
+ }
+ return false;
+}
+
+void
+BoxPlot::CreateData()
+{
+ int i, j, k, l, m, n, *ny;
+ double x, y, ss, d, lo, hi, **ay, *ax, *tay, *q1, *q2, *q3;
+ lfPOINT *xy;
+ AccRange *rX, *rY;
+
+ if(curr_data) delete curr_data; curr_data = 0L;
+ if(!data || !xRange || !yRange || !xRange[0] || !yRange[0]) return;
+ if(!(rX = new AccRange(xRange)) || !(rY = new AccRange(yRange))) return;
+ m = rX->CountItems(); n = 0;
+ if(m < 2 || !(xy = (lfPOINT*) malloc(m * sizeof(lfPOINT)))) {
+ delete rX; delete rY;
+ return;
+ }
+ ny = (int*) calloc(m, sizeof(int));
+ ay = (double**) calloc(m, sizeof(double*));
+ ax = (double*) calloc(m, sizeof(double));
+ tay = (double*)malloc(m * sizeof(double));
+ if(!ny || !ay || !ax || !tay) {
+ if(ny) free(ny); if(ay) free(ay);
+ if(ax) free(ax); if(tay) free(tay);
+ delete rX; delete rY;
+ return;
+ }
+ rX->GetFirst(&i, &j); rY->GetFirst(&k, &l);
+ rX->GetNext(&i, &j); rY->GetNext(&k, &l); n=0;
+ do {
+ if(data->GetValue(j, i, &x) && data->GetValue(l, k, &y)){
+ xy[n].fx = x; xy[n].fy = y;
+ n++;
+ }
+ }while(rX->GetNext(&i, &j) && rY->GetNext(&k, &l));
+ delete rX; delete rY;
+ if(!n) {
+ if(ny) free(ny); if(ay) free(ay);
+ if(ax) free(ax); if(tay) free(tay);
+ return;
+ }
+ SortFpArray(n, xy);
+ for(i = j = 0; i < (n-1); i++, j++) {
+ ax[j] = xy[i].fx; tay[0] = xy[i].fy;
+ ny[j] = 1;
+ for(k = 1; xy[i+1].fx == xy[i].fx; k++) {
+ tay[k] = xy[i+1].fy;
+ i++; ny[j]++;
+ }
+ ay[j] = (double*)memdup(tay, k * sizeof(double), 0);
+ }
+ if(xy[i].fx > xy[i-1].fx) {
+ ax[j] = xy[i].fx; tay[0] = xy[i].fy;
+ ny[j] = 1;
+ ay[j++] = (double*)memdup(tay, sizeof(double), 0);
+ }
+ if((type & 0x0004) == 0x0004 || (type & 0x0030) == 0x0030 || (type & 0x0300) == 0x0300) {
+ //medians and/or percentiles required
+ q1 = (double *)malloc(j * sizeof(double));
+ q2 = (double *)malloc(j * sizeof(double));
+ q3 = (double *)malloc(j * sizeof(double));
+ if(q1 && q2 && q3) {
+ for(i = 0; i < j; i++) {
+ if(ny[i] > 1) d_quartile(ny[i], ay[i], q1+i, q2+i, q3+i);
+ else q1[i] = q2[i] = q3[i] = *ay[i];
+ }
+ }
+ else type = 0;
+ }
+ else q1 = q2 = q3 = 0L;
+ if(type && (curr_data = new DataObj()) && curr_data->Init(j, 8)) {
+ for(i = 0; i < j; i++) curr_data->SetValue(i,0,ax[i]); // set x-values
+ for(i = 0; i < j; i++) { // set means
+ if(ny[i] > 1) switch(type & 0x000f) {
+ case 0x0001: default:
+ curr_data->SetValue(i, 1, y=d_amean(ny[i], ay[i]));
+ break;
+ case 0x0002:
+ curr_data->SetValue(i, 1, y=d_gmean(ny[i], ay[i]));
+ break;
+ case 0x0003:
+ curr_data->SetValue(i, 1, y=d_hmean(ny[i], ay[i]));
+ break;
+ case 0x0004:
+ curr_data->SetValue(i, 1, y=q2[i]);
+ break;
+ }
+ else curr_data->SetValue(i, 1, y= *ay[i]);
+ curr_data->SetValue(i, 6, y); //label's y
+ }
+ if((type & 0x00f0) == 0x0010 || (type & 0x00f0) == 0x0020 || (type & 0x00f0) == 0x0050
+ || (type & 0x0f0f) == 0x0201 || (type & 0x0f0f) == 0x0501) for(i = 0; i < j; i++) {
+ // set SD, SE, Conf. Intervall
+ if(ny[i] > 1) {
+ y = d_amean(ny[i], ay[i]);
+ for(k = 0, ss = 0.0; k < (ny[i]); k++) {
+ ss += ((d=ay[i][k]-y)*d);
+ ny[i] = ny[i];
+ }
+ ss = sqrt(ss/(double)(ny[i]-1));
+ }
+ else {
+ y = *ay[i]; ss = 0.0;
+ }
+ //Box info is in cols 2 & 3
+ if((type & 0x00f0) == 0x0010) {
+ curr_data->SetValue(i, 2, y - ss); curr_data->SetValue(i, 3, y + ss);
+ }
+ else if((type & 0x00f0) == 0x0020) {
+ curr_data->SetValue(i, 2, y - ss/sqrt(ny[i]));
+ curr_data->SetValue(i, 3, y + ss/sqrt(ny[i]));
+ }
+ else if((type & 0x00f0) == 0x0050) {
+ d = ny[i] > 1 ? distinv(t_dist, ny[i]-1, 1, 1.0-(ci_box/100.0), 2.0) : 0;
+ curr_data->SetValue(i, 2, y - d*ss/sqrt(ny[i]));
+ curr_data->SetValue(i, 3, y + d*ss/sqrt(ny[i]));
+ }
+ //Whisker info is in cols 4 & 5
+ if((type & 0x0f0f) == 0x0101) {
+ curr_data->SetValue(i, 4, y - ss); curr_data->SetValue(i, 5, y + ss);
+ }
+ else if((type & 0x0f0f) == 0x0201) {
+ curr_data->SetValue(i, 4, y - ss/sqrt(ny[i]));
+ curr_data->SetValue(i, 5, y + ss/sqrt(ny[i]));
+ }
+ else if((type & 0x0f0f) == 0x0501) {
+ d = ny[i] > 1 ? distinv(t_dist, ny[i]-1, 1, 1.0-(ci_err/100.0), 2.0) : 0;
+ curr_data->SetValue(i, 4, y - d*ss/sqrt(ny[i]));
+ curr_data->SetValue(i, 5, y + d*ss/sqrt(ny[i]));
+ }
+ }
+ if((type & 0x00f0) == 0x0040 || (type & 0x0f00) == 0x0400) for(i = 0; i < j; i++) {
+ // set min and max
+ lo = hi = *ay[i];
+ if(ny[i] > 1) {
+ for(k = 1; k < ny[i]; k++) {
+ if(ay[i][k] < lo) lo = ay[i][k];
+ if(ay[i][k] > hi) hi = ay[i][k];
+ }
+ }
+ if((type & 0x00f0) == 0x0040) {
+ curr_data->SetValue(i, 2, lo); curr_data->SetValue(i, 3, hi);
+ }
+ if((type & 0x0f00) == 0x0400) {
+ curr_data->SetValue(i, 4, lo); curr_data->SetValue(i, 5, hi);
+ }
+ }
+ if(q1 && q3 && ((type & 0x00f0) == 0x0030 || (type & 0x0f00) == 0x0300)) for(i = 0; i < j; i++) {
+ // percentiles ....
+ if((type & 0x00f0) == 0x0030) {
+ curr_data->SetValue(i, 2, q1[i]); curr_data->SetValue(i, 3, q3[i]);
+ }
+ if((type & 0x0f00) == 0x0300) {
+ curr_data->SetValue(i, 4, q1[i]); curr_data->SetValue(i, 5, q3[i]);
+ }
+ }
+ if(type & 0xc000) for(i = 0; i < j; i++) {
+ //labels ...
+ if((type & 0x4000) && curr_data->GetValue(i, 5, &y)) curr_data->SetValue(i, 6, y);
+ sprintf(TmpTxt, "%s%d", case_prefix ? case_prefix : "", ny[i]);
+ curr_data->SetText(i, 7, TmpTxt);
+ }
+ }
+ else {
+ if(curr_data) delete curr_data;
+ curr_data = 0L;
+ }
+ if(q1) free(q1); if(q2) free(q2); if(q3) free(q3);
+ for(i = 0; i < m; i++) if(ay[i]) free(ay[i]);
+ free(tay); free(ay); free(ax); free(ny); free(xy);
+}
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Density distribution plot
DensDisp::DensDisp(GraphObj *par, DataObj *d):Plot(par, d)
@@ -1791,6 +2239,7 @@ DensDisp::~DensDisp()
}
if(yRange) free(yRange); if(xRange) free(xRange);
yRange = xRange = 0L;
+ if(name) free(name); name=0L;
Undo.InvalidGO(this);
}
@@ -1852,8 +2301,7 @@ DensDisp::Command(int cmd, void *tmpl, anyOutput *o)
switch (cmd) {
case CMD_MRK_DIRTY:
dirty = true;
- case CMD_SETSCROLL:
- case CMD_REDRAW:
+ case CMD_SETSCROLL: case CMD_REDRAW:
if(parent) return parent->Command(cmd, tmpl, o);
return false;
case CMD_USEAXIS:
@@ -1877,13 +2325,8 @@ DensDisp::Command(int cmd, void *tmpl, anyOutput *o)
return true;
case CMD_DELOBJ:
if(!parent || !o) return false;
- for(i = 0; i < nPoints; i++) {
- if(Boxes[i] && tmpl == (void*)Boxes[i]){
- o->HideMark();
- Undo.DeleteGO((GraphObj**)(&Boxes[i]), 0L, o);
- return parent->Command(CMD_REDRAW, NULL, o);
- }
- }
+ if(DeleteGOL((GraphObj***)&Boxes, nPoints, (GraphObj*)tmpl, o))
+ return parent->Command(CMD_REDRAW, 0L, o);
break;
case CMD_AUTOSCALE:
if(dirty){
@@ -1892,13 +2335,12 @@ DensDisp::Command(int cmd, void *tmpl, anyOutput *o)
}
else return true;
dirty = false;
- case CMD_BOX_TYPE:
- case CMD_BOX_FILL:
+ case CMD_BOX_TYPE: case CMD_BOX_FILL:
if(Boxes) for (i = 0; i < nPoints; i++)
if(Boxes[i]) Boxes[i]->Command(cmd, tmpl, o);
return true;
case CMD_UPDATE:
- Undo.ObjConf(this, UNDO_CONTINUE);
+ if(Boxes) SavVarObs((GraphObj **)Boxes, nPoints, UNDO_CONTINUE);
DoUpdate();
return true;
}
@@ -1912,15 +2354,17 @@ DensDisp::DoUpdate()
int i, j, k, l, ic, n;
double v, w;
lfPOINT fp1, fp2;
+ Box **op = Boxes;
if(xRange && yRange && (rX = new AccRange(xRange)) && (rY = new AccRange(yRange))) {
if((n=rX->CountItems()) == rY->CountItems()) {
- if(Boxes) {
- for(i = 0; i < nPoints; i++) if(Boxes[i]) DeleteGO(Boxes[i]);
- free (Boxes);
- }
Bounds.Xmin = Bounds.Ymin = HUGE_VAL; Bounds.Xmax = Bounds.Ymax = -HUGE_VAL;
- Boxes = (Box**)calloc(nPoints = n, sizeof(Box*));
+ if(!(Boxes = (Box**)realloc(Boxes, n * sizeof(Box*)))) return;
+ if(op && op != Boxes) Undo.InvalidGO(this);
+ for(i = nPoints; i < n; i++) {
+ Boxes[i] = 0L;
+ }
+ nPoints = n;
rX->GetFirst(&i, &j); rY->GetFirst(&k, &l);
rX->GetNext(&i, &j); rY->GetNext(&k, &l);
for(ic = 0; ic < n && !data->GetValue(j, i, &v); ic++) {
@@ -1936,7 +2380,7 @@ DensDisp::DoUpdate()
ic = 0;
do {
if(data->GetValue(j, i, &v) && data->GetValue(l, k, &w)){
- memcpy(&fp1, &fp2, sizeof(lfPOINT));
+ fp1.fx = fp2.fx; fp1.fy = fp2.fy;
if(type & 0x10) {
CheckBounds(w, fp1.fy); CheckBounds(-w, v);
fp2.fy = v;
@@ -1955,16 +2399,22 @@ DensDisp::DoUpdate()
default: fp2.fy = 0.0; break;
}
}
- if(Boxes[ic] = new Box(this, data, fp1, fp2, BAR_WIDTHDATA))
+ if(op && Boxes[ic]) {
+ Boxes[ic]->SetSize(SIZE_XPOS, fp1.fx); Boxes[ic]->SetSize(SIZE_XPOS+1, fp2.fx);
+ Boxes[ic]->SetSize(SIZE_YPOS, fp1.fy); Boxes[ic]->SetSize(SIZE_YPOS+1, fp2.fy);
+ Boxes[ic]->SetSize(SIZE_BOX, (type &0x03) ? w/2.0 : w);
+ }
+ else if(!op && (Boxes[ic] = new Box(this, data, fp1, fp2, BAR_WIDTHDATA)))
Boxes[ic]->SetSize(SIZE_BOX, (type &0x03) ? w/2.0 : w);
}
ic++;
}while(rX->GetNext(&i, &j) && rY->GetNext(&k, &l));
- SetSize(SIZE_BOX_LINE, DefLine.width);
- SetColor(COL_BOX_LINE, DefLine.color);
- Command(CMD_BOX_FILL, (void*)&DefFill, 0L);
+ if(!op) {
+ SetSize(SIZE_BOX_LINE, DefLine.width);
+ SetColor(COL_BOX_LINE, DefLine.color);
+ Command(CMD_BOX_FILL, (void*)&DefFill, 0L);
+ }
}
- else InfoBox("Error updating Plot!");
delete(rX); delete(rY);
}
}
@@ -2019,6 +2469,7 @@ StackBar::~StackBar()
}
if(ssXrange) free(ssXrange); if(ssYrange) free(ssYrange);
if(CumData) delete CumData; CumData = 0L;
+ if(name) free(name); name=0L;
Undo.InvalidGO(this);
}
@@ -2131,6 +2582,10 @@ StackBar::Command(int cmd, void *tmpl, anyOutput *o)
if(Boxes[i]) Boxes[i]->Command(cmd, tmpl, o);
if(Polygons) for (i = numPG-1; i >= 0; i--)
if(Polygons[i]) Polygons[i]->Command(cmd, tmpl, o);
+ if(Lines) for (i = numPL-1; i >= 0; i--)
+ if(Lines[i]) Lines[i]->Command(cmd, tmpl, o);
+ if(xyPlots) for (i = 0; i < numXY; i++)
+ if(xyPlots[i]) xyPlots[i]->Command(cmd, tmpl, o);
break;
case CMD_USEAXIS:
UseAxis(*((int*)tmpl));
@@ -2153,7 +2608,6 @@ StackBar::Command(int cmd, void *tmpl, anyOutput *o)
if(data == tmpl) return true;
data = (DataObj *)tmpl;
case CMD_AUTOSCALE: case CMD_UPDATE:
- if(cmd == CMD_UPDATE) Undo.ObjConf(this, UNDO_CONTINUE);
if(cmd == CMD_AUTOSCALE) {
if(hidden) return false;
Bounds.Xmin = Bounds.Ymin = HUGE_VAL;
@@ -2193,28 +2647,19 @@ StackBar::Command(int cmd, void *tmpl, anyOutput *o)
case CMD_DELOBJ:
if(o) o->HideMark();
if(!tmpl || !parent) return false;
- if(Polygons) for(i = 0; i < numPG; i++) if(Polygons[i] == tmpl) {
- Undo.DeleteGO((GraphObj**)(&Polygons[i]), 0L, o);
+ if(DeleteGOL((GraphObj***)&Polygons, numPG, (GraphObj*)tmpl, o))
return parent->Command(CMD_REDRAW, 0L, o);
- }
- if(Lines) for(i = 0; i < numPL; i++) if(Lines[i] == tmpl) {
- Undo.DeleteGO((GraphObj**)(&Lines[i]), 0L, o);
+ if(DeleteGOL((GraphObj***)&Lines, numPL, (GraphObj*)tmpl, o))
return parent->Command(CMD_REDRAW, 0L, o);
- }
- if(xyPlots) for(i = 0; i < numXY; i++){
- if(xyPlots[i] == tmpl) {
- Undo.DeleteGO((GraphObj**)(&xyPlots[i]), 0L, o);
- return parent->Command(CMD_REDRAW, 0L, o);
- }
- else if(xyPlots[i] && xyPlots[i]->Command(cmd, tmpl, o)) return true;
- }
- if(Boxes) for(i = 0; i < numPlots; i++){
- if(Boxes[i] == tmpl) {
- Undo.DeleteGO((GraphObj**)(&Boxes[i]), 0L, o);
- return parent->Command(CMD_REDRAW, 0L, o);
- }
- else if(Boxes[i] && Boxes[i]->Command(cmd, tmpl, o)) return true;
- }
+ if(DeleteGOL((GraphObj***)&xyPlots, numXY, (GraphObj*)tmpl, o))
+ return parent->Command(CMD_REDRAW, 0L, o);
+ if(DeleteGOL((GraphObj***)&Boxes, numPlots, (GraphObj*)tmpl, o))
+ return parent->Command(CMD_REDRAW, 0L, o);
+ if(xyPlots) for(i = 0; i < numXY; i++)
+ if(xyPlots[i] && xyPlots[i]->Command(cmd, tmpl, o)) return true;
+ if(Boxes) for(i = 0; i < numPlots; i++)
+ if(Boxes[i] && Boxes[i]->Command(cmd, tmpl, o)) return true;
+ return false;
}
return false;
}
@@ -2272,6 +2717,7 @@ PieChart::~PieChart()
}
if(ssRefA) free(ssRefA); if(ssRefR) free(ssRefR);
ssRefA = ssRefR = 0L;
+ if(name) free(name); name=0L;
Undo.InvalidGO(this);
}
@@ -2359,7 +2805,7 @@ PieChart::DoUpdate()
int i, ix, iy, rix, riy;
if(ssRefA && (rY = new AccRange(ssRefA))) {
- Undo.ObjConf(this, UNDO_CONTINUE);
+ SavVarObs((GraphObj **)Segments, nPts, UNDO_CONTINUE);
if(ssRefR) rR = new AccRange(ssRefR);
rY->GetFirst(&ix, &iy); rY->GetNext(&ix, &iy);
for(i = 0, sum = 0.0; i < nPts; i++){
@@ -2431,6 +2877,7 @@ GoGroup::~GoGroup()
for(i = 0; i < nObs; i++) if(Objects[i]) DeleteGO(Objects[i]);
free(Objects);
}
+ if(name) free(name); name=0L;
Undo.InvalidGO(this);
}
@@ -2594,6 +3041,7 @@ Scatt3D::~Scatt3D()
if(rib) {
DeleteGO(rib); rib = 0L;
}
+ if(name) free(name); name=0L;
}
double
@@ -2772,8 +3220,12 @@ Scatt3D::Command(int cmd, void *tmpl, anyOutput *o)
if(Balls[i]) ((Legend*)tmpl)->HasSym(&Line->Line, Balls[i]);
}
else {
- for (i = 0; i < nBalls && i < 100; i++)
- if(Balls[i]) ((Legend*)tmpl)->HasSym(0L, Balls[i]);
+ for (i = 0; i < nBalls && i < 100; i++) {
+ if(Balls[i]) {
+ if(Balls[i]->type) Balls[i]->Command(cmd, tmpl, o);
+ else ((Legend*)tmpl)->HasSym(0L, Balls[i]);
+ }
+ }
}
}
else if(Line) Line->Command(cmd, tmpl, o);
@@ -2785,15 +3237,22 @@ Scatt3D::Command(int cmd, void *tmpl, anyOutput *o)
Id = GO_SCATT3D;
data = (DataObj *)tmpl;
case CMD_UPDATE:
- if(cmd == CMD_UPDATE) Undo.ObjConf(this, UNDO_CONTINUE);
- if(Balls) for(i = 0; i < nBalls; i++)
- if(Balls[i]) Balls[i]->Command(cmd, tmpl, o);
- if(Columns) for(i = 0; i < nColumns; i++)
- if(Columns[i]) Columns[i]->Command(cmd, tmpl, o);
- if(DropLines) for(i = 0; i < nDropLines; i++)
- if(DropLines[i]) DropLines[i]->Command(cmd, tmpl, o);
- if(Arrows) for(i = 0; i < nArrows; i++)
- if(Arrows[i]) Arrows[i]->Command(cmd, tmpl, o);
+ if(Balls) {
+ SavVarObs((GraphObj**)Balls, nBalls, UNDO_CONTINUE);
+ for(i = 0; i < nBalls; i++) if(Balls[i]) Balls[i]->Command(cmd, tmpl, o);
+ }
+ if(Columns) {
+ SavVarObs((GraphObj**)Columns, nColumns, UNDO_CONTINUE);
+ for(i = 0; i < nColumns; i++) if(Columns[i]) Columns[i]->Command(cmd, tmpl, o);
+ }
+ if(DropLines) {
+ SavVarObs((GraphObj**)DropLines, nDropLines, UNDO_CONTINUE);
+ for(i = 0; i < nDropLines; i++) if(DropLines[i]) DropLines[i]->Command(cmd, tmpl, o);
+ }
+ if(Arrows) {
+ SavVarObs((GraphObj**)Arrows, nArrows, UNDO_CONTINUE);
+ for(i = 0; i < nArrows; i++) if(Arrows[i]) Arrows[i]->Command(cmd, tmpl, o);
+ }
if(Line) Line->Command(cmd, tmpl, o);
if(rib) rib->Command(cmd, tmpl, o);
return true;
@@ -2904,6 +3363,7 @@ Ribbon::~Ribbon()
free(planes); planes = 0L;
}
if(values) free(values); values = 0L; nVal = 0;
+ if(name) free(name); name=0L;
}
double
@@ -3184,10 +3644,13 @@ Ribbon::UpdateObs(bool bNewData)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// draw a 3dimensional grid
-Grid3D::Grid3D(GraphObj *par, DataObj *d)
+Grid3D::Grid3D(GraphObj *par, DataObj *d, int sel, double x1, double xstep, double z1, double zstep)
:Plot(par, d)
{
FileIO(INIT_VARS); Id = GO_GRID3D;
+ start.fx = x1; step.fx = xstep;
+ start.fz = z1; step.fz = zstep;
+ type = sel;
}
Grid3D::Grid3D(int src):Plot(0L, 0L)
@@ -3207,7 +3670,38 @@ Grid3D::~Grid3D()
for(i = 0; i < nLines; i++) if(lines[i]) DeleteGO(lines[i]);
free(lines); lines = 0L;
}
- nLines = 0;
+ if(planes) {
+ for(i = 0; i < nPlanes; i++) if(planes[i]) DeleteGO(planes[i]);
+ free(planes); planes = 0L;
+ }
+ nLines = nPlanes = 0;
+ if(name) free(name); name=0L;
+}
+
+bool
+Grid3D::SetSize(int select, double value)
+{
+ int i;
+
+ switch (select) {
+ case SIZE_SYM_LINE:
+ if(planes) for(i = 0; i < nPlanes; i++) if(planes[i]) planes[i]->SetSize(select, value);
+ return true;
+ }
+ return false;
+}
+
+bool
+Grid3D::SetColor(int select, DWORD col)
+{
+ int i;
+
+ switch (select) {
+ case COL_POLYLINE:
+ if(planes) for(i = 0; i < nPlanes; i++) if(planes[i]) planes[i]->SetColor(select, col);
+ return true;
+ }
+ return false;
}
void
@@ -3215,8 +3709,9 @@ Grid3D::DoPlot(anyOutput *o)
{
int i;
- if(!lines) CreateObs();
+ if(!lines && !planes) CreateObs();
if(lines) for(i = 0; i < nLines; i++) if(lines[i]) lines[i]->DoPlot(o);
+ if(planes) for(i = 0; i < nPlanes; i++) if(planes[i]) planes[i]->DoPlot(o);
dirty = false;
}
@@ -3234,17 +3729,29 @@ Grid3D::Command(int cmd, void *tmpl, anyOutput *o)
case MOUSE_LBUP:
if(lines && !CurrGO) for(i = 0; i < nLines; i++)
if(lines[i]) if(lines[i]->Command(cmd, tmpl, o)) return true;
+ if(planes && !CurrGO) for(i = 0; i < nPlanes; i++)
+ if(planes[i]) if(planes[i]->Command(cmd, tmpl, o)) return true;
break;
}
break;
case CMD_SET_LINE:
- if(tmpl && lines) {
- SavVarObs((GraphObj**)lines, nLines, 0L);
+ if(tmpl) {
memcpy(&Line, tmpl, sizeof(LineDEF));
- if(lines) for(i = 0; i < nLines; i++)
- if(lines[i]) lines[i]->Command(cmd, tmpl, o);
+ if(lines) {
+ SavVarObs((GraphObj**)lines, nLines, 0L);
+ for(i = 0; i < nLines; i++)
+ if(lines[i]) lines[i]->Command(cmd, tmpl, o);
+ }
+ if(planes) {
+ SavVarObs((GraphObj**)planes, nPlanes, 0L);
+ for(i = 0; i < nPlanes; i++)
+ if(planes[i]) planes[i]->Command(cmd, tmpl, o);
+ }
}
break;
+ case CMD_LEGEND:
+ if(!hidden) ((Legend*)tmpl)->HasFill(&Line, planes ? &Fill : 0L);
+ break;
case CMD_MRK_DIRTY:
dirty = true;
case CMD_SET_GO3D: case CMD_SETSCROLL: case CMD_REDRAW:
@@ -3252,34 +3759,42 @@ Grid3D::Command(int cmd, void *tmpl, anyOutput *o)
break;
case CMD_SET_DATAOBJ:
Id = GO_GRID3D;
+ if(tmpl == data) return true;
data = (DataObj *)tmpl;
- if(lines) for(i = 0; i < nLines; i++)
- if(lines[i]) lines[i]->Command(cmd, tmpl, o);
- return true;
case CMD_UPDATE:
- InfoBox("Don't know how to update Grid");
- return true;
+ if(lines) for(i = 0; i < nLines; i++) if(lines[i]) lines[i]->Command(cmd, tmpl, o);
+ if(planes) for(i = 0; i < nPlanes; i++) if(planes[i]) planes[i]->Command(cmd, tmpl, o);
+ return dirty = true;
case CMD_AUTOSCALE:
- if(!lines) CreateObs();
+ if(!lines && !planes) CreateObs();
if(dirty) {
Bounds.Xmin = Bounds.Ymin = HUGE_VAL; Bounds.Xmax = Bounds.Ymax = -HUGE_VAL;
xBounds.fx = yBounds.fx = zBounds.fx = HUGE_VAL;
xBounds.fy = yBounds.fy = zBounds.fy = -HUGE_VAL;
if(lines) for(i = 0; i < nLines; i++)
if(lines[i]) lines[i]->Command(cmd, tmpl, o);
+ if(planes) for(i = 0; i < nPlanes; i++)
+ if(planes[i]) planes[i]->Command(cmd, tmpl, o);
}
+ if(zBounds.fx > zBounds.fy) zBounds.fx = zBounds.fy = 0.0;
if(parent && parent->Id > GO_PLOT && parent->Id < GO_GRAPH &&
- xBounds.fx <= xBounds.fy && yBounds.fx <= yBounds.fy && zBounds.fx <= zBounds.fy){
+ xBounds.fx <= xBounds.fy && yBounds.fx <= yBounds.fy){
((Plot*)parent)->CheckBounds3D(xBounds.fx, yBounds.fx, zBounds.fx);
((Plot*)parent)->CheckBounds3D(xBounds.fy, yBounds.fy, zBounds.fy);
}
return true;
+ case CMD_SYM_FILL:
+ if(!tmpl) return false;
+ memcpy(&Fill, tmpl, sizeof(FillDEF));
+ if(planes) for(i = 0; i < nPlanes; i++) if(planes[i]) planes[i]->Command(cmd, tmpl, o);
+ return true;
+ case CMD_SAVE_SYMBOLS:
+ return SavVarObs((GraphObj **)planes, nPlanes, 0L);
case CMD_DELOBJ:
- if(!tmpl || !parent) return false;
- if(lines) for(i = 0; i < nLines; i++) if(lines[i] == tmpl) {
- Undo.DeleteGO((GraphObj**)(&lines[i]), 0L, o);
- return parent->Command(CMD_REDRAW, 0L, o);
- }
+ if(!parent) return false;
+ if(DeleteGOL((GraphObj***)&lines,nLines,(GraphObj*)tmpl,o)) return parent->Command(CMD_REDRAW, 0L, o);
+ if(DeleteGOL((GraphObj***)&planes,nPlanes,(GraphObj*)tmpl,o)) return parent->Command(CMD_REDRAW, 0L, o);
+ break;
}
return false;
}
@@ -3290,30 +3805,67 @@ Grid3D::CreateObs()
int i, ir, ic, idx, w, h;
fPOINT3D *vec;
- if(!parent || !data || lines) return;
- if(!(vec = (fPOINT3D*)malloc(sizeof(fPOINT3D) * 2))) return;
- data->GetSize(&w, &h);
- if(0 >= (nLines = 2 * w * h - w - h)) return;
- if(!(lines =(Line3D**)calloc(nLines, sizeof(Line3D*)))) return;
- vec[0].fx = start.fx; data->GetValue(0, 0, &vec[0].fy);
- for(ic = 1, idx = 0; ic <= w; ic++) {
- vec[0].fz = start.fz;
- data->GetValue(0, ic-1, &vec[0].fy);
- for(ir = 1; ir <= h; ir++){
- if(ic < w && data->GetValue(ir-1, ic, &vec[1].fy)) {
- vec[1].fx = vec[0].fx + step.fx; vec[1].fz = vec[0].fz;
- lines[idx++] = new Line3D(this, 0L, vec, 2);
+ if(!parent || !data || lines || planes) return;
+ dirty = true;
+ if(type == 0) {
+ if(!(vec = (fPOINT3D*)malloc(sizeof(fPOINT3D) * 2))) return;
+ data->GetSize(&w, &h);
+ if(0 >= (nLines = 2 * w * h - w - h)) return;
+ if(!(lines =(Line3D**)calloc(nLines, sizeof(Line3D*)))) return;
+ vec[0].fz = start.fz; data->GetValue(0, 0, &vec[0].fy);
+ for(ic = 1, idx = 0; ic <= w; ic++) {
+ vec[0].fx = start.fx;
+ data->GetValue(0, ic-1, &vec[0].fy);
+ for(ir = 1; ir <= h; ir++){
+ if(ic < w && data->GetValue(ir-1, ic, &vec[1].fy)) {
+ vec[1].fz = vec[0].fz + step.fz; vec[1].fx = vec[0].fx;
+ lines[idx++] = new Line3D(this, data, vec, 2,
+ -1, -1, ic-1, ir-1, -1, -1, -1, -1, ic, ir-1, -1, -1);
+ }
+ if(ir < h && data->GetValue(ir, ic-1, &vec[1].fy)) {
+ vec[1].fz = vec[0].fz; vec[1].fx = vec[0].fx + step.fx;
+ lines[idx++] = new Line3D(this, data, vec, 2,
+ -1, -1, ic-1, ir-1, -1, -1, -1, -1, ic-1, ir, -1, -1);
+ }
+ vec[0].fx += step.fx; vec[0].fy = vec[1].fy;
}
- if(ir < h && data->GetValue(ir, ic-1, &vec[1].fy)) {
- vec[1].fx = vec[0].fx; vec[1].fz = vec[0].fz + step.fz;
- lines[idx++] = new Line3D(this, 0L, vec, 2);
+ vec[0].fz += step.fz;
+ }
+ for(i = 0; i < nLines; i++) if(lines[i]) lines[i]->Command(CMD_SET_LINE, &Line, 0L);
+ free(vec);
+ }
+ else if(type == 1) {
+ if(!(vec = (fPOINT3D*)malloc(sizeof(fPOINT3D) * 5))) return;
+ vec[0].fz = vec[4].fz = start.fz;
+ vec[3].fz = (start.fz +step.fz);
+ data->GetSize(&w, &h);
+ if(0 >= (nPlanes = w * h)) return;
+ if(!(planes =(Plane3D**)calloc(nPlanes, sizeof(Plane3D*)))) return;
+ for(ic = 1, idx = 0; ic <= w; ic++) {
+ vec[0].fx = vec[3].fx = vec[4].fx = (start.fx+step.fx);
+ vec[1].fx = vec[2].fx = start.fx;
+ vec[1].fz = vec[4].fz; vec[2].fz = vec[3].fz;
+ data->GetValue(0, ic-1, &vec[1].fy); data->GetValue(0, ic, &vec[2].fy);
+ for(ir = 1; ir <= h; ir++){
+ if(ic < w && ir < h && data->GetValue(ir, ic, &vec[3].fy)
+ && data->GetValue(ir, ic-1, &vec[4].fy)) {
+ vec[0].fz = vec[4].fz; vec[0].fy = vec[4].fy; vec[0].fx = vec[4].fx;
+ planes[idx++] = new Plane3D(this, 0L, vec, 5);
+ }
+ vec[1].fz = vec[4].fz; vec[1].fy = vec[4].fy; vec[1].fx = vec[4].fx;
+ vec[2].fz = vec[3].fz; vec[2].fy = vec[3].fy; vec[2].fx = vec[3].fx;
+ vec[3].fx += step.fx; vec[4].fx += step.fx;
}
- vec[0].fz += step.fz; vec[0].fy = vec[1].fy;
+ vec[3].fz += step.fz; vec[4].fz += step.fz;
+ }
+ nPlanes = idx;
+ for(i = 0; i < nPlanes; i++) if(planes[i]){
+ planes[i]->Command(CMD_SET_LINE, &Line, 0L);
+ planes[i]->Command(CMD_SYM_FILL, &Fill, 0L);
}
- vec[0].fx += step.fx;
+ SetSize(SIZE_SYM_LINE, Line.width); SetColor(COL_POLYLINE, Line.color);
+ free(vec);
}
- for(i = 0; i < nLines; i++) if(lines[i]) lines[i]->Command(CMD_SET_LINE, &Line, 0L);
- free(vec);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -3328,6 +3880,7 @@ Limits::Limits(int src):Plot(0L, 0L)
Limits::~Limits()
{
+ if(name) free(name); name=0L;
}
double
@@ -3377,6 +3930,7 @@ Function::~Function()
if(cmdxy) free(cmdxy); cmdxy = 0L;
if(param) free(param); param = 0L;
if(dl) DeleteGO(dl); dl = 0L;
+ if(name) free(name); name=0L;
}
bool
@@ -3393,7 +3947,7 @@ Function::SetSize(int select, double value)
void
Function::DoPlot(anyOutput *o)
{
- if(!dl && cmdxy && cmdxy[0]) Update(o, 0);
+ if((!dl || dirty) && cmdxy && cmdxy[0]) Update(o, 0);
dirty = false;
if(dl && o) {
dl->Command(CMD_SET_LINE, &Line, o);
@@ -3475,7 +4029,6 @@ Function::Update(anyOutput *o, DWORD flags)
long ndata;
if(!parent || !cmdxy) return false;
- if(parent->Id != GO_FITFUNC && dl) Undo.DeleteGO((GraphObj**)&dl, flags, o);
do_xyfunc(data, x1, x2, xstep, cmdxy, &xydata, &ndata, param);
if(xydata && ndata >1) {
if(!dl) dl = new DataLine(this, data, xydata, ndata);
@@ -3532,6 +4085,7 @@ FitFunc::~FitFunc()
if(ssXref) free(ssXref); ssXref = 0L;
if(ssYref) free(ssYref); ssYref = 0L;
if(dl) DeleteGO(dl); dl = 0L;
+ if(name) free(name); name=0L;
Undo.InvalidGO(this);
}
@@ -3572,14 +4126,7 @@ FitFunc::DoPlot(anyOutput *o)
if(!data || x1 >= x2) return;
dirty = false;
- if(xstep <= 0.0) xstep = (x2-x1)/100.0;
- if(!dl) dl = new Function(this, data);
- if(dl && o){
- dl->SetSize(SIZE_MIN_X, x1); dl->SetSize(SIZE_MAX_X, x2);
- dl->SetSize(SIZE_XSTEP, xstep); dl->Command(CMD_SETFUNC, cmdxy, 0L);
- dl->Command(CMD_SETPARAM, parxy, 0L); dl->Command(CMD_SET_LINE, &Line, 0L);
- dl->Update(o, 0L); dl->DoPlot(o);
- }
+ if(dl && o) dl->DoPlot(o);
if(Symbols) for(i = 0; i < nPoints; i++) if(Symbols[i]) Symbols[i]->DoPlot(o);
}
@@ -3619,20 +4166,25 @@ FitFunc::Command(int cmd, void *tmpl, anyOutput *o)
return false;
case CMD_AUTOSCALE:
if(dirty) {
- if(!dl) if(!(dl = new Function(this, data))) return false;
- dl->SetSize(SIZE_MIN_X, x1); dl->SetSize(SIZE_MAX_X, x2);
- dl->SetSize(SIZE_XSTEP, xstep); dl->Command(CMD_SETFUNC, cmdxy, 0L);
- dl->Command(CMD_SETPARAM, parxy, 0L); dl->Update(o, 0L);
+ if(dl) dl->Command(cmd, tmpl, o);
memcpy(&Bounds, &dl->Bounds, sizeof(fRECT));
if(Symbols) for(i = 0; i < nPoints; i++) if(Symbols[i])Symbols[i]->Command(cmd, tmpl, o);
dirty = false;
}
return true;
case CMD_UPDATE:
- Undo.ObjConf(this, UNDO_CONTINUE);
- if(Symbols) for(i = 0; i < nPoints; i++)
- if(Symbols[i]) Symbols[i]->Command(cmd, tmpl, o);
+ if(Symbols) {
+ SavVarObs((GraphObj**)Symbols, nPoints, UNDO_CONTINUE);
+ for(i = 0; i < nPoints; i++) if(Symbols[i]) Symbols[i]->Command(cmd, tmpl, o);
+ }
do_fitfunc(data, ssXref, ssYref, 0L, &parxy, cmdxy, conv, maxiter, &chi2);
+ if(!dl) dl = new Function(this, data);
+ if(dl){
+ dl->SetSize(SIZE_MIN_X, x1); dl->SetSize(SIZE_MAX_X, x2);
+ dl->SetSize(SIZE_XSTEP, xstep); dl->Command(CMD_SETFUNC, cmdxy, 0L);
+ dl->Command(CMD_SETPARAM, parxy, 0L); dl->Command(CMD_SET_LINE, &Line, 0L);
+ dl->Update(o, UNDO_CONTINUE);
+ }
dirty = true;
if(parent) parent->Command(CMD_MRK_DIRTY, 0L, o);
return true;
@@ -3642,6 +4194,10 @@ FitFunc::Command(int cmd, void *tmpl, anyOutput *o)
break;
case CMD_MRK_DIRTY:
dirty = true;
+ if(dl){
+ dl->SetSize(SIZE_MIN_X, x1); dl->SetSize(SIZE_MAX_X, x2);
+ dl->SetSize(SIZE_XSTEP, xstep);
+ }
case CMD_REDRAW:
if(parent) return parent->Command(cmd, tmpl, o);
break;
@@ -3707,6 +4263,7 @@ Plot3D::~Plot3D()
if(drag) DeleteGO(drag); drag = 0L;
if(dispObs) free(dispObs); dispObs = 0L;
free(RotDef);
+ if(name) free(name); name=0L;
Undo.InvalidGO(this);
}
@@ -3785,35 +4342,35 @@ Plot3D::DoPlot(anyOutput *o)
if(!parent || !o) return;
o->MouseCursor(MC_WAIT, true);
if(dirty) DoAutoscale();
- o->LightSource(8.0, -16.0);
- cu1.fx = cub1.fx; cu1.fy = cub1.fy; cu1.fz = cub1.fz;
- cu2.fx = cub2.fx; cu2.fy = cub2.fy; cu2.fz = cub2.fz;
- rc.fx = rotC.fx; rc.fy = rotC.fy; rc.fz = rotC.fz;
- if(Axes && nAxes >2) {
+ if(Axes && nAxes >2) { //if no axes then parent is another Plot3D ...
+ o->LightSource(32.0, 16.0);
+ cu1.fx = cub1.fx; cu1.fy = cub1.fy; cu1.fz = cub1.fz;
+ cu2.fx = cub2.fx; cu2.fy = cub2.fy; cu2.fz = cub2.fz;
+ rc.fx = rotC.fx; rc.fy = rotC.fy; rc.fz = rotC.fz;
o->SetSpace(&cu1, &cu2, defs.cUnits, RotDef, &rc, Axes[0]->GetAxis(),
Axes[1]->GetAxis(), Axes[2]->GetAxis());
for(i = 0; i< nAxes; i++) if(Axes[i]) Axes[i]->DoPlot(o);
- if(plots) for(i = 0; i < nPlots; i++) if(plots[i]){
- if(plots[i]->Id >= GO_PLOT && plots[i]->Id < GO_GRAPH) {
- if(((Plot*)plots[i])->hidden == 0) plots[i]->DoPlot(o);
- }
- else plots[i]->DoPlot(o);
- if(i) {
- UpdateMinMaxRect(&rDims, plots[i]->rDims.right, plots[i]->rDims.top);
- UpdateMinMaxRect(&rDims, plots[i]->rDims.left, plots[i]->rDims.bottom);
- }
- else memcpy(&rDims, &plots[i]->rDims, sizeof(RECT));
+ }
+ if(plots) for(i = 0; i < nPlots; i++) if(plots[i]){
+ if(plots[i]->Id >= GO_PLOT && plots[i]->Id < GO_GRAPH) {
+ if(((Plot*)plots[i])->hidden == 0) plots[i]->DoPlot(o);
+ }
+ else plots[i]->DoPlot(o);
+ if(i) {
+ UpdateMinMaxRect(&rDims, plots[i]->rDims.right, plots[i]->rDims.top);
+ UpdateMinMaxRect(&rDims, plots[i]->rDims.left, plots[i]->rDims.bottom);
}
- for(i = 0; i< nAxes; i++) if(Axes[i]){
- UpdateMinMaxRect(&rDims, Axes[i]->rDims.right, Axes[i]->rDims.top);
- UpdateMinMaxRect(&rDims, Axes[i]->rDims.left, Axes[i]->rDims.bottom);
+ else memcpy(&rDims, &plots[i]->rDims, sizeof(RECT));
}
+ for(i = 0; i< nAxes; i++) if(Axes[i]){
+ UpdateMinMaxRect(&rDims, Axes[i]->rDims.right, Axes[i]->rDims.top);
+ UpdateMinMaxRect(&rDims, Axes[i]->rDims.left, Axes[i]->rDims.bottom);
}
for(i = j = 1; i < nObs; i++) if(dispObs[i] && dispObs[i]->go)
dispObs[j++] = dispObs[i];
nObs = j;
- SortObj();
- if(nObs && dispObs){
+ if(nObs >1 && dispObs){
+ SortObj();
for (i = fo = 1; i <= nObs; i++){
while(dispObs[fo]->Zmax < dispObs[i]->Zmin && fo < (nObs-1)) fo++;
for(j = fo; j <= nObs; j++) {
@@ -3870,7 +4427,7 @@ Plot3D::Command(int cmd, void *tmpl, anyOutput *o)
case CMD_HIDE_MARK:
if(!tmpl) return false;
//do all axes
- if(Axes)for(i = nAxes-1; i>=0; i--) {
+ if(Axes)for(i = nAxes-1; i>=0; i--) if(Axes[i]){
if(tmpl == (void*)Axes[i]){
Axes[i]->DoMark(o, false);
return true;
@@ -3880,7 +4437,7 @@ Plot3D::Command(int cmd, void *tmpl, anyOutput *o)
}
}
//do all plots
- if(plots)for(i = nPlots-1; i>=0; i--) {
+ if(plots)for(i = nPlots-1; i>=0; i--) if(plots[i]){
if(tmpl == (void*)plots[i]){
plots[i]->DoMark(o, false);
return true;
@@ -3892,8 +4449,10 @@ Plot3D::Command(int cmd, void *tmpl, anyOutput *o)
return false;
case CMD_OBJTREE:
if(!tmpl || !plots) return false;
- for(i = 0; i < nPlots; i++) if(plots[i])
+ for(i = 0; i < nPlots; i++) if(plots[i]) {
((ObjTree*)tmpl)->Command(CMD_UPDATE, plots[i], 0L);
+ if(plots[i]->Id > GO_PLOT && plots[i]->Id < GO_GRAPH) plots[i]->Command(cmd, tmpl, o);
+ }
return true;
case CMD_REPL_GO:
if(!(tmpPlots = (GraphObj **)tmpl) || !tmpPlots[0] || !tmpPlots[1]) return false;
@@ -3902,14 +4461,15 @@ Plot3D::Command(int cmd, void *tmpl, anyOutput *o)
}
return false;
case CMD_MRK_DIRTY:
+ if(IsPlot3D(parent)) return parent->Command(cmd, tmpl, o);
return dirty = true;
case CMD_ADDAXIS:
InfoBox("Add axis to 3D graph:\n\nThis feature is not yet implemented!");
return false;
case CMD_SET_GO3D:
+ if(IsPlot3D(parent)) return parent->Command(cmd, tmpl, o);
return AcceptObj((GraphObj *)tmpl);
- case CMD_SETSCROLL:
- case CMD_REDRAW:
+ case CMD_SETSCROLL: case CMD_REDRAW:
if(parent) return parent->Command(cmd, tmpl, o);
break;
case CMD_SHIFTLEFT:
@@ -3948,13 +4508,8 @@ Plot3D::Command(int cmd, void *tmpl, anyOutput *o)
if(Axes[i]) Axes[i]->Command(cmd, tmpl, o);
return true;
case CMD_DELOBJ:
- if(o) o->HideMark();
- if(!tmpl || !parent) return false;
- if(plots) for(i = 0; i < nPlots; i++) if(plots[i] == tmpl) {
- Undo.DeleteGO((GraphObj**)(&plots[i]), 0L, o);
- return parent->Command(CMD_REDRAW, 0L, o);
- }
- return true;
+ if(DeleteGOL((GraphObj***)&plots,nPlots,(GraphObj*)tmpl,o)) return parent->Command(CMD_REDRAW,0L,o);
+ return false;
case CMD_MOVE:
if(CurrGO && CurrGO->Id == GO_DRAGHANDLE) {
CalcRotation(((lfPOINT*)tmpl)[0].fx, ((lfPOINT*)tmpl)[0].fy, o, true);
@@ -3969,6 +4524,7 @@ Plot3D::Command(int cmd, void *tmpl, anyOutput *o)
return true;
case CMD_DROP_PLOT:
if(!parent || !tmpl || ((GraphObj*)tmpl)->Id < GO_PLOT) return false;
+ if(IsPlot3D(parent)) return parent->Command(cmd, tmpl, o);
if(!nPlots) {
plots = (GraphObj**)calloc(2, sizeof(GraphObj*));
if(plots) {
@@ -4158,7 +4714,14 @@ Plot3D::DoAutoscale()
Bounds.Xmin = Bounds.Ymin = HUGE_VAL; Bounds.Xmax = Bounds.Ymax = -HUGE_VAL;
xBounds.fx = yBounds.fx = zBounds.fx = HUGE_VAL;
xBounds.fy = yBounds.fy = zBounds.fy = -HUGE_VAL;
- for(i = 0; i < nPlots; i++) if(plots[i]) plots[i]->Command(CMD_AUTOSCALE, 0L, 0L);
+ for(i = 0; i < nPlots; i++) {
+ if(plots[i]) {
+ if(plots[i]->Id >= GO_PLOT && plots[i]->Id < GO_GRAPH) {
+ if(!((Plot*)plots[i])->hidden) plots[i]->Command(CMD_AUTOSCALE, 0L, 0L);
+ }
+ else plots[i]->Command(CMD_AUTOSCALE, 0L, 0L);
+ }
+ }
if(xBounds.fx <= xBounds.fy && yBounds.fx <= yBounds.fy && zBounds.fx <= zBounds.fy){
if(Axes)for(i = 0; i < 3; i++) if(Axes[i]){
ad = Axes[i]->axis;
@@ -4188,6 +4751,10 @@ Plot3D::DoAutoscale()
Axes[i]->Command(CMD_AUTOSCALE, ad, 0L);
}
}
+ else if(parent && parent->Id >= GO_PLOT && parent->Id < GO_GRAPH) {
+ ((Plot*)parent)->CheckBounds3D(xBounds.fx, yBounds.fx, zBounds.fx);
+ ((Plot*)parent)->CheckBounds3D(xBounds.fy, yBounds.fy, zBounds.fy);
+ }
}
}
@@ -4401,6 +4968,7 @@ Chart25D::Chart25D(GraphObj *par, DataObj *d, DWORD flags)
Chart25D::~Chart25D()
{
+ if(name) free(name); name=0L;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -4413,6 +4981,7 @@ Ribbon25D::Ribbon25D(GraphObj *par, DataObj *d, DWORD flags)
Ribbon25D::~Ribbon25D()
{
+ if(name) free(name); name=0L;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -4424,4 +4993,83 @@ BubblePlot3D::BubblePlot3D(GraphObj *par, DataObj *d)
BubblePlot3D::~BubblePlot3D()
{
+ if(name) free(name); name=0L;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// 3D function plotter
+Func3D::Func3D(GraphObj *par, DataObj *d)
+ :Plot3D(par, d, 0x0L)
+{
+ FileIO(INIT_VARS);
+ cmdxy = strdup("r=sqrt(x*x+z*z)\ny=1-exp(-8/(r+1))");
+ Id = GO_FUNC3D;
+}
+
+Func3D::Func3D(int src):Plot3D(0)
+{
+ int i;
+
+ FileIO(INIT_VARS);
+ if(src == FILE_READ) {
+ FileIO(FILE_READ);
+ //now set parent in all children
+ if(Axes) for(i = 0; i < nAxes; i++)
+ if(Axes[i]) Axes[i]->parent = this;
+ if(plots) for(i = 0; i < nPlots; i++)
+ if(plots[i]) plots[i]->parent = this;
+ }
+}
+
+Func3D::~Func3D()
+{
+ if(param) free(param); param = 0L;
+ if(cmdxy) free(cmdxy); cmdxy = 0L;
+ if(gda) delete(gda); gda = 0L;
+ if(name) free(name); name=0L;
+}
+
+bool
+Func3D::Command(int cmd, void *tmpl, anyOutput *o)
+{
+ switch(cmd) {
+ case CMD_SET_DATAOBJ:
+ Plot3D::Command(cmd, tmpl, o);
+ if(gob && gda) gob->Command(cmd, gda, o);
+ Id = GO_FUNC3D;
+ return true;
+ case CMD_UPDATE:
+ return Update();
+ }
+ return Plot3D::Command(cmd, tmpl, o);
+}
+
+bool
+Func3D::Update()
+{
+ if(cmdxy) {
+ dirty = true;
+ if(xstep == 0.0) xstep = 1.0; if(zstep == 0.0) zstep = 1.0;
+ if(!gda) gda = new DataObj();
+ if(gda && do_func3D(gda, x1, x2, xstep, z1, z2, zstep, cmdxy, param)) {
+ if(gob = new Grid3D(this, gda, type, x1, xstep, z1, zstep)) {
+ gob->Command(CMD_SET_LINE, &Line, 0L);
+ gob->Command(CMD_SYM_FILL, &Fill, 0L);
+ if(!plots && (plots = (GraphObj**)calloc(2, sizeof(GraphObj*)))) {
+ nPlots = 1; plots[0] = (Plot *)gob;
+ if(parent->Id == GO_GRAPH) CreateAxes();
+ return dirty = parent->Command(CMD_REDRAW, 0L, 0L);
+ }
+ else if(plots && nPlots && plots[0]->Id == GO_GRID3D) {
+ Undo.DeleteGO(&plots[0], UNDO_CONTINUE, 0L);
+ Undo.SetGO(this, &plots[0], gob, UNDO_CONTINUE);
+ return true;
+ }
+ else {
+ DeleteGO(gob); gob=0L;
+ }
+ }
+ }
+ }
+ return false;
}
diff --git a/PropertyDlg.cpp b/PropertyDlg.cpp
index c6f160f..73d8eac 100755
--- a/PropertyDlg.cpp
+++ b/PropertyDlg.cpp
@@ -109,6 +109,7 @@ Symbol::PropertyDlg()
DWORD tmpCol, undo_flags = 0L;
double tmpVal, o_size, n_size, o_lwidth, n_lwidth;
TextDEF textdef;
+ anyOutput *cdisp = Undo.cdisp;
lfPOINT o_pos, n_pos;
if(!parent) return false;
@@ -161,6 +162,7 @@ Symbol::PropertyDlg()
switch(res) {
case 2:
case 1:
+ Undo.SetDisp(cdisp);
if(PrevSym->type == SYM_TEXT && Dlg->GetCheck(250)){
Dlg->GetText(251, text1);
if(PrevSym->Command(CMD_GETTEXT, (void *)text2, 0L) && strcmp(text1, text2)) {
@@ -326,6 +328,7 @@ Bubble::PropertyDlg()
LineDEF newLine, newFillLine;
FillDEF newFill;
DWORD undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
double o_size, n_size;
bool bRet = false;
@@ -362,6 +365,7 @@ Bubble::PropertyDlg()
switch(res) {
case 1: //accept for current bubble only
case 2: //accept for plot
+ Undo.SetDisp(cdisp);
OD_filldef(OD_GETLINE, 0L, 0L, 0L, (void *)&newLine, 0);
OD_filldef(OD_GETFILL, 0L, 0L, 0L, (void *)&newFill, 0);
memcpy(&newFillLine, &BubbleFillLine, sizeof(LineDEF));
@@ -464,6 +468,7 @@ Bar::PropertyDlg()
LineDEF newLine, newFillLine;
FillDEF newFill;
DWORD undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
lfPOINT o_bl, n_bl, o_pos, n_pos;
if(!parent) return false;
@@ -539,6 +544,7 @@ Bar::PropertyDlg()
break;
case 1:
case 2:
+ Undo.SetDisp(cdisp);
OD_filldef(OD_GETLINE, 0L, 0L, 0L, (void *)&newLine, 0);
OD_filldef(OD_GETFILL, 0L, 0L, 0L, (void *)&newFill, 0);
memcpy(&newFillLine, &HatchLine, sizeof(LineDEF));
@@ -612,36 +618,45 @@ DataLine::PropertyDlg()
{
TabSHEET tab1 = {0, 40, 10, "Line"};
TabSHEET tab2 = {40, 80, 10, "Style"};
+ TabSHEET tab3 = {80, 120, 10, "Edit"};
DlgInfo LineDlg[] = {
{1, 2, 0, DEFAULT, PUSHBUTTON, (void*)"OK", 150, 10, 45, 12},
{2, 3, 0, 0x0L, PUSHBUTTON, (void*)"Cancel", 150, 25, 45, 12},
{3, 0, 4, ISPARENT | CHECKED, GROUP, NULL, 138, 40, 55, 12},
{4, 5, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 139, 120},
- {5, 0, 200, ISPARENT, SHEET, &tab2, 5, 10, 139, 120},
+ {5, 6, 200, ISPARENT, SHEET, &tab2, 5, 10, 139, 120},
+ {6, 0, 300, ISPARENT | HIDDEN, SHEET, &tab3, 5, 10, 139, 120},
{100, 0, 0, NOSELECT, ODBUTTON, (void*)OD_linedef, 10, 38, 130, 100},
- {200, 201, 0, 0x0L, LTEXT, (void*)"select style:", 10, 38, 130, 100},
- {201, 202, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 12, 50, 25, 25},
- {202, 203, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 37, 50, 25, 25},
- {203, 204, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 62, 50, 25, 25},
- {204, 205, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 87, 50, 25, 25},
- {205, 206, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 112, 50, 25, 25},
- {206, 207, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 37, 75, 25, 25},
- {207, 208, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 62, 75, 25, 25},
- {208, 209, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 87, 75, 25, 25},
- {209, 0, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 112, 75, 25, 25},
- {800, 0, 0, LASTOBJ, NONE, 0L, 0, 0, 0, 0}};
+ {200, 201, 0, 0x0L, LTEXT, (void*)"select style:", 10, 32, 130, 100},
+ {201, 202, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 12, 45, 25, 25},
+ {202, 203, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 37, 45, 25, 25},
+ {203, 204, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 62, 45, 25, 25},
+ {204, 205, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 87, 45, 25, 25},
+ {205, 206, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 112, 45, 25, 25},
+ {206, 207, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 37, 70, 25, 25},
+ {207, 208, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 62, 70, 25, 25},
+ {208, 209, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 87, 70, 25, 25},
+ {209, 210, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 112, 70, 25, 25},
+ {210, 211, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 37, 95, 25, 25},
+ {211, 0, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_LineStyleTempl), 62, 95, 25, 25},
+ {300, 301, 0, 0x0L, LTEXT, (void*)"range for x-values", 15, 30, 80, 9},
+ {301, 302, 0, 0x0L, EDTEXT, (void*)ssXref, 15, 40, 119, 10},
+ {302, 303, 0, 0x0L, LTEXT, (void*)"range for y-values", 15, 55, 80, 9},
+ {303, 0, 0, LASTOBJ, EDTEXT, (void*)ssYref, 15, 65, 119, 10}};
DlgRoot *Dlg;
void *hDlg;
int res, tmpType = type;
DWORD undo_flags = 0L;
LineDEF newLine;
bool bRet = false;
+ anyOutput *cdisp = Undo.cdisp;
if(!parent) return false;
if(parent->Id == GO_FUNCTION) return parent->PropertyDlg();
OD_linedef(OD_SETLINE, 0L, 0L, 0L, (void *)&LineDef, 0);
if(!(Dlg = new DlgRoot(LineDlg)))return false;
- Dlg->SetCheck(201 + (type & 0x7), 0L, true);
+ Dlg->SetCheck(201 + (type & 0x0f), 0L, true);
+ if(ssXref && ssYref) Dlg->ShowItem(6, true);
if(parent && parent->name) sprintf(TmpTxt, "Line of %s", parent->name);
else strcpy(TmpTxt, "Line properties");
hDlg = CreateDlgWnd(TmpTxt, 50, 50, 410, 300, Dlg, 0x0L);
@@ -650,14 +665,31 @@ DataLine::PropertyDlg()
res = Dlg->GetResult();
switch (res) {
case 201: case 202: case 203: case 204: case 205:
- case 206: case 207: case 208: case 209:
- tmpType &= ~0x0f;
- tmpType |= (res-201);
- res = -1;
+ case 206: case 207: case 208: case 209: case 210: case 211:
+ if((tmpType & 0x0f) == (res-201)) res = 1;
+ else {
+ tmpType &= ~0x0f; tmpType |= (res-201);
+ res = -1;
+ }
break;
}
}while (res < 0);
if(res == 1){ //OK pressed
+ Undo.SetDisp(cdisp);
+ if(ssXref && ssYref) {
+ if(Dlg->GetText(301, TmpTxt) && strcmp(ssXref, TmpTxt)) {
+ Undo.String(this, &ssXref, undo_flags); undo_flags |= UNDO_CONTINUE;
+ if(ssXref = (char*)realloc(ssXref, strlen(TmpTxt)+1))
+ strcpy(ssXref, TmpTxt);
+ }
+ if(Dlg->GetText(303, TmpTxt) && strcmp(ssYref, TmpTxt)) {
+ Undo.String(this, &ssYref, undo_flags); undo_flags |= UNDO_CONTINUE;
+ if(ssYref = (char*)realloc(ssYref, strlen(TmpTxt)+1))
+ strcpy(ssYref, TmpTxt);
+ }
+ if(undo_flags & UNDO_CONTINUE) Command(CMD_UPDATE, 0L, cdisp);
+ parent->Command(CMD_MRK_DIRTY, 0L, cdisp);
+ }
OD_linedef(OD_GETLINE, 0L, 0L, 0L, (void *)&newLine, 0);
if(cmpLineDEF(&LineDef, &newLine)) {
Undo.Line(parent, &LineDef, undo_flags); undo_flags |= UNDO_CONTINUE;
@@ -688,6 +720,7 @@ DataPolygon::PropertyDlg()
LineDEF newLine, newFillLine;
FillDEF newFill;
DWORD undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
int res;
bool bRet = false;
@@ -702,6 +735,7 @@ DataPolygon::PropertyDlg()
res = Dlg->GetResult();
}while (res < 0);
if(res == 1){ //OK pressed
+ Undo.SetDisp(cdisp);
OD_filldef(OD_GETLINE, 0L, 0L, 0L, (void *)&newLine, 0);
OD_filldef(OD_GETFILL, 0L, 0L, 0L, (void *)&newFill, 0);
memcpy(&newFillLine, &pgFillLine, sizeof(LineDEF));
@@ -778,6 +812,7 @@ RegLine::PropertyDlg()
bool bRet = false;
LineDEF newLine;
DWORD undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
lfPOINT o_l5, n_l5;
fRECT o_clip, n_clip;
char *tx, *ty;
@@ -865,6 +900,7 @@ RegLine::PropertyDlg()
}
}while (res < 0);
if(res == 1){ //OK pressed
+ Undo.SetDisp(cdisp);
OD_linedef(OD_GETLINE, 0L, 0L, 0L, (void *)&newLine, 0);
if(cmpLineDEF(&LineDef, &newLine)) {
Undo.Line(parent, &LineDef, undo_flags); undo_flags |= UNDO_CONTINUE;
@@ -926,6 +962,7 @@ SDellipse::PropertyDlg()
LineDEF newLine;
bool bRet = false;
DWORD undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
if(!parent) return false;
OD_linedef(OD_SETLINE, 0L, 0L, 0L, (void *)&LineDef, 0);
@@ -945,6 +982,7 @@ SDellipse::PropertyDlg()
res = Dlg->GetResult();
}while (res < 0);
if(res == 1){ //OK pressed
+ Undo.SetDisp(cdisp);
OD_linedef(OD_GETLINE, 0L, 0L, 0L, (void *)&newLine, 0);
if(cmpLineDEF(&LineDef, &newLine)) {
Undo.Line(parent, &LineDef, undo_flags); undo_flags |= UNDO_CONTINUE;
@@ -1003,6 +1041,7 @@ ErrorBar::PropertyDlg()
double n_sb, o_sb, n_lw, o_lw, n_err, o_err;
lfPOINT n_pos, o_pos;
DWORD n_col, undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
bool bRet = false;
if(!parent) return false;
@@ -1028,6 +1067,7 @@ ErrorBar::PropertyDlg()
break;
case 1: //accept for this object
case 2: // or all objects of plot
+ Undo.SetDisp(cdisp);
Dlg->GetValue(101, &n_sb); Dlg->GetValue(104, &n_lw);
Dlg->GetColor(107, &n_col); Dlg->GetValue(305, &n_err);
Dlg->GetValue(301, &n_pos.fx); Dlg->GetValue(303, &n_pos.fy);
@@ -1113,6 +1153,7 @@ Arrow::PropertyDlg()
int res, tmptype = type, undo_level = *Undo.pcb;
bool bRet = false;
DWORD o_col, n_col, undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
if(!parent) return false;
if(!(Dlg = new DlgRoot(ArrowDlg))) return false;
@@ -1134,13 +1175,18 @@ Arrow::PropertyDlg()
else strcpy(TmpTxt, "Arrow properties");
hDlg = CreateDlgWnd(TmpTxt, 50, 50, 328, 260, Dlg, 0x0L);
do {
- LoopDlgWnd();
- res = ExecDrawOrderButt(parent, this, Dlg->GetResult());
+ LoopDlgWnd(); res = Dlg->GetResult();
+ switch (res) {
+ case 600: case 601: case 602: case 603:
+ Undo.SetDisp(cdisp);
+ res = ExecDrawOrderButt(parent, this, res);
+ }
switch (res) {
case 200: tmptype = ARROW_NOCAP; res = -1; break;
case 201: tmptype = ARROW_LINE; res = -1; break;
case 202: tmptype = ARROW_TRIANGLE; res = -1; break;
case 1: case 2:
+ Undo.SetDisp(cdisp);
Dlg->GetValue(301, &n_pos2.fx); Dlg->GetValue(303, &n_pos2.fy);
Dlg->GetValue(305, &n_pos1.fx); Dlg->GetValue(307, &n_pos1.fy);
Dlg->GetValue(101, &n_cw); Dlg->GetValue(104, &n_cl);
@@ -1180,6 +1226,7 @@ Arrow::PropertyDlg()
}
break;
case 3: //Cancel
+ Undo.SetDisp(cdisp);
if(*Undo.pcb > undo_level) { //restore plot order
while(*Undo.pcb > undo_level) Undo.Restore(false, 0L);
bRet = true;
@@ -1233,6 +1280,7 @@ Box::PropertyDlg()
FillDEF newFill;
LineDEF newLine, newHatchLine;
DWORD undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
lfPOINT n_pos;
double tmpVal, o_size, n_size;
bool bRet = false;
@@ -1267,11 +1315,12 @@ Box::PropertyDlg()
switch (res) {
case 1: //accept for this object
case 2: // or all objects of plot
+ Undo.SetDisp(cdisp);
OD_filldef(OD_GETLINE, 0L, 0L, 0L, (void *)&newLine, 0);
OD_filldef(OD_GETFILL, 0L, 0L, 0L, (void *)&newFill, 0);
if(newFill.hatch) memcpy(&newHatchLine, newFill.hatch, sizeof(LineDEF));
newFill.hatch = &newHatchLine;
- if(type & BAR_WIDTHDATA) Dlg->GetValue(309, &size);
+ if(type & BAR_WIDTHDATA) Dlg->GetValue(309, &n_size);
else {
if(Dlg->GetCheck(113)) {
tmpType |= BAR_RELWIDTH;
@@ -1378,6 +1427,7 @@ Whisker::PropertyDlg()
void *hDlg;
int res, tmp_type;
DWORD undo_flags = 0L, n_col = LineDef.color;
+ anyOutput *cdisp = Undo.cdisp;
lfPOINT n_pos;
double tmpVal, o_size, n_size, o_lw, n_lw;
bool bRet = false;
@@ -1399,8 +1449,8 @@ Whisker::PropertyDlg()
break;
case 1: //accept for this object
case 2: // or all objects of plot
- Dlg->GetValue(101, &n_size); Dlg->GetValue(104, &n_lw);
- Dlg->GetColor(107, &n_col);
+ Undo.SetDisp(cdisp); Dlg->GetValue(101, &n_size);
+ Dlg->GetValue(104, &n_lw); Dlg->GetColor(107, &n_col);
break;
}
}while (res <0);
@@ -1472,6 +1522,7 @@ DropLine::PropertyDlg()
bool bRet = false;
LineDEF newLine;
DWORD undo_flags = 0L;
+ anyOutput * cdisp = Undo.cdisp;
lfPOINT o_pos, n_pos;
if(!parent) return false;
@@ -1493,7 +1544,7 @@ DropLine::PropertyDlg()
switch (res) {
case 1: //this line
case 2: //all lines of plot
- tmptype = 0;
+ Undo.SetDisp(cdisp); tmptype = 0;
if(Dlg->GetCheck(251)) tmptype |= DL_LEFT;
if(Dlg->GetCheck(252)) tmptype |= DL_RIGHT;
if(Dlg->GetCheck(253)) tmptype |= DL_YAXIS;
@@ -1565,6 +1616,7 @@ DropLine3D::PropertyDlg()
bool bRet = false;
LineDEF newLine;
DWORD undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
fPOINT3D o_pos, n_pos;
if(!parent) return false;
@@ -1584,6 +1636,7 @@ DropLine3D::PropertyDlg()
switch (res) {
case 1: //this line
case 2: //all lines of plot
+ Undo.SetDisp(cdisp);
OD_linedef(OD_GETLINE, 0L, 0L, 0L, (void *)&newLine, 0);
for(i = tmptype = 0; i < 6; i++) {
tmptype |= Dlg->GetCheck(251+i) ? 1<<i : 0;
@@ -1640,7 +1693,7 @@ Sphere::PropertyDlg()
{11, 0, 200, ISPARENT, SHEET, &tab2, 5, 10, 100, 80},
{100, 101, 0, 0x0L, RTEXT, (void*)"ball size", 15, 35, 28, 8},
{101, 102, 0, 0x0L, EDVAL1, &size, 46, 35, 25, 10},
- {102, 103, 0, 0x0L, LTEXT, (void*)type_text[type], 73, 35, 15, 8},
+ {102, 103, 0, 0x0L, LTEXT, (void*)type_text[type < 4 ? type : 0], 73, 35, 15, 8},
{103, 104, 0, 0x0L, RTEXT, (void*)"line width", 15, 47, 28, 8},
{104, 105, 0, 0x0L, EDVAL1, &Line.width, 46, 47, 25, 10},
{105, 106, 0, 0x0L, LTEXT, (void*)Units[defs.cUnits].display, 73, 47, 15, 8},
@@ -1660,6 +1713,7 @@ Sphere::PropertyDlg()
bool bRet = false, bContinue = false;
fPOINT3D n_pos, o_pos;
DWORD new_lcolor = Line.color, undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
double o_size, n_size, o_lsize, n_lsize;
if(!parent) return false;
@@ -1680,12 +1734,11 @@ Sphere::PropertyDlg()
bContinue = false;
break;
case 1: case 2:
- Dlg->GetColor(107, &new_lcolor); Dlg->GetValue(101, &n_size);
- Dlg->GetValue(104, &n_lsize);
+ Undo.SetDisp(cdisp); Dlg->GetColor(107, &new_lcolor);
+ Dlg->GetValue(101, &n_size); Dlg->GetValue(104, &n_lsize);
break;
case 109:
- Dlg->DoPlot(0L);
- bContinue = true;
+ Dlg->DoPlot(0L); bContinue = true;
break;
}
}while (res < 0);
@@ -1755,6 +1808,7 @@ Plane3D::PropertyDlg()
int res;
bool bRet = false;
DWORD new_lcolor = Line.color, undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
double o_lsize, n_lsize, o_rbw, n_rbw, o_rbz, n_rbz;
if(!parent) return false;
@@ -1766,7 +1820,7 @@ Plane3D::PropertyDlg()
Dlg = new DlgRoot(PlaneDlg);
Dlg->GetValue(101, &o_lsize); Dlg->GetValue(202, &o_rbw);
Dlg->GetValue(205, &o_rbz);
- if(parent && parent->Id==GO_RIBBON && parent->type == 2)
+ if(parent && ((parent->Id==GO_RIBBON && parent->type == 2) || parent->Id==GO_GRID3D))
Dlg->ShowItem(200, false); //paravent plot
if(parent->name) sprintf(TmpTxt, "Plane of %s", parent->name);
else strcpy(TmpTxt, "Plane properties");
@@ -1776,7 +1830,8 @@ Plane3D::PropertyDlg()
res = Dlg->GetResult();
switch (res) {
case 1: case 2:
- Dlg->GetColor(104, &new_lcolor); Dlg->GetValue(101, &n_lsize); Dlg->GetValue(202, &n_rbw);
+ Undo.SetDisp(cdisp); Dlg->GetColor(104, &new_lcolor);
+ Dlg->GetValue(101, &n_lsize); Dlg->GetValue(202, &n_rbw);
Dlg->GetValue(205, &n_rbz);
break;
}
@@ -1852,6 +1907,7 @@ Brick::PropertyDlg()
int res;
bool bRet = false;
DWORD col1 = Line.color, undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
double o_lw = Line.width, n_lw, o_height = height, n_height, o_width = width, n_width;
double o_depth = depth, n_depth;
fPOINT3D o_pos, n_pos;
@@ -1871,9 +1927,8 @@ Brick::PropertyDlg()
LoopDlgWnd();
res = Dlg->GetResult();
switch (res) {
- case 1:
- case 2:
- Dlg->GetColor(104, &col1);
+ case 1: case 2:
+ Undo.SetDisp(cdisp); Dlg->GetColor(104, &col1);
Dlg->GetValue(101, &n_lw); Dlg->GetValue(301, &n_pos.fx);
Dlg->GetValue(303, &n_pos.fy); Dlg->GetValue(305, &n_pos.fz);
Dlg->GetValue(307, &n_height); Dlg->GetValue(108, &n_width);
@@ -1971,6 +2026,7 @@ Arrow3D::PropertyDlg()
int res, tmptype = type, undo_level = *Undo.pcb;
bool bRet = false;
DWORD o_col, n_col, undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
if(!parent) return false;
if(!(Dlg = new DlgRoot(ArrowDlg))) return false;
@@ -1995,6 +2051,7 @@ Arrow3D::PropertyDlg()
case 201: tmptype = ARROW_LINE; res = -1; break;
case 202: tmptype = ARROW_TRIANGLE; res = -1; break;
case 1: case 2:
+ Undo.SetDisp(cdisp);
Dlg->GetValue(301, &n_pos2.fx); Dlg->GetValue(303, &n_pos2.fy);
Dlg->GetValue(305, &n_pos2.fz); Dlg->GetValue(307, &n_pos1.fx);
Dlg->GetValue(309, &n_pos1.fy); Dlg->GetValue(311, &n_pos1.fz);
@@ -2065,6 +2122,7 @@ Line3D::PropertyDlg()
int res;
bool bRet = false;
LineDEF newLine;
+ anyOutput *cdisp = Undo.cdisp;
if(!parent) return false;
OD_linedef(OD_SETLINE, 0L, 0L, 0L, (void *)&Line, 0);
@@ -2077,6 +2135,7 @@ Line3D::PropertyDlg()
}while (res < 0);
switch(res) {
case 1: //OK pressed
+ Undo.SetDisp(cdisp);
OD_linedef(OD_GETLINE, 0L, 0L, 0L, (void *)&newLine, 0);
if(cmpLineDEF(&Line, &newLine)) {
if(parent->Id == GO_GRID3D) {
@@ -2105,24 +2164,32 @@ Label::PropertyDlg()
TabSHEET tab1 = {0, 27, 10, "Label"};
TabSHEET tab2 = {27, 75, 10, "Font & Style"};
TabSHEET tab3 = {75, 110, 10, "Position"};
+ bool isDataLabel = ((parent) && (parent->Id == GO_PLOTSCATT || parent->Id == GO_XYSTAT || parent->Id == GO_BOXPLOT));
+ int bwidth = isDataLabel ? 55 : 45;
+ double lspc = 100.0;
DlgInfo LabelDlg[] = {
- {1, 2, 0, DEFAULT, PUSHBUTTON, (void*)"OK", 170, 10, 45, 12},
- {2, 3, 0, 0x0L, PUSHBUTTON, (void*)"Cancel", 170, 25, 45, 12},
- {3, 50, 4, ISPARENT | CHECKED, GROUP, 0L, 138, 40, 55, 12},
+ {1, 2, 0, DEFAULT, PUSHBUTTON, isDataLabel ? (void*)"Apply to LABEL" : (void*)"OK", 170, 10, bwidth, 12},
+ {2, 3, 0, 0x0L, PUSHBUTTON, (void*)"Cancel", 170, isDataLabel ? 40 : 25, bwidth, 12},
+ {3, isDataLabel ? 10 : 50, 4, ISPARENT | CHECKED, GROUP, 0L, 138, 40, 55, 12},
{4, 5, 100, ISPARENT, SHEET, &tab1, 5, 10, 159, 100},
{5, 6, 200, ISPARENT | CHECKED, SHEET, &tab2, 5, 10, 159, 100},
{6, 0, 300, ISPARENT, SHEET, &tab3, 5, 10, 159, 100},
+ {10, 50, 0, 0x0L, PUSHBUTTON, (void*)"Apply to PLOT", 170, 25, bwidth, 12},
{50, 0, 600, ISPARENT | CHECKED | HIDDEN, GROUP, 0L, 0, 0, 0, 0},
- {100, 101, 0, 0x0L, RTEXT, (void*)"size", 10, 33, 45, 8},
- {101, 102, 0, 0x0L, EDVAL1, &TextDef.fSize, 60, 33, 25, 10},
- {102, 103, 0, 0x0L, LTEXT, (void *) Units[defs.cUnits].display, 87, 33, 20, 8},
- {103, 104, 0, 0x0L, RTEXT, (void*)"color", 10, 45, 45, 8},
- {104, 107, 0, OWNDIALOG, COLBUTTON, (void *)TextDef.ColTxt, 60, 45, 25, 10},
+ {100, 101, 0, 0x0L, RTEXT, (void*)"size", 30, 33, 45, 8},
+ {101, 102, 0, 0x0L, INCDECVAL1, &TextDef.fSize, 80, 33, 33, 10},
+ {102, 103, 0, 0x0L, LTEXT, (void *) Units[defs.cUnits].display, 115, 33, 20, 8},
+ {103, 104, 0, 0x0L, RTEXT, (void*)"color", 30, 45, 45, 8},
+ {104, 107, 0, OWNDIALOG, COLBUTTON, (void *)TextDef.ColTxt, 80, 45, 25, 10},
{105, 106, 0, 0x0L, LTEXT, (void*)"text:", 10, 83, 25, 8},
{106, 0, 0, TOUCHEXIT, EDTEXT, (void*)TextDef.text, 10, 95, 149, 10},
- {107, 108, 0, 0x0L, RTEXT, (void*)"rotation", 10, 57, 45, 8},
- {108, 109, 0, 0x0L, EDVAL1, &TextDef.RotBL, 60, 57, 25, 10},
- {109, 105, 0, 0x0L, LTEXT, (void *)"deg.", 87, 57, 20, 8},
+ {107, 108, 0, 0x0L, RTEXT, (void*)"rotation", 30, 57, 45, 8},
+ {108, 109, 0, 0x0L, EDVAL1, &TextDef.RotBL, 80, 57, 25, 10},
+ {109, 150, 0, 0x0L, LTEXT, (void *)"deg.", 107, 57, 20, 8},
+ {150, 105, 151, ISPARENT | CHECKED | HIDDEN, GROUP, 0L, 0, 0, 0, 0},
+ {151, 152, 0, 0x0L, RTEXT, (void *)"line spacing", 30, 69, 45, 8},
+ {152, 153, 0, 0x0L, INCDECVAL1, &lspc, 80, 69, 33, 10},
+ {153, 0, 0, 0x0L, LTEXT, (void *)"%", 115, 69, 20, 8},
{200, 244, 221, CHECKED | ISPARENT, GROUPBOX, (void*)" font ", 17, 28, 60, 50},
{221, 222, 0, TOUCHEXIT, RADIO1, (void*)"Helvetica", 20, 35, 45, 8},
{222, 223, 0, TOUCHEXIT, RADIO1, (void*)"Times", 20, 45, 45, 8},
@@ -2158,13 +2225,21 @@ Label::PropertyDlg()
void *hDlg;
int res, i, c_style, c_font;
bool RetVal = false, check;
+ double tmp;
DWORD undo_flags = 0x0;
+ anyOutput *cdisp = Undo.cdisp;
lfPOINT o_pos, o_dist, n_pos, n_dist;
TextDEF OldTxtDef, NewTxtDef;
Axis *pa;
fmtText *fmt = 0L;
- if(parent && (Dlg = new DlgRoot(LabelDlg))) {
+ if(!parent) return false;
+ if(parent->Id == GO_MLABEL) {
+ lspc = 100.0 * parent->GetSize(SIZE_LSPC);
+ }
+ if (lspc < 50.0) lspc = 100.0;
+ if(Dlg = new DlgRoot(LabelDlg)) {
+ if(parent->Id == GO_MLABEL) Dlg->ShowItem(150, true);
Dlg->TextFont(221, FONT_HELVETICA); Dlg->TextFont(222, FONT_TIMES);
Dlg->TextFont(223, FONT_COURIER); Dlg->TextFont(224, FONT_GREEK);
Dlg->TextStyle(205, TXS_BOLD); Dlg->TextStyle(206, TXS_ITALIC);
@@ -2236,15 +2311,22 @@ Label::PropertyDlg()
Dlg->GetValue(302, &o_pos.fx); Dlg->GetValue(305, &o_pos.fy);
Dlg->GetValue(309, &o_dist.fx); Dlg->GetValue(312, &o_dist.fy);
n_pos.fx = o_pos.fx; n_pos.fy = o_pos.fy; n_dist.fx = o_dist.fx; n_dist.fy = o_dist.fy;
- hDlg = CreateDlgWnd("Label properties", 50, 50, 450, 254, Dlg, 0x0L);
+ hDlg = CreateDlgWnd("Label properties", 50, 50, isDataLabel ? 470 : 450, 254, Dlg, 0x0L);
do{
- LoopDlgWnd();
- res = ExecDrawOrderButt(parent, this, Dlg->GetResult());
+ LoopDlgWnd(); res = Dlg->GetResult();
switch (res) {
+ case 600: case 601: case 602: case 603:
+ Undo.SetDisp(cdisp);
+ res = ExecDrawOrderButt(parent, this, res);
+ }
+ switch (res) {
+ case 10:
+ Undo.SetDisp(cdisp);
+ parent->Command(CMD_SAVE_LABELS, 0L, 0L);
+ undo_flags |= UNDO_CONTINUE;
case 1:
Dlg->GetValue(101, &NewTxtDef.fSize); Dlg->GetColor(104, &NewTxtDef.ColTxt);
- Dlg->GetValue(108, &NewTxtDef.RotBL);
- Dlg->GetInt(315, &NewTxtDef.Align);
+ Dlg->GetValue(108, &NewTxtDef.RotBL); Dlg->GetInt(315, &NewTxtDef.Align);
Dlg->GetValue(302, &n_pos.fx); Dlg->GetValue(305, &n_pos.fy);
Dlg->GetValue(309, &n_dist.fx); Dlg->GetValue(312, &n_dist.fy);
break;
@@ -2299,7 +2381,8 @@ Label::PropertyDlg()
break;
}
}while (res < 0);
- if(res == 1) {
+ if(res == 1 || res == 10) {
+ Undo.SetDisp(cdisp);
if(parent->Id == GO_TICK && parent->parent && parent->parent->Id == GO_AXIS)
pa = (Axis*)parent->parent;
else if(parent->Id == GO_MLABEL && parent->parent->Id == GO_TICK
@@ -2311,14 +2394,14 @@ Label::PropertyDlg()
pa->Command(CMD_SAVE_TICKS, 0L, 0L); undo_flags |= UNDO_CONTINUE;
}
TmpTxt[0] = 0; Dlg->GetText(106, TmpTxt);
- if(TextDef.text && TextDef.text[0] && strcmp(TextDef.text, TmpTxt)) {
+ if(res == 1 && TextDef.text && TextDef.text[0] && strcmp(TextDef.text, TmpTxt)) {
Undo.String(this, &TextDef.text, undo_flags); undo_flags |= UNDO_CONTINUE;
if(TextDef.text) free(TextDef.text); TextDef.text = strdup(TmpTxt);
}
if(cmpTextDEF(&OldTxtDef, &NewTxtDef)){
if(NewTxtDef.ColTxt != TextDef.ColTxt) bBGvalid = false;
if (pa) pa->Command(CMD_TLB_TXTDEF, &NewTxtDef, 0L);
- else if(parent->Id == GO_MLABEL) {
+ else if(res == 10 || parent->Id == GO_MLABEL) {
if(parent->Command(CMD_SETTEXTDEF, &NewTxtDef, 0L))RetVal = true;
}
else {
@@ -2341,15 +2424,18 @@ Label::PropertyDlg()
if(pa) {
pa->SetSize(SIZE_TLB_XDIST, n_dist.fx); pa->SetSize(SIZE_TLB_YDIST, n_dist.fy);
}
- else if(parent->Id == GO_MLABEL) {
- if(parent->SetSize(SIZE_LB_XDIST, n_dist.fx) ||
- parent->SetSize(SIZE_LB_YDIST, n_dist.fy)) RetVal = true;
+ else if(res == 10 || parent->Id == GO_MLABEL) {
+ if(n_dist.fx != o_dist.fx && parent->SetSize(SIZE_LB_XDIST, n_dist.fx)) RetVal = true;
+ if(n_dist.fy != o_dist.fy && parent->SetSize(SIZE_LB_YDIST, n_dist.fy)) RetVal = true;
}
else {
Undo.SaveLFP(this, &fDist, undo_flags); undo_flags |= UNDO_CONTINUE;
fDist.fx = n_dist.fx; fDist.fy = n_dist.fy;
}
}
+ if(parent->Id == GO_MLABEL && Dlg->GetValue(152, &tmp) && tmp != lspc) {
+ parent->SetSize(SIZE_LSPC, tmp/100.0); RetVal = true;
+ }
if(undo_flags & UNDO_CONTINUE) RetVal = true;
}
CloseDlgWnd(hDlg);
@@ -2407,6 +2493,7 @@ segment::PropertyDlg()
LineDEF newLine, newFillLine;
FillDEF newFill;
DWORD undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
if(!parent) return false;
OD_filldef(OD_SETLINE, 0L, 0L, 0L, (void *)&segLine, 0);
@@ -2425,8 +2512,8 @@ segment::PropertyDlg()
LoopDlgWnd();
res = Dlg->GetResult();
switch(res) {
- case 1:
- case 2:
+ case 1: case 2:
+ Undo.SetDisp(cdisp);
OD_filldef(OD_GETLINE, 0L, 0L, 0L, (void *)&newLine, 0);
OD_filldef(OD_GETFILL, 0L, 0L, 0L, (void *)&newFill, 0);
memcpy(&newFillLine, &segFillLine, sizeof(LineDEF));
@@ -2511,6 +2598,7 @@ polyline::PropertyDlg()
DlgRoot *Dlg;
void *hDlg;
int res, undo_level = *Undo.pcb;
+ anyOutput *cdisp = Undo.cdisp;
bool bRet = false;
LineDEF newLine;
@@ -2520,8 +2608,14 @@ polyline::PropertyDlg()
if(parent->Id == GO_GRAPH || parent->Id == GO_PAGE) Dlg->ShowItem(50, true);
hDlg = CreateDlgWnd("line properties", 50, 50, 410, 314, Dlg, 0x0L);
do{
- LoopDlgWnd();
- res = ExecDrawOrderButt(parent, this, Dlg->GetResult());
+ LoopDlgWnd(); res = Dlg->GetResult();
+ switch (res) {
+ case 600: case 601: case 602: case 603:
+ Undo.SetDisp(cdisp);
+ res = ExecDrawOrderButt(parent, this, res); break;
+ case 1: case 2:
+ Undo.SetDisp(cdisp); break;
+ }
}while (res < 0);
switch(res) {
case 1: //OK pressed
@@ -2570,6 +2664,7 @@ polygon::PropertyDlg()
FillDEF newFill;
DWORD undo_flags = 0L;
int res, undo_level = *Undo.pcb;
+ anyOutput *cdisp = Undo.cdisp;
bool bRet = false;
OD_filldef(OD_SETLINE, 0L, 0L, 0L, (void *)&pgLine, 0);
@@ -2578,8 +2673,14 @@ polygon::PropertyDlg()
if(parent->Id == GO_GRAPH || parent->Id == GO_PAGE) Dlg->ShowItem(50, true);
hDlg = CreateDlgWnd("polygon properties", 50, 50, 310, 224, Dlg, 0x0L);
do{
- LoopDlgWnd();
- res = ExecDrawOrderButt(parent, this, Dlg->GetResult());
+ LoopDlgWnd(); res = Dlg->GetResult();
+ switch(res) {
+ case 600: case 601: case 602: case 603:
+ Undo.SetDisp(cdisp);
+ res = ExecDrawOrderButt(parent, this, res); break;
+ case 1: case 2:
+ Undo.SetDisp(cdisp); break;
+ }
}while (res < 0);
switch (res) {
case 1: //OK pressed
@@ -2662,6 +2763,7 @@ rectangle::PropertyDlg()
LineDEF old_Line, new_Line, old_FillLine, new_FillLine;
FillDEF old_Fill, new_Fill;
DWORD undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
bool bRet = false;
OD_filldef(OD_SETLINE, 0L, 0L, 0L, (void *)&Line, 0);
@@ -2679,8 +2781,14 @@ rectangle::PropertyDlg()
type == 2 ? (char*)"rounded rectangle" : (char*)"rectangle properties",
50, 50, 330, 248, Dlg, 0x0L);
do{
- LoopDlgWnd();
- res = ExecDrawOrderButt(parent, this, Dlg->GetResult());
+ LoopDlgWnd(); res = Dlg->GetResult();
+ switch(res) {
+ case 600: case 601: case 602: case 603:
+ Undo.SetDisp(cdisp);
+ res = ExecDrawOrderButt(parent, this, res); break;
+ case 1: case 2:
+ Undo.SetDisp(cdisp); break;
+ }
}while (res < 0);
switch (res) {
case 1: //OK pressed
@@ -2744,9 +2852,9 @@ PlotScatt::CreateBarChart()
{3, 0, 4, ISPARENT | CHECKED, GROUP, NULL, 138, 40, 55, 12},
{4, 5, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 120, 110},
{5, 10, 200, ISPARENT, SHEET, &tab2, 5, 10, 120, 110},
- {10, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {10, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"spread sheet range for values", 10, 25, 60, 8},
- {101, 102, 0, 0x0L, EDTEXT, TmpTxt, 10, 38, 110, 10},
+ {101, 102, 0, 0x0L, RANGEINPUT, TmpTxt, 10, 38, 110, 10},
{102, 0, 110, ISPARENT | CHECKED, GROUPBOX, (void*)" style ", 10, 55, 110, 61},
{110, 0, 0, NOSELECT, ODBUTTON, (void*)OD_filldef, 25, 62, 90, 50},
{200, 201, 0, 0x0L, RTEXT, (void*)"start value", 10, 35, 38, 8},
@@ -2765,6 +2873,7 @@ PlotScatt::CreateBarChart()
LineDEF Line;
FillDEF Fill;
+ if(!parent || !data) return false;
memcpy(&Line, defs.GetOutLine(), sizeof(LineDEF));
memcpy(&Fill, defs.GetFill(), sizeof(FillDEF));
OD_filldef(OD_SETLINE, 0L, 0L, 0L, (void *)&Line, 0);
@@ -2772,6 +2881,7 @@ PlotScatt::CreateBarChart()
data->GetSize(&width, &height);
sprintf(TmpTxt, "a1:a%d", height);
if(!(Dlg = new DlgRoot(BarDlg)))return false;
+ Dlg->ItemCmd(101, CMD_SET_DATAOBJ, data);
hDlg = CreateDlgWnd("Simple bar chart", 50, 50, 370, 280, Dlg, 0x0L);
do {
LoopDlgWnd();
@@ -2848,11 +2958,11 @@ PlotScatt::PropertyDlg()
{5, 6, 200, TOUCHEXIT | ISPARENT, SHEET, &tab2, 5, 10, 131, 100},
{6, 7, 300, ISPARENT, SHEET, &tab3, 5, 10, 131, 100},
{7, 10, 400, ISPARENT, SHEET, &tab4, 5, 10, 131, 100},
- {10, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {10, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"range for X Data", 10, 30, 60, 8},
- {101, 102, 0, 0x0L, EDTEXT, text1, 20, 40, 100, 10},
+ {101, 102, 0, 0x0L, RANGEINPUT, text1, 20, 40, 100, 10},
{102, 103, 0, 0x0L, LTEXT, (void*)"range for Y Data", 10, 55, 60, 8},
- {103, 104, 0, 0x0L, EDTEXT, text2, 20, 65, 100, 10},
+ {103, 104, 0, 0x0L, RANGEINPUT, text2, 20, 65, 100, 10},
{104, 105, 0, 0x0L, ICON, (void*)&icon, 10, 85, 10, 10},
{105, 106, 0, 0x0L, LTEXT, (void*)"Valid ranges include e.g. \'a1:g13\'", 30, 85, 30, 6},
{106, 107, 0, 0x0L, LTEXT, (void*)"or \'b4:j4\' if data are available.", 30, 91, 30, 6},
@@ -2870,10 +2980,10 @@ PlotScatt::PropertyDlg()
{301, 302, 0, 0x0L, CHECKBOX, (void*)"draw error bars", 15, 28, 50, 8},
{302, 303, 0, 0x0L, LTEXT, (void*)"style:", 35, 40, 20, 8},
{303, 304, 0, 0x0L, LTEXT, (void*)"range for error data:", 15, 82, 60, 8},
- {304, 0, 0, 0x0L, EDTEXT, text3, 20, 93, 100, 10},
+ {304, 0, 0, 0x0L, RANGEINPUT, text3, 20, 93, 100, 10},
{400, 401, 0, 0x0L, CHECKBOX, (void*)"add labels to data points", 15, 28, 50, 8},
{401, 402, 0, 0x0L, LTEXT, (void*)"spread sheet range for labels:", 15, 40, 60, 8},
- {402, 0, 0, 0x0L, EDTEXT, text4, 20, 51, 100, 10},
+ {402, 0, 0, 0x0L, RANGEINPUT, text4, 20, 51, 100, 10},
{500, 501, 0, TOUCHEXIT|CHECKED|ISRADIO, ODBUTTON, (void*)(OD_ErrBarTempl),60,40,20,20},
{501, 502, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_ErrBarTempl), 80, 40, 20, 20},
{502, 503, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)(OD_ErrBarTempl), 100, 40, 20, 20},
@@ -2891,12 +3001,17 @@ PlotScatt::PropertyDlg()
TXA_HLEFT | TXA_VBOTTOM, TXM_TRANSPARENT, TXS_NORMAL, FONT_HELVETICA, TmpTxt};
AccRange *rX, *rY, *rE, *rL;
+ if(!parent || !data) return false;
if(Id == GO_BARCHART) return CreateBarChart();
data->GetSize(&width, &height);
sprintf(text1, "a1:a%d", height); sprintf(text2, "b1:b%d", height);
sprintf(text3, "c1:c%d", height); sprintf(text4, "b1:b%d", height);
rX = rY = rE = rL = 0L;
if(!(Dlg = new DlgRoot(XYDlg)))return false;
+ Dlg->ItemCmd(101, CMD_SET_DATAOBJ, data);
+ Dlg->ItemCmd(103, CMD_SET_DATAOBJ, data);
+ Dlg->ItemCmd(304, CMD_SET_DATAOBJ, data);
+ Dlg->ItemCmd(402, CMD_SET_DATAOBJ, data);
#ifdef _WINDOWS
for(i = 104; i <= 107; i++) Dlg->TextSize(i, 12);
#else
@@ -3072,7 +3187,161 @@ PlotScatt::PropertyDlg()
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Regression properties dialog
+// calculate means and error to create a xy-plot
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+bool
+xyStat::PropertyDlg()
+{
+ char text1[100], text2[100];
+ DlgInfo StatDlg[] = {
+ {1, 2, 0, DEFAULT, PUSHBUTTON, (void*)"OK", 130, 10, 45, 12},
+ {2, 10, 0, 0x0L, PUSHBUTTON, (void*)"Cancel", 130, 25, 45, 12},
+ {10, 100, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
+ {100, 101, 0, 0x0L, LTEXT, (void*)"range for grouping variable", 10, 10, 90, 9},
+ {101, 102, 0, 0x0L, LTEXT, (void*)"(X data)", 10, 20, 60, 9},
+ {102, 103, 0, 0x0L, RANGEINPUT, text1, 10, 30, 100, 10},
+ {103, 104, 0, 0x0L, LTEXT, (void*)"range for Y data", 10, 45, 90, 9},
+ {104, 200, 0, 0x0L, RANGEINPUT, text2, 10, 55, 100, 10},
+ {200, 300, 201, ISPARENT | CHECKED, GROUPBOX, (void*) " draw means ", 10, 75, 165, 50},
+ {201, 202, 0, CHECKED, CHECKBOX, (void*)" line", 15, 80, 50, 9},
+ {202, 203, 0, CHECKED, CHECKBOX, (void*)" symbols", 15, 90, 50, 9},
+ {203, 204, 0, 0x0L, CHECKBOX, (void*)" bars", 15, 100, 50, 9},
+ {204, 205, 0, 0x0L, LTEXT, (void*)"using", 65, 90, 30, 9},
+ {205, 206, 0, CHECKED, RADIO1, (void*)" arithmetic mean", 95, 80, 50, 9},
+ {206, 207, 0, 0x0L, RADIO1, (void*)" geometric mean", 95, 90, 50, 9},
+ {207, 208, 0, 0x0L, RADIO1, (void*)" harmonic mean", 95, 100, 50, 9},
+ {208, 0, 0, 0x0L, RADIO1, (void*)" median", 95, 110, 50, 9},
+ {300, 400, 301, ISPARENT | CHECKED, GROUPBOX, (void*) " draw error bars ", 10, 130, 165, 40},
+ {301, 302, 0, ISRADIO | CHECKED, CHECKBOX, (void*)" std. deviation (SD)", 15, 135, 70, 9},
+ {302, 303, 0, ISRADIO, CHECKBOX, (void*)" std. error (SEM)", 15, 145, 70, 9},
+ {303, 304, 0, ISRADIO, CHECKBOX, (void*)" 25, 75% percentiles", 95, 135, 70, 9},
+ {304, 305, 0, ISRADIO, CHECKBOX, (void*)" min and max", 95, 145, 70, 9},
+ {305, 306, 0, ISRADIO, CHECKBOX, (void*)" ", 15, 155, 70, 9},
+ {306, 307, 0, 0x0L, EDVAL1, &ci, 28, 154, 15, 10},
+ {307, 0, 0, 0x0L, LTEXT, (void*) "% conf. interval", 45, 155, 70, 9},
+ {400, 0, 401, ISPARENT | CHECKED, GROUPBOX, (void*) " number of cases ", 10, 175, 165, 30},
+ {401, 402, 0, ISRADIO | CHECKED, CHECKBOX, (void*)" on top of error", 15, 180, 70, 9},
+ {402, 403, 0, ISRADIO, CHECKBOX, (void*)" on top of mean", 95, 180, 70, 9},
+ {403, 404, 0, 0x0L, LTEXT, (void*)"prefix:", 15, 190, 24, 9},
+ {404, 0, 0, LASTOBJ, EDTEXT, (void*)"n = ", 40, 189, 30, 10}};
+ DlgRoot *Dlg;
+ void *hDlg;
+ bool bRet = false;
+ int i, res, width, height;
+ double x, y, e, f, dx, dy;
+ lfPOINT fp1, fp2;
+ TextDEF lbdef = {defs.Color(COL_TEXT), defs.Color(COL_BG), defs.GetSize(SIZE_TEXT), 0.0f, 0.0f, 0,
+ TXA_HLEFT | TXA_VBOTTOM, TXM_TRANSPARENT, TXS_NORMAL, FONT_HELVETICA, TmpTxt};
+
+ if(!parent || !data) return false;
+ data->GetSize(&width, &height);
+ sprintf(text1, "a1:a%d", height); sprintf(text2, "b1:b%d", height);
+ if(!(Dlg = new DlgRoot(StatDlg)))return false;
+ Dlg->ItemCmd(102, CMD_SET_DATAOBJ, data);
+ Dlg->ItemCmd(104, CMD_SET_DATAOBJ, data);
+ text1[0] = text2[0] = 0;
+ hDlg = CreateDlgWnd("Mean and Error Plot", 50, 50, 370, 450, Dlg, 0x0L);
+ do {
+ LoopDlgWnd();
+ res = Dlg->GetResult();
+ switch(res) {
+ case 0:
+ if(Dlg->GetCheck(10)) res=-1;
+ break;
+ case 1:
+ if(!(Dlg->GetText(102, text1) && Dlg->GetText(104, text2) && text1[0] && text2[0])) res = 2;
+ break;
+ }
+ }while (res <0);
+ if(res == 1) {
+ xRange = strdup(text1); yRange = strdup(text2);
+ type = 0;
+ if(Dlg->GetCheck(201)) type |= 0x0001; if(Dlg->GetCheck(202)) type |= 0x0002;
+ if(Dlg->GetCheck(203)) type |= 0x0004;
+ if(Dlg->GetCheck(205)) type |= 0x0010; if(Dlg->GetCheck(206)) type |= 0x0020;
+ if(Dlg->GetCheck(207)) type |= 0x0040; if(Dlg->GetCheck(208)) type |= 0x0080;
+ if(Dlg->GetCheck(301)) type |= 0x0100; if(Dlg->GetCheck(302)) type |= 0x0200;
+ if(Dlg->GetCheck(303)) type |= 0x0400; if(Dlg->GetCheck(304)) type |= 0x0800;
+ if(Dlg->GetCheck(305)) type |= 0x1000;
+ if(Dlg->GetCheck(401)) type |= 0x2000; if(Dlg->GetCheck(402)) type |= 0x4000;
+ Dlg->GetValue(306, &ci); TmpTxt[0] = 0;
+ if(Dlg->GetText(404, TmpTxt) && TmpTxt[0]) case_prefix = strdup(TmpTxt);
+ CreateData();
+ if(type && curr_data) {
+ data->GetSize(&width, &height); nPoints = height;
+ sprintf(text1, "a1:a%d", height); sprintf(text2, "b1:b%d", height);
+ Bounds.Xmin = Bounds.Ymin = HUGE_VAL; Bounds.Xmax = Bounds.Ymax = -HUGE_VAL;
+ for(i= 0; i < height; i++) {
+ if(curr_data->GetValue(i, 0, &x) && curr_data->GetValue(i, 1, &y))
+ CheckBounds(x, y);
+ }
+ if(type & 0x0001) {
+ if(nPoints >1) TheLine = new DataLine(this, curr_data, text1, text2);
+ }
+ if((type & 0x0002) && (Symbols = (Symbol**)calloc(nPoints, sizeof(Symbol*)))) {
+ for(i = 0; i < height; i++) {
+ if(curr_data->GetValue(i, 0, &x) && curr_data->GetValue(i, 1, &y)
+ && (Symbols[i] = new Symbol(this, curr_data, x, y, DefSym, 0, i, 1, i)))
+ Symbols[i]->idx = i;
+ }
+ }
+ if((type & 0x0004) && (Bars = (Bar**)calloc(nPoints, sizeof(Bar*)))) {
+ for(i = 0; i < height; i++) {
+ if(curr_data->GetValue(i, 0, &x) && curr_data->GetValue(i, 1, &y))
+ Bars[i] = new Bar(this, curr_data, x, y, BAR_VERTB | BAR_RELWIDTH, 0, i, 1, i);
+ }
+ }
+ if(type & 0x1f00) Errors = (ErrorBar**)calloc(nPoints, sizeof(ErrorBar*));
+ if((type & 0x1300) && Errors) {
+ for(i = 0; i < height; i++) {
+ if(curr_data->GetValue(i, 0, &x) && curr_data->GetValue(i, 1, &y)
+ && curr_data->GetValue(i, 2, &e))
+ Errors[i]= new ErrorBar(this, curr_data, x, y, e, 0, 0, i, 1, i, 2, i);
+ }
+ }
+ if((type & 0x0c00) && Errors) {
+ for(i = 0; i < height; i++) {
+ if(curr_data->GetValue(i, 0, &x) && curr_data->GetValue(i, 2, &e) && curr_data->GetValue(i, 3, &f)){
+ fp1.fx = fp2.fx = x; fp1.fy = e; fp2.fy = f;
+ Errors[i]= (ErrorBar*)new Whisker(this, curr_data, fp1, fp2, 0, 0, i, 2, i, 0, i, 3, i);
+ }
+ }
+ }
+ if((type & 0x6000) && (Labels = (Label**)calloc(nPoints, sizeof(Label*)))) {
+ dy = -0.4 * defs.GetSize(SIZE_SYMBOL);
+ if(type & 0x2000){
+ lbdef.Align = TXA_HCENTER | TXA_VBOTTOM;
+ dx = 0.0;
+ }
+ else {
+ lbdef.Align = TXA_HLEFT | TXA_VBOTTOM;
+ dx = -dy;
+ }
+ for(i = 0; i < height; i++) {
+ if(curr_data->GetValue(i, 0, &x) && curr_data->GetText(i, 5, TmpTxt, TMP_TXT_SIZE)){
+ if((type & 0x2000) && curr_data->GetValue(i, 4, &y))
+ Labels[i] = new Label(this, curr_data, x, y, &lbdef,
+ LB_X_DATA | LB_Y_DATA, 0, i, 4, i, 5, i);
+ else if((type & 0x4000) && curr_data->GetValue(i, 1, &y))
+ Labels[i] = new Label(this, curr_data, x, y, &lbdef,
+ LB_X_DATA | LB_Y_DATA, 0, i, 1, i, 5, i);
+ if(Labels[i]){
+ Labels[i]->SetSize(SIZE_LB_YDIST, dy);
+ Labels[i]->SetSize(SIZE_LB_XDIST, dx);
+ }
+ }
+ }
+ }
+ bRet = true;
+ }
+ }
+ CloseDlgWnd(hDlg);
+ delete Dlg;
+ return bRet;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Frequency distribution
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
FreqDist::PropertyDlg()
@@ -3085,9 +3354,9 @@ FreqDist::PropertyDlg()
{3, 0, 4, ISPARENT | CHECKED, GROUP, NULL, 138, 40, 55, 12},
{4, 5, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 120, 113},
{5, 10, 200, ISPARENT, SHEET, &tab2, 5, 10, 120, 113},
- {10, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {10, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"spread sheet range for values", 10, 25, 60, 8},
- {101, 102, 0, 0x0L, EDTEXT, TmpTxt, 10, 38, 110, 10},
+ {101, 102, 0, 0x0L, RANGEINPUT, TmpTxt, 10, 38, 110, 10},
{102, 103, 120, ISPARENT | CHECKED, GROUPBOX, (void*)" classes ", 10, 55, 110, 42},
{103, 0, 150, ISPARENT | CHECKED, GROUPBOX, (void*)" plot function ", 10, 102, 110, 17},
{120, 121, 0, CHECKED, RADIO1, (void*)"create", 15, 60, 30, 9},
@@ -3112,6 +3381,7 @@ FreqDist::PropertyDlg()
data->GetSize(&width, &height);
sprintf(TmpTxt, "a1:a%d", height);
if(!(Dlg = new DlgRoot(FreqDlg)))return false;
+ Dlg->ItemCmd(101, CMD_SET_DATAOBJ, data);
hDlg = CreateDlgWnd("Frequency Distribution", 50, 50, 370, 280, Dlg, 0x0L);
do {
LoopDlgWnd();
@@ -3161,11 +3431,11 @@ Regression::PropertyDlg()
{3, 0, 4, ISPARENT | CHECKED, GROUP, 0L, 0, 0, 0, 0},
{4, 5, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 130, 85},
{5, 10, 200, ISPARENT, SHEET, &tab2, 5, 10, 130, 85},
- {10, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {10, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"range for X Data", 10, 20, 60, 8},
- {101, 102, 0, 0x0L, EDTEXT, text1, 20, 30, 100, 10},
+ {101, 102, 0, 0x0L, RANGEINPUT, text1, 20, 30, 100, 10},
{102, 103, 0, 0x0L, LTEXT, (void*)"range for Y Data", 10, 45, 60, 8},
- {103, 104, 0, 0x0L, EDTEXT, text2, 20, 55, 100, 10},
+ {103, 104, 0, 0x0L, RANGEINPUT, text2, 20, 55, 100, 10},
{104, 105, 0, CHECKED, CHECKBOX, (void*)" include symbols in plot", 10, 70, 100, 8},
{105, 0, 0, 0x0L, CHECKBOX, (void*) " draw SD ellipse", 10, 80, 100, 8},
{200, 210, 201, CHECKED | ISPARENT, GROUPBOX, (void*)" x-values ", 10, 30, 58, 50},
@@ -3186,11 +3456,13 @@ Regression::PropertyDlg()
bool bRet = false, bContinue = false, dValid;
lfPOINT *values = 0L;
+ if(!parent || !data) return false;
rX = rY = 0L;
data->GetSize(&width, &height);
sprintf(text1, "a1:a%d", height);
sprintf(text2, "b1:b%d", height);
- Dlg = new DlgRoot(RegDlg);
+ if(!(Dlg = new DlgRoot(RegDlg)))return false;
+ Dlg->ItemCmd(101, CMD_SET_DATAOBJ, data); Dlg->ItemCmd(103, CMD_SET_DATAOBJ, data);
hDlg = CreateDlgWnd("Linear regression analysis step 1/2", 50, 50, 380, 225, Dlg, 0x0L);
do {
LoopDlgWnd();
@@ -3310,13 +3582,13 @@ BubblePlot::PropertyDlg()
{4, 5, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 130, 120},
{5, 6, 200, ISPARENT, SHEET, &tab2, 5, 10, 130, 120},
{6, 10, 300, ISPARENT, SHEET, &tab3, 5, 10, 130, 120},
- {10, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {10, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"range for X Data", 10, 40, 60, 8},
- {101, 102, 0, 0x0L, EDTEXT, text1, 20, 50, 100, 10},
+ {101, 102, 0, 0x0L, RANGEINPUT, text1, 20, 50, 100, 10},
{102, 103, 0, 0x0L, LTEXT, (void*)"range for Y Data", 10, 65, 60, 8},
- {103, 104, 0, 0x0L, EDTEXT, text2, 20, 75, 100, 10},
+ {103, 104, 0, 0x0L, RANGEINPUT, text2, 20, 75, 100, 10},
{104, 105, 0, 0x0L, LTEXT, (void*)"range for sizes", 10, 90, 60, 8},
- {105, 0, 0, 0x0L, EDTEXT, text3, 20, 100, 100, 10},
+ {105, 0, 0, 0x0L, RANGEINPUT, text3, 20, 100, 100, 10},
{200, 201, 0, 0x0L, LTEXT, (void*)"Select one of the following shapes", 10, 30, 110, 8},
{201, 202, 0, CHECKED, SYMRADIO, (void *)&syms[0], 30, 40, 20, 20},
{202, 203, 0, 0x0L, SYMRADIO, (void *)&syms[1], 50, 40, 20, 20},
@@ -3352,6 +3624,7 @@ BubblePlot::PropertyDlg()
AccRange *rX, *rY, *rS;
LineDEF ShowFillLine ={0.2f, 1.0f, 0x0L, 0x0L};
+ if(!parent || !data) return false;
data->GetSize(&width, &height);
sprintf(text1, "a1:a%d", height);
sprintf(text2, "b1:b%d", height);
@@ -3359,7 +3632,10 @@ BubblePlot::PropertyDlg()
memcpy(&ShowFill, &BubbleFill, sizeof(FillDEF));
if(BubbleFill.hatch) memcpy(&ShowFillLine, BubbleFill.hatch, sizeof(LineDEF));
ShowFill.hatch = &ShowFillLine;
- Dlg = new DlgRoot(PlotDlg);
+ if(!(Dlg = new DlgRoot(PlotDlg)))return false;
+ Dlg->ItemCmd(101, CMD_SET_DATAOBJ, data);
+ Dlg->ItemCmd(103, CMD_SET_DATAOBJ, data);
+ Dlg->ItemCmd(105, CMD_SET_DATAOBJ, data);
hDlg = CreateDlgWnd("Create Bubble Plot", 50, 50, 400, 300, Dlg, 0x0L);
rX = rY = rS = 0L;
do {
@@ -3463,6 +3739,7 @@ PolarPlot::AddPlot()
DataLine *TheLine = 0L;
Plot **tmpPlots;
Function *func;
+ anyOutput *cdisp = Undo.cdisp;
data->GetSize(&width, &height);
sprintf(text1, "a1:a%d", height);
@@ -3492,6 +3769,7 @@ PolarPlot::AddPlot()
(rX = new AccRange(text1)) && (rY = new AccRange(text2)) &&
(n = rX ? rX->CountItems() : 0) &&
(tmpPlots = (Plot**)realloc(Plots, (nPlots+2)*sizeof(Plot*)))) {
+ Undo.SetDisp(cdisp);
Plots = tmpPlots;
if(Dlg->GetCheck(200) || Dlg->GetCheck(201))
Symbols = (Symbol**) calloc(n+1, sizeof(Symbol*));
@@ -3588,9 +3866,9 @@ PolarPlot::PropertyDlg()
{1, 2, 0, DEFAULT, PUSHBUTTON, (void*)"OK", 140, 10, 45, 12},
{2, 3, 0, 0x0L, PUSHBUTTON, (void*)"Cancel", 140, 25, 45, 12},
{3, 50, 4, ISPARENT | CHECKED, GROUP, 0L, 138, 40, 55, 12},
- {4, 5, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 131, 100},
- {5, 10, 200, ISPARENT | TOUCHEXIT, SHEET, &tab2, 5, 10, 131, 100},
- {10, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {4, 5, 100, ISPARENT | TOUCHEXIT, SHEET, &tab1, 5, 10, 131, 100},
+ {5, 10, 200, ISPARENT | TOUCHEXIT | CHECKED, SHEET, &tab2, 5, 10, 131, 100},
+ {10, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"angular range (full circle)", 10, 25, 60, 8},
{101, 102, 0, 0x0L, RTEXT, (void*)"min =", 5, 37, 25, 8},
{102, 103, 0, 0x0L, EDVAL1, &lox, 30, 37, 30, 10},
@@ -3613,9 +3891,9 @@ PolarPlot::PropertyDlg()
{203, 204, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PolarTempl, 70, 25, 20, 20},
{204, 210, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PolarTempl, 90, 25, 20, 20},
{210, 211, 0, 0x0L, LTEXT, (void*)"range for x-data (circular or angular data)", 10, 55, 50, 8},
- {211, 212, 0, 0x0L, EDTEXT, (void*)text1, 20, 67, 100, 10},
+ {211, 212, 0, 0x0L, RANGEINPUT, (void*)text1, 20, 67, 100, 10},
{212, 213, 0, 0x0L, LTEXT, (void*)"range for y-data (radial data)", 10, 80, 50, 8},
- {213, 0, 0, LASTOBJ, EDTEXT, (void*)text2, 20, 92, 100, 10}};
+ {213, 0, 0, LASTOBJ, RANGEINPUT, (void*)text2, 20, 92, 100, 10}};
DlgRoot *Dlg;
void *hDlg;
int res, width, height, i, j, k, l, n, ic, cType = 200;
@@ -3627,13 +3905,11 @@ PolarPlot::PropertyDlg()
TextDEF tlbdef;
AxisDEF ang_axis, rad_axis;
+ if(!parent || !data) return false;
if(Plots) return Config();
- if(parent) {
- frad = (parent->GetSize(SIZE_DRECT_BOTTOM) - parent->GetSize(SIZE_DRECT_TOP))/2.0f;
- fcx = parent->GetSize(SIZE_GRECT_LEFT) + parent->GetSize(SIZE_DRECT_LEFT)*1.5 + frad;
- fcy = parent->GetSize(SIZE_GRECT_TOP) + parent->GetSize(SIZE_DRECT_TOP) + frad;
- }
- else return false;
+ frad = (parent->GetSize(SIZE_DRECT_BOTTOM) - parent->GetSize(SIZE_DRECT_TOP))/2.0f;
+ fcx = parent->GetSize(SIZE_GRECT_LEFT) + parent->GetSize(SIZE_DRECT_LEFT)*1.5 + frad;
+ fcy = parent->GetSize(SIZE_GRECT_TOP) + parent->GetSize(SIZE_DRECT_TOP) + frad;
data->GetSize(&width, &height);
sprintf(text1, "a1:a%d", height);
sprintf(text2, "b1:b%d", height);
@@ -3647,6 +3923,7 @@ PolarPlot::PropertyDlg()
tlbdef.Font = FONT_HELVETICA;
tlbdef.text = 0L;
if(!(Dlg = new DlgRoot(PolDlg)))return false;
+ Dlg->ItemCmd(211, CMD_SET_DATAOBJ, data); Dlg->ItemCmd(213, CMD_SET_DATAOBJ, data);
hDlg = CreateDlgWnd("Create Polar Plot", 50, 50, 388, 260, Dlg, 0x0L);
do {
LoopDlgWnd();
@@ -3655,14 +3932,14 @@ PolarPlot::PropertyDlg()
case 0:
if(Dlg->GetCheck(10)) res = -1;
break;
- case 5:
+ case 5: case 4:
bType = true;
res = -1;
break;
case 1:
- if(!bType) { //the 'Type' sheet must have been visited
+ if(!bType) { //the 'Coordinates' sheet must have been visited
bType = true;
- Dlg->SetCheck(5, 0L, true);
+ Dlg->SetCheck(4, 0L, true);
res = -1;
}
break;
@@ -3765,228 +4042,257 @@ PolarPlot::PropertyDlg()
bool
BoxPlot::PropertyDlg()
{
- TabSHEET tab1 = {0, 36, 10, "Summary"};
- TabSHEET tab2 = {36, 56, 10, "Box"};
- TabSHEET tab3 = {56, 89, 10, "Whisker"};
- TabSHEET tab4 = {89, 119, 10, "Symbol"};
- TabSHEET tab5 = {119, 140, 10, "Line"};
- char text1[100];
+ char text1[50], text2[50], text3[50], text4[50], text5[50], text6[50];
DlgInfo PlotDlg[] = {
- {1, 2, 0, DEFAULT, PUSHBUTTON, (void*)"OK", 158, 10, 45, 12},
- {2, 3, 0, 0x0L, PUSHBUTTON, (void*)"Cancel", 158, 25, 45, 12},
- {3, 800, 4, ISPARENT | CHECKED, GROUP, NULL, 138, 40, 55, 12},
- {4, 5, 0, 0x0L, LTEXT, (void*)"spreadsheet range for common X values", 15, 88, 120, 8},
- {5, 6, 0, 0x0L, EDTEXT, text1, 25, 100, 100, 10},
- {6, 7, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 140, 75},
- {7, 8, 200, ISPARENT, SHEET, &tab2, 5, 10, 140, 75},
- {8, 9, 300, ISPARENT, SHEET, &tab3, 5, 10, 140, 75},
- {9, 10, 400, ISPARENT, SHEET, &tab4, 5, 10, 140, 75},
- {10, 20, 500, ISPARENT, SHEET, &tab5, 5, 10, 140, 75},
- {20, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
- {100, 101, 0, 0x0L, LTEXT, (void*)"items:", 15, 30, 15, 8},
- {101, 102, 0, 0x0L, CHECKBOX, (void*)" boxes (rectangles)", 40, 30, 60, 8},
- {102, 103, 0, 0x0L, CHECKBOX, (void*)" whiskers (error bars)", 40, 40, 60, 8},
- {103, 104, 0, 0x0L, CHECKBOX, (void*)" symbol in the middle", 40, 50, 60, 8},
- {104, 105, 0, 0x0L, CHECKBOX, (void*)" line connecting close - open", 40, 60, 60, 8},
- {105, 0, 0, 0x0L, CHECKBOX, (void*)" horizontal plot", 15, 72, 60, 8},
- {200, 201, 0, 0x0L, LTEXT, (void*)"range for high values", 15, 30, 60, 8},
- {201, 202, 0, 0x0L, EDTEXT, 0L, 25, 40, 100, 10},
- {202, 203, 0, 0x0L, LTEXT, (void*)"range for low values", 15, 55, 60, 8},
- {203, 0, 0, 0x0L, EDTEXT, 0L, 25, 65, 100, 10},
- {300, 301, 0, 0x0L, LTEXT, (void*)"range for maxima", 15, 30, 60, 8},
- {301, 302, 0, 0x0L, EDTEXT, 0L, 25, 40, 100, 10},
- {302, 303, 0, 0x0L, LTEXT, (void*)"range for minima", 15, 55, 60, 8},
- {303, 0, 0, 0x0L, EDTEXT, 0L, 25, 65, 100, 10},
- {400, 401, 0, 0x0L, LTEXT, (void*)"mark centers with symbols,", 15, 30, 60, 8},
- {401, 402, 0, 0x0L, LTEXT, (void*)"range for centers (means):", 15, 40, 60, 8},
- {402, 0, 0, 0x0L, EDTEXT, 0L, 25, 55, 100, 10},
- {500, 501, 0, 0x0L, LTEXT, (void*)"range for first value (open)", 15, 30, 60, 8},
- {501, 502, 0, 0x0L, EDTEXT, 0L, 25, 40, 100, 10},
- {502, 503, 0, 0x0L, LTEXT, (void*)"range for second value (close)", 15, 55, 60, 8},
- {503, 0, 0, LASTOBJ, EDTEXT, 0L, 25, 65, 100, 10}};
+ {1, 2, 0, DEFAULT, PUSHBUTTON, (void*)"OK", 130, 10, 45, 12},
+ {2, 10, 0, 0x0L, PUSHBUTTON, (void*)"Cancel", 130, 25, 45, 12},
+ {10, 50, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
+ {50, 60, 51, ISPARENT | CHECKED, GROUP, 0L, 0, 0, 0, 0},
+ {51, 52, 0, 0x0L, LTEXT, (void*)"Data Source:", 10, 12, 40, 9},
+ {52, 53, 0, CHECKED | TOUCHEXIT, RADIO2, (void*)" user values", 60, 12, 50, 9},
+ {53, 0, 0, TOUCHEXIT, RADIO2, (void*)" statistical data", 60, 22, 60, 9},
+ {60, 61, 100, HIDDEN | ISPARENT | CHECKED, GROUP, 0L, 0, 0, 0, 0},
+ {61, 0, 200, ISPARENT | CHECKED, GROUP, 0L, 0, 0, 0, 0},
+ {100, 102, 0, 0x0L, LTEXT, (void*)"range for grouping variable (X data)", 10, 39, 140, 9},
+ {102, 103, 0, 0x0L, RANGEINPUT, text1, 10, 49, 165, 10},
+ {103, 104, 0, 0x0L, LTEXT, (void*)"range for Y data", 10, 60, 90, 9},
+ {104, 150, 0, 0x0L, RANGEINPUT, text2, 10, 70, 165, 10},
+ {150, 160, 151, ISPARENT | CHECKED, GROUPBOX, (void*) " draw means ", 10, 87, 165, 45},
+ {151, 152, 0, 0x0L, CHECKBOX, (void*)" line", 15, 92, 50, 9},
+ {152, 153, 0, CHECKED, CHECKBOX, (void*)" symbols", 15, 101, 50, 9},
+ {153, 154, 0, 0x0L, LTEXT, (void*)"using", 65, 101, 30, 9},
+ {154, 155, 0, 0x0L, RADIO1, (void*)" arithmetic mean", 95, 90, 50, 9},
+ {155, 156, 0, 0x0L, RADIO1, (void*)" geometric mean", 95, 99, 50, 9},
+ {156, 157, 0, 0x0L, RADIO1, (void*)" harmonic mean", 95, 108, 50, 9},
+ {157, 0, 0, CHECKED, RADIO1, (void*)" median", 95, 117, 50, 9},
+ {160, 170, 161, ISPARENT | CHECKED, GROUPBOX, (void*) " draw boxes ", 10, 137, 165, 38},
+ {161, 162, 0, ISRADIO, CHECKBOX, (void*)" std. deviation (SD)", 15, 142, 70, 9},
+ {162, 163, 0, ISRADIO, CHECKBOX, (void*)" std. error (SEM)", 15, 151, 70, 9},
+ {163, 164, 0, ISRADIO | CHECKED, CHECKBOX, (void*)" 25, 75% percentiles", 95, 142, 70, 9},
+ {164, 165, 0, ISRADIO, CHECKBOX, (void*)" min and max", 95, 151, 70, 9},
+ {165, 166, 0, ISRADIO, CHECKBOX, (void*)" ", 15, 161, 70, 9},
+ {166, 167, 0, 0x0L, EDVAL1, &ci_box, 28, 160, 15, 10},
+ {167, 0, 0, 0x0L, LTEXT, (void*) "% conf. interval", 45, 161, 70, 9},
+ {170, 400, 171, ISPARENT | CHECKED, GROUPBOX, (void*) " draw whiskers ", 10, 180, 165, 38},
+ {171, 172, 0, ISRADIO, CHECKBOX, (void*)" std. deviation (SD)", 15, 185, 70, 9},
+ {172, 173, 0, ISRADIO, CHECKBOX, (void*)" std. error (SEM)", 15, 194, 70, 9},
+ {173, 174, 0, ISRADIO, CHECKBOX, (void*)" 25, 75% percentiles", 95, 185, 70, 9},
+ {174, 175, 0, ISRADIO | CHECKED, CHECKBOX, (void*)" min and max", 95, 194, 70, 9},
+ {175, 176, 0, ISRADIO, CHECKBOX, (void*)" ", 15, 204, 70, 9},
+ {176, 177, 0, 0x0L, EDVAL1, &ci_err, 28, 203, 15, 10},
+ {177, 0, 0, 0x0L, LTEXT, (void*) "% conf. interval", 45, 203, 70, 9},
+ {200, 202, 0, 0x0L, LTEXT, (void*)"range for common X values", 10, 39, 140, 9},
+ {202, 250, 0, 0x0L, RANGEINPUT, text1, 10, 49, 165, 10},
+ {250, 260, 251, ISPARENT | CHECKED, GROUPBOX, (void*) " ", 10, 68, 165, 30},
+ {251, 252, 0, 0x0L, CHECKBOX, (void*)" draw line", 15, 63, 50, 9},
+ {252, 253, 0, 0x0L, LTEXT, (void*)"range for line values", 15, 73, 80, 9},
+ {253, 0, 0, 0x0L, RANGEINPUT, text2, 15, 83, 155, 10},
+ {260, 270, 261, ISPARENT | CHECKED, GROUPBOX, (void*) " ", 10, 106, 165, 30},
+ {261, 262, 0, CHECKED, CHECKBOX, (void*)" draw symbols", 15, 101, 50, 9},
+ {262, 263, 0, 0x0L, LTEXT, (void*)"range for symbol values", 15, 111, 80, 9},
+ {263, 0, 0, 0x0L, RANGEINPUT, text2, 15, 121, 155, 10},
+ {270, 280, 271, ISPARENT | CHECKED, GROUPBOX, (void*) " ", 10, 144, 165, 50},
+ {271, 272, 0, CHECKED, CHECKBOX, (void*)" draw boxes", 15, 139, 50, 9},
+ {272, 273, 0, 0x0L, LTEXT, (void*)"range for HI values", 15, 149, 80, 9},
+ {273, 274, 0, 0x0L, RANGEINPUT, text3, 15, 159, 155, 10},
+ {274, 275, 0, 0x0L, LTEXT, (void*)"range for LO values", 15, 169, 80, 9},
+ {275, 0, 0, 0x0L, RANGEINPUT, text4, 15, 179, 155, 10},
+ {280, 0, 281, ISPARENT | CHECKED, GROUPBOX, (void*) " ", 10, 202, 165, 50},
+ {281, 282, 0, CHECKED, CHECKBOX, (void*)" draw whiskers", 15, 197, 50, 9},
+ {282, 283, 0, 0x0L, LTEXT, (void*)"range for HI values", 15, 207, 80, 9},
+ {283, 284, 0, 0x0L, RANGEINPUT, text5, 15, 217, 155, 10},
+ {284, 285, 0, 0x0L, LTEXT, (void*)"range for LO values", 15, 227, 80, 9},
+ {285, 0, 0, 0x0L, RANGEINPUT, text6, 15, 237, 155, 10},
+ {400, 0, 401, ISPARENT | CHECKED, GROUPBOX, (void*) " number of cases ", 10, 223, 165, 30},
+ {401, 402, 0, ISRADIO | CHECKED, CHECKBOX, (void*)" on top of error", 15, 228, 70, 9},
+ {402, 403, 0, ISRADIO, CHECKBOX, (void*)" on top of mean", 95, 228, 70, 9},
+ {403, 404, 0, 0x0L, LTEXT, (void*)"prefix:", 15, 238, 24, 9},
+ {404, 0, 0, LASTOBJ, EDTEXT, (void*)"n = ", 40, 237, 30, 10}};
DlgRoot *Dlg;
void *hDlg;
- int i, j, k, l, m, n, ic, res, width, height;
- bool bHor, bRet, bContinue = false;
+ bool bRet = false;
+ int i, j, k, k1, l, l1, n, ic, c, res, width, height;
+ double x, y1, y2, dx, dy;
lfPOINT fp1, fp2;
- double x, y1, y2;
- AccRange *rX, *rB1, *rB2, *rW1, *rW2, *rS, *rL1, *rL2;
+ TextDEF lbdef = {defs.Color(COL_TEXT), defs.Color(COL_BG), defs.GetSize(SIZE_TEXT), 0.0f, 0.0f, 0,
+ TXA_HLEFT | TXA_VBOTTOM, TXM_TRANSPARENT, TXS_NORMAL, FONT_HELVETICA, TmpTxt};
+ AccRange *rX = 0L, *rY1 = 0L, *rY2 = 0L;
+ int it_racc[] = {102, 104, 202, 253, 263, 273, 275, 283, 285};
- rX = rB1 = rB2 = rW1 = rW2 = rS = rL1 = rL2 = 0L;
+ if(!parent || !data) return false;
data->GetSize(&width, &height);
- sprintf(text1, "a1:a%d", height);
- Dlg = new DlgRoot(PlotDlg);
- hDlg = CreateDlgWnd("Box and Whisker Plot", 50, 50, 420, 260, Dlg, 0x0L);
+ sprintf(text1, "a1:a%d", height); sprintf(text2, "b1:b%d", height);
+ sprintf(text3, "c1:c%d", height); sprintf(text4, "d1:d%d", height);
+ sprintf(text5, "e1:e%d", height); sprintf(text6, "f1:f%d", height);
+ ci_box = ci_err = 95.0;
+ if(!(Dlg = new DlgRoot(PlotDlg)))return false;
+ for(i=0; i < 9; i++) Dlg->ItemCmd(it_racc[i], CMD_SET_DATAOBJ, data);
+ text1[0] = text2[0] = 0;
+ hDlg = CreateDlgWnd("Box and Whisker Plot", 50, 50, 370, 550, Dlg, 0x0L);
do {
LoopDlgWnd();
res = Dlg->GetResult();
- switch (res) {
+ switch(res) {
case 0:
- if(bContinue) res = -1;
- else if(Dlg->GetCheck(20)) res = -1;
- break;
- case -1:
- bContinue = false;
+ if(Dlg->GetCheck(10)) res=-1;
break;
- case 1:
- if(rX) delete rX;
- if(rB1) delete rB1; if(rB2) delete rB2;
- if(rW1) delete rW1; if(rW2) delete rW2;
- if(rS) delete rS;
- if(rL1) delete rL1; if(rL2) delete rL2;
- rX = rB1 = rB2 = rW1 = rW2 = rS = rL1 = rL2 = 0L;
- bHor = Dlg->GetCheck(105);
- if(Dlg->GetText(5, text1)) rX = new AccRange(text1);
- n = rX ? rX->CountItems() : 0;
- if(!n) {
- ErrorBox("Common X-range not specified\nor not valid.");
- bContinue = true;
- res = -1;
+ case 52: case 53:
+ if(res == 53) {
+ Dlg->ShowItem(60, true); Dlg->ShowItem(61, false);
}
- if(n && Dlg->GetCheck(101)) { //do boxes ?
- if(Dlg->GetText(201, TmpTxt)) rB1 = new AccRange(TmpTxt);
- if(Dlg->GetText(203, TmpTxt)) rB2 = new AccRange(TmpTxt);
- if(!rB1 || !rB2 || n != rB1->CountItems() || n != rB2->CountItems()) {
- ErrorBox("Range for boxes missing\nor not valid.\n"
- "Size must match common X-range.");
- Dlg->SetCheck(7, 0L, true);
- bContinue = true;
- res = -1;
- }
- }
- if(n && Dlg->GetCheck(102)) { //do whiskers ?
- if(Dlg->GetText(301, TmpTxt)) rW1 = new AccRange(TmpTxt);
- if(Dlg->GetText(303, TmpTxt)) rW2 = new AccRange(TmpTxt);
- if(!rW1 || !rW2 || n != rW1->CountItems() || n != rW2->CountItems()) {
- ErrorBox("Range for whiskers missing\nor not valid.\n"
- "Size must match common X-range.");
- Dlg->SetCheck(8, 0L, true);
- bContinue = true;
- res = -1;
- }
- }
- if(n && Dlg->GetCheck(103)) { //do symbols ?
- if(Dlg->GetText(402, TmpTxt)) rS = new AccRange(TmpTxt);
- if(!rS || n != rS->CountItems()) {
- ErrorBox("Range for symbols missing\nor not valid.\n"
- "Size must match common X-range.");
- bContinue = true;
- Dlg->SetCheck(9, 0L, true);
- res = -1;
- }
- }
- if(n && Dlg->GetCheck(104)) { //do line ?
- if(Dlg->GetText(501, TmpTxt)) rL1 = new AccRange(TmpTxt);
- if(Dlg->GetText(503, TmpTxt)) rL2 = new AccRange(TmpTxt);
- if(!rL1 || !rL2 || n != rL1->CountItems() || n != rL2->CountItems()) {
- ErrorBox("Range for line missing\nor not valid.\n"
- "Size must match common X-range.");
- Dlg->SetCheck(10, 0L, true);
- bContinue = true;
- res = -1;
- }
- }
- if(n && res > 0 && !rB1 && !rB2 && !rW1 && !rW2 && !rS && !rL1 && !rL2) {
- ErrorBox("Nothing to do !\n\nSelect at least one of either\n"
- "Box, Whisker, Symbol or Line.");
- bContinue = true;
- res = -1;
+ else {
+ Dlg->ShowItem(60, false); Dlg->ShowItem(61, true);
}
+ Dlg->Command(CMD_REDRAW, 0L, 0L); res=-1;
break;
}
- }while (res < 0);
- bRet = false;
- if(res == 1 && n && rX){ //ok: create objects for plot
- nPoints = n;
- Bounds.Xmin = Bounds.Ymin = HUGE_VAL; Bounds.Xmax = Bounds.Ymax = -HUGE_VAL;
- if(rB1 && rB2) {
- //DEBUG: delete existing objects first
- Boxes =(Box**)calloc(nPoints, sizeof(Box*));
- if(Boxes) {
- rX->GetFirst(&i, &j); rB1->GetFirst(&k, &l); rB2->GetFirst(&m, &n);
- rX->GetNext(&i, &j); rB1->GetNext(&k, &l); rB2->GetNext(&m, &n);
- ic = 0;
+ }while (res <0);
+ if(res == 1) {
+ type = 0; dirty = true;
+ if(Dlg->GetCheck(52) && Dlg->GetText(202, text1) && text1[0] &&(rX = new AccRange(text1))) {
+ xRange = strdup(text1);
+ n = rX->CountItems(); nPoints = n;
+ // data line
+ if(n > 1 && Dlg->GetCheck(251) && Dlg->GetText(253, TmpTxt)) {
+ TheLine = new DataLine(this, data, text1, TmpTxt);
+ bRet = true;
+ }
+ // symbols
+ if(n > 0 && Dlg->GetCheck(261) && Dlg->GetText(263, TmpTxt) && TmpTxt[0]
+ && (Symbols = (Symbol**)calloc(n, sizeof(Symbol*)))
+ && (rY1 = new AccRange(TmpTxt))) {
+ yRange = strdup(TmpTxt);
+ rX->GetFirst(&i, &j); rY1->GetFirst(&k, &l);
+ rX->GetNext(&i, &j); rY1->GetNext(&k, &l);
+ ic = c = 0;
do {
- if(data->GetValue(j, i, &x) && data->GetValue(l, k, &y1) &&
- data->GetValue(n, m, &y2)){
- if(bHor) {
- fp1.fx = y2; fp2.fx = y1; fp1.fy = fp2.fy = x;
- CheckBounds(y1, x); CheckBounds(y2, x);
- Boxes[ic++] = new Box(this, data, fp1, fp2, 0, m, n, i, j, k, l, i, j);
- }
- else {
- fp1.fy = y2; fp2.fy = y1; fp1.fx = fp2.fx = x;
- CheckBounds(x, y1); CheckBounds(x, y2);
- Boxes[ic++] = new Box(this, data, fp1, fp2, 0, i, j, m, n, i, j, k, l);
- }
+ if(data->GetValue(j, i, &x) && data->GetValue(l, k, &y1)) {
+ if(Symbols[ic] = new Symbol(this, data, x, y1, SYM_PLUS, i, j, k, l))
+ Symbols[ic++]->idx = c;
}
- }while(rX->GetNext(&i, &j) && rB1->GetNext(&k, &l) && rB2->GetNext(&m, &n));
+ c++;
+ }while(rX->GetNext(&i, &j) && rY1->GetNext(&k, &l));
+ delete rY1; rY1 = 0L;
if(ic) bRet = true;
- BoxDist.fx = BoxDist.fy = GetSize(bHor ? SIZE_BOXMINY : SIZE_BOXMINX);
}
- }
- if(rW1 && rW2) {
- Whiskers = (Whisker**)calloc(nPoints, sizeof(Whisker*));
- if(Whiskers) {
- rX->GetFirst(&i, &j); rW1->GetFirst(&k, &l); rW2->GetFirst(&m, &n);
- rX->GetNext(&i, &j); rW1->GetNext(&k, &l); rW2->GetNext(&m, &n);
+ // boxes
+ if(n > 0 && Dlg->GetCheck(271) && Dlg->GetText(273, text3) && Dlg->GetText(275, text4)
+ && (Boxes = (Box**)calloc(n, sizeof(Box*)))
+ && (rY1 = new AccRange(text3)) && (rY2 = new AccRange(text4))) {
+ rX->GetFirst(&i, &j); rY1->GetFirst(&k, &l); rY2->GetFirst(&k1, &l1);
+ rX->GetNext(&i, &j); rY1->GetNext(&k, &l); rY2->GetNext(&k1, &l1);
ic = 0;
do {
- if(data->GetValue(j, i, &x) && data->GetValue(l, k, &y1) &&
- data->GetValue(n, m, &y2)){
- if(bHor) {
- fp1.fx = y2; fp2.fx = y1; fp1.fy = fp2.fy = x;
- CheckBounds(y1, x); CheckBounds(y2, x);
- Whiskers[ic++] = new Whisker(this, data, fp1, fp2, 0, m, n, i, j, k, l, i, j);
- }
- else {
- fp1.fy = y2; fp2.fy = y1; fp1.fx = fp2.fx = x;
- CheckBounds(x, y1); CheckBounds(x, y2);
- Whiskers[ic++] = new Whisker(this, data, fp1, fp2, 0, i, j, m, n, i, j, k, l);
- }
+ if(data->GetValue(j, i, &x) && data->GetValue(l, k, &y1) && data->GetValue(l1, k1, &y2)) {
+ fp1.fy = y1; fp2.fy = y2; fp1.fx = fp2.fx = x;
+ Boxes[ic] = new Box(this, data, fp1, fp2, BAR_RELWIDTH, i, j, k, l, i, j, k1, l1);
+ if(Boxes[ic]) Boxes[ic++]->SetSize(SIZE_BOX, 60.0);
}
- }while(rX->GetNext(&i, &j) && rW1->GetNext(&k, &l) && rW2->GetNext(&m, &n));
+ }while(rX->GetNext(&i, &j) && rY1->GetNext(&k, &l) && rY2->GetNext(&k1, &l1));
+ delete rY1; rY1 = 0L; delete rY2; rY2 = 0L;
if(ic) bRet = true;
}
- }
- if(rS) {
- Symbols = (Symbol**)calloc(nPoints, sizeof(Symbol*));
- if(Symbols) {
- rX->GetFirst(&i, &j); rS->GetFirst(&k, &l);
- rX->GetNext(&i, &j); rS->GetNext(&k, &l);
+ // whiskers
+ if(n > 0 && Dlg->GetCheck(281) && Dlg->GetText(283, text3) && Dlg->GetText(285, text4)
+ && (Whiskers = (Whisker**)calloc(n, sizeof(Whisker*)))
+ && (rY1 = new AccRange(text3)) && (rY2 = new AccRange(text4))) {
+ rX->GetFirst(&i, &j); rY1->GetFirst(&k, &l); rY2->GetFirst(&k1, &l1);
+ rX->GetNext(&i, &j); rY1->GetNext(&k, &l); rY2->GetNext(&k1, &l1);
ic = 0;
do {
- if(data->GetValue(j, i, &x) && data->GetValue(l, k, &y1)){
- if(bHor) {
- CheckBounds(y1, x);
- Symbols[ic++] = new Symbol(this, data, y1, x,
- SYM_PLUS, k, l, i, j);
+ if(data->GetValue(j, i, &x) && data->GetValue(l, k, &y1) && data->GetValue(l1, k1, &y2)) {
+ fp1.fy = y1; fp2.fy = y2; fp1.fx = fp2.fx = x;
+ Whiskers[ic++] = new Whisker(this, data, fp1, fp2, 0, i, j, k, l, i, j, k1, l1);
+ }
+ }while(rX->GetNext(&i, &j) && rY1->GetNext(&k, &l) && rY2->GetNext(&k1, &l1));
+ delete rY1; rY1 = 0L; delete rY2; rY2 = 0L;
+ if(ic) bRet = true;
+ }
+ if (bRet) Command(CMD_AUTOSCALE, 0L, 0L);
+ }
+ else if(Dlg->GetText(102, text1) && text1[0] && Dlg->GetText(104, text2) && text2[0]){
+ xRange = strdup(text1); yRange = strdup(text2);
+ if(Dlg->GetCheck(154)) type |= 0x0001; if(Dlg->GetCheck(155)) type |= 0x0002;
+ if(Dlg->GetCheck(156)) type |= 0x0003; if(Dlg->GetCheck(157)) type |= 0x0004;
+ if(Dlg->GetCheck(161)) type |= 0x0010; if(Dlg->GetCheck(162)) type |= 0x0020;
+ if(Dlg->GetCheck(163)) type |= 0x0030; if(Dlg->GetCheck(164)) type |= 0x0040;
+ if(Dlg->GetCheck(165)) type |= 0x0050;
+ if(Dlg->GetCheck(171)) type |= 0x0100; if(Dlg->GetCheck(172)) type |= 0x0200;
+ if(Dlg->GetCheck(173)) type |= 0x0300; if(Dlg->GetCheck(174)) type |= 0x0400;
+ if(Dlg->GetCheck(175)) type |= 0x0500;
+ if(Dlg->GetCheck(151)) type |= 0x1000; if(Dlg->GetCheck(152)) type |= 0x2000;
+ if(Dlg->GetCheck(401)) type |= 0x4000; if(Dlg->GetCheck(402)) type |= 0x8000;
+ Dlg->GetValue(166, &ci_box); Dlg->GetValue(176, &ci_err);
+ if(Dlg->GetText(404, TmpTxt) && TmpTxt[0]) case_prefix = strdup(TmpTxt);
+ CreateData();
+ if(curr_data && type) {
+ curr_data->GetSize(&width, &height);
+ sprintf(text1, "a1:a%d", height); sprintf(text2, "b1:b%d", height);
+ nPoints = height;
+ if(nPoints > 1 && (type & 0x1000)) {
+ TheLine = new DataLine(this, curr_data, text1, text2);
+ bRet = true;
+ }
+ if(nPoints > 0 && (type & 0x2000) && (Symbols = (Symbol**)calloc(nPoints, sizeof(Symbol*)))) {
+ for(i = 0; i < height; i++) {
+ if(curr_data->GetValue(i, 0, &x) && curr_data->GetValue(i, 1, &y1)
+ && (Symbols[i] = new Symbol(this, curr_data, x, y1, SYM_PLUS, 0, i, 1, i)))
+ Symbols[i]->idx = i;
+ }
+ bRet = true;
+ }
+ if(nPoints > 0 && (type & 0x00f0) && (Boxes = (Box**)calloc(nPoints, sizeof(Box*)))) {
+ for(i = 0; i < height; i++) {
+ if(curr_data->GetValue(i, 0, &x) && curr_data->GetValue(i, 2, &y1)
+ && curr_data->GetValue(i, 3, &y2)) {
+ fp1.fy = y1; fp2.fy = y2; fp1.fx = fp2.fx = x;
+ Boxes[i] = new Box(this, curr_data, fp1, fp2, BAR_RELWIDTH, 0, i, 2, i, 0, i, 3, i);
+ if(Boxes[i]) Boxes[i]->SetSize(SIZE_BOX, 60.0);
}
- else {
- CheckBounds(x, y1);
- Symbols[ic++] = new Symbol(this, data, x, y1,
- SYM_PLUS, i, j, k, l);
+ }
+ bRet = true;
+ }
+ if(nPoints > 0 && (type & 0x0f00) && (Whiskers = (Whisker**)calloc(nPoints, sizeof(Whisker*)))) {
+ for(i = 0; i < height; i++) {
+ if(curr_data->GetValue(i, 0, &x) && curr_data->GetValue(i, 4, &y1)
+ && curr_data->GetValue(i, 5, &y2)) {
+ fp1.fy = y1; fp2.fy = y2; fp1.fx = fp2.fx = x;
+ Whiskers[i] = new Whisker(this, curr_data, fp1, fp2, 0, 0, i, 4, i, 0, i, 5, i);
}
}
- }while(rX->GetNext(&i, &j) && rS->GetNext(&k, &l));
- if(ic) bRet = true;
+ bRet = true;
+ }
+ if(nPoints > 0 && (type & 0xc000) && (Labels = (Label**)calloc(nPoints, sizeof(Label*)))) {
+ dy = -0.4 * defs.GetSize(SIZE_SYMBOL);
+ if(type & 0x4000){
+ lbdef.Align = TXA_HCENTER | TXA_VBOTTOM;
+ dx = 0.0;
+ }
+ else {
+ lbdef.Align = TXA_HLEFT | TXA_VBOTTOM;
+ dx = -dy;
+ }
+ for(i = 0; i < height; i++) {
+ if(curr_data->GetValue(i, 0, &x) && curr_data->GetText(i, 7, TmpTxt, TMP_TXT_SIZE)){
+ if(curr_data->GetValue(i, 6, &y1))Labels[i] = new Label(this, curr_data, x, y1, &lbdef,
+ LB_X_DATA | LB_Y_DATA, 0, i, 6, i, 7, i);
+ if(Labels[i]){
+ Labels[i]->SetSize(SIZE_LB_YDIST, dy); Labels[i]->SetSize(SIZE_LB_XDIST, dx);
+ }
+ }
+ }
+ bRet = true;
+ }
}
}
- if(rL1 && rL2) {
- Dlg->GetText(501, TmpTxt); i = strlen(TmpTxt);
- TmpTxt[i++] = ';'; TmpTxt[i++] = ' ';
- Dlg->GetText(503, TmpTxt+i);
- TheLine = new DataLine(this, data, text1, TmpTxt);
- bRet = true;
- }
+ }
+ if(bRet) {
+ dirty = true;
+ Command(CMD_AUTOSCALE, 0L, 0L);
}
CloseDlgWnd(hDlg);
delete Dlg;
if(rX) delete rX;
- if(rB1) delete rB1; if(rB2) delete rB2;
- if(rW1) delete rW1; if(rW2) delete rW2;
- if(rS) delete rS;
- if(rL1) delete rL1; if(rL2) delete rL2;
return bRet;
}
@@ -4005,11 +4311,11 @@ DensDisp::PropertyDlg()
{3, 0, 4, ISPARENT | CHECKED, GROUP, NULL, 138, 40, 55, 12},
{4, 5, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 130, 100},
{5, 10, 200, TOUCHEXIT | ISPARENT, SHEET, &tab2, 5, 10, 130, 100},
- {10, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {10, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"range for direction (time, depth) data", 10, 30, 60, 8},
- {101, 102, 0, 0x0L, EDTEXT, text1, 20, 40, 100, 10},
+ {101, 102, 0, 0x0L, RANGEINPUT, text1, 20, 40, 100, 10},
{102, 103, 0, 0x0L, LTEXT, (void*)"range for width (density) data", 10, 55, 60, 8},
- {103, 104, 0, 0x0L, EDTEXT, text2, 20, 65, 100, 10},
+ {103, 104, 0, 0x0L, RANGEINPUT, text2, 20, 65, 100, 10},
{104, 0, 0, 0x0L, CHECKBOX, (void*)"vertical profile", 10, 90, 100, 8},
{200, 201, 0, NOSELECT, ODBUTTON, (void*)OD_filldef, 25, 30, 90, 45},
{201, 202, 0, TOUCHEXIT | CHECKED, RADIO1, (void*)"symmetric bars", 25, 80, 60, 8},
@@ -4021,12 +4327,14 @@ DensDisp::PropertyDlg()
bool bRet = false, bContinue = false, bVert;
AccRange *rX = 0L, *rY = 0L;
+ if(!parent || !data) return false;
OD_filldef(OD_SETLINE, 0L, 0L, 0L, (void *)defs.GetOutLine(), 0);
OD_filldef(OD_SETFILL, 0L, 0L, 0L, (void *)defs.GetFill(), 0);
data->GetSize(&width, &height);
sprintf(text1, "a1:a%d", height);
sprintf(text2, "b1:b%d", height);
- Dlg = new DlgRoot(PlotDlg);
+ if(!(Dlg = new DlgRoot(PlotDlg)))return false;
+ Dlg->ItemCmd(101, CMD_SET_DATAOBJ, data); Dlg->ItemCmd(103, CMD_SET_DATAOBJ, data);
hDlg = CreateDlgWnd("Density profile", 50, 50, 420, 260, Dlg, 0x0L);
do {
LoopDlgWnd();
@@ -4180,12 +4488,12 @@ StackBar::PropertyDlg()
{10, 11, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 140, 100},
{11, 12, 200, ISPARENT, SHEET, &tab2, 5, 10, 140, 100},
{12, 20, 300, ISPARENT, SHEET, &tab3, 5, 10, 140, 100},
- {20, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {20, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"range for common x values", 15, 30, 60, 8},
- {101, 152, 0, 0x0L, EDTEXT, TmpTxt, 25, 40, 100, 10},
+ {101, 152, 0, 0x0L, RANGEINPUT, TmpTxt, 25, 40, 100, 10},
{152, 153, 0, ISPARENT | CHECKED, GROUPBOX, (void*)" ranges for y values ", 12, 60, 128, 45},
{153, 154, 0, 0x0L, LTEXT, 0L, 25, 65, 60, 8},
- {154, 155, 0, 0x0L, EDTEXT, 0L, 25, 75, 100, 10},
+ {154, 155, 0, 0x0L, RANGEINPUT, 0L, 25, 75, 100, 10},
{155, 156, 0, 0x0L, PUSHBUTTON, (void*)"Next >>", 95, 87, 30, 12},
{156, 0, 0, 0x0L, PUSHBUTTON, (void*)"<< Prev.", 60, 87, 35, 12},
{200, 201, 0, CHECKED, RADIO1, (void*)" add each y to start value", 25, 35, 60, 8},
@@ -4201,10 +4509,12 @@ StackBar::PropertyDlg()
char **rd;
AccRange *rX = 0L, *rY = 0L;
+ if(!parent || !data) return false;
data->GetSize(&width, &height);
sprintf(TmpTxt, "a1:a%d", height);
if(!(rd = (char**)calloc(1, sizeof(char*))))return false;
- Dlg = new DlgRoot(StackBarDlg);
+ if(!(Dlg = new DlgRoot(StackBarDlg))) return false;
+ Dlg->ItemCmd(101, CMD_SET_DATAOBJ, data); Dlg->ItemCmd(154, CMD_SET_DATAOBJ, data);
hDlg = CreateDlgWnd(Id == GO_STACKBAR ? (char*)"Stacked bar plot" :
(char*)"Stacked polygons", 50, 50, 420, 260, Dlg, 0x0L);
do {
@@ -4308,12 +4618,12 @@ GroupBars::PropertyDlg()
{4, 5, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 120, 90},
{5, 6, 200, ISPARENT, SHEET, &tab2, 5, 10, 120, 90},
{6, 10, 300, ISPARENT, SHEET, &tab3, 5, 10, 120, 90},
- {10, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {10, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"Get values from spreadsheet:", 10, 25, 60, 8},
{101, 150, 0, 0x0L, LTEXT, (void*)"All ranges should have equal size!", 10, 33, 60, 8},
{150, 0, 153, ISPARENT | CHECKED, GROUPBOX, (void*)" ranges for y values ", 10, 50, 110, 45},
{153, 154, 0, 0x0L, LTEXT, 0L, 15, 55, 60, 8},
- {154, 155, 0, 0x0L, EDTEXT, 0L, 15, 65, 100, 10},
+ {154, 155, 0, 0x0L, RANGEINPUT, 0L, 15, 65, 100, 10},
{155, 156, 0, 0x0L, PUSHBUTTON, (void*)"Next >>", 85, 77, 30, 12},
{156, 0, 0, 0x0L, PUSHBUTTON, (void*)"<< Prev.", 50, 77, 35, 12},
{200, 201, 0, 0x0L, RTEXT, (void*)"start value", 10, 35, 38, 8},
@@ -4336,9 +4646,11 @@ GroupBars::PropertyDlg()
int i, ic, res, ix, iy, ny, sc = 0, currYR = 0, maxYR = 0;
double x, y, xinc;
+ if(!parent || !data) return false;
Id = GO_STACKBAR;
if(!(rd = (char**)calloc(1, sizeof(char*))))return false;
if(!(Dlg = new DlgRoot(GBDlg)))return false;
+ Dlg->ItemCmd(154, CMD_SET_DATAOBJ, data);
hDlg = CreateDlgWnd("Grouped bar chart", 50, 50, 370, 240, Dlg, 0x0L);
do {
if(updateYR) {
@@ -4442,12 +4754,12 @@ Waterfall::PropertyDlg()
{10, 11, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 140, 100},
{11, 12, 200, ISPARENT, SHEET, &tab2, 5, 10, 140, 100},
{12, 20, 300, ISPARENT, SHEET, &tab3, 5, 10, 140, 100},
- {20, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {20, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"range for common x values", 15, 30, 60, 8},
- {101, 152, 0, 0x0L, EDTEXT, text1, 25, 40, 100, 10},
+ {101, 152, 0, 0x0L, RANGEINPUT, text1, 25, 40, 100, 10},
{152, 153, 0, ISPARENT | CHECKED, GROUPBOX, (void*)" ranges for y values ", 12, 60, 128, 45},
{153, 154, 0, 0x0L, LTEXT, 0L, 25, 65, 60, 8},
- {154, 155, 0, 0x0L, EDTEXT, 0L, 25, 75, 100, 10},
+ {154, 155, 0, 0x0L, RANGEINPUT, 0L, 25, 75, 100, 10},
{155, 156, 0, 0x0L, PUSHBUTTON, (void*)"Next >>", 95, 87, 30, 12},
{156, 0, 0, 0x0L, PUSHBUTTON, (void*)"<< Prev.", 60, 87, 35, 12},
{200, 201, 0, 0x0L, LTEXT, (void*)"line to line displacement:", 20, 35, 80, 8},
@@ -4475,10 +4787,12 @@ Waterfall::PropertyDlg()
bool updateYR = true, bContinue = false, bRet = false, bUseSch;
AccRange *rX = 0L, *rY = 0L;
+ if(!parent || !data) return false;
data->GetSize(&width, &height);
sprintf(text1, "a1:a%d", height);
if(!(rd = (char**)calloc(1, sizeof(char*))))return false;
- Dlg = new DlgRoot(StackBarDlg);
+ if(!(Dlg = new DlgRoot(StackBarDlg))) return false;
+ Dlg->ItemCmd(101, CMD_SET_DATAOBJ, data); Dlg->ItemCmd(154, CMD_SET_DATAOBJ, data);
hDlg = CreateDlgWnd("Create waterfall plot", 50, 50, 420, 260, Dlg, 0x0L);
do {
if(updateYR) {
@@ -4567,15 +4881,16 @@ MultiLines::PropertyDlg()
{3, 0, 10, ISPARENT | CHECKED, GROUP, NULL, 138, 40, 55, 12},
{10, 11, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 140, 100},
{11, 20, 300, ISPARENT, SHEET, &tab2, 5, 10, 140, 100},
- {20, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {20, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, ISPARENT | CHECKED, GROUPBOX, (void*)" ranges for x- and y- values ", 12, 30, 128, 75},
{101, 102, 0, 0x0L, LTEXT, 0L, 25, 39, 60, 8},
- {102, 103, 0, 0x0L, EDTEXT, (void*)x_txt, 25, 49, 100, 10},
+ {102, 103, 0, 0x0L, RANGEINPUT, (void*)x_txt, 25, 49, 100, 10},
{103, 104, 0, 0x0L, LTEXT, 0L, 25, 61, 60, 8},
- {104, 105, 0, 0x0L, EDTEXT, (void*)y_txt, 25, 71, 100, 10},
+ {104, 105, 0, 0x0L, RANGEINPUT, (void*)y_txt, 25, 71, 100, 10},
{105, 106, 0, 0x0L, PUSHBUTTON, (void*)"Next >>", 95, 87, 30, 12},
{106, 107, 0, 0x0L, PUSHBUTTON, (void*)"<< Prev.", 60, 87, 35, 12},
- {107, 0, 0, OWNDIALOG, COLBUTTON, (void*)colarr[0], 25, 87, 20, 12},
+ {107, 108, 0, OWNDIALOG, COLBUTTON, (void*)colarr[0], 25, 87, 20, 12},
+ {108, 0, 0, 0x0L, LTEXT, (void*)"line color", 47, 90, 30, 9},
{300, 301, 0, TOUCHEXIT, RADIO1, (void*)" common color for lines:", 20, 35, 80, 9},
{301, 302, 0, OWNDIALOG | TOUCHEXIT, COLBUTTON, (void*)defcol, 105, 35, 20, 10},
{302, 303, 0, CHECKED | TOUCHEXIT, RADIO1, (void*)" increment color scheme:", 20, 55, 80, 9},
@@ -4597,15 +4912,21 @@ MultiLines::PropertyDlg()
AccRange *rX = 0L, *rY = 0L;
DataLine *dl;
+ if(!parent || !data) return false;
data->GetSize(&width, &height);
sprintf(x_txt, "a1:a%d", height);
sprintf(y_txt, "b1:b%d", height);
- Dlg = new DlgRoot(StackBarDlg);
+ if(!(Dlg = new DlgRoot(StackBarDlg))) return false;
+ Dlg->ItemCmd(102, CMD_SET_DATAOBJ, data); Dlg->ItemCmd(104, CMD_SET_DATAOBJ, data);
hDlg = CreateDlgWnd("Create multi line plot", 50, 50, 420, 260, Dlg, 0x0L);
do {
if(updateYR) {
- if(currYR >0) Dlg->ShowItem(106, true);
- else Dlg->ShowItem(106, false);
+ if(currYR >0) {
+ Dlg->ShowItem(106, true); Dlg->ShowItem(108, false);
+ }
+ else {
+ Dlg->ShowItem(106, false); Dlg->ShowItem(108, true);
+ }
sprintf(TmpTxt,"x-range # %d/%d", currYR+1, maxYR+1);
//SetText will also cause a redraw of the whole dialog
Dlg->SetText(101, TmpTxt);
@@ -4761,9 +5082,9 @@ PieChart::PropertyDlg()
{4, 5, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 120, 103},
{5, 6, 200, ISPARENT, SHEET, &tab2, 5, 10, 120, 103},
{6, 10, 300, ISPARENT, SHEET, &tab3, 5, 10, 120, 103},
- {10, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {10, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"spread sheet range for values", 10, 25, 60, 8},
- {101, 105, 0, 0x0L, EDTEXT, TmpTxt, 15, 35, 100, 10},
+ {101, 105, 0, 0x0L, RANGEINPUT, TmpTxt, 15, 35, 100, 10},
{105, 106, 500, ISPARENT | CHECKED, GROUP, 0L, 0, 0, 0, 0},
{106, 107, 600, ISPARENT | CHECKED, GROUP, 0L, 0, 0, 0, 0},
{107, 108, 0, 0x0L, EDVAL1, &frad, 58, 59, 30, 10},
@@ -4787,7 +5108,7 @@ PieChart::PropertyDlg()
{411, 0, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PieTempl, 70, 75, 30, 30},
{500, 501, 0, CHECKED, RADIO1, (void*)"fixed radius", 10, 59, 20, 8},
{501, 502, 0, 0x0L, RADIO1, (void*)"pick radii from spreadsheet range", 10, 71, 40, 8},
- {502, 503, 0, 0x0L, EDTEXT, TmpTxt+100, 15, 82, 100, 10},
+ {502, 503, 0, 0x0L, RANGEINPUT, TmpTxt+100, 15, 82, 100, 10},
{503, 504, 0, 0x0L, LTEXT, (void*)"x factor", 15, 94, 10, 8},
{504, 505, 0, 0x0L, EDVAL1, &FacRad, 42, 94, 25, 10},
{505, 0, 0, 0x0L, LTEXT, &txt2, 70, 94, 15, 8},
@@ -4804,17 +5125,17 @@ PieChart::PropertyDlg()
lfPOINT fpCent;
AccRange *rY = 0L, *rR = 0L;
+ if(!parent || !data) return false;
data->GetSize(&width, &height);
sprintf(TmpTxt, "a1:a%d", height);
sprintf(TmpTxt+100, "b1:b%d", height);
sprintf(txt2, "= [%s]", Units[defs.cUnits].display);
- if(parent) {
- frad = (parent->GetSize(SIZE_DRECT_BOTTOM) - parent->GetSize(SIZE_DRECT_TOP))/2.0;
- fcx = parent->GetSize(SIZE_GRECT_LEFT) + (parent->GetSize(SIZE_DRECT_LEFT))/2.0 + frad;
- fcy = parent->GetSize(SIZE_GRECT_TOP) + parent->GetSize(SIZE_DRECT_TOP) + frad;
- }
+ frad = (parent->GetSize(SIZE_DRECT_BOTTOM) - parent->GetSize(SIZE_DRECT_TOP))/2.0;
+ fcx = parent->GetSize(SIZE_GRECT_LEFT) + (parent->GetSize(SIZE_DRECT_LEFT))/2.0 + frad;
+ fcy = parent->GetSize(SIZE_GRECT_TOP) + parent->GetSize(SIZE_DRECT_TOP) + frad;
firad = frad-frad/10.0f;
- Dlg = new DlgRoot(PieDlg);
+ if(!(Dlg = new DlgRoot(PieDlg)))return false;
+ Dlg->ItemCmd(101, CMD_SET_DATAOBJ, data); Dlg->ItemCmd(502, CMD_SET_DATAOBJ, data);
if(Id == GO_PIECHART) {
Dlg->ShowItem(105, true); Dlg->ShowItem(106, false);
Dlg->ShowItem(210, true); Dlg->ShowItem(211, false);
@@ -4922,9 +5243,9 @@ StarChart::PropertyDlg()
{3, 0, 4, ISPARENT | CHECKED, GROUP, NULL, 138, 40, 55, 12},
{4, 5, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 120, 103},
{5, 10, 200, ISPARENT, SHEET, &tab2, 5, 10, 120, 103},
- {10, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {10, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"spread sheet range for values", 10, 30, 60, 8},
- {101, 102, 0, 0x0L, EDTEXT, txt1, 15, 45, 100, 10},
+ {101, 102, 0, 0x0L, RANGEINPUT, txt1, 15, 45, 100, 10},
{102, 103, 0, 0x0L, RTEXT, (void*)"x factor", 17, 57, 30, 8},
{103, 104, 0, 0x0L, EDVAL1, &factor, 48, 57, 30, 10},
{104, 105, 0, 0x0L, LTEXT, &txt2, 79, 57, 15, 8},
@@ -4934,7 +5255,7 @@ StarChart::PropertyDlg()
{108, 109, 0, CHECKED, CHECKBOX, (void*)"draw polygon", 25, 87, 20, 8},
{109, 0, 0, CHECKED, CHECKBOX, (void*)"draw rays", 25, 97, 20, 8},
{200, 201, 0, 0x0L, CHECKBOX, (void*)"add labels to data points", 15, 28, 50, 8},
- {201, 202, 0, 0x0L, EDTEXT, (void*)txt1, 15, 51, 100, 10},
+ {201, 202, 0, 0x0L, RANGEINPUT, (void*)txt1, 15, 51, 100, 10},
{202, 203, 0, 0x0L, LTEXT, (void*)"spread sheet range for labels:", 15, 40, 60, 8},
{203, 204, 0, 0x0L, RTEXT, (void*)"distance:", 10, 70, 40, 8},
{204, 205, 0, 0x0L, EDVAL1, &lbdist, 52, 70, 30, 10},
@@ -4952,7 +5273,7 @@ StarChart::PropertyDlg()
TextDEF td = {0x00000000L, 0x00ffffffL, defs.GetSize(SIZE_TEXT), 0.0, 0.0, 0,
TXA_HCENTER | TXA_VCENTER, TXM_TRANSPARENT, TXS_NORMAL, FONT_HELVETICA, 0L};
-
+ if(!parent || !data) return false;
data->GetSize(&width, &height);
sprintf(txt1, "a1:a%d", height);
sprintf(txt2, "= [%s]", Units[defs.cUnits].display);
@@ -4962,6 +5283,7 @@ StarChart::PropertyDlg()
fPos.fy = parent->GetSize(SIZE_GRECT_TOP) + parent->GetSize(SIZE_DRECT_TOP) + frad;
}
if(!(Dlg = new DlgRoot(StarDlg)))return false;
+ Dlg->ItemCmd(101, CMD_SET_DATAOBJ, data); Dlg->ItemCmd(201, CMD_SET_DATAOBJ, data);
hDlg = CreateDlgWnd("Create star chart", 50, 50, 370, 260, Dlg, 0x0L);
do {
LoopDlgWnd();
@@ -5054,17 +5376,17 @@ Scatt3D::PropertyDlg()
{4, 5, 100, TOUCHEXIT | ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 131, 100},
{5, 6, 200, TOUCHEXIT | ISPARENT, SHEET, &tab2, 5, 10, 131, 100},
{6, 10, 400, TOUCHEXIT | ISPARENT, SHEET, &tab3, 5, 10, 131, 100},
- {10, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {10, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{50, 60, 0, NOSELECT, ODBUTTON, (void*)(OD_AxisDesc3D), 142, 65, 45, 45},
{60, 61, 0, 0x0L, ICON, (void*)&icon, 10, 114, 20, 20},
{61, 62, 0, 0x0L, LTEXT, (void*)"Use [arrow keys], [shift]+[arrow key],", 30, 116, 100, 6},
{62, 0, 0, 0x0L, LTEXT, (void*)"and [r], [R], [l] or [L] to rotate graph.", 30, 122, 100, 6},
{100, 101, 0, 0x0L, LTEXT, (void*)"range for X Data", 10, 30, 60, 8},
- {101, 102, 0, 0x0L, EDTEXT, text1, 20, 40, 100, 10},
+ {101, 102, 0, 0x0L, RANGEINPUT, text1, 20, 40, 100, 10},
{102, 103, 0, 0x0L, LTEXT, (void*)"range for Y Data", 10, 55, 60, 8},
- {103, 104, 0, 0x0L, EDTEXT, text2, 20, 65, 100, 10},
+ {103, 104, 0, 0x0L, RANGEINPUT, text2, 20, 65, 100, 10},
{104, 105, 0, 0x0L, LTEXT, (void*)"range for Z Data", 10, 80, 60, 8},
- {105, 0, 0, 0x0L, EDTEXT, text3, 20, 90, 100, 10},
+ {105, 0, 0, 0x0L, RANGEINPUT, text3, 20, 90, 100, 10},
{200, 201, 0, 0x0L, LTEXT, (void*)"select style:", 25, 30, 60, 8},
{201, 202, 0, 0x0L, CHECKBOX, (void*)" balls", 30, 55, 60, 8},
{202, 203, 0, TOUCHEXIT, CHECKBOX, (void*)" columns", 30, 65, 60, 8},
@@ -5084,12 +5406,15 @@ Scatt3D::PropertyDlg()
AccRange *rX, *rY, *rZ;
fPOINT3D pos1, pos2;
- if(!data || !parent || parent->Id != GO_PLOT3D)return false;
+ if(!data || !parent)return false;
data->GetSize(&width, &height);
sprintf(text1, "a1:a%d", height); sprintf(text2, "b1:b%d", height);
sprintf(text3, "c1:c%d", height);
if(!(Dlg = new DlgRoot(Dlg3D)))return false;
Dlg->SetCheck(410 + AxisTempl3D, 0L, true);
+ Dlg->ItemCmd(101, CMD_SET_DATAOBJ, data);
+ Dlg->ItemCmd(103, CMD_SET_DATAOBJ, data);
+ Dlg->ItemCmd(105, CMD_SET_DATAOBJ, data);
for(i = 0; i < 5; i++) Dlg->SetCheck(201+i, 0L, (c_flags & (1<<i))!=0);
if(c_flags == 0x2000) {
Dlg->ShowItem(5, false); Dlg->ShowItem(6, false);
@@ -5250,6 +5575,7 @@ Function::PropertyDlg()
DWORD undo_flags = 0L;
LineDEF newLine;
double o_x1, n_x1, o_x2, n_x2, o_xstep, n_xstep;
+ anyOutput *cdisp = Undo.cdisp;
if(!parent) return false;
if(parent->Id == GO_FITFUNC) return parent->PropertyDlg();
@@ -5270,13 +5596,14 @@ Function::PropertyDlg()
break;
}
}while (res < 0);
- while(*Undo.pcb > undo_level) Undo.Pop();
+ Undo.SetDisp(cdisp);
+ while(*Undo.pcb > undo_level) Undo.Pop(cdisp);
if(res == 1){ //OK pressed
if(bNew) { //create function
OD_linedef(OD_GETLINE, 0L, 0L, 0L, (void *)&Line, 0);
Dlg->GetValue(102, &x1); Dlg->GetValue(104, &x2);
Dlg->GetValue(106, &xstep); Dlg->GetText(200, TmpTxt);
- cmdxy = strdup(TmpTxt);
+ cmdxy = strdup(TmpTxt); ReshapeFormula(&cmdxy);
bRet = Update(0L, 0L);
}
else { //edit existing function
@@ -5290,7 +5617,10 @@ Function::PropertyDlg()
Undo.String(this, &cmdxy, undo_flags);
free(cmdxy); cmdxy = strdup(TmpTxt); undo_flags |= UNDO_CONTINUE;
}
- if(undo_flags & UNDO_CONTINUE) Update(0L, UNDO_CONTINUE);
+ if(undo_flags & UNDO_CONTINUE){
+ Update(0L, UNDO_CONTINUE);
+ Command(CMD_MRK_DIRTY, 0L, 0L);
+ }
OD_linedef(OD_GETLINE, 0L, 0L, 0L, (void *)&newLine, 0);
if(cmpLineDEF(&Line, &newLine)) {
Undo.Line(parent, &Line, undo_flags); undo_flags |= UNDO_CONTINUE;
@@ -5324,7 +5654,7 @@ FitFunc::PropertyDlg()
{5, 6, 100, ISPARENT, SHEET, &tab2, 5, 10, 149, 125},
{6, 7, 500, ISPARENT, SHEET, &tab3, 5, 10, 149, 125},
{7, 0, 0, 0x0L, PUSHBUTTON, (void*)"Fit", 160, 123, 32, 12},
- {10, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {10, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"fit function by nonlinear regression", 10, 24, 100, 8},
{101, 102, 0, 0x0L, LTEXT, (void*)"parameters and initial values:", 10, 34, 100, 8},
{102, 150, 0, 0x0L, TEXTBOX, (void*)parxy, 22, 44, 122, 25},
@@ -5336,9 +5666,9 @@ FitFunc::PropertyDlg()
{155, 200, 0, 0x0L, EDVAL1, &iter, 119, 118, 25, 10},
{200, 0, 0, 0x0L, TEXTBOX, (void*)cmdxy, 22, 84, 122, 30},
{400, 401, 0, 0x0L, LTEXT, (void*)"range for X Data", 10, 30, 60, 8},
- {401, 402, 0, 0x0L, EDTEXT, (void*)ssXref, 20, 40, 100, 10},
+ {401, 402, 0, 0x0L, RANGEINPUT, (void*)ssXref, 20, 40, 100, 10},
{402, 403, 0, 0x0L, LTEXT, (void*)"range for Y Data", 10, 55, 60, 8},
- {403, 404, 0, 0x0L, EDTEXT, (void*)ssYref, 20, 65, 100, 10},
+ {403, 404, 0, 0x0L, RANGEINPUT, (void*)ssYref, 20, 65, 100, 10},
{404, 405, 0, CHECKED, CHECKBOX, (void*)"draw symbols", 20, 95, 60, 8},
{405, 0, 0, HIDDEN, LTEXT, 0L, 20, 95, 60, 8},
{500, 550, 501, CHECKED, GROUP, 0L, 0, 0, 0, 0},
@@ -5358,6 +5688,7 @@ FitFunc::PropertyDlg()
double tmp, tmpy, o_x1, n_x1, o_x2, n_x2, o_xstep, n_xstep, n_chi2=chi2;
AccRange *rX, *rY;
char *o_cmdxy, *o_parxy, *tmp_char;
+ anyOutput *cdisp = Undo.cdisp;
if(!parent || !data) return false;
if(!(o_cmdxy = strdup(cmdxy))) return false;
@@ -5365,6 +5696,7 @@ FitFunc::PropertyDlg()
iter = (double)maxiter;
OD_linedef(OD_SETLINE, 0L, 0L, 0L, (void *)&Line, 0);
if(!(Dlg = new DlgRoot(FuncDlg))) return false;
+ Dlg->ItemCmd(401, CMD_SET_DATAOBJ, data); Dlg->ItemCmd(403, CMD_SET_DATAOBJ, data);
if(!bNew){
Dlg->ShowItem(10, false); Dlg->Activate(401, false);
Dlg->Activate(403, false); Dlg->SetCheck(6, 0L, true);
@@ -5404,6 +5736,7 @@ FitFunc::PropertyDlg()
break;
}
case 7: //Start: do nonlinear regression
+ Undo.SetDisp(cdisp);
if(Dlg->GetCheck(5)) { // the function tab must be shown
if(Dlg->CurrDisp) Dlg->CurrDisp->MouseCursor(MC_WAIT, true);
Dlg->GetText(401, text1); Dlg->GetText(403, text2);
@@ -5432,7 +5765,8 @@ FitFunc::PropertyDlg()
break;
}
}while (res < 0);
- while(*Undo.pcb > undo_level) Undo.Pop();
+ Undo.SetDisp(cdisp);
+ while(*Undo.pcb > undo_level) Undo.Pop(cdisp);
if(res == 1){ //OK pressed
//get ranges for x- and y data (again).
chi2 = n_chi2;
@@ -5477,6 +5811,13 @@ FitFunc::PropertyDlg()
Dlg->GetValue(506, &n_xstep);
undo_flags = CheckNewFloat(&x1, o_x1, n_x1, this, undo_flags);
undo_flags = CheckNewFloat(&x2, o_x2, n_x2, this, undo_flags);
+ undo_flags = CheckNewFloat(&xstep, o_xstep, n_xstep, this, undo_flags);
+ if(undo_flags){
+ dl->SetSize(SIZE_MIN_X, x1); dl->SetSize(SIZE_MAX_X, x2);
+ dl->SetSize(SIZE_XSTEP, xstep); dl->Command(CMD_SETFUNC, cmdxy, 0L);
+ dl->Command(CMD_SETPARAM, parxy, 0L); dl->Command(CMD_SET_LINE, &Line, 0L);
+ dl->Update(0L, UNDO_CONTINUE);
+ }
if(o_parxy && parxy && strcmp(o_parxy, parxy)) {
tmp_char = parxy; parxy = o_parxy;
Undo.String(this, &parxy, undo_flags);
@@ -5493,7 +5834,6 @@ FitFunc::PropertyDlg()
Undo.ValInt(parent, (int*)&dirty, undo_flags);
Command(CMD_MRK_DIRTY, 0L, 0L);
}
- undo_flags = CheckNewFloat(&xstep, o_xstep, n_xstep, this, undo_flags);
// Dlg->GetText(200, TmpTxt);
// if(cmdxy && strcmp(cmdxy, TmpTxt)) {
// Undo.String(this, &cmdxy, undo_flags);
@@ -5530,7 +5870,8 @@ Plot3D::AddPlot(int family)
{561, 562, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 37, 20, 25, 25},
{562, 563, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 62, 20, 25, 25},
{563, 564, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 87, 20, 25, 25},
- {564, 0, 0, LASTOBJ | TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 112, 20, 25, 25}};
+ {564, 565, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 112, 20, 25, 25},
+ {565, 0, 0, LASTOBJ | TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 12, 45, 25, 25}};
DlgRoot *Dlg;
void *hDlg;
int res, cSel = 560;
@@ -5543,7 +5884,7 @@ Plot3D::AddPlot(int family)
LoopDlgWnd();
res = Dlg->GetResult();
switch(res) {
- case 560: case 561: case 562: case 563: case 564:
+ case 560: case 561: case 562: case 563: case 564: case 565:
if(res == cSel) res = 1;
else {
cSel = res;
@@ -5558,9 +5899,9 @@ Plot3D::AddPlot(int family)
else if(Dlg->GetCheck(562)) p = new Scatt3D(this, data, 0x04);
else if(Dlg->GetCheck(563)) p = new BubblePlot3D(this, data);
else if(Dlg->GetCheck(564)) p = new Scatt3D(this, data, 0x2000);
+ else if(Dlg->GetCheck(565)) p = new Func3D(this, data);
if(p && p->PropertyDlg()) {
- if(p->Id == GO_PLOT3D) delete p;
- else if(!(bRet = Command(CMD_DROP_PLOT, p, (anyOutput *)NULL))) delete p;
+ if(!(bRet = Command(CMD_DROP_PLOT, p, (anyOutput *)NULL))) delete p;
}
else if(p) delete p;
}
@@ -5606,12 +5947,12 @@ Chart25D::PropertyDlg()
{10, 11, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 140, 100},
{11, 12, 200, ISPARENT, SHEET, &tab2, 5, 10, 140, 100},
{12, 20, 300, ISPARENT, SHEET, &tab3, 5, 10, 140, 100},
- {20, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {20, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"range for common x values", 15, 30, 60, 8},
- {101, 152, 0, 0x0L, EDTEXT, text1, 25, 40, 100, 10},
+ {101, 152, 0, 0x0L, RANGEINPUT, text1, 25, 40, 100, 10},
{152, 153, 0, ISPARENT | CHECKED, GROUPBOX, (void*)" ranges for y values ", 12, 60, 128, 45},
{153, 154, 0, 0x0L, LTEXT, 0L, 25, 65, 60, 8},
- {154, 155, 0, 0x0L, EDTEXT, 0L, 25, 75, 100, 10},
+ {154, 155, 0, 0x0L, RANGEINPUT, 0L, 25, 75, 100, 10},
{155, 156, 0, 0x0L, PUSHBUTTON, (void*)"Next >>", 95, 87, 30, 12},
{156, 0, 0, 0x0L, PUSHBUTTON, (void*)"<< Prev.", 60, 87, 35, 12},
{200, 201, 0, 0x0L, LTEXT, (void*)"distances:", 20, 35, 80, 8},
@@ -5642,6 +5983,7 @@ Chart25D::PropertyDlg()
Scatt3D *plot;
AxisDEF *ax;
+ if(!parent || !data) return false;
if(plots) {
//Plots alredy defined: jump to config dialog
return false;
@@ -5649,7 +5991,8 @@ Chart25D::PropertyDlg()
data->GetSize(&width, &height);
sprintf(text1, "a1:a%d", height);
if(!(rd = (char**)calloc(1, sizeof(char*))))return false;
- Dlg = new DlgRoot(Bar3D_Dlg);
+ if(!(Dlg = new DlgRoot(Bar3D_Dlg))) return false;
+ Dlg->ItemCmd(101, CMD_SET_DATAOBJ, data); Dlg->ItemCmd(154, CMD_SET_DATAOBJ, data);
hDlg = CreateDlgWnd("Create 3D Bar Chart", 50, 50, 420, 260, Dlg, 0x0L);
do {
if(updateYR) {
@@ -5771,12 +6114,12 @@ Ribbon25D::PropertyDlg()
{10, 11, 100, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 140, 100},
{11, 12, 200, ISPARENT, SHEET, &tab2, 5, 10, 140, 100},
{12, 20, 300, ISPARENT, SHEET, &tab3, 5, 10, 140, 100},
- {20, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {20, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"range for common x values", 15, 30, 60, 8},
- {101, 152, 0, 0x0L, EDTEXT, text1, 25, 40, 100, 10},
+ {101, 152, 0, 0x0L, RANGEINPUT, text1, 25, 40, 100, 10},
{152, 153, 0, ISPARENT | CHECKED, GROUPBOX, (void*)" ranges for y values ", 12, 60, 128, 45},
{153, 154, 0, 0x0L, LTEXT, 0L, 25, 65, 60, 8},
- {154, 155, 0, 0x0L, EDTEXT, 0L, 25, 75, 100, 10},
+ {154, 155, 0, 0x0L, RANGEINPUT, 0L, 25, 75, 100, 10},
{155, 156, 0, 0x0L, PUSHBUTTON, (void*)"Next >>", 95, 87, 30, 12},
{156, 0, 0, 0x0L, PUSHBUTTON, (void*)"<< Prev.", 60, 87, 35, 12},
{200, 201, 0, 0x0L, LTEXT, (void*)"distances:", 20, 35, 80, 8},
@@ -5806,6 +6149,7 @@ Ribbon25D::PropertyDlg()
AxisDEF *ax;
Ribbon *plot;
+ if(!parent || !data) return false;
if(plots) {
//Plots alredy defined: jump to config dialog
return false;
@@ -5813,7 +6157,8 @@ Ribbon25D::PropertyDlg()
data->GetSize(&width, &height);
sprintf(text1, "a1:a%d", height);
if(!(rd = (char**)calloc(1, sizeof(char*))))return false;
- Dlg = new DlgRoot(Bar3D_Dlg);
+ if(!(Dlg = new DlgRoot(Bar3D_Dlg)))return false;
+ Dlg->ItemCmd(101, CMD_SET_DATAOBJ, data); Dlg->ItemCmd(154, CMD_SET_DATAOBJ, data);
hDlg = CreateDlgWnd("Create 3D Ribbon Chart", 50, 50, 420, 260, Dlg, 0x0L);
do {
if(updateYR) {
@@ -5909,17 +6254,17 @@ BubblePlot3D::PropertyDlg()
{3, 50, 4, ISPARENT | CHECKED, GROUP, 0L, 138, 40, 55, 12},
{4, 5, 100, TOUCHEXIT | ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 131, 142},
{5, 10, 400, TOUCHEXIT | ISPARENT, SHEET, &tab3, 5, 10, 131, 142},
- {10, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {10, 0, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{50, 0, 0, NOSELECT, ODBUTTON, (void*)(OD_AxisDesc3D), 142, 65, 45, 45},
{100, 101, 0, 0x0L, LTEXT, (void*)"range for X Data", 10, 25, 60, 8},
- {101, 102, 0, 0x0L, EDTEXT, text1, 20, 35, 100, 10},
+ {101, 102, 0, 0x0L, RANGEINPUT, text1, 20, 35, 100, 10},
{102, 103, 0, 0x0L, LTEXT, (void*)"range for Y Data", 10, 48, 60, 8},
- {103, 104, 0, 0x0L, EDTEXT, text2, 20, 58, 100, 10},
+ {103, 104, 0, 0x0L, RANGEINPUT, text2, 20, 58, 100, 10},
{104, 105, 0, 0x0L, LTEXT, (void*)"range for Z Data", 10, 71, 60, 8},
- {105, 106, 0, 0x0L, EDTEXT, text3, 20, 81, 100, 10},
+ {105, 106, 0, 0x0L, RANGEINPUT, text3, 20, 81, 100, 10},
{106, 0, 150, ISPARENT | CHECKED, GROUPBOX, (void*)" diameter ", 8, 98, 125, 50},
{150, 151, 0, 0x0L, LTEXT, (void*)"range for diameters", 12, 102, 60, 8},
- {151, 152, 0, 0x0L, EDTEXT, text4, 20, 112, 100, 10},
+ {151, 152, 0, 0x0L, RANGEINPUT, text4, 20, 112, 100, 10},
{152, 153, 0, 0x0L, LTEXT, (void*)"scaling:", 12, 125, 20, 8},
{153, 154, 0, TOUCHEXIT | CHECKED, RADIO1, (void*)Units[defs.cUnits].display, 38, 125, 20, 8},
{154, 155, 0, TOUCHEXIT, RADIO1, (void*)"with x-values", 70, 125, 20, 8},
@@ -5932,18 +6277,20 @@ BubblePlot3D::PropertyDlg()
DlgRoot *Dlg;
void *hDlg;
int i, res, width, height, count;
- int cx, rx, cy, ry, cz, rz, cr, rr, s_type = 0;
+ int cx, rx, cy, ry, cz, rz, cr, rr, s_type = 5;
bool bRet = false;
double fx, fy, fz, fr;
Sphere **Balls;
AccRange *rX, *rY, *rZ, *rR;
Scatt3D *sc_plot;
+ int etracc[] = {101, 103, 105, 151};
if(!data || !parent)return false;
data->GetSize(&width, &height);
sprintf(text1, "a1:a%d", height); sprintf(text2, "b1:b%d", height);
sprintf(text3, "c1:c%d", height); sprintf(text4, "d1:d%d", height);
if(!(Dlg = new DlgRoot(BubDlg3D)))return false;
+ for(i = 0; i < 4; i++) Dlg->ItemCmd(etracc[i], CMD_SET_DATAOBJ, data);
rX = rY = rZ = rR = 0L;
Dlg->SetCheck(410 + AxisTempl3D, 0L, true);
hDlg = CreateDlgWnd("Bubble Plot 3D", 50, 50, 388, 340, Dlg, 0x0L);
@@ -5957,7 +6304,11 @@ BubblePlot3D::PropertyDlg()
case 4: case 5: //the tab sheets
res = -1;
break;
- case 153: case 154: case 155: case 156:
+ case 153:
+ s_type = 5; //absolute size, but use 5 to distinguish
+ res = -1; // from symbol
+ break;
+ case 154: case 155: case 156:
s_type = res - 153;
res = -1;
break;
@@ -5986,7 +6337,7 @@ BubblePlot3D::PropertyDlg()
}
}
sc_plot = new Scatt3D(this, data, Balls, count);
- if(parent->Id == GO_PLOT3D) {
+ if(parent->Id == GO_PLOT3D || parent->Id == GO_FUNC3D) {
if(!(parent->Command(CMD_DROP_PLOT, sc_plot, 0L))) delete(sc_plot);
bRet = true;
}
@@ -6000,6 +6351,141 @@ BubblePlot3D::PropertyDlg()
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Create a 3D function plot
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+bool
+Func3D::PropertyDlg()
+{
+ TabSHEET tab1 = {0, 37, 10, "Function"};
+ TabSHEET tab2 = {37, 65, 10, "Style"};
+ FillDEF newFill;
+ DlgInfo FuncDlg[] = {
+ {1, 2, 0, DEFAULT, PUSHBUTTON, (void*)"OK", 160, 10, 45, 12},
+ {2, 3, 0, 0x0L, PUSHBUTTON, (void*)"Cancel", 160, 25, 45, 12},
+ {3, 10, 4, ISPARENT | CHECKED, GROUP, 0L, 138, 40, 55, 12},
+ {4, 5, 100, ISPARENT, SHEET, &tab1, 5, 10, 149, 134},
+ {5, 50, 300, ISPARENT | CHECKED, SHEET, &tab2, 5, 10, 149, 134},
+ {10, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {50, 0, 0, NOSELECT, ODBUTTON, (void*)(OD_AxisDesc3D), 160, 85, 45, 45},
+ {100, 101, 0, 0x0L, LTEXT, (void*)"plot user defined function", 10, 30, 100, 8},
+ {101, 102, 0, 0x0L, RTEXT, (void*)"where x=", 10, 50, 28, 8},
+ {102, 103, 0, 0x0L, EDVAL1, &x1, 38, 50, 25, 10},
+ {103, 104, 0, 0x0L, RTEXT, (void*)"until", 61, 50, 17, 8},
+ {104, 105, 0, 0x0L, EDVAL1, &x2, 78, 50, 25, 10},
+ {105, 106, 0, 0x0L, RTEXT, (void*)"step", 102, 50, 17, 8},
+ {106, 107, 0, 0x0L, EDVAL1, &xstep, 119, 50, 25, 10},
+ {107, 108, 0, 0x0L, RTEXT, (void*)"z=", 10, 62, 28, 8},
+ {108, 109, 0, 0x0L, EDVAL1, &z1, 38, 62, 25, 10},
+ {109, 110, 0, 0x0L, EDVAL1, &z2, 78, 62, 25, 10},
+ {110, 150, 0, 0x0L, EDVAL1, &zstep, 119, 62, 25, 10},
+ {150, 200, 0, 0x0L, RTEXT, (void*)"y=", 10, 91, 10, 8},
+ {200, 0, 0, 0x0L, TEXTBOX, (void*)cmdxy, 22, 89, 122, 40},
+ {300, 301, 500, CHECKED, GROUPBOX, (void*)" grid ", 10, 40, 140, 100},
+ {301, 305, 400, HIDDEN | CHECKED, GROUPBOX, (void*)" surface ", 10, 40, 140, 100},
+ {305, 306, 0, CHECKED | TOUCHEXIT, RADIO1, (void*) " grid lines", 15, 25, 50, 10},
+ {306, 0, 0, TOUCHEXIT, RADIO1, (void*) " surface", 85, 25, 50, 10},
+ {400, 401, 0, 0x0L, RTEXT, (void*)"grid line width", 38, 50, 40, 8},
+ {401, 402, 0, 0x0L, EDVAL1, &Line.width, 80, 50, 25, 10},
+ {402, 403, 0, 0x0L, LTEXT, (void*)Units[defs.cUnits].display, 107, 50, 20, 8},
+ {403, 404, 0, 0x0L, RTEXT, (void*)"grid line color", 38, 62, 40, 8},
+ {404, 405, 0, OWNDIALOG, COLBUTTON, (void *)Line.color, 80, 62, 25, 10},
+ {405, 406, 0, 0x0L, RTEXT,(void*)"plane color" , 38, 74, 40, 8},
+ {406, 0, 0, OWNDIALOG, SHADE3D, &newFill, 80, 74, 25, 10},
+ {500, 0, 0, LASTOBJ | NOSELECT, ODBUTTON, (void*)OD_linedef, 15, 45, 130, 100}};
+ DlgRoot *Dlg;
+ void *hDlg;
+ int res, undo_level = *Undo.pcb;
+ bool bRet = false, bNew = true;
+ DWORD undo_flags = 0L;
+ LineDEF newLine;
+ double o_x1, n_x1, o_x2, n_x2, o_xstep, n_xstep;
+ double o_z1, n_z1, o_z2, n_z2, o_zstep, n_zstep;
+ anyOutput *cdisp = Undo.cdisp;
+
+ if(!parent) return false;
+// if(parent->Id == GO_FITFUNC) return parent->PropertyDlg();
+ memcpy(&newFill, &Fill, sizeof(FillDEF));
+ OD_linedef(OD_SETLINE, 0L, 0L, 0L, (void *)&Line, 0);
+ if(!(Dlg = new DlgRoot(FuncDlg))) return false;
+ if(!bNew) Dlg->ShowItem(10, false);
+ Dlg->GetValue(102, &o_x1); n_x1 = o_x1;
+ Dlg->GetValue(104, &o_x2); n_x2 = o_x2;
+ Dlg->GetValue(106, &o_xstep); n_xstep = o_xstep;
+ Dlg->GetValue(108, &o_z1); n_z1 = o_z1;
+ Dlg->GetValue(109, &o_z2); n_z2 = o_z2;
+ Dlg->GetValue(110, &o_zstep); n_zstep = o_zstep;
+ hDlg = CreateDlgWnd("3D Function Plot", 50, 50, 426, 320, Dlg, 0x0L);
+ if(bNew) Dlg->SetCheck(4, 0L, true);
+ do{
+ LoopDlgWnd();
+ res = Dlg->GetResult();
+ switch (res) {
+ case 305: case 306:
+ if(Dlg->GetCheck(305)) {
+ Dlg->ShowItem(300, true); Dlg->ShowItem(301, false);
+ }
+ else {
+ Dlg->ShowItem(300, false); Dlg->ShowItem(301, true);
+ }
+ Dlg->DoPlot(0L);
+ res = -1;
+ break;
+ case 0:
+ if(Dlg->GetCheck(10)) res = -1;
+ break;
+ }
+ }while (res < 0);
+ Undo.SetDisp(cdisp);
+ while(*Undo.pcb > undo_level) Undo.Pop(cdisp);
+ if(res == 1){ //OK pressed
+ if(bNew) { //create function
+ if(Dlg->GetCheck(305)) {
+ type = 0;
+ OD_linedef(OD_GETLINE, 0L, 0L, 0L, (void *)&Line, 0);
+ }
+ else {
+ type = 1;
+ memcpy(&Fill, &newFill, sizeof(FillDEF));
+ Dlg->GetValue(401, &Line.width);
+ Dlg->GetColor(404, &Line.color);
+ Line.pattern = 0L;
+ Line.patlength = 1;
+ }
+ Dlg->GetValue(102, &x1); Dlg->GetValue(104, &x2);
+ Dlg->GetValue(106, &xstep);
+ Dlg->GetValue(108, &z1); Dlg->GetValue(109, &z2);
+ Dlg->GetValue(110, &zstep); type = Dlg->GetCheck(305) ? 0 : 1;
+ if(Dlg->GetText(200, TmpTxt)) {
+ cmdxy = strdup(TmpTxt); ReshapeFormula(&cmdxy);
+ bRet = Update();
+ }
+ }
+ else { //edit existing function
+ Dlg->GetValue(102, &n_x1); Dlg->GetValue(104, &n_x2);
+ Dlg->GetValue(106, &n_xstep);
+ undo_flags = CheckNewFloat(&x1, o_x1, n_x1, this, undo_flags);
+ undo_flags = CheckNewFloat(&x2, o_x2, n_x2, this, undo_flags);
+ undo_flags = CheckNewFloat(&xstep, o_xstep, n_xstep, this, undo_flags);
+ Dlg->GetText(200, TmpTxt);
+ if(cmdxy && strcmp(cmdxy, TmpTxt)) {
+ Undo.String(this, &cmdxy, undo_flags);
+ free(cmdxy); cmdxy = strdup(TmpTxt); undo_flags |= UNDO_CONTINUE;
+ }
+// if(undo_flags & UNDO_CONTINUE) Update(0L, UNDO_CONTINUE);
+ OD_linedef(OD_GETLINE, 0L, 0L, 0L, (void *)&newLine, 0);
+ if(cmpLineDEF(&Line, &newLine)) {
+ Undo.Line(parent, &Line, undo_flags); undo_flags |= UNDO_CONTINUE;
+ memcpy(&Line, &newLine, sizeof(LineDEF));
+ }
+ bRet = (undo_flags & UNDO_CONTINUE) != 0;
+ }
+ }
+ CloseDlgWnd(hDlg);
+ delete Dlg;
+ return bRet;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Grid line properties
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
@@ -6037,6 +6523,7 @@ GridLine::PropertyDlg()
int res, tmptype;
bool bRet = false;
DWORD undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
LineDEF newLine;
if(!parent || !parent->parent) return false;
@@ -6075,23 +6562,18 @@ GridLine::PropertyDlg()
switch (res) {
case 1: //this line
case 2: //all lines of plot
+ Undo.SetDisp(cdisp);
if(flags &AXIS_3D) {
tmptype = 0;
- if(Dlg->GetCheck(120)) tmptype |= 0x01;
- if(Dlg->GetCheck(121)) tmptype |= 0x02;
- if(Dlg->GetCheck(125)) tmptype |= 0x04;
- if(Dlg->GetCheck(126)) tmptype |= 0x08;
- if(Dlg->GetCheck(130)) tmptype |= 0x10;
- if(Dlg->GetCheck(131)) tmptype |= 0x20;
+ if(Dlg->GetCheck(120)) tmptype |= 0x01; if(Dlg->GetCheck(121)) tmptype |= 0x02;
+ if(Dlg->GetCheck(125)) tmptype |= 0x04; if(Dlg->GetCheck(126)) tmptype |= 0x08;
+ if(Dlg->GetCheck(130)) tmptype |= 0x10; if(Dlg->GetCheck(131)) tmptype |= 0x20;
}
else {
tmptype = (type & ~0xff);
- if(Dlg->GetCheck(112)) tmptype |= DL_LEFT;
- if(Dlg->GetCheck(113)) tmptype |= DL_RIGHT;
- if(Dlg->GetCheck(114)) tmptype |= DL_YAXIS;
- if(Dlg->GetCheck(115)) tmptype |= DL_TOP;
- if(Dlg->GetCheck(116)) tmptype |= DL_BOTTOM;
- if(Dlg->GetCheck(117)) tmptype |= DL_XAXIS;
+ if(Dlg->GetCheck(112)) tmptype |= DL_LEFT; if(Dlg->GetCheck(113)) tmptype |= DL_RIGHT;
+ if(Dlg->GetCheck(114)) tmptype |= DL_YAXIS; if(Dlg->GetCheck(115)) tmptype |= DL_TOP;
+ if(Dlg->GetCheck(116)) tmptype |= DL_BOTTOM; if(Dlg->GetCheck(117)) tmptype |= DL_XAXIS;
}
OD_linedef(OD_GETLINE, 0L, 0L, 0L, (void *)&newLine, 0);
break;
@@ -6165,6 +6647,7 @@ Tick::PropertyDlg()
int res, tmp_type = type;
bool bRet = false;
DWORD new_flags = flags, undo_flags = 0;
+ anyOutput *cdisp = Undo.cdisp;
char *old_label = 0L;
TextDEF *td;
@@ -6229,7 +6712,7 @@ Tick::PropertyDlg()
res = Dlg->GetResult();
switch(res) {
case 1: case 2:
- new_flags &= ~0x7;
+ Undo.SetDisp(cdisp); new_flags &= ~0x7;
if(Dlg->GetCheck(105)) new_flags |= AXIS_POSTICKS;
else if(Dlg->GetCheck(106)) new_flags |= AXIS_NEGTICKS;
else new_flags |= AXIS_SYMTICKS;
@@ -6461,6 +6944,7 @@ Axis::PropertyDlg()
double tmp, tmp2, old_x1, old_x2, old_y1, old_y2;
bool bRet = false, bChanged = false, upd_brk = true, bContinue = false;
DWORD new_color, undo_flags = 0L;
+ anyOutput *cdisp = Undo.cdisp;
lfPOINT *brks = 0L, *tmpbrks = 0L;
char *old_Label = 0L, *type_txt;
TextDEF label_def, *lb_def;
@@ -6755,6 +7239,7 @@ Axis::PropertyDlg()
break;
}
}while (res < 0);
+ Undo.SetDisp(cdisp);
switch (res) {
case 1: //OK pressed
bModified = true;
@@ -6918,9 +7403,10 @@ Graph::AddPlot(int family)
{528, 529, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 60, 45, 25, 25},
{529, 530, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 85, 45, 25, 25},
{530, 531, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 110, 45, 25, 25},
- {531, 540, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 10, 70, 25, 25},
- {540, 541, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 35, 70, 25, 25},
- {541, 0, 0, LASTOBJ | TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 60, 70, 25, 25}};
+ {531, 532, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 10, 70, 25, 25},
+ {532, 540, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 35, 70, 25, 25},
+ {540, 541, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 60, 70, 25, 25},
+ {541, 0, 0, LASTOBJ | TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 85, 70, 25, 25}};
DlgRoot *Dlg;
void *hDlg;
int i, res, cSel = 520;
@@ -6950,7 +7436,7 @@ Graph::AddPlot(int family)
switch(res) {
case 520: case 521: case 522: case 523: case 524:
case 525: case 526: case 528: case 529: case 530:
- case 531: case 540: case 541:
+ case 531: case 532: case 540: case 541:
if(res == cSel) res = 1;
else {
cSel = res; res = -1;
@@ -6969,6 +7455,7 @@ Graph::AddPlot(int family)
else if(Dlg->GetCheck(529)) p = new Function(this, data);
else if(Dlg->GetCheck(530)) p = new FitFunc(this, data);
else if(Dlg->GetCheck(531)) p = new MultiLines(this, data);
+ else if(Dlg->GetCheck(532)) p = new xyStat(this, data);
else if(Dlg->GetCheck(540)) p = new StackBar(this, data);
else if(Dlg->GetCheck(541)) p = new StackPG(this, data);
else p = new PlotScatt(this, data, 0x01);
@@ -7001,10 +7488,10 @@ Graph::PropertyDlg()
{5, 6, 200, ISPARENT, SHEET, &tab2, 5, 10, 157, 122},
{6, 7, 300, ISPARENT, SHEET, &tab3, 5, 10, 157, 122},
{100, 101, 0, 0x0L, LTEXT, (void*)"arrangement of data: select plot", 10, 25, 60, 8},
- {101, 102, 500, TOUCHEXIT | ISPARENT, SHEET, &tab_A, 10, 37, 147, 88},
+ {101, 102, 500, TOUCHEXIT | ISPARENT, SHEET, &tab_A, 10, 37, 147, 90},
{102, 103, 520, TOUCHEXIT | ISPARENT | CHECKED, SHEET, &tab_B, 10, 37, 147, 90},
- {103, 104, 540, TOUCHEXIT | ISPARENT, SHEET, &tab_C, 10, 37, 147, 88},
- {104, 0, 560, TOUCHEXIT | ISPARENT, SHEET, &tab_D, 10, 37, 147, 88},
+ {103, 104, 540, TOUCHEXIT | ISPARENT, SHEET, &tab_C, 10, 37, 147, 90},
+ {104, 0, 560, TOUCHEXIT | ISPARENT, SHEET, &tab_D, 10, 37, 147, 90},
{200, 201, 0, 0x0L, LTEXT, (void*)"bounding rectangle (relative to page)", 10, 35, 60, 8},
{201, 202, 0, 0x0L, RTEXT, (void*)"upper left corner x", 5, 47, 58, 8},
{202, 203, 0, 0x0L, EDVAL1, &GRect.Xmin, 64, 47, 30, 10},
@@ -7060,7 +7547,8 @@ Graph::PropertyDlg()
{528, 529, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 95, 75, 25, 25},
{529, 530, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 120, 75, 25, 25},
{530, 531, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 20, 100, 25, 25},
- {531, 0, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 45, 100, 25, 25},
+ {531, 532, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 45, 100, 25, 25},
+ {532, 0, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 70, 100, 25, 25},
{540, 541, 0, TOUCHEXIT | CHECKED | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 20, 60, 25, 25},
{541, 542, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 45, 60, 25, 25},
{542, 543, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 70, 60, 25, 25},
@@ -7070,7 +7558,8 @@ Graph::PropertyDlg()
{561, 562, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 45, 60, 25, 25},
{562, 563, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 70, 60, 25, 25},
{563, 564, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 95, 60, 25, 25},
- {564, 0, 0, LASTOBJ | TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 120, 60, 25, 25}};
+ {564, 565, 0, TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 120, 60, 25, 25},
+ {565, 0, 0, LASTOBJ | TOUCHEXIT | ISRADIO, ODBUTTON, (void*)OD_PlotTempl, 20, 85, 25, 25}};
DlgRoot *Dlg;
GraphObj *p;
void *hDlg;
@@ -7105,7 +7594,7 @@ Graph::PropertyDlg()
res = -1;
break;
case 102:
- for(i = 520; i <= 531; i++) if(Dlg->GetCheck(i))selPlt = i;
+ for(i = 520; i <= 532; i++) if(Dlg->GetCheck(i))selPlt = i;
Dlg->ShowItem(301, true); Dlg->ShowItem(400, false);
res = -1;
break;
@@ -7115,7 +7604,7 @@ Graph::PropertyDlg()
res = -1;
break;
case 104:
- for(i = 560; i <= 564; i++) if(Dlg->GetCheck(i))selPlt = i;
+ for(i = 560; i <= 565; i++) if(Dlg->GetCheck(i))selPlt = i;
Dlg->ShowItem(301, false); Dlg->ShowItem(400, true);
res = -1;
break;
@@ -7143,11 +7632,11 @@ Graph::PropertyDlg()
case 504: case 505:
case 520: case 521: case 522: case 523:
case 524: case 525: case 526: case 527:
- case 528: case 529: case 530: case 531:
+ case 528: case 529: case 530: case 531: case 532:
case 540: case 541: case 542: case 543:
case 544:
case 560: case 561: case 562: case 563:
- case 564:
+ case 564: case 565:
if(res != selPlt) {
selPlt = res;
res = -1;
@@ -7210,6 +7699,7 @@ Graph::PropertyDlg()
else if(Dlg->GetCheck(529)) p = new Function(this, data);
else if(Dlg->GetCheck(530)) p = new FitFunc(this, data);
else if(Dlg->GetCheck(531)) p = new MultiLines(this, data);
+ else if(Dlg->GetCheck(532)) p = new xyStat(this, data);
else p = new PlotScatt(this, data, 0x01);
}
else if(Dlg->GetCheck(103)) {
@@ -7225,6 +7715,7 @@ Graph::PropertyDlg()
else if(Dlg->GetCheck(562)) p = new Plot3D(this, data, 0x1004);
else if(Dlg->GetCheck(563)) p = new BubblePlot3D(this, data);
else if(Dlg->GetCheck(564)) p = new Plot3D(this, data, 0x2000);
+ else if(Dlg->GetCheck(565)) p = new Func3D(this, data);
}
if(p && p->PropertyDlg()) {
if(!Command(CMD_DROP_PLOT, p, 0L)) DeleteGO(p);
@@ -7306,6 +7797,7 @@ Graph::Configure()
void *hDlg;
int i, res, undo_level = *Undo.pcb;
DWORD undo_flags = 0, tmpcol;
+ anyOutput *cdisp = Undo.cdisp;
bool bRet = false, bContinue = false;
fRECT o_gr, n_gr, o_dr, n_dr;
@@ -7318,8 +7810,12 @@ Graph::Configure()
sprintf(TmpTxt, "%s properties", name ? name : "Graph");
hDlg = CreateDlgWnd(TmpTxt, 50, 50, 450, 300, Dlg, 0x0L);
do{
- LoopDlgWnd();
- res = ExecDrawOrderButt(parent, this, Dlg->GetResult());
+ LoopDlgWnd(); res = Dlg->GetResult();
+ switch (res) {
+ case 600: case 601: case 602: case 603:
+ Undo.SetDisp(cdisp);
+ res = ExecDrawOrderButt(parent, this, res);
+ }
switch(res) {
case 0:
if(bContinue) res = -1;
@@ -7376,6 +7872,7 @@ Graph::Configure()
}
}while(res <0);
if(res == 1 && bRet) {
+ Undo.SetDisp(cdisp);
if(n_gr.Xmin != o_gr.Xmin || n_gr.Xmax != o_gr.Xmax ||
n_gr.Ymin != o_gr.Ymin || n_gr.Ymax != o_gr.Ymax ||
n_dr.Xmin != o_dr.Xmin || n_dr.Xmax != o_dr.Xmax ||
@@ -7395,11 +7892,12 @@ Graph::Configure()
undo_flags = CheckNewDword(&ColAX, ColAX, tmpcol, this, undo_flags);
if(Axes) for(i = 0; i < NumAxes; i++)
if(Axes[i]) Axes[i]->SetColor(COL_AXIS | UNDO_STORESET, ColAX);
- if(Plots && NumPlots && Plots[0] && Plots[0]->Id == GO_PLOT3D)
+ if(Plots && NumPlots && Plots[0] && (Plots[0]->Id == GO_PLOT3D || Plots[0]->Id == GO_FUNC3D))
Plots[0]->SetColor(COL_AXIS | UNDO_STORESET, ColAX);
}
}
else if(res == 2) {
+ Undo.SetDisp(cdisp);
if(*Undo.pcb > undo_level) { //restore plot order
while(*Undo.pcb > undo_level) Undo.Restore(false, 0L);
bRet = true;
@@ -7469,6 +7967,7 @@ Graph::AddAxis()
double tlb_dist, tlb_dx, tlb_dy, lb_x, lb_y;
TextDEF label_def, tlbdef;
DWORD flags;
+ anyOutput *cdisp = Undo.cdisp;
Axis *the_new, **tmpAxes;
bool bAxis = false, bRet = false;
char **names;
@@ -7542,6 +8041,7 @@ Graph::AddAxis()
}
}while (res < 0);
if(res == 1) {
+ Undo.SetDisp(cdisp);
Dlg->GetValue(122, &sizAxLine); Dlg->GetColor(125, &colAxis);
Dlg->GetValue(221, &axis.loc[0].fx); Dlg->GetValue(223, &axis.loc[1].fx);
Dlg->GetValue(226, &axis.loc[0].fy); Dlg->GetValue(228, &axis.loc[1].fy);
diff --git a/QT_Spec.cpp b/QT_Spec.cpp
index 9d46d8d..221de54 100755
--- a/QT_Spec.cpp
+++ b/QT_Spec.cpp
@@ -32,8 +32,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
-#include "QT_Spec.h"
-
+#include "QT_Spec.h"
+
extern tag_Units Units[];
extern GraphObj *CurrGO; //Selected Graphic Objects
extern Graph *CurrGraph;
@@ -48,61 +48,63 @@ QWidget *MainWidget =0L;
POINT CurrWidgetPos = {0,0};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Menu tem identifiers: synchronize this table with rlplot.rc for
+// Menu item identifiers: synchronize this table with rlplot.rc for
// compatibility with windows
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#define CM_OPEN 500
-#define CM_SAVEDATAAS 501
-#define CM_EXIT 502
-#define CM_NEWGRAPH 503
-#define CM_NEWPAGE 504
-#define CM_DELGRAPH 505
-#define CM_ADDPLOT 506
-#define CM_ABOUT 507
-#define CM_ADDROWCOL 508
-#define CM_COPYGRAPH 509
-#define CM_SAVEGRAPHAS 510
-#define CM_REDRAW 511
-#define CM_ZOOM25 512
-#define CM_ZOOM50 513
-#define CM_ZOOM100 514
-#define CM_ZOOM200 515
-#define CM_ZOOM400 516
-#define CM_PRINT 517
-#define CM_EXPORT 518
-#define CM_DELOBJ 519
-#define CM_REBOOT 520
-#define CM_SHUTDOWN 521
-#define CM_DEFAULTS 522
-#define CM_COPY 523
-#define CM_PASTE 524
-#define CM_UPDATE 525
-#define CM_ADDAXIS 526
-#define CM_UNDO 527
-#define CM_ZOOMIN 528
-#define CM_ZOOMOUT 529
-#define CM_ZOOMFIT 530
-#define CM_FILE1 531
-#define CM_FILE2 532
-#define CM_FILE3 533
-#define CM_FILE4 534
-#define CM_FILE5 535
-#define CM_FILE6 536
-#define CM_FILLRANGE 537
-#define CM_CUT 538
-#define CM_LEGEND 539
-#define CM_LAYERS 540
-
-#define CM_T_STANDARD 550
-#define CM_T_DRAW 551
-#define CM_T_POLYLINE 552
-#define CM_T_POLYGON 553
-#define CM_T_RECTANGLE 554
-#define CM_T_ROUNDREC 555
-#define CM_T_ELLIPSE 556
-#define CM_T_ARROW 557
-#define CM_T_TEXT 558
-
+#define CM_OPEN 500
+#define CM_SAVEDATAAS 501
+#define CM_EXIT 502
+#define CM_NEWGRAPH 503
+#define CM_NEWPAGE 504
+#define CM_DELGRAPH 505
+#define CM_ADDPLOT 506
+#define CM_ABOUT 507
+#define CM_ADDROWCOL 508
+#define CM_COPYGRAPH 509
+#define CM_SAVEGRAPHAS 510
+#define CM_REDRAW 511
+#define CM_ZOOM25 512
+#define CM_ZOOM50 513
+#define CM_ZOOM100 514
+#define CM_ZOOM200 515
+#define CM_ZOOM400 516
+#define CM_PRINT 517
+#define CM_EXPORT 518
+#define CM_DELOBJ 519
+#define CM_DEFAULTS 520
+#define CM_COPY 521
+#define CM_PASTE 522
+#define CM_UPDATE 523
+#define CM_ADDAXIS 524
+#define CM_UNDO 525
+#define CM_ZOOMIN 526
+#define CM_ZOOMOUT 527
+#define CM_ZOOMFIT 528
+#define CM_FILE1 529
+#define CM_FILE2 530
+#define CM_FILE3 531
+#define CM_FILE4 532
+#define CM_FILE5 533
+#define CM_FILE6 534
+#define CM_FILLRANGE 535
+#define CM_CUT 536
+#define CM_LEGEND 537
+#define CM_LAYERS 538
+#define CM_INSROW 539
+#define CM_INSCOL 540
+#define CM_DELROW 541
+#define CM_DELCOL 542
+
+#define CM_T_STANDARD 560
+#define CM_T_DRAW 561
+#define CM_T_POLYLINE 562
+#define CM_T_POLYGON 563
+#define CM_T_RECTANGLE 564
+#define CM_T_ROUNDREC 565
+#define CM_T_ELLIPSE 566
+#define CM_T_ARROW 567
+#define CM_T_TEXT 568
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Exute a file open dialog for the different situations
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -203,9 +205,9 @@ void OpenExportName(GraphObj *g, char *oldname)
// Common alert boxes
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void InfoBox(char *Msg)
-{
- QMessageBox::information(QAppl->focusWidget(), "Info", Msg);
-}
+{
+ QMessageBox::information(QAppl->focusWidget(), "Info", Msg);
+}
void ErrorBox(char *Msg)
{
@@ -217,7 +219,21 @@ bool YesNoBox(char *Msg)
if(QMessageBox::information(QAppl->focusWidget(), "RLPlot", Msg,
"&Yes", "&No", 0L, 0, -1)) return false;
return true;
-}
+}
+
+int YesNoCancelBox(char *Msg)
+{
+ int res;
+
+ res = QMessageBox::information(QAppl->focusWidget(), "RLPlot", Msg,
+ "&Yes", "&No", "&Cancel", 0, -1);
+ switch(res) {
+ case 0: return 1;
+ case 1: return 0;
+ default: return 2;
+ }
+ return 0;
+}
void Qt_Box()
{
@@ -291,8 +307,8 @@ void ShowCopyMark(anyOutput *out, RECT *mrk, int nRec)
UpdateMinMaxRect(&rCopyMark, mrk[i].left, mrk[i].top);
UpdateMinMaxRect(&rCopyMark, mrk[i].right, mrk[i].bottom);
}
- cTxtCur->bmCopyMark = new BitMapQT(rCopyMark.right - rCopyMark.left,
- rCopyMark.bottom - rCopyMark.top, out->hres, out->vres);
+ cTxtCur->bmCopyMark = new BitMapQT(rCopyMark.right - rCopyMark.left+1,
+ rCopyMark.bottom - rCopyMark.top+1, out->hres, out->vres);
}
LineDEF liCopyMark1 = {0.0f, 1.0f, 0x00ffffffL, 0L};
@@ -444,7 +460,7 @@ KSpreadTextDrag::format(int i) const
const char *
KSpreadTextDrag::selectionMimeType()
{
- return(MIME_KSPREAD);
+ return(MIME_RLPLOT);
}
RLPGraphDrag::RLPGraphDrag(QWidget *dragSource, const char *name)
@@ -523,12 +539,12 @@ void TestClipboard(GraphObj *g)
{
QClipboard *cb;
- QMimeSource *mime;
+ QDragObject *mime;
- if(!(cb = QAppl->clipboard()))return;
- if(!(mime = cb->data()))return;
+ if(!(cb = QAppl->clipboard()))return;
+ if(!(mime = (QDragObject *)cb->data()))return;
if(g->Id == GO_SPREADDATA) {
- if(mime->provides(MIME_RLPLOT)){
+ if(mime->provides(MIME_RLPLOT)){
QByteArray b = mime->encodedData(MIME_RLPLOT);
if(b) g->Command(CMD_PASTE_XML, (void*)b.data(), 0L);
return;
@@ -595,6 +611,47 @@ void EmptyClip()
HideCopyMark();
QAppl->clipboard()->clear();
}
+
+void CopyText(char *txt, int len)
+{
+ QClipboard *cb;
+ char tmp_txt[90];
+
+ if(!(cb = QAppl->clipboard()) || !txt || !txt[0])return;
+ EmptyClip();
+ if(!len) len = strlen(txt);
+ memcpy(tmp_txt, txt, len); tmp_txt[len] = 0;
+#ifdef Q_CHECK_PTR //n.a. in Qt version 2
+ cb->setText(tmp_txt, QClipboard::Clipboard);
+ cb->setText(tmp_txt, QClipboard::Selection);
+#else
+ cb->setText(tmp_txt);
+#endif
+}
+
+unsigned char* PasteText()
+{
+ QClipboard *cb;
+ QMimeSource *mime;
+ unsigned char *tmp_txt = 0L;
+
+ if(!(cb = QAppl->clipboard())) return 0L;
+#ifdef Q_CHECK_PTR //n.a. in Qt version 2
+ QString qstr = cb->text(QClipboard::Clipboard);
+#else
+ QString qstr = cb->text();
+#endif
+ if(qstr.length()) tmp_txt = (unsigned char*) strdup(qstr);
+ else {
+#ifdef Q_CHECK_PTR //n.a. in Qt version 2
+ qstr = cb->text(QClipboard::Selection);
+#else
+ QString qstr = cb->text();
+#endif
+ if(qstr.length()) tmp_txt = (unsigned char*) strdup(qstr);
+ }
+ return tmp_txt;
+}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get display (desktop) size
@@ -641,10 +698,10 @@ bool com_TextOut(int x, int y, char *ctxt, TextDEF *TxtSet, QPainter *qP, anyOut
oldBrush = qP->brush(); dxf = qP->worldMatrix();
oldPen = currPen = qP->pen();
o->oGetTextExtent(ctxt, -1, &w, &h);
- if(TxtSet->Align & TXA_VCENTER) iy = y + h/3;
+ if(TxtSet->Align & TXA_VCENTER) iy = y + iround(TxtSet->iSize *0.4);
else if(TxtSet->Align & TXA_VBOTTOM) iy = y;
- else iy = y + iround(h*.8);
- if(TxtSet->Align & TXA_HCENTER) ix = x - w/2;
+ else iy = y + TxtSet->iSize + 1;
+ if(TxtSet->Align & TXA_HCENTER) ix = x - (w >> 1);
else if(TxtSet->Align & TXA_HRIGHT) ix = x - w;
else ix = x;
currPen.setColor(SwapRB(TxtSet->ColTxt));
@@ -661,16 +718,8 @@ bool com_TextOut(int x, int y, char *ctxt, TextDEF *TxtSet, QPainter *qP, anyOut
currPen.setColor(SwapRB(TxtSet->ColTxt));
qP->setPen(currPen);
}
- if(TxtSet->Style & TXS_SUB) {
- if((TxtSet->Align & TXA_VCENTER) == TXA_VCENTER) iy += o->un2iy(TxtSet->fSize*0.4);
- else if((TxtSet->Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy += o->un2iy(TxtSet->fSize*0.2);
- else if((TxtSet->Align & TXA_VTOP) == TXA_VTOP) iy += o->un2iy(TxtSet->fSize*.6);
- }
- else if(TxtSet->Style & TXS_SUPER) {
- if((TxtSet->Align & TXA_VCENTER) == TXA_VCENTER) iy -= o->un2iy(TxtSet->fSize*0.4);
- else if((TxtSet->Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy -= o->un2iy(TxtSet->fSize*0.6);
- else if((TxtSet->Align & TXA_VTOP) == TXA_VTOP) iy += o->un2iy(TxtSet->fSize*.0);
- }
+ if(TxtSet->Style & TXS_SUB) iy += o->un2iy(TxtSet->fSize*0.4);
+ else if(TxtSet->Style & TXS_SUPER) iy -= o->un2iy(TxtSet->fSize*0.4);
qP->drawText(ix-x, iy-y, txt, -1);
}
else {
@@ -682,16 +731,8 @@ bool com_TextOut(int x, int y, char *ctxt, TextDEF *TxtSet, QPainter *qP, anyOut
currPen.setColor(SwapRB(TxtSet->ColTxt));
qP->setPen(currPen);
}
- if(TxtSet->Style & TXS_SUB) {
- if((TxtSet->Align & TXA_VCENTER) == TXA_VCENTER) iy += o->un2iy(TxtSet->fSize*0.4);
- else if((TxtSet->Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy += o->un2iy(TxtSet->fSize*0.2);
- else if((TxtSet->Align & TXA_VTOP) == TXA_VTOP) iy += o->un2iy(TxtSet->fSize*.6);
- }
- else if(TxtSet->Style & TXS_SUPER) {
- if((TxtSet->Align & TXA_VCENTER) == TXA_VCENTER) iy -= o->un2iy(TxtSet->fSize*0.4);
- else if((TxtSet->Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy -= o->un2iy(TxtSet->fSize*0.6);
- else if((TxtSet->Align & TXA_VTOP) == TXA_VTOP) iy += o->un2iy(TxtSet->fSize*.0);
- }
+ if(TxtSet->Style & TXS_SUB) iy += o->un2iy(TxtSet->fSize*0.4);
+ else if(TxtSet->Style & TXS_SUPER) iy -= o->un2iy(TxtSet->fSize*0.4);
qP->drawText(ix, iy, txt, -1);
}
qP->setPen(oldPen);
@@ -814,54 +855,215 @@ static char *critical_xpm[]={
".........aa********aaaaa........",
"...........aaaaaaaaaaa..........",
".............aaaaaaa............"};
-
+
+//thanks to Markus Bongard for the following icon
static char *RLPlot_xpm[]={
-"32 32 12 1",
-"j c #000083",
-"i c #0000ff",
-"d c #008100",
-"e c #00ff00",
-"b c #00ffff",
-"g c #830000",
-"c c #838100",
-"a c #838183",
-". c #c5c2c5",
-"h c #ff0000",
-"f c #ffff00",
-"# c #ffffff",
-".##a###a##bbbbbbbbbbbbbbbbbbbbbb",
-"##a###a###bbbbbbbbbbbbbbbbbbbbbb",
-"#a###a#.#a.b.b.b.b.b.b.b.b.b.b.b",
-"a#.#a#.#a#bbbbbbbbbbbbbbbbbbbbbb",
-"###a##.cccbbbbbbbbbbbbbdddbbbbbb",
-".#a###a#c#bbbbbbbbbbbbbbdbbbbbbb",
-"#a#.#a#.c.b.b.b.b.b.b.b.d.b.b.b.",
-"a###a###c#bbbbbbbbbbbdddddddbbbb",
-"#.#a#.#ac#bbbbbbbbbbbdeedeedbbbb",
-".#a.#cccccccbbbbbbbbbdeedeedbbbb",
-"#a###cffcffc.b.ggg.b.deddded.b.b",
-"a###acffcffcbbbbgbbbbdeeeeedbbbb",
-"..#a.cffcffcbbbbgbbbbdeeeeedbbbb",
-"##a##cffcffcbgggggggbdeeeeedbbbb",
-"#a#.#cfcccfcbghhghhgbdeeeeedb.b.",
-"a###acfffffcbghhghhgbdeeeeedbbbb",
-"#.#a#cfffffcbghggghgbdeeeeedbbbb",
-".#a.#cfffffcbghhhhhgbdeeeeedbbbb",
-"#a###cfffffcbghhhhhg.deeeeed.b.b",
-"a#.#acfffffcbghhhhhgbdeeeeedbbbb",
-"###a#cfffffcbghhhhhgbdeeeeedbbbb",
-".#a#.cfffffcighhhhhgideeeeediiii",
-"#a.##cfffffcighhhhhgideeeeedjiij",
-"a###acccccccigggggggidddddddiiii",
-"#.#a###ijiiijiiijiiijiiijiiiijii",
-".#a#.#ijijjiijiiijiiijiiijiiiiii",
-"#a###ijjiiijiijiijjijiijiijiijii",
-"a##.iijiijijjiijjiiijjijjiijjiij",
-".##jijiijjjiijjjiijjjiijjjiijjji",
-"##jjijijiijjjjijjjjijjjjijjjjijj",
-".jjjjjijjjjjijjjjijjjijjjjjjjjij",
-"jjijjjjjjjjjjjjijjjjjjjjjjijjjjj"};
-
+/* width height ncolors chars_per_pixel */
+"32 32 169 2",
+/* colors */
+"AA c #FFFFFFFFFFFF",
+"BA c #FFFFF7F79494",
+"CA c #FFFFF7F78484",
+"DA c #FFFFF7F77373",
+"EA c #FFFFF7F75252",
+"FA c #FFFFF7F74242",
+"GA c #FFFFF7F73939",
+"HA c #FFFFEFEF8C8C",
+"IA c #FFFFEFEF4A4A",
+"JA c #FFFFEFEF2929",
+"KA c #F7F7E7E77B7B",
+"LA c #F7F7C6C6ADAD",
+"MA c #F7F7B5B59C9C",
+"NA c #F7F7ADAD9494",
+"OA c #EFEFF7F7F7F7",
+"PA c #EFEFF7F7EFEF",
+"AB c #EFEFEFEFEFEF",
+"BB c #EFEFEFEFDEDE",
+"CB c #EFEFE7E7A5A5",
+"DB c #EFEFDEDE7373",
+"EB c #EFEFDEDE3939",
+"FB c #EFEFDEDE2929",
+"GB c #EFEFD6D64242",
+"HB c #EFEFA5A58C8C",
+"IB c #EFEF94947B7B",
+"JB c #EFEF84847373",
+"KB c #EFEF84846363",
+"LB c #EFEF7B7B7373",
+"MB c #E7E7E7E7CECE",
+"NB c #E7E7E7E79494",
+"OB c #E7E7DEDE6B6B",
+"PB c #E7E7DEDE5252",
+"AC c #E7E7CECE5252",
+"BC c #E7E77B7B6363",
+"CC c #E7E773735A5A",
+"DC c #E7E76B6B5252",
+"EC c #E7E75A5A4A4A",
+"FC c #DEDEE7E7F7F7",
+"GC c #DEDEE7E7EFEF",
+"HC c #DEDEDEDEDEDE",
+"IC c #DEDEDEDEBDBD",
+"JC c #DEDECECE4A4A",
+"KC c #DEDE4A4A3939",
+"LC c #D6D6EFEFCECE",
+"MC c #D6D6DEDEEFEF",
+"NC c #D6D6DEDECECE",
+"OC c #CECEDEDEDEDE",
+"PC c #CECED6D6CECE",
+"AD c #CECECECEB5B5",
+"BD c #CECECECE5A5A",
+"CD c #C6C6E7E7C6C6",
+"DD c #C6C6DEDEEFEF",
+"ED c #C6C6D6D67373",
+"FD c #C6C6CECE4A4A",
+"GD c #BDBDDEDEB5B5",
+"HD c #BDBDCECEE7E7",
+"ID c #BDBDCECECECE",
+"JD c #BDBDC6C6D6D6",
+"KD c #BDBD39394242",
+"LD c #B5B5DEDEADAD",
+"MD c #B5B5BDBDCECE",
+"ND c #B5B5BDBD4242",
+"OD c #B5B5B5B59C9C",
+"PD c #ADADD6D6ADAD",
+"AE c #ADADCECEDEDE",
+"BE c #ADADBDBDB5B5",
+"CE c #ADADB5B54242",
+"DE c #ADAD4A4A5252",
+"EE c #A5A5BDBDDEDE",
+"FE c #A5A5BDBDCECE",
+"GE c #A5A5ADADB5B5",
+"HE c #A5A5ADAD4242",
+"IE c #A5A563637B7B",
+"JE c #9C9CD6D6A5A5",
+"KE c #9C9CBDBDD6D6",
+"LE c #9C9CBDBDBDBD",
+"ME c #9C9CADADCECE",
+"NE c #9C9CADADA5A5",
+"OE c #9C9C52525252",
+"PE c #9C9C4A4A5252",
+"AF c #9494CECE9C9C",
+"BF c #9494B5B5CECE",
+"CF c #9494ADAD5A5A",
+"DF c #9494ADAD3939",
+"EF c #8C8CCECE9494",
+"FF c #8C8CCECE8C8C",
+"GF c #8C8CB5B5B5B5",
+"HF c #8C8CADADD6D6",
+"IF c #8C8CADADCECE",
+"JF c #8C8CADADB5B5",
+"KF c #8C8CADADA5A5",
+"LF c #8C8C9C9CB5B5",
+"MF c #8C8C9C9CADAD",
+"NF c #8C8C8C8CA5A5",
+"OF c #8C8C52526363",
+"PF c #8C8C42425252",
+"AG c #8484B5B5CECE",
+"BG c #7B7BCECE9494",
+"CG c #7B7BC6C68484",
+"DG c #7B7BC6C67B7B",
+"EG c #7B7BADADC6C6",
+"FG c #7B7BADADADAD",
+"GG c #7B7B9C9CC6C6",
+"HG c #7B7B9C9CB5B5",
+"IG c #7B7B9C9CADAD",
+"JG c #7B7B84849C9C",
+"KG c #7B7B42425252",
+"LG c #737384848C8C",
+"MG c #737373738484",
+"NG c #737339395252",
+"OG c #6B6BC6C68484",
+"PG c #6B6BBDBD7B7B",
+"AH c #6B6BA5A5CECE",
+"BH c #6B6B9C9CBDBD",
+"CH c #6B6B9C9CA5A5",
+"DH c #6B6B94949C9C",
+"EH c #6B6B8C8CA5A5",
+"FH c #6B6B8C8C9C9C",
+"GH c #6B6B6B6B7B7B",
+"HH c #6B6B42425252",
+"IH c #6363BDBD6B6B",
+"JH c #6363B5B58C8C",
+"KH c #6363A5A58C8C",
+"LH c #63639C9CC6C6",
+"MH c #5A5AB5B56363",
+"NH c #5A5A9C9CBDBD",
+"OH c #5A5A8C8C9C9C",
+"PH c #5A5A7B7B8C8C",
+"AI c #5A5A6B6B8484",
+"BI c #5A5A63637B7B",
+"CI c #5252BDBD7373",
+"DI c #5252ADAD8484",
+"EI c #5252A5A57B7B",
+"FI c #4A4AB5B55A5A",
+"GI c #4A4A8C8CBDBD",
+"HI c #4A4A8C8CADAD",
+"II c #4A4A7B7B9C9C",
+"JI c #4A4A7B7B8484",
+"KI c #4A4A6B6B7B7B",
+"LI c #42429C9C7373",
+"MI c #42428C8C7B7B",
+"NI c #42425A5A7373",
+"OI c #42424A4A6B6B",
+"PI c #3939ADAD6B6B",
+"AJ c #3939ADAD5A5A",
+"BJ c #39399C9C6B6B",
+"CJ c #39398484BDBD",
+"DJ c #39397B7BADAD",
+"EJ c #39397B7B8C8C",
+"FJ c #393973737B7B",
+"GJ c #313163637B7B",
+"HJ c #31315A5A7B7B",
+"IJ c #292984846B6B",
+"JJ c #29296B6B7B7B",
+"KJ c #21217B7BB5B5",
+"LJ c #21217373A5A5",
+"MJ c #212173739C9C",
+"NJ c #21216B6B8C8C",
+"OJ c #212152527373",
+"PJ c #181884846363",
+"AK c #18186B6B7B7B",
+"BK c #18185A5A7373",
+"CK c #10106B6B9C9C",
+"DK c #10105A5A8484",
+"EK c #08087B7B6363",
+"FK c #08085A5A7B7B",
+"GK c #00006B6B9C9C",
+"HK c #000063637B7B",
+"IK c #00005A5A8C8C",
+/* pixels */
+"CJAHAHAHAHHILHLHBHLHLJNHNHNHGINHGINHGINHGINHGINHGINHGINHGINHGIKJ",
+"AHAAAAAAAGHDABBBGCBFBFHCPCOCEEHDJDEEJDEEHDJDEEHDJDEEJDEEHDEEJDNH",
+"AHAAAGAAABABABKEOCHCHCPCFEFEABAEHDFCDDJDDDMCJDHDFCHDHDGCDDJDDDLH",
+"EGAEDDABOAABOCEGHCHCPCHCBHJDJDEEJDEEJDEEJDAEJDEEAEJDEEJDEEJDEELH",
+"AHAAAAAAMCJDGCABHCHCBFOCPCJDEEJDEEJDEEAEEEEEAEJDEEFEFEFEEEEEJDGI",
+"AHAAAAPAAGGCABBBMCEGJDNCPCPCEEEEEEEEEEEEEEJDEEEEFEDIPIGFFEFEEENH",
+"EGOAKEAAABPAABKEHCHCHCHCMEBFABJDAEMCOCEEMCMCFEOCDDLEKHIDIDEEDDLH",
+"LHAEMCAAABABAEIFHCHCHCPCBHOCKEKEEEFEEEFEEEFEEEKEBFGEDIKFMEFEEEGI",
+"AHAAAAABGCJDABGCBBOCHGHCPCMDEEFEKEEEFEKEFEKEEEMEBFJFDIGEIFBFFEGI",
+"AHAAAAPAAHGCABBBMCJFMDOCPCJDMEKEKEMEKEKEKEKEMEIFGEFGEIIGJFGEMEGI",
+"AHAAAEAAABABGCNBDBOCNCNCMDEEMCEEEEMCJDKEDDDDLFCIDIEIPICIDIDIJDNH",
+"AHKEDDAAPAABOCKFPBICNCPCHGFEMEMEMEMEHFMEMEIFJFJELCCDCGBBCDLIIGHI",
+"EGAAAAABABJDMBNCPBADGENCMDMDMEHFIFHFMEHFIFMECHJEPCLDBGGDGDLIIGDJ",
+"AHAAAAAAAHEDKAOBEBBDCEODICMDIFIFMEIFIFIFIFIFCHEFLDPDOGGDPDMIFHHI",
+"AHAAOCABMBEABABAFABABAGBNELEHDKEHFDDEEIFJDEEFGCGLDPDPGPDPDAJMFHI",
+"AHDDEGABBBEABACAFABACBGBFHGEIFGGIFGGIFIFGGIFDHCGJEMHFIAFAFBJDHII",
+"AHAAAAABMBEAHAEAEADACABDODBEHGIFGGIFHGGGIFHGCHJHAFAFEFAFFFFJDHMJ",
+"AHAAAAAABEIADADAKACADAGBODNEGGHGIEIENFGGHGGGOHDGFFFFFFFFFFAJOHHI",
+"AHAAABABPCGAKADADAKADAFDODMFHIHIAIPFIIIIHIHIEJCIFFDGFFDGDGJJFJCK",
+"AHAAAHHCMBGAEAEAEAFAFAJCLGFKPEPEPEKDPEPEOIIKHKLIDGDGPGDGIHEKIKGK",
+"EGFCDDAANCJAIAIAIAIAIANDBKOJJBLALALBLAMANGFKHKFIMHPGMHFILIEKFKGK",
+"LHAAAABBNCFBJAJAJAEBGBDFBKOJBCNADCDCIBHBNGBKAKFIMHMHMHMHMHEKHKGK",
+"AHAAAAABADEBJCEBGBACACHEBKNIBCJBJBHBJBJBHHOJJJPIIHPGIHIHIHPJDKGK",
+"AHAAOCJDNCEBOBACOBOBOBHEEJNIKCLBKBBCKBCCKGHJJJMHDGIHPGDGIHEKEJCK",
+"AHAAKEABMBEBDBDBOBOBOBHENIAIKCDCDCDCDCECKGKIGJCIDGFFLGDGDGPJNJMJ",
+"CJAAOAABBBIADBHADBHAKAHEAIBIDCDCBCCCDCCCPFKIJIPGBGCFDGFFDGIJIIMJ",
+"AHAAAAABMBIABADBBAHAHAHEAIGHKCJBBCKBKBBCKGPHJIPGFFGFFFFFFFIJJILJ",
+"AHAAAAABMDFDFDBDFDNDBDHEFHJGDEDEDEDEOEDEOFPHMGBJBJAJBJBJBJMIOHDJ",
+"EGAAAAJDHGNFFHMGFHJGMGEHJGNFNFMGMGMGMGMGLGJGCHEHFHPHMGOHPHFHIGDJ",
+"LHAAOCIFIFIFLFLFMFMFJFLFIFJFHGIGMFIGNFMFMFLFIFLFHGIGFGIGIGHGJFCJ",
+"EGDDKEKEMEBFBFBFBFMEBFBFFEKEMEMEMEGEBFMEBFBFBFKEMEBFMEBFBFKEKEGI",
+"KJLHGINHGINHNHNHNHGINHNHGINHGINHNHGIGINHGINHNHGINHNHGIGINHNHGICJ"};
+
//this icon has been taken from trolltech's Qt: qmessagebox.cpp
static char *qtlogo_xpm[] = {
/* width height ncolors chars_per_pixel */
@@ -944,8 +1146,7 @@ BitMapQT::BitMapQT(GraphObj *g, QWidget *wi, int vr, int hr):anyOutput()
int w, h;
hres = (double)hr; vres = (double)vr;
- image = 0L;
- hgo = 0L;
+ image = 0L; hgo = 0L;
if(wi) {
w = wi->width(); h = wi->height();
}
@@ -968,8 +1169,8 @@ BitMapQT::BitMapQT(GraphObj *g, QWidget *wi, int vr, int hr):anyOutput()
BitMapQT::BitMapQT(int w, int h, double hr, double vr):anyOutput()
{
hres = hr; vres = vr;
- image = 0L;
- hgo = 0L;
+ image = 0L; hgo = 0L;
+ w = abs(w); h = abs(h);
Box1.Xmin = Box1.Ymin = 0.0;
Box1.Xmax = w; Box1.Ymax = h;
DeskRect.right = w; DeskRect.bottom = h;
@@ -1039,7 +1240,7 @@ BitMapQT::SetFill(FillDEF *fill)
bool
BitMapQT::SetTextSpec(TextDEF *set)
{
- return com_SetTextSpec(set, &TxtSet, this, qFont, &qPainter);
+ return com_SetTextSpec(set, &TxtSet, this, qFont, &qPainter);
}
bool
@@ -1072,7 +1273,7 @@ BitMapQT::oGetTextExtent(char *text, int cb, int *width, int *height)
if(!text) return false;
QRect rc = qPainter.boundingRect(0, 0, 10000, 1000, Qt::AlignLeft | Qt::AlignTop,
text, cb > 0 ? cb : strlen(text));
- *width = rc.rRight() - rc.rLeft(); *height = rc.rBottom() - rc.rTop();
+ *width = rc.rRight() - rc.rLeft(); *height = TxtSet.iSize +2;
return true;
}
@@ -1370,7 +1571,9 @@ OutputQT::UpdateRect(RECT *rc, bool invert)
}
else {
y1 = rc->bottom; y2 = rc->top;
- }
+ }
+ if(x2 > DeskRect.right) x2 = DeskRect.right;
+ if(y2 > DeskRect.bottom) y2 = DeskRect.right;
bitBlt(widget, x1, y1, mempic, x1, y1,
x2 - x1, y2 - y1, invert ? Qt::NotCopyROP : Qt::CopyROP);
return true;
@@ -1437,11 +1640,21 @@ OutputQT::SetMenu(int type)
file->insertItem("n.a.", widget, SLOT(cmFile4()), 0, CM_FILE4);
file->insertItem("n.a.", widget, SLOT(cmFile5()), 0, CM_FILE5);
file->insertItem("n.a.", widget, SLOT(cmFile6()), 0, CM_FILE6);
+
+ QPopupMenu *insert = new QPopupMenu(widget);
+ insert->insertItem("&Rows", widget, SLOT(cmInsRow()));
+ insert->insertItem("&Columns", widget, SLOT(cmInsCol()));
+ QPopupMenu *Delete = new QPopupMenu(widget);
+ Delete->insertItem("&Rows", widget, SLOT(cmDelRow()));
+ Delete->insertItem("&Columns", widget, SLOT(cmDelCol()));
+
QPopupMenu *edit = new QPopupMenu(widget);
edit->insertItem("&Undo", widget, SLOT(cmUndo()), Qt::CTRL + Qt::Key_Z);
edit->insertSeparator();
edit->insertItem("&Rows/Cols", widget, SLOT(cmAddRowCol()));
+ edit->insertItem("&Insert", insert);
+ edit->insertItem("&Delete", Delete);
edit->insertSeparator();
edit->insertItem("&Copy", widget, SLOT(cmCopy()), Qt::CTRL + Qt::Key_C);
edit->insertItem("C&ut", widget, SLOT(cmCut()), Qt::CTRL + Qt::Key_X);
@@ -1696,11 +1909,12 @@ RLPwidget::RLPwidget(QWidget *par, const char *name, anyOutput *o, GraphObj *g)
RLPwidget::~RLPwidget()
{
+ if(OutputClass)((OutputQT*)OutputClass)->widget = 0L;
+ OutputClass = 0L;
if(BaseObj){
BaseObj->Command(CMD_CAN_DELETE, 0L, 0L);
BaseObj = 0L;
}
- if(OutputClass)((OutputQT*)OutputClass)->widget = 0L;
}
//public slots: menu items, events
@@ -1738,7 +1952,13 @@ RLPwidget::cmSaveDataAs()
void
RLPwidget::cmExit()
{
- delete(this);
+ if(BaseObj) {
+ if(BaseObj->Command(CMD_CAN_CLOSE, 0L, 0L)){
+ BaseObj = 0L;
+ delete this;
+ }
+ }
+ else delete(this);
}
void
@@ -1793,8 +2013,8 @@ void
RLPwidget::cmCopy()
{
if(BaseObj && BaseObj->Id == GO_SPREADDATA) {
- BaseObj->Command(CMD_QUERY_COPY, 0L, OutputClass);
- CopyData(BaseObj);
+ if(BaseObj->Command(CMD_QUERY_COPY, 0L, OutputClass))
+ CopyData(BaseObj);
}
}
@@ -1954,7 +2174,31 @@ void
RLPwidget::cmFillRange()
{
BaseObj->Command(CMD_FILLRANGE, 0L, OutputClass);
+}
+
+void
+RLPwidget::cmInsRow()
+{
+ BaseObj->Command(CMD_INSROW, 0L, OutputClass);
}
+
+void
+RLPwidget::cmInsCol()
+{
+ BaseObj->Command(CMD_INSCOL, 0L, OutputClass);
+}
+
+void
+RLPwidget::cmDelRow()
+{
+ BaseObj->Command(CMD_DELROW, 0L, OutputClass);
+}
+
+void
+RLPwidget::cmDelCol()
+{
+ BaseObj->Command(CMD_DELCOL, 0L, OutputClass);
+}
void ToolMenu(GraphObj *b, anyOutput *o, int tm)
{
@@ -2040,10 +2284,14 @@ void
RLPwidget::closeEvent(QCloseEvent *e)
{
if(BaseObj){
- BaseObj->Command(CMD_CAN_DELETE, 0L, 0L);
- BaseObj = 0L;
+ if(BaseObj->Command(CMD_CAN_CLOSE, 0L, 0L)) {
+ if(OutputClass)((OutputQT*)OutputClass)->widget = 0L;
+ OutputClass = 0L;
+ BaseObj = 0L;
+ e->accept();
+ }
}
- e->accept();
+ else e->accept();
}
void
@@ -2056,42 +2304,58 @@ RLPwidget::mouseDoubleClickEvent(QMouseEvent *e)
void
RLPwidget::mousePressEvent(QMouseEvent *e)
-{
+{
+ int i;
MouseEvent mev = {1, e->button() == Qt::LeftButton ? MOUSE_LBDOWN : -1, e->x(), e->y()};
HideTextCursor();
+ i = e->state();
+ if(i & Qt::ShiftButton) mev.StateFlags |= 0x08;
+ if(i & Qt::ControlButton) mev.StateFlags |= 0x10;
if (BaseObj)BaseObj->Command(CMD_MOUSE_EVENT, (void *)&mev, OutputClass);
}
void
RLPwidget::mouseReleaseEvent(QMouseEvent *e)
-{
+{
+ int i;
MouseEvent mev = {0, e->button() == Qt::LeftButton ? MOUSE_LBUP :
e->button() == Qt::RightButton ? MOUSE_RBUP : -1, e->x(), e->y()};
-
+
+ i = e->state();
+ if(i & Qt::ShiftButton) mev.StateFlags |= 0x08;
+ if(i & Qt::ControlButton) mev.StateFlags |= 0x10;
if (BaseObj) BaseObj->Command(CMD_MOUSE_EVENT, (void *)&mev, OutputClass);
}
void
RLPwidget::mouseMoveEvent(QMouseEvent *e)
-{
+{
+ int i;
MouseEvent mev = {0, MOUSE_MOVE, e->x(), e->y()};
- if(e->state() == Qt::LeftButton) mev.StateFlags = 1;
+ i = e->state();
+ if(i & Qt::LeftButton) mev.StateFlags |= 0x01;
+ if(i & Qt::ShiftButton) mev.StateFlags |= 0x08;
+ if(i & Qt::ControlButton) mev.StateFlags |= 0x10;
if (BaseObj) BaseObj->Command(CMD_MOUSE_EVENT, (void *)&mev, OutputClass);
}
void
RLPwidget::keyPressEvent(QKeyEvent *e)
{
- int c;
+ int i, c;
if(BaseObj) switch(c = e->key()) {
case Key_Prior:
- BaseObj->Command(CMD_PAGEUP, 0L, OutputClass);
+ i = e->state();
+ if(i & Qt::ShiftButton) BaseObj->Command(CMD_SHPGUP, 0L, OutputClass);
+ else BaseObj->Command(CMD_PAGEUP, 0L, OutputClass);
break;
case Key_Next:
- BaseObj->Command(CMD_PAGEDOWN, 0L, OutputClass);
+ i = e->state();
+ if(i & Qt::ShiftButton) BaseObj->Command(CMD_SHPGDOWN, 0L, OutputClass);
+ else BaseObj->Command(CMD_PAGEDOWN, 0L, OutputClass);
break;
case Key_Left:
if(e->state() & ShiftButton) BaseObj->Command(CMD_SHIFTLEFT, 0L, OutputClass);
@@ -2556,6 +2820,8 @@ DlgWidget::keyPressEvent(QKeyEvent *e)
c = e->ascii();
if(c >1 && c < 256)
if(c == 26) dlg->Command(CMD_UNDO, 0L, OutputClass);
+ else if(c == 0x03) dlg->Command(CMD_COPY, 0L, OutputClass);
+ else if(c == 0x16) dlg->Command(CMD_PASTE, 0L, OutputClass);
else dlg->Command(CMD_ADDCHAR, (void *)(& c), OutputClass);
break;
}
@@ -2610,7 +2876,7 @@ void *CreateDlgWnd(char *title, int x, int y, int width, int height, tag_DlgObj
else w->move(CurrWidgetPos.x+x, CurrWidgetPos.y+y);
o = new OutputQT(w);
o->units = defs.cUnits;
- o->Erase(0x00c0c0c0L);
+ o->Erase(0x00e0e0e0L);
if(flags & 0x04) {
w->startTimer(100);
}
@@ -2626,6 +2892,7 @@ void LoopDlgWnd() //keep message processing running
void CloseDlgWnd(void *hDlg)
{
+ HideCopyMark();
if(hDlg) {
delete((DlgWidget*) hDlg);
}
diff --git a/QT_Spec.h b/QT_Spec.h
index 582f9b3..0f4b425 100755
--- a/QT_Spec.h
+++ b/QT_Spec.h
@@ -128,6 +128,10 @@ public slots:
void cmLayers();
void cmUndo();
void cmFillRange();
+ void cmInsRow();
+ void cmInsCol();
+ void cmDelRow();
+ void cmDelCol();
void cmtStandard();
void cmtDraw();
void cmtPolyline();
@@ -232,6 +236,7 @@ public:
OutputQT(DlgWidget *wi);
~OutputQT();
bool ActualSize(RECT *rc);
+ void Focus(){if(widget){widget->show(); widget->setActiveWindow();widget->raise();}};
void Caption(char *txt);
void MouseCursor(int cid, bool force);
bool SetScroll(bool isVert, int iMin, int iMax, int iPSize, int iPos);
diff --git a/RLPLOT.ICO b/RLPLOT.ICO
old mode 100755
new mode 100644
index 0ba1c92..593b642
Binary files a/RLPLOT.ICO and b/RLPLOT.ICO differ
diff --git a/RLPLOT.RC b/RLPLOT.RC
index f7ea45f..2be39ca 100755
--- a/RLPLOT.RC
+++ b/RLPLOT.RC
@@ -36,37 +36,39 @@
#define CM_PRINT 517
#define CM_EXPORT 518
#define CM_DELOBJ 519
-#define CM_REBOOT 520
-#define CM_SHUTDOWN 521
-#define CM_DEFAULTS 522
-#define CM_COPY 523
-#define CM_PASTE 524
-#define CM_UPDATE 525
-#define CM_ADDAXIS 526
-#define CM_UNDO 527
-#define CM_ZOOMIN 528
-#define CM_ZOOMOUT 529
-#define CM_ZOOMFIT 530
-#define CM_FILE1 531
-#define CM_FILE2 532
-#define CM_FILE3 533
-#define CM_FILE4 534
-#define CM_FILE5 535
-#define CM_FILE6 536
-#define CM_FILLRANGE 537
-#define CM_CUT 538
-#define CM_LEGEND 539
-#define CM_LAYERS 540
+#define CM_DEFAULTS 520
+#define CM_COPY 521
+#define CM_PASTE 522
+#define CM_UPDATE 523
+#define CM_ADDAXIS 524
+#define CM_UNDO 525
+#define CM_ZOOMIN 526
+#define CM_ZOOMOUT 527
+#define CM_ZOOMFIT 528
+#define CM_FILE1 529
+#define CM_FILE2 530
+#define CM_FILE3 531
+#define CM_FILE4 532
+#define CM_FILE5 533
+#define CM_FILE6 534
+#define CM_FILLRANGE 535
+#define CM_CUT 536
+#define CM_LEGEND 537
+#define CM_LAYERS 538
+#define CM_INSROW 539
+#define CM_INSCOL 540
+#define CM_DELROW 541
+#define CM_DELCOL 542
-#define CM_T_STANDARD 550
-#define CM_T_DRAW 551
-#define CM_T_POLYLINE 552
-#define CM_T_POLYGON 553
-#define CM_T_RECTANGLE 554
-#define CM_T_ROUNDREC 555
-#define CM_T_ELLIPSE 556
-#define CM_T_ARROW 557
-#define CM_T_TEXT 558
+#define CM_T_STANDARD 560
+#define CM_T_DRAW 561
+#define CM_T_POLYLINE 562
+#define CM_T_POLYGON 563
+#define CM_T_RECTANGLE 564
+#define CM_T_ROUNDREC 565
+#define CM_T_ELLIPSE 566
+#define CM_T_ARROW 567
+#define CM_T_TEXT 568
#define CM_DELKEY 600
#define CM_LEFTARRKEY 601
@@ -83,6 +85,8 @@
#define CM_SHRIGHT 612
#define CM_SHUP 613
#define CM_SHDOWN 614
+#define CM_SHPGUP 615
+#define CM_SHPGDOWN 616
#define MENU_1 400
#define MENU_2 401
@@ -174,9 +178,6 @@ BEGIN
MENUITEM SEPARATOR
MENUITEM "&Print", CM_PRINT
MENUITEM SEPARATOR
- MENUITEM "&Reboot", CM_REBOOT
- MENUITEM "Shut &down", CM_SHUTDOWN
- MENUITEM SEPARATOR
MENUITEM "E&xit", CM_EXIT
END
POPUP "&Edit"
@@ -184,6 +185,16 @@ BEGIN
MENUITEM "&Undo" CM_UNDO
MENUITEM SEPARATOR
MENUITEM "&Rows/Cols", CM_ADDROWCOL
+ POPUP "&Insert"
+ BEGIN
+ MENUITEM "&Rows", CM_INSROW
+ MENUITEM "&Columns", CM_INSCOL
+ END
+ POPUP "&Delete"
+ BEGIN
+ MENUITEM "&Rows", CM_DELROW
+ MENUITEM "&Columns", CM_DELCOL
+ END
MENUITEM SEPARATOR
MENUITEM "&Copy", CM_COPY
MENUITEM "C&ut", CM_CUT
@@ -322,6 +333,8 @@ BEGIN
VK_TAB, CM_SHTAB, VIRTKEY, SHIFT
VK_PRIOR, CM_PGUP, VIRTKEY
VK_NEXT, CM_PGDOWN, VIRTKEY
+ VK_PRIOR, CM_SHPGUP, VIRTKEY, SHIFT
+ VK_NEXT, CM_SHPGDOWN, VIRTKEY, SHIFT
VK_HOME, CM_POS_FIRST, VIRTKEY
VK_END, CM_POS_LAST, VIRTKEY
VK_ESCAPE, CM_T_STANDARD, VIRTKEY
diff --git a/RLPlot-Icons.zip b/RLPlot-Icons.zip
new file mode 100755
index 0000000..91ec8e2
Binary files /dev/null and b/RLPlot-Icons.zip differ
diff --git a/RLPlot.bmp b/RLPlot.bmp
old mode 100755
new mode 100644
index ac10363..d204d1b
Binary files a/RLPlot.bmp and b/RLPlot.bmp differ
diff --git a/RLPlot.xpm b/RLPlot.xpm
old mode 100755
new mode 100644
index 77b8e92..1ee9a00
--- a/RLPlot.xpm
+++ b/RLPlot.xpm
@@ -1,47 +1,207 @@
-/* XPM */
-static char *RLPlot[]={
-"32 32 12 1",
-"j c #000083",
-"i c #0000ff",
-"d c #008100",
-"e c #00ff00",
-"b c #00ffff",
-"g c #830000",
-"c c #838100",
-"a c #838183",
-". c #c5c2c5",
-"h c #ff0000",
-"f c #ffff00",
-"# c #ffffff",
-".##a###a##bbbbbbbbbbbbbbbbbbbbbb",
-"##a###a###bbbbbbbbbbbbbbbbbbbbbb",
-"#a###a#.#a.b.b.b.b.b.b.b.b.b.b.b",
-"a#.#a#.#a#bbbbbbbbbbbbbbbbbbbbbb",
-"###a##.cccbbbbbbbbbbbbbdddbbbbbb",
-".#a###a#c#bbbbbbbbbbbbbbdbbbbbbb",
-"#a#.#a#.c.b.b.b.b.b.b.b.d.b.b.b.",
-"a###a###c#bbbbbbbbbbbdddddddbbbb",
-"#.#a#.#ac#bbbbbbbbbbbdeedeedbbbb",
-".#a.#cccccccbbbbbbbbbdeedeedbbbb",
-"#a###cffcffc.b.ggg.b.deddded.b.b",
-"a###acffcffcbbbbgbbbbdeeeeedbbbb",
-"..#a.cffcffcbbbbgbbbbdeeeeedbbbb",
-"##a##cffcffcbgggggggbdeeeeedbbbb",
-"#a#.#cfcccfcbghhghhgbdeeeeedb.b.",
-"a###acfffffcbghhghhgbdeeeeedbbbb",
-"#.#a#cfffffcbghggghgbdeeeeedbbbb",
-".#a.#cfffffcbghhhhhgbdeeeeedbbbb",
-"#a###cfffffcbghhhhhg.deeeeed.b.b",
-"a#.#acfffffcbghhhhhgbdeeeeedbbbb",
-"###a#cfffffcbghhhhhgbdeeeeedbbbb",
-".#a#.cfffffcighhhhhgideeeeediiii",
-"#a.##cfffffcighhhhhgideeeeedjiij",
-"a###acccccccigggggggidddddddiiii",
-"#.#a###ijiiijiiijiiijiiijiiiijii",
-".#a#.#ijijjiijiiijiiijiiijiiiiii",
-"#a###ijjiiijiijiijjijiijiijiijii",
-"a##.iijiijijjiijjiiijjijjiijjiij",
-".##jijiijjjiijjjiijjjiijjjiijjji",
-"##jjijijiijjjjijjjjijjjjijjjjijj",
-".jjjjjijjjjjijjjjijjjijjjjjjjjij",
-"jjijjjjjjjjjjjjijjjjjjjjjjijjjjj"};
+/* XPM */
+static char *rlplot-icon[] = {
+/* width height ncolors chars_per_pixel */
+"32 32 169 2",
+/* colors */
+"AA c #FFFFFFFFFFFF",
+"BA c #FFFFF7F79494",
+"CA c #FFFFF7F78484",
+"DA c #FFFFF7F77373",
+"EA c #FFFFF7F75252",
+"FA c #FFFFF7F74242",
+"GA c #FFFFF7F73939",
+"HA c #FFFFEFEF8C8C",
+"IA c #FFFFEFEF4A4A",
+"JA c #FFFFEFEF2929",
+"KA c #F7F7E7E77B7B",
+"LA c #F7F7C6C6ADAD",
+"MA c #F7F7B5B59C9C",
+"NA c #F7F7ADAD9494",
+"OA c #EFEFF7F7F7F7",
+"PA c #EFEFF7F7EFEF",
+"AB c #EFEFEFEFEFEF",
+"BB c #EFEFEFEFDEDE",
+"CB c #EFEFE7E7A5A5",
+"DB c #EFEFDEDE7373",
+"EB c #EFEFDEDE3939",
+"FB c #EFEFDEDE2929",
+"GB c #EFEFD6D64242",
+"HB c #EFEFA5A58C8C",
+"IB c #EFEF94947B7B",
+"JB c #EFEF84847373",
+"KB c #EFEF84846363",
+"LB c #EFEF7B7B7373",
+"MB c #E7E7E7E7CECE",
+"NB c #E7E7E7E79494",
+"OB c #E7E7DEDE6B6B",
+"PB c #E7E7DEDE5252",
+"AC c #E7E7CECE5252",
+"BC c #E7E77B7B6363",
+"CC c #E7E773735A5A",
+"DC c #E7E76B6B5252",
+"EC c #E7E75A5A4A4A",
+"FC c #DEDEE7E7F7F7",
+"GC c #DEDEE7E7EFEF",
+"HC c #DEDEDEDEDEDE",
+"IC c #DEDEDEDEBDBD",
+"JC c #DEDECECE4A4A",
+"KC c #DEDE4A4A3939",
+"LC c #D6D6EFEFCECE",
+"MC c #D6D6DEDEEFEF",
+"NC c #D6D6DEDECECE",
+"OC c #CECEDEDEDEDE",
+"PC c #CECED6D6CECE",
+"AD c #CECECECEB5B5",
+"BD c #CECECECE5A5A",
+"CD c #C6C6E7E7C6C6",
+"DD c #C6C6DEDEEFEF",
+"ED c #C6C6D6D67373",
+"FD c #C6C6CECE4A4A",
+"GD c #BDBDDEDEB5B5",
+"HD c #BDBDCECEE7E7",
+"ID c #BDBDCECECECE",
+"JD c #BDBDC6C6D6D6",
+"KD c #BDBD39394242",
+"LD c #B5B5DEDEADAD",
+"MD c #B5B5BDBDCECE",
+"ND c #B5B5BDBD4242",
+"OD c #B5B5B5B59C9C",
+"PD c #ADADD6D6ADAD",
+"AE c #ADADCECEDEDE",
+"BE c #ADADBDBDB5B5",
+"CE c #ADADB5B54242",
+"DE c #ADAD4A4A5252",
+"EE c #A5A5BDBDDEDE",
+"FE c #A5A5BDBDCECE",
+"GE c #A5A5ADADB5B5",
+"HE c #A5A5ADAD4242",
+"IE c #A5A563637B7B",
+"JE c #9C9CD6D6A5A5",
+"KE c #9C9CBDBDD6D6",
+"LE c #9C9CBDBDBDBD",
+"ME c #9C9CADADCECE",
+"NE c #9C9CADADA5A5",
+"OE c #9C9C52525252",
+"PE c #9C9C4A4A5252",
+"AF c #9494CECE9C9C",
+"BF c #9494B5B5CECE",
+"CF c #9494ADAD5A5A",
+"DF c #9494ADAD3939",
+"EF c #8C8CCECE9494",
+"FF c #8C8CCECE8C8C",
+"GF c #8C8CB5B5B5B5",
+"HF c #8C8CADADD6D6",
+"IF c #8C8CADADCECE",
+"JF c #8C8CADADB5B5",
+"KF c #8C8CADADA5A5",
+"LF c #8C8C9C9CB5B5",
+"MF c #8C8C9C9CADAD",
+"NF c #8C8C8C8CA5A5",
+"OF c #8C8C52526363",
+"PF c #8C8C42425252",
+"AG c #8484B5B5CECE",
+"BG c #7B7BCECE9494",
+"CG c #7B7BC6C68484",
+"DG c #7B7BC6C67B7B",
+"EG c #7B7BADADC6C6",
+"FG c #7B7BADADADAD",
+"GG c #7B7B9C9CC6C6",
+"HG c #7B7B9C9CB5B5",
+"IG c #7B7B9C9CADAD",
+"JG c #7B7B84849C9C",
+"KG c #7B7B42425252",
+"LG c #737384848C8C",
+"MG c #737373738484",
+"NG c #737339395252",
+"OG c #6B6BC6C68484",
+"PG c #6B6BBDBD7B7B",
+"AH c #6B6BA5A5CECE",
+"BH c #6B6B9C9CBDBD",
+"CH c #6B6B9C9CA5A5",
+"DH c #6B6B94949C9C",
+"EH c #6B6B8C8CA5A5",
+"FH c #6B6B8C8C9C9C",
+"GH c #6B6B6B6B7B7B",
+"HH c #6B6B42425252",
+"IH c #6363BDBD6B6B",
+"JH c #6363B5B58C8C",
+"KH c #6363A5A58C8C",
+"LH c #63639C9CC6C6",
+"MH c #5A5AB5B56363",
+"NH c #5A5A9C9CBDBD",
+"OH c #5A5A8C8C9C9C",
+"PH c #5A5A7B7B8C8C",
+"AI c #5A5A6B6B8484",
+"BI c #5A5A63637B7B",
+"CI c #5252BDBD7373",
+"DI c #5252ADAD8484",
+"EI c #5252A5A57B7B",
+"FI c #4A4AB5B55A5A",
+"GI c #4A4A8C8CBDBD",
+"HI c #4A4A8C8CADAD",
+"II c #4A4A7B7B9C9C",
+"JI c #4A4A7B7B8484",
+"KI c #4A4A6B6B7B7B",
+"LI c #42429C9C7373",
+"MI c #42428C8C7B7B",
+"NI c #42425A5A7373",
+"OI c #42424A4A6B6B",
+"PI c #3939ADAD6B6B",
+"AJ c #3939ADAD5A5A",
+"BJ c #39399C9C6B6B",
+"CJ c #39398484BDBD",
+"DJ c #39397B7BADAD",
+"EJ c #39397B7B8C8C",
+"FJ c #393973737B7B",
+"GJ c #313163637B7B",
+"HJ c #31315A5A7B7B",
+"IJ c #292984846B6B",
+"JJ c #29296B6B7B7B",
+"KJ c #21217B7BB5B5",
+"LJ c #21217373A5A5",
+"MJ c #212173739C9C",
+"NJ c #21216B6B8C8C",
+"OJ c #212152527373",
+"PJ c #181884846363",
+"AK c #18186B6B7B7B",
+"BK c #18185A5A7373",
+"CK c #10106B6B9C9C",
+"DK c #10105A5A8484",
+"EK c #08087B7B6363",
+"FK c #08085A5A7B7B",
+"GK c #00006B6B9C9C",
+"HK c #000063637B7B",
+"IK c #00005A5A8C8C",
+/* pixels */
+"CJAHAHAHAHHILHLHBHLHLJNHNHNHGINHGINHGINHGINHGINHGINHGINHGINHGIKJ",
+"AHAAAAAAAGHDABBBGCBFBFHCPCOCEEHDJDEEJDEEHDJDEEHDJDEEJDEEHDEEJDNH",
+"AHAAAGAAABABABKEOCHCHCPCFEFEABAEHDFCDDJDDDMCJDHDFCHDHDGCDDJDDDLH",
+"EGAEDDABOAABOCEGHCHCPCHCBHJDJDEEJDEEJDEEJDAEJDEEAEJDEEJDEEJDEELH",
+"AHAAAAAAMCJDGCABHCHCBFOCPCJDEEJDEEJDEEAEEEEEAEJDEEFEFEFEEEEEJDGI",
+"AHAAAAPAAGGCABBBMCEGJDNCPCPCEEEEEEEEEEEEEEJDEEEEFEDIPIGFFEFEEENH",
+"EGOAKEAAABPAABKEHCHCHCHCMEBFABJDAEMCOCEEMCMCFEOCDDLEKHIDIDEEDDLH",
+"LHAEMCAAABABAEIFHCHCHCPCBHOCKEKEEEFEEEFEEEFEEEKEBFGEDIKFMEFEEEGI",
+"AHAAAAABGCJDABGCBBOCHGHCPCMDEEFEKEEEFEKEFEKEEEMEBFJFDIGEIFBFFEGI",
+"AHAAAAPAAHGCABBBMCJFMDOCPCJDMEKEKEMEKEKEKEKEMEIFGEFGEIIGJFGEMEGI",
+"AHAAAEAAABABGCNBDBOCNCNCMDEEMCEEEEMCJDKEDDDDLFCIDIEIPICIDIDIJDNH",
+"AHKEDDAAPAABOCKFPBICNCPCHGFEMEMEMEMEHFMEMEIFJFJELCCDCGBBCDLIIGHI",
+"EGAAAAABABJDMBNCPBADGENCMDMDMEHFIFHFMEHFIFMECHJEPCLDBGGDGDLIIGDJ",
+"AHAAAAAAAHEDKAOBEBBDCEODICMDIFIFMEIFIFIFIFIFCHEFLDPDOGGDPDMIFHHI",
+"AHAAOCABMBEABABAFABABAGBNELEHDKEHFDDEEIFJDEEFGCGLDPDPGPDPDAJMFHI",
+"AHDDEGABBBEABACAFABACBGBFHGEIFGGIFGGIFIFGGIFDHCGJEMHFIAFAFBJDHII",
+"AHAAAAABMBEAHAEAEADACABDODBEHGIFGGIFHGGGIFHGCHJHAFAFEFAFFFFJDHMJ",
+"AHAAAAAABEIADADAKACADAGBODNEGGHGIEIENFGGHGGGOHDGFFFFFFFFFFAJOHHI",
+"AHAAABABPCGAKADADAKADAFDODMFHIHIAIPFIIIIHIHIEJCIFFDGFFDGDGJJFJCK",
+"AHAAAHHCMBGAEAEAEAFAFAJCLGFKPEPEPEKDPEPEOIIKHKLIDGDGPGDGIHEKIKGK",
+"EGFCDDAANCJAIAIAIAIAIANDBKOJJBLALALBLAMANGFKHKFIMHPGMHFILIEKFKGK",
+"LHAAAABBNCFBJAJAJAEBGBDFBKOJBCNADCDCIBHBNGBKAKFIMHMHMHMHMHEKHKGK",
+"AHAAAAABADEBJCEBGBACACHEBKNIBCJBJBHBJBJBHHOJJJPIIHPGIHIHIHPJDKGK",
+"AHAAOCJDNCEBOBACOBOBOBHEEJNIKCLBKBBCKBCCKGHJJJMHDGIHPGDGIHEKEJCK",
+"AHAAKEABMBEBDBDBOBOBOBHENIAIKCDCDCDCDCECKGKIGJCIDGFFLGDGDGPJNJMJ",
+"CJAAOAABBBIADBHADBHAKAHEAIBIDCDCBCCCDCCCPFKIJIPGBGCFDGFFDGIJIIMJ",
+"AHAAAAABMBIABADBBAHAHAHEAIGHKCJBBCKBKBBCKGPHJIPGFFGFFFFFFFIJJILJ",
+"AHAAAAABMDFDFDBDFDNDBDHEFHJGDEDEDEDEOEDEOFPHMGBJBJAJBJBJBJMIOHDJ",
+"EGAAAAJDHGNFFHMGFHJGMGEHJGNFNFMGMGMGMGMGLGJGCHEHFHPHMGOHPHFHIGDJ",
+"LHAAOCIFIFIFLFLFMFMFJFLFIFJFHGIGMFIGNFMFMFLFIFLFHGIGFGIGIGHGJFCJ",
+"EGDDKEKEMEBFBFBFBFMEBFBFFEKEMEMEMEGEBFMEBFBFBFKEMEBFMEBFBFKEKEGI",
+"KJLHGINHGINHNHNHNHGINHNHGINHGINHNHGIGINHGINHNHGINHNHGIGINHNHGICJ"};
diff --git a/TheDialog.cpp b/TheDialog.cpp
index 7d94615..d6721ee 100755
--- a/TheDialog.cpp
+++ b/TheDialog.cpp
@@ -39,9 +39,9 @@ char *LoadFile = 0L;
// internal declarations
static int xbase = 2;
static int ybase = 2;
-int dlgtxtheight = 11;
-static unsigned long DlgBGcolor = 0x00c0c0c0L;
-static unsigned long DlgBGhigh = 0x00d0d0d0L;
+int dlgtxtheight = 10;
+static unsigned long DlgBGcolor = 0x00e0e0e0L;
+static unsigned long DlgBGhigh = 0x00e8e8e8L;
TextDEF DlgText = {0x00000000L, 0x00ffffffL, 4.0, 0.0f, 0.0f, 0,
TXA_HLEFT | TXA_VTOP, TXM_TRANSPARENT, TXS_NORMAL, FONT_HELVETICA, 0L};
@@ -64,7 +64,7 @@ DlgRoot::DlgRoot(DlgInfo *tmpl)
dlg = 0L; flags = 0L; tabstops = 0L;
DlgText.iSize = dlgtxtheight; DlgText.ColBg = DlgBGcolor;
type = NONE; Id = -2; cContinue = 0;
- bActive = false; Result = -1;
+ bActive = false; Result = -1; c_go = CurrGO;
CurrDisp = 0L; oldFocus = DialogFocus; DialogFocus = 0L;
oldDefault = DialogDefault; oldTabStop = DialogTabStop;
if(tmpl) {
@@ -137,6 +137,9 @@ DlgRoot::DlgRoot(DlgInfo *tmpl)
case EDTEXT:
dlg[i]->dialog = new InputText(this, &tmpl[i],rc,(char*)tmpl[i].ptype);
break;
+ case RANGEINPUT:
+ dlg[i]->dialog = new RangeInput(this, &tmpl[i],rc,(char*)tmpl[i].ptype);
+ break;
case EDVAL1:
dlg[i]->dialog = new InputValue(this, &tmpl[i],rc,(double*)tmpl[i].ptype);
break;
@@ -214,6 +217,7 @@ DlgRoot::~DlgRoot()
case LTEXT: case RTEXT:
case CTEXT: delete((Text*)dlg[i]->dialog); break;
case EDTEXT: delete((InputText*)dlg[i]->dialog); break;
+ case RANGEINPUT: delete((RangeInput*)dlg[i]->dialog); break;
case EDVAL1: delete((InputValue*)dlg[i]->dialog); break;
case INCDECVAL1: delete((IncDecValue*)dlg[i]->dialog); break;
case TXTHSP: delete((TxtHSP*)dlg[i]->dialog); break;
@@ -240,8 +244,8 @@ DlgRoot::~DlgRoot()
free(dlg);
}
if(tabstops) free(tabstops);
- DialogFocus = oldFocus; DialogDefault = oldDefault;
- DialogTabStop = oldTabStop;
+ DialogFocus = oldFocus; DialogDefault = oldDefault;
+ DialogTabStop = oldTabStop; CurrGO = c_go;
}
bool
@@ -255,6 +259,7 @@ DlgRoot::Command(int cmd, void *tmpl, anyOutput *o)
case CMD_UNDO:
if(CurrDisp) {
Undo.Restore(false, CurrDisp);
+ DoPlot(CurrDisp);
}
return true;
case CMD_REDRAW:
@@ -267,7 +272,6 @@ DlgRoot::Command(int cmd, void *tmpl, anyOutput *o)
mev = (MouseEvent *) tmpl;
switch(mev->Action) {
case MOUSE_LBDOWN:
- DialogFocus = NULL; CurrGO = 0L;
bActive = true;
case MOUSE_MOVE:
if(!(mev->StateFlags & 1))return false;
@@ -279,7 +283,6 @@ DlgRoot::Command(int cmd, void *tmpl, anyOutput *o)
bActive = false; //skip next event (LB up);
return true;
case MOUSE_LBUP:
- CurrGO = 0L;
if(bActive)ForEach(CMD_LBUP, 0, o);
return true;
}
@@ -327,7 +330,7 @@ DlgRoot::Command(int cmd, void *tmpl, anyOutput *o)
d->DoPlot(o);
DialogDefault->DoPlot(o);
break;
- case EDTEXT: case EDVAL1:
+ case EDTEXT: case EDVAL1: case RANGEINPUT:
case INCDECVAL1:
DialogTabStop = DialogFocus = tabstops[i];
if((InputText*)DialogFocus->bActive)
@@ -351,6 +354,7 @@ DlgRoot::Command(int cmd, void *tmpl, anyOutput *o)
DialogDefault->DoPlot(o);
break;
case EDTEXT: case EDVAL1: case INCDECVAL1:
+ case RANGEINPUT:
DialogTabStop = DialogFocus = tabstops[i];
((InputText*)DialogFocus)->Activate(DialogFocus->Id, true);
break;
@@ -363,13 +367,20 @@ DlgRoot::Command(int cmd, void *tmpl, anyOutput *o)
else return CurUpDown(cmd);
case CMD_CURRLEFT: case CMD_CURRIGHT: case CMD_DELETE:
case CMD_POS_FIRST: case CMD_POS_LAST: case CMD_SHIFTLEFT:
- case CMD_SHIFTRIGHT:
+ case CMD_SHIFTRIGHT: case CMD_COPY: case CMD_PASTE:
+ Undo.SetDisp(CurrDisp);
bActive = true;
- if(DialogFocus)return DialogFocus->Command(cmd, tmpl, o);
+ if(DialogFocus)return DialogFocus->Command(cmd, tmpl, CurrDisp);
else return false;
case CMD_ADDCHAR:
if(!tmpl) return false;
bActive = true;
+ if(*((int*)tmpl) == 27) { //Esc
+ HideCopyMark();
+ for (i = 0; dlg[i] && i < cDlgs; i++)
+ if(dlg[i]->dialog) dlg[i]->dialog->Command(cmd, tmpl, o);
+ return Command(CMD_REDRAW, 0L, 0L);
+ }
if(DialogDefault && *((int*)tmpl) == 0x0d){ //return pressed
HideTextCursor();
return DialogDefault->Command(cmd, tmpl, o);
@@ -377,6 +388,7 @@ DlgRoot::Command(int cmd, void *tmpl, anyOutput *o)
if(DialogFocus)return DialogFocus->Command(cmd, tmpl, o);
else return false;
case CMD_UNLOCK:
+ CurrDisp = 0L;
for(i = 0; i < cDlgs; i++)
if(dlg[i] && dlg[i]->dialog) dlg[i]->dialog->Command(CMD_UNLOCK, 0L, 0L);
break;
@@ -389,6 +401,7 @@ DlgRoot::DoPlot(anyOutput *o)
{
int i;
+ HideCopyMark();
if(tabstops) for(i = 0; i < cDlgs; tabstops[i++] = 0);
if(o)CurrDisp = o;
if(CurrDisp) {
@@ -408,7 +421,7 @@ DlgRoot::CurUpDown(int cmd)
for(i = 0; tabstops[i] && i < cDlgs; i++) {
if(tabstops[i] != DialogTabStop) {
switch(tabstops[i]->type) {
- case EDVAL1: case INCDECVAL1: case EDTEXT:
+ case EDVAL1: case INCDECVAL1: case EDTEXT: case RANGEINPUT:
if(rTxtCur.left > tabstops[i]->cr.left &&
rTxtCur.right < tabstops[i]->cr.right) {
if((dy = (tabstops[i]->cr.top - rTxtCur.top))< 0) {
@@ -764,6 +777,7 @@ PushButton::Command(int cmd, void *tmpl, anyOutput *o)
{
switch(cmd) {
case CMD_ADDCHAR:
+ HideCopyMark();
if(parent && *((int*)tmpl) == 0x0d) //return pressed
parent->Command(CMD_ENDDIALOG, (void *)this, o);
return true;
@@ -778,8 +792,7 @@ PushButton::DoPlot(anyOutput *o)
Line.color = 0x00000000L;
Fill.color = DlgBGhigh;
- o->SetLine(&Line);
- o->SetFill(&Fill);
+ o->SetLine(&Line); o->SetFill(&Fill);
if(bLBdown) o->oRectangle(cr.left, cr.top, cr.right, cr.bottom);
else {
o->oRectangle(cr.left, cr.top, cr.right-1, cr.bottom-1);
@@ -1702,13 +1715,13 @@ Text::SetColor(int id, DWORD color)
InputText::InputText(tag_DlgObj *par, DlgInfo * desc, RECT rec, char *text)
:Dialog(par, desc, rec)
{
- POINT p1, p2;
+ RECT rc;
- p1.x = rec.left+1; p1.y = rec.top+1;
- p2.x = rec.right-1; p2.y = rec.bottom-1;
- if(type == INCDECVAL1) cr.right = p2.x = cr.right - 7*xbase;
+ rc.left = rec.left+1; rc.top = rec.top+1;
+ rc.right = rec.right-1; rc.bottom = rec.bottom-1;
+ if(type == INCDECVAL1) cr.right = rc.right = cr.right - 7*xbase;
Line.color = 0x00000000L;
- Text = new EditText(0L, p1, p2, text);
+ if(Text = new EditText(0L, text, -1, -1)) Text->SetRec(&rc);
Disp = 0L;
}
@@ -1737,6 +1750,12 @@ InputText::Command(int cmd, void *tmpl, anyOutput *o)
case CMD_SETFONT: case CMD_SETSTYLE:
if(Text) return Text->Command(cmd, o, tmpl);
return false;
+ case CMD_UPDATE:
+ if(Text && bActive && o) Text->Command(cmd, o, 0L);
+ break;
+ case CMD_COPY: case CMD_PASTE:
+ if(Text && bActive && !(flags & NOEDIT)) return Text->Command(cmd, o, NULL);
+ return false;
case CMD_ADDCHAR:
if(Text && bActive && !(flags & NOEDIT)){
if(flags & TOUCHEXIT) parent->Command(CMD_ENDDIALOG, (void *)this, o);
@@ -1748,12 +1767,7 @@ InputText::Command(int cmd, void *tmpl, anyOutput *o)
}
return false;
case CMD_SETTEXT:
- if(Text) {
- if(Text->text) free(Text->text);
- if(tmpl)Text->text = strdup((char*)tmpl);
- else Text->text = 0L;
- return false;
- }
+ if(Text) return Text->SetText((char*)tmpl);
break;
case CMD_ENDDIALOG: //we should come here for IncDecValue class only
if(type == INCDECVAL1 && GetValue(Id, &tmpVal)) {
@@ -1782,6 +1796,7 @@ InputText::DoPlot(anyOutput *o)
{
POINT pts[5];
+ if(!o) return;
Disp = o;
pts[0].x = pts[0].y = 0; //that means no caret with update(5)
o->SetTextSpec(&TextDef);
@@ -1808,6 +1823,7 @@ InputText::Select(int x, int y, anyOutput *o)
o->SetTextSpec(&TextDef);
if(Text) Text->Update(1, o, &p1);
if(flags & TOUCHEXIT) parent->Command(CMD_ENDDIALOG, (void *)this, o);
+ return true;
}
return false;
}
@@ -1880,6 +1896,49 @@ InputText::Activate(int id, bool activate)
}
}
+RangeInput::RangeInput(tag_DlgObj *par, DlgInfo * desc, RECT rec, char *text)
+ :InputText(par, desc, rec, text)
+{
+ data = 0L;
+}
+
+RangeInput::~RangeInput()
+{
+ if(data) data->Command(CMD_ETRACC, 0L, 0L);
+ if(Text) delete (Text); Text = 0L;
+}
+
+bool
+RangeInput::Command(int cmd, void *tmpl, anyOutput *o)
+{
+ switch(cmd) {
+ case CMD_SET_DATAOBJ:
+ data = (DataObj*)tmpl;
+ return true;
+ }
+ return InputText::Command(cmd, tmpl, o);
+}
+
+bool
+RangeInput::Select(int x, int y, anyOutput *o)
+{
+ bool bRes;
+
+ bRes = InputText::Select(x, y, o);
+ if(bRes && data) {
+ if(DialogFocus == this) data->Command(CMD_ETRACC, Text, 0L);
+ else data->Command(CMD_ETRACC, 0L, 0L);
+ }
+ return bRes;
+}
+
+void
+RangeInput::Activate(int id, bool activate)
+{
+ InputText::Activate(id, activate);
+ if(activate && data) data->Command(CMD_ETRACC, Text, 0L);
+}
+
InputValue::InputValue(tag_DlgObj *par, DlgInfo * desc, RECT rec, double *value)
:InputText(par, desc, rec, 0L)
{
@@ -2455,7 +2514,7 @@ Group::Command(int cmd, void *tmpl, anyOutput *o)
case CMD_ADDCHILD:
if(Children && numChildren && (d = (Dialog*)tmpl)) {
d->parent = this;
- if(!TextFocus &&(d->type == EDTEXT ||
+ if(!TextFocus &&(d->type == EDTEXT || d->type == RANGEINPUT ||
d->type == INCDECVAL1 || d->type == EDVAL1))
TextFocus = ((InputText*)tmpl)->bActive ? (InputText*)tmpl: 0L ;
for(i = 0; i < numChildren; i++) {
@@ -2601,7 +2660,7 @@ TabSheet::DoPlot(anyOutput *o)
pts[2].x = rctab.left + (rctab.bottom - rctab.top)/2;
pts[2].y = pts[3].y = rctab.top;
pts[3].x = pts[4].x = rctab.right-1;
-
+ HideCopyMark();
Line.color = 0x00000000L;
Line.width = 0.0;
Fill.color = bChecked ? DlgBGhigh : DlgBGcolor;
@@ -2616,7 +2675,11 @@ TabSheet::DoPlot(anyOutput *o)
o->oSolidLine(pts+4);
}
o->SetTextSpec(&TextDef);
- o->oTextOut(rctab.right - 6, rctab.top + 1, Text, 0);
+#ifdef _WINDOWS
+ o->oTextOut(rctab.right - 6, rctab.top + 3, Text, 0);
+#else
+ o->oTextOut(rctab.right - 6, rctab.top + 5, Text, 0);
+#endif
Group::DoPlot(o);
o->UpdateRect(&cr, false);
}
@@ -2730,7 +2793,7 @@ Listbox::Command(int cmd, void *tmpl, anyOutput *o)
double ps;
char *txt;
- ps = ((double)(cr.bottom - cr.top))/((double)(bmh+TextDef.iSize+1));
+ ps = ((double)(cr.bottom - cr.top))/((double)(bmh+TextDef.iSize+_SBINC));
switch(cmd) {
case CMD_REDRAW:
DoPlot(o);
@@ -2777,12 +2840,12 @@ Listbox::DoPlot(anyOutput *o)
}
o->CopyBitmap(hcr.left+1, hcr.top+1, bmp, 0, startY, (hcr.right-hcr.left)-2,
(hcr.bottom-hcr.top)-2, false);
- mrk.left = hcr.left+2; mrk.top = (cl)*TextDef.iSize - startY + hcr.top;
- mrk.right = hcr.right-2; mrk.bottom = mrk.top + TextDef.iSize;
+ mrk.left = hcr.left+2; mrk.top = (cl)*(TextDef.iSize+_SBINC) - startY + hcr.top;
+ mrk.right = hcr.right-2; mrk.bottom = mrk.top + (TextDef.iSize+_SBINC);
if(mrk.bottom > (hcr.top+1) && mrk.top < (hcr.bottom-1)){
if(mrk.top < (hcr.top+1)) mrk.top = hcr.top+1;
if(mrk.bottom > (hcr.bottom-1)) mrk.bottom = hcr.bottom-1;
- o->CopyBitmap(mrk.left, mrk.top, bmp, 1, cl*TextDef.iSize,
+ o->CopyBitmap(mrk.left, mrk.top, bmp, 1, cl*(TextDef.iSize+_SBINC),
(hcr.right-hcr.left)-4, mrk.bottom-mrk.top, true);
}
o->UpdateRect(&cr, false);
@@ -2795,17 +2858,17 @@ Listbox::Select(int x, int y, anyOutput *o)
RECT mrk;
if(IsInRect(&hcr, x, y)) {
- il = (y+startY-hcr.top)/TextDef.iSize;
+ il = (y+startY-hcr.top)/(TextDef.iSize+_SBINC);
if(il >= ns || il < 0){
o->UpdateRect(&hcr, false);
return false;
}
cl = il;
- mrk.left = hcr.left+2; mrk.top = (il)*TextDef.iSize - startY + hcr.top;
- mrk.right = hcr.right-2; mrk.bottom = mrk.top + TextDef.iSize;
+ mrk.left = hcr.left+2; mrk.top = (il)*(TextDef.iSize+_SBINC) - startY + hcr.top;
+ mrk.right = hcr.right-2; mrk.bottom = mrk.top + (TextDef.iSize+_SBINC);
o->CopyBitmap(hcr.left+1, hcr.top+1, bmp, 0, startY, (hcr.right-hcr.left)-2,
(hcr.bottom-hcr.top)-2, false);
- o->CopyBitmap(mrk.left, mrk.top, bmp, 1, (cl)*TextDef.iSize,
+ o->CopyBitmap(mrk.left, mrk.top, bmp, 1, (cl)*(TextDef.iSize+_SBINC),
(hcr.right-hcr.left)-4, mrk.bottom-mrk.top, true);
o->UpdateRect(&hcr, false);
if((flags & TOUCHEXIT) && parent)
@@ -2847,13 +2910,13 @@ Listbox::CreateBitMap(anyOutput *tmpl)
if(bmp) DelBitmapClass(bmp);
bmp = 0L;
if(tmpl && strings) {
- h = TextDef.iSize * ns; w = (hcr.right - hcr.left);
+ h = (TextDef.iSize+_SBINC) * ns; w = (hcr.right - hcr.left);
if(bmp = NewBitmapClass(w, h, tmpl->hres, tmpl->vres)){
bmp->Erase(0x00ffffffL);
bmp->SetTextSpec(&TextDef);
- bmh = h - TextDef.iSize;
+ bmh = h - (TextDef.iSize+_SBINC);
for(i = 0; i < ns; i++) {
- bmp->oTextOut(5, i*TextDef.iSize, strings[i], 0);
+ bmp->oTextOut(5, i*(TextDef.iSize+_SBINC), strings[i], 0);
}
return true;
}
@@ -2891,7 +2954,7 @@ Treeview::Command(int cmd, void *tmpl, anyOutput *o)
{
double ps;
- ps = ((double)(cr.bottom - cr.top))/((double)(bmh+TextDef.iSize+1));
+ ps = ((double)(cr.bottom - cr.top))/((double)(bmh+TextDef.iSize+_SBINC));
switch(cmd) {
case CMD_LAYERS:
ot->Command(cmd, tmpl, o);
@@ -2942,12 +3005,12 @@ Treeview::DoPlot(anyOutput *o)
}
o->CopyBitmap(hcr.left+1, hcr.top+1, bmp, 0, startY, (hcr.right-hcr.left)-2,
(hcr.bottom-hcr.top)-2, false);
- mrk.left = hcr.left+2; mrk.top = (cl)*TextDef.iSize - startY + hcr.top;
- mrk.right = hcr.right-2; mrk.bottom = mrk.top + TextDef.iSize;
+ mrk.left = hcr.left+2; mrk.top = (cl)*(TextDef.iSize+_SBINC) - startY + hcr.top;
+ mrk.right = hcr.right-2; mrk.bottom = mrk.top + (TextDef.iSize+_SBINC);
if(mrk.bottom > (hcr.top+1) && mrk.top < (hcr.bottom-1)){
if(mrk.top < (hcr.top+1)) mrk.top = hcr.top+1;
if(mrk.bottom > (hcr.bottom-1)) mrk.bottom = hcr.bottom-1;
- o->CopyBitmap(mrk.left, mrk.top, bmp, 1, cl*TextDef.iSize,
+ o->CopyBitmap(mrk.left, mrk.top, bmp, 1, cl*(TextDef.iSize+_SBINC),
(hcr.right-hcr.left)-4, mrk.bottom-mrk.top, true);
}
o->UpdateRect(&cr, false);
@@ -2960,17 +3023,17 @@ Treeview::Select(int x, int y, anyOutput *o)
RECT mrk;
if(IsInRect(&hcr, x, y)) {
- il = (y+startY-hcr.top)/TextDef.iSize;
+ il = (y+startY-hcr.top)/(TextDef.iSize+_SBINC);
if(il >= ns || il < 0){
o->UpdateRect(&hcr, false);
return false;
}
cl = il;
- mrk.left = hcr.left+2; mrk.top = (il)*TextDef.iSize - startY + hcr.top;
- mrk.right = hcr.right-2; mrk.bottom = mrk.top + TextDef.iSize;
+ mrk.left = hcr.left+2; mrk.top = (il)*(TextDef.iSize+_SBINC) - startY + hcr.top;
+ mrk.right = hcr.right-2; mrk.bottom = mrk.top + (TextDef.iSize+_SBINC);
o->CopyBitmap(hcr.left+1, hcr.top+1, bmp, 0, startY, (hcr.right-hcr.left)-2,
(hcr.bottom-hcr.top)-2, false);
- o->CopyBitmap(mrk.left, mrk.top, bmp, 1, (cl)*TextDef.iSize,
+ o->CopyBitmap(mrk.left, mrk.top, bmp, 1, (cl)*(TextDef.iSize+_SBINC),
(hcr.right-hcr.left)-4, mrk.bottom-mrk.top, true);
o->UpdateRect(&hcr, false);
if((flags & TOUCHEXIT) && parent)
@@ -3404,7 +3467,8 @@ bool ShowLayers(GraphObj *root)
}
if((cgo = ot->get_obj(cl)) && cgo->parent) {
if(cgo->parent->Id == GO_STACKBAR || cgo->parent->Id == GO_STACKPG ||
- cgo->parent->Id == GO_WATERFALL) {
+ cgo->parent->Id == GO_WATERFALL || cgo->parent->Id == GO_PLOT3D ||
+ cgo->parent->Id == GO_FUNC3D) {
Dlg->ShowItem(501, true);
}
else if(cgo->parent->Id == GO_GRAPH || cgo->parent->Id == GO_PAGE){
@@ -3503,7 +3567,7 @@ void RLPlotInfo()
{4, 5, 0, 0x0L, CTEXT, (void*)"scientific plotting program", 10, 30, 100, 8},
{5, 6, 0, 0x0L, CTEXT, (void*)"version "SZ_VERSION, 10, 38, 100, 8},
{6, 7, 0, HREF, CTEXT, (void*)"http://rlplot.sourceforge.net/", 5, 46, 110, 8},
- {7, 8, 0, 0x0L, CTEXT, (void*)"Copyright (C) 2002-2004 R. Lackner", 5, 54, 110, 8},
+ {7, 8, 0, 0x0L, CTEXT, (void*)"Copyright (C) 2002-2005 R. Lackner", 5, 54, 110, 8},
{8, 9, 0, 0x0L, CTEXT, (void*)"reinhard.lackner at uibk.ac.at", 5, 62, 110, 9},
{9, 10, 0, 0x0L, CTEXT, (void*)"This is free software published", 5, 80, 110, 8},
{10, 11, 0, 0x0L, CTEXT, (void*)"under the GNU general public.", 5, 88, 110, 8},
@@ -3517,7 +3581,7 @@ void RLPlotInfo()
{4, 5, 0, 0x0L, CTEXT, (void*)"scientific plotting program", 10, 30, 100, 8},
{5, 6, 0, 0x0L, CTEXT, (void*)"version "SZ_VERSION, 10, 38, 100, 8},
{6, 7, 0, HREF, CTEXT, (void*)"http://rlplot.sourceforge.net/", 5, 46, 110, 8},
- {7, 8, 0, 0x0L, CTEXT, (void*)"Copyright (C) 2002-2004 R. Lackner", 5, 54, 110, 8},
+ {7, 8, 0, 0x0L, CTEXT, (void*)"Copyright (C) 2002-2005 R. Lackner", 5, 54, 110, 8},
{8, 9, 0, 0x0L, CTEXT, (void*)"reinhard.lackner at uibk.ac.at", 5, 62, 110, 9},
{9, 10, 0, 0x0L, LTEXT, (void*)"powered by Trolltech\'s Qt", 35, 72, 80, 8},
{10, 11, 0, HREF, LTEXT, (void*)"http://www.trolltech.com", 35, 80, 80, 9},
@@ -3564,7 +3628,7 @@ DoSpShSize(DataObj *dt)
TabSHEET tab1 = {0, 45, 10, "Dimensions"};
TabSHEET tab2 = {45, 105, 10, "Width and Height"};
char txt1[40], txt2[40];
- double fw, cw, ch;
+ double fw, cw, ch, th;
DlgInfo SSDlg[] = {
{1, 2, 0, DEFAULT, PUSHBUTTON, (void*)"OK", 115, 10, 40, 12},
{2, 3, 0, 0x0L, PUSHBUTTON, (void*)"Cancel", 115, 25, 40, 12},
@@ -3575,33 +3639,35 @@ DoSpShSize(DataObj *dt)
{101, 102, 0, 0x0L, EDTEXT, txt1, 40, 37, 40, 10},
{102, 103, 0, 0x0L, LTEXT, (void*)"number of rows:", 15, 52, 60, 8},
{103, 0, 0, 0x0L, EDTEXT, txt2, 40, 64, 40, 10},
- {200, 201, 0, 0x0L, RTEXT, (void*)"row buttons", 10, 34, 40, 8},
- {201, 202, 0, 0x0L, EDVAL1, &fw, 52, 34, 25, 10},
- {202, 203, 0, 0x0L, LTEXT, (void*)"[digits]", 79, 34, 20, 8},
- {203, 204, 0, 0x0L, RTEXT, (void*)"column width", 10, 49, 40, 8},
- {204, 205, 0, 0x0L, EDVAL1, &cw, 52, 49, 25, 10},
- {205, 206, 0, 0x0L, LTEXT, (void*)"[digits]", 79, 49, 20, 8},
- {206, 207, 0, 0x0L, RTEXT, (void*)"text size", 10, 64, 40, 8},
- {207, 208, 0, 0x0L, EDVAL1, &ch, 52, 64, 25, 10},
- {208, 0, 0, LASTOBJ, LTEXT, (void *) Units[defs.cUnits].display, 79, 64, 20, 8}};
+ {200, 201, 0, 0x0L, RTEXT, (void*)"row buttons", 10, 29, 40, 8},
+ {201, 202, 0, 0x0L, EDVAL1, &fw, 52, 29, 25, 10},
+ {202, 203, 0, 0x0L, LTEXT, (void*)"[digits]", 79, 29, 20, 8},
+ {203, 204, 0, 0x0L, RTEXT, (void*)"column width", 10, 44, 40, 8},
+ {204, 205, 0, 0x0L, EDVAL1, &cw, 52, 44, 25, 10},
+ {205, 206, 0, 0x0L, LTEXT, (void*)"[digits]", 79, 44, 20, 8},
+ {206, 207, 0, 0x0L, RTEXT, (void*)"row height", 10, 59, 40, 8},
+ {207, 208, 0, 0x0L, EDVAL1, &ch, 52, 59, 25, 10},
+ {208, 209, 0, 0x0L, LTEXT, (void *) Units[defs.cUnits].display, 79, 59, 20, 8},
+ {209, 210, 0, 0x0L, RTEXT, (void*)"text size", 10, 74, 40, 8},
+ {210, 211, 0, 0x0L, INCDECVAL1, &th, 52, 74, 33, 10},
+ {211, 0, 0, LASTOBJ, LTEXT, (void *)"%", 87, 74, 20, 8}};
DlgRoot *Dlg;
void *hDlg;
- int w1, w2, h1, h2, res, celldim[3];
+ int w1, w2, h1, h2, res, celldim[3], ith;
bool bRet = false;
- double fw1, cw1, ch1;
+ double fw1, cw1, ch1, th1;
if(!dt || !dt->GetSize(&w1, &h1)) return false;
dt->Command(CMD_GET_CELLDIMS, &celldim, 0L);
- fw1 = fw = NiceValue(((double)celldim[0])/((double)(celldim[2]-3)/2.0));
- cw1 = cw = NiceValue(((double)celldim[1])/((double)(celldim[2]-3)/2.0));
+ fw1 = fw = NiceValue(((double)celldim[0])/((double)(celldim[2]-2)/2.0));
+ cw1 = cw = NiceValue(((double)celldim[1])/((double)(celldim[2]-2)/2.0));
switch(defs.cUnits) {
case 1: ch = NiceValue(((double)(celldim[2]-2))*0.0259183673); break;
case 2: ch = NiceValue(((double)(celldim[2]-2))/98.0); break;
default: ch = NiceValue(((double)(celldim[2]-2))*0.259183673); break;
}
- ch1 = ch;
- sprintf(txt1, "%d", w1);
- sprintf(txt2, "%d", h1);
+ ch1 = ch; th = th1 = defs.ss_txt*100.0;
+ sprintf(txt1, "%d", w1); sprintf(txt2, "%d", h1);
Dlg = new DlgRoot(SSDlg);
hDlg = CreateDlgWnd("Change spread sheet settings", 50, 50, 320, 220, Dlg, 0x0L);
Dlg->GetValue(201, &fw1); Dlg->GetValue(204, &cw1); Dlg->GetValue(207, &ch1);
@@ -3619,14 +3685,20 @@ DoSpShSize(DataObj *dt)
}
}while(res <0);
if(res == 1){
- Dlg->GetValue(207, &ch);
- if(ch != ch1 && ch > 0.001) {
+ if(Dlg->GetValue(207, &ch) && Dlg->GetValue(210, &th) && ch > 0.001) {
+ defs.ss_txt = th = th >= 10.0 && th <= 100 ? th/100.0 : 1.0;
switch(defs.cUnits) {
- case 1: celldim[2] = iround(ch/0.0259183673)+2; break;
- case 2: celldim[2] = iround(ch*98.0)+2; break;
- default: celldim[2] = iround(ch/0.259183673)+2; break;
+ case 1:
+ celldim[2] = iround(ch/0.0259183673)+2; ith = iround(th * ch/0.0259183673);
+ break;
+ case 2:
+ celldim[2] = iround(ch*98.0)+2; ith = iround(th * ch*98.0);
+ break;
+ default:
+ celldim[2] = iround(ch/0.259183673)+2; ith = iround(th * ch/0.259183673);
+ break;
}
- dt->Command(CMD_TEXTSIZE, (void*)(& celldim[2]), 0L);
+ bRet = dt->Command(CMD_TEXTSIZE, (void*)(& ith), 0L);
}
Dlg->GetValue(201, &fw); Dlg->GetValue(204, &cw);
if(fw >0.001 && (fw != fw1 || ch != ch1))
@@ -3644,50 +3716,8 @@ DoSpShSize(DataObj *dt)
return bRet;
}
-bool GetCopyRange(RECT *rc, DataObj *d)
-{
- char text1[80];
- DlgInfo CopyDlg[] = {
- {1, 2, 0, DEFAULT, PUSHBUTTON, (void*)"OK", 115, 5, 40, 12},
- {2, 3, 0, 0x0L, PUSHBUTTON, (void*)"Cancel", 115, 20, 40, 12},
- {3, 4, 0, 0x0L, PUSHBUTTON, (void*)"copy all", 115, 40, 40, 12},
- {4, 5, 0, 0x0L, LTEXT, (void*)"enter range to copy from:", 10, 10, 80, 9},
- {5, 0, 0, 0x0L, EDTEXT, text1, 10, 25, 90, 10},
- {800, 0, 0, LASTOBJ, NONE, 0L, 0, 0, 0, 0}};
- DlgRoot *Dlg;
- void *hDlg;
- int r = rc->left, c = rc->top, res, width = 1, height = 1;
- bool bRet = false;
- AccRange *rC;
- sprintf(TmpTxt, "%s", Int2ColLabel(rc->right-1, false));
- sprintf(text1, "%s%d:%s%d", Int2ColLabel(rc->left, false), rc->top+1, TmpTxt, rc->bottom);
- if(d) d->GetSize(&width, &height);
- if(!(Dlg = new DlgRoot(CopyDlg))) return false;
- hDlg = CreateDlgWnd("Copy data", 50, 50, 322, 140, Dlg, 0x0L);
- do{
- LoopDlgWnd();
- res = Dlg->GetResult();
- switch (res){
- case 3:
- sprintf(text1, "a1:%s%d", Int2ColLabel(width-1, false), height);
- Dlg->SetText(5, text1);
- Dlg->DoPlot(0L);
- res = -1;
- break;
- }
- }while(res <0);
- if(res == 1 && Dlg->GetText(5, TmpTxt) && (rC = new AccRange(TmpTxt))) {
- if(rC->CountItems() >0) {
- bRet = true; rC->BoundRec(rc);
- }
- delete rC;
- }
- CloseDlgWnd(hDlg); delete Dlg;
- return bRet;
-}
-
-bool FillSsRange(DataObj *d, char **range)
+bool FillSsRange(DataObj *d, char **range, GraphObj *msg_go)
{
TabSHEET tab1 = {0, 37, 10, "fill range "};
char *ra = range ? *range:0L;
@@ -3702,10 +3732,10 @@ bool FillSsRange(DataObj *d, char **range)
{2, 3, 0, 0x0L, PUSHBUTTON, (void*)"Cancel", 162, 20, 38, 12},
{3, 0, 5, CHECKED, GROUP, 0L, 0, 0, 0, 0},
{5, 0, 6, ISPARENT | CHECKED, SHEET, &tab1, 5, 10, 150, 75},
- {6, 7, 0, 0x0L, EDTEXT, (void*)ra, 10, 25, 140, 10},
+ {6, 7, 0, 0x0L, RANGEINPUT, (void*)ra, 10, 25, 140, 10},
{7, 8, 0, CHECKED | TOUCHEXIT, RADIO1, (void*)"with values", 10, 37, 45, 8},
{8, 9, 0, TOUCHEXIT, RADIO1, (void*)"with formulas", 60, 37, 60, 8},
- {9, 10, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {9, 10, 0, CHECKED, CHECKPIN, 0L, 5, 0, 12, 8},
{10, 20, 11, CHECKED, GROUP, 0L, 0, 0, 0, 0},
{11, 12, 0, 0x0L, RTEXT, (void*)"start value=", 10, 60, 35, 8},
{12, 13, 0, 0x0L, EDVAL1, &startval, 45, 60, 30, 10},
@@ -3721,9 +3751,12 @@ bool FillSsRange(DataObj *d, char **range)
int i, res, row, col, r1, c1;
bool bRet = false, bContinue = false;
AccRange *rF;
+ RECT rc_dest;
+ anyOutput *cdisp = Undo.cdisp;
if(!d || !range) return false;
if(!(Dlg = new DlgRoot(RangeDlg))) return false;
+ Dlg->ItemCmd(6, CMD_SET_DATAOBJ, d);
#ifdef _WINDOWS
for(i = 23; i <= 24; i++) Dlg->TextSize(i, 12);
#else
@@ -3747,6 +3780,7 @@ bool FillSsRange(DataObj *d, char **range)
bContinue = true; res = -1;
}
else ra = strdup(TmpTxt);
+ rc_dest.left = rc_dest.right = rc_dest.top = rc_dest.bottom = 0;
break;
case 7:
Dlg->ShowItem(10, true); Dlg->ShowItem(20, false);
@@ -3762,10 +3796,13 @@ bool FillSsRange(DataObj *d, char **range)
break;
}
}while(res <0);
+ Undo.SetDisp(cdisp);
if(res == 1 && ra) {
if(Dlg->GetCheck(7)) {
Dlg->GetValue(12, &startval); Dlg->GetValue(14, &stepval);
if((rF = new AccRange(ra)) && rF->GetFirst(&col, &row)) {
+ rF->BoundRec(&rc_dest);
+ Undo.DataObject(msg_go, Undo.cdisp, d, &rc_dest, 0L);
for( ; rF->GetNext(&col, &row); startval += stepval) {
d->SetValue(row, col, startval);
}
@@ -3778,8 +3815,11 @@ bool FillSsRange(DataObj *d, char **range)
Dlg->GetText(22, TmpTxt) && (formula = strdup(TmpTxt))){
r1 = row; c1 = col;
for( ; rF->GetNext(&col, &row); startval += stepval) {
- MoveFormula(d, formula, TmpTxt, col-c1, row-r1);
- d->SetText(row, col, TmpTxt);
+ if(formula[0] == '=') {
+ MoveFormula(d, formula, TmpTxt, col-c1, row-r1, -1, -1);
+ d->SetText(row, col, TmpTxt);
+ }
+ else d->SetText(row, col, formula);
}
delete rF; bRet = true;
}
diff --git a/TheDialog.h b/TheDialog.h
index d3ea251..e41ffcf 100755
--- a/TheDialog.h
+++ b/TheDialog.h
@@ -39,7 +39,7 @@ typedef struct {
//types of dialogs
enum {NONE, PUSHBUTTON, ARROWBUTT, COLBUTTON, FILLBUTTON, SHADE3D, LINEBUTT, SYMBUTT,
FILLRADIO, SYMRADIO, CHECKBOX, RADIO0, RADIO1, RADIO2, LTEXT, RTEXT, CTEXT, EDTEXT,
- EDVAL1, INCDECVAL1, HSCROLL, VSCROLL, TXTHSP, ICON, GROUP,
+ RANGEINPUT, EDVAL1, INCDECVAL1, HSCROLL, VSCROLL, TXTHSP, ICON, GROUP,
GROUPBOX, SHEET, ODBUTTON, LISTBOX1, TREEVIEW, LINEPAT, TEXTBOX, CHECKPIN, TRASH,
CONFIG};
@@ -136,6 +136,7 @@ private:
int cDlgs, Result, cContinue;
Dialog *oldFocus, *oldDefault, *oldTabStop;
bool bActive;
+ GraphObj *c_go;
Dialog **tabstops;
DlgTmpl **dlg;
MouseEvent *mev;
@@ -320,19 +321,31 @@ public:
InputText(tag_DlgObj *par, DlgInfo * desc, RECT rec, char *text);
~InputText();
- bool Command(int cmd, void *tmpl, anyOutput *o);
+ virtual bool Command(int cmd, void *tmpl, anyOutput *o);
virtual void DoPlot(anyOutput *o);
virtual bool Select(int x, int y, anyOutput *o);
bool GetValue(int id, double *val);
bool GetInt(int id, int *val);
bool GetText(int id, char *txt);
virtual void MBtrack(MouseEvent *mev, anyOutput *o);
- void Activate(int id, bool active);
+ virtual void Activate(int id, bool active);
private:
anyOutput *Disp;
};
+class RangeInput:public InputText {
+public:
+ RangeInput(tag_DlgObj *par, DlgInfo * desc, RECT rec, char *text);
+ ~RangeInput();
+ bool Command(int cmd, void *tmpl, anyOutput *o);
+ bool Select(int x, int y, anyOutput *o);
+ void Activate(int id, bool active);
+
+private:
+ DataObj *data;
+};
+
class InputValue:public InputText {
public:
InputValue(tag_DlgObj *par, DlgInfo * desc, RECT rec, double *value);
diff --git a/UtilObj.cpp b/UtilObj.cpp
index c604c25..7950b37 100755
--- a/UtilObj.cpp
+++ b/UtilObj.cpp
@@ -33,16 +33,19 @@
Default defs;
-static LineDEF ETbgnn = {0.0f, 1.0f, 0x00d8d8d8L, 0L};
-static LineDEF ETbgna = {0.0f, 1.0f, 0x00ffffffL, 0L};
-static LineDEF ETbgmn = {0.0f, 1.0f, 0x00000000L, 0L};
-static LineDEF ETbgma = {0.0f, 1.0f, 0x00ffff00L, 0L};
-extern const LineDEF BlackLine = {0.0f, 1.0f, 0x00000000L, 0L};
-
-static FillDEF ETfbnn = {FILL_NONE, 0x00d8d8d8L, 1.0f, NULL, 0x00ffffffL};
-static FillDEF ETfbna = {FILL_NONE, 0x00ffffffL, 1.0f, NULL, 0x00ffffffL};
-static FillDEF ETfbmn = {FILL_NONE, 0x00000000L, 1.0f, NULL, 0x00ffffffL};
-static FillDEF ETfbma = {FILL_NONE, 0x00ffff00L, 1.0f, NULL, 0x00ffffffL};
+static LineDEF ETbgnn = {0.0, 1.0, 0x00e8e8e8L, 0L};
+static LineDEF ETbgna = {0.0, 1.0, 0x00ffffffL, 0L};
+static LineDEF ETbgmn = {0.0, 1.0, 0x00cbcbcbL, 0L};
+static LineDEF ETbgma = {0.0, 1.0, 0x00ffffc0L, 0L};
+static LineDEF yLine = {0.0, 1.0, 0x0000ffffL, 0L};
+extern const LineDEF BlackLine = {0.0, 1.0, 0x00000000L, 0L};
+extern const LineDEF GrayLine = {0.0, 1.0, 0x00c0c0c0L, 0L};
+
+static FillDEF ETfbnn = {FILL_NONE, 0x00e8e8e8L, 1.0, NULL, 0x00ffffffL};
+static FillDEF ETfbna = {FILL_NONE, 0x00ffffffL, 1.0, NULL, 0x00ffffffL};
+static FillDEF ETfbmn = {FILL_NONE, 0x00e8cbcbL, 1.0, NULL, 0x00ffffffL};
+static FillDEF ETfbma = {FILL_NONE, 0x00ffffc0L, 1.0, NULL, 0x00ffffffL};
+static FillDEF yFill = {FILL_NONE, 0x0000ffffL, 1.0, NULL, 0x0000ffffL};
extern char TmpTxt[500];
extern unsigned long cObsW; //count objects written
@@ -56,33 +59,29 @@ extern UndoObj Undo;
EditText *CurrText = 0L, *scroll_et = 0;
int scroll_dist = 0;
-EditText::EditText(void *par, POINT where, POINT right, char *msg)
-{
- loc.x = where.x; loc.y = where.y;
- crb.x = rb.x = right.x; crb.y = rb.y = right.y;
- if(msg && msg[0]) text = strdup(msg);
- else text = 0L; Value = 0.0;
- CursorPos = length = Align = 0; type = ET_UNKNOWN; TextCol=0x00000000L;
- bgLine = &ETbgnn; bgFill = &ETfbnn; parent = par;
- FindType();
- m1 = m2 = -1; //cursor positions track marks
-}
-
-EditText::EditText(void *par, char *msg)
+EditText::EditText(void *par, char *msg, int r, int c)
{
loc.x = loc.y = crb.x = rb.x = crb.y = rb.y = 0; Value = 0.0;
- if(msg && msg[0]) text = strdup(msg);
- else text = 0L;
+ row = r; col = c; disp = 0L; text = 0L;
CursorPos = length = Align = 0; type = ET_UNKNOWN; TextCol=0x00000000L;
bgLine = &ETbgnn; bgFill = &ETfbnn; parent = par;
- FindType();
+ if(msg && msg[0]) {
+ SetText(msg); FindType();
+ }
+ else {
+ Align = TXA_VCENTER | TXA_HRIGHT;
+ type = ET_UNKNOWN;
+ }
m1 = m2 = -1; //cursor positions track marks
+ ftext = 0L; //store formula text result here
}
EditText::~EditText()
{
+ HideCopyMark();
if(CurrText == this) CurrText = 0L;
if(text) free(text); text = 0L;
+ if(ftext) free(ftext); ftext = 0L;
}
bool
@@ -97,30 +96,42 @@ EditText::AddChar(int ci, anyOutput *Out, void *data_obj)
m1 = m2 = -1; Redraw(Out, true); return true;
}
else return false;
+ if(parent) {
+ ((DataObj*)parent)->Command(CMD_MRK_DIRTY, 0L, 0L);
+ ((DataObj*)parent)->Command(CMD_SAVEPOS, 0L, 0L);
+ }
Undo.TextCell(this, Out, text, &CursorPos, &m1, &m2, parent, 0L);
+ bgLine = &ETbgna; bgFill = &ETfbna; TextCol = 0x00000000L;
if(text)length = strlen(text);
else length = 0;
if(text) tmp = (char *)realloc(text, length+2);
else tmp = (char *)calloc(2, sizeof(char));
if(!tmp) return false;
text = tmp;
- if(parent) ((DataObj*)parent)->Command(CMD_MRK_DIRTY, 0L, 0L);
byte1 = byte2 = 0;
//replace mark by character if mark exists
- if(m1 > -1 && m2 > -1) Command(CMD_DELETE, (anyOutput *)0L, (DataObj *)0L);
+ if(hasMark()) { //delete marked part of text
+ if(m1 > m2) Swap(m1, m2);
+ if(m2 >= (short int)strlen(text)) text[m1] = 0;
+ else strcpy(text+m1, text+m2);
+ CursorPos = m1;
+ m1 = m2 = -1;
+ }
byte1 = text[CursorPos];
i = CursorPos;
text[i++] = c;
while(byte1) {
byte2 = byte1; byte1 = text[i]; text[i++] = byte2;
}
- text[i] = byte1;
- CursorPos++;
+ text[i] = byte1; CursorPos++; type = ET_UNKNOWN;
Redraw(Out, true);
MyPos.y = loc.y;
MyPos.x = Align & TXA_HRIGHT ? crb.x - 2 : loc.x + 2;
if(Out)Out->TextCursor(text, MyPos, (POINT *) NULL, &CursorPos,
scroll_et == this ? scroll_dist : scroll_dist=0);
+ if(parent && text) {
+ ((DataObj*)parent)->Command(CMD_ETRACC, text[0] == '=' && ci != ')' ? this : 0L, 0L);
+ }
return true;
}
@@ -129,39 +140,46 @@ EditText::Update(int select, anyOutput *Out, POINT *MousePos)
{
POINT MyPos;
+ if(!parent && !disp) disp = Out;
if(select != 1 && select != 5) m1 = m2 = -1; //no mark;
switch(select) {
case 0: //just redraw with current settings
Redraw(Out, true);
break;
case 5: //dialog control
- if(!text)Align = TXA_VTOP | TXA_HLEFT;
+ if(!text)Align = TXA_VCENTER | TXA_HLEFT;
case 1: //active spread sheet cell with cursor
- if((type & 0xff) == ET_FORMULA) Align = TXA_VTOP | TXA_HLEFT;
- if(!text && !(text = (char *) calloc(2, sizeof(char))))return;
+ if((type & 0xff) == ET_FORMULA) Align = TXA_VCENTER | TXA_HLEFT;
+ if(!text && !(text = (char *) calloc(10, sizeof(char))))return;
if(CursorPos > (int)strlen(text)) CursorPos = (int)strlen(text);
+ if(MousePos && (type & 0xff) == ET_TEXT && (text && text[0] == '\'' && (bgLine == &ETbgnn || bgLine == &ETbgmn))) {
+ MousePos->x += 4;
+ }
bgLine = &ETbgna; bgFill = &ETfbna; TextCol = 0x00000000L;
- Redraw(Out, true);
- MyPos.y = loc.y;
- MyPos.x = Align & TXA_HRIGHT ? crb.x - 2 : loc.x + 2;
- if(MousePos && MousePos->x && MousePos->y) Out->TextCursor(text, MyPos, MousePos,&CursorPos,
- scroll_et == this ? scroll_dist : scroll_dist=0);
- else if(select ==1) Out->TextCursor(text, MyPos, NULL, &CursorPos,
- scroll_et == this ? scroll_dist : scroll_dist=0);
+ if(Out) {
+ Redraw(Out, true);
+ MyPos.y = loc.y; MyPos.x = Align & TXA_HRIGHT ? crb.x - 4 : loc.x + 4;
+ if(MousePos && MousePos->x && MousePos->y) {
+ Out->TextCursor(text, MyPos, MousePos,&CursorPos,
+ scroll_et == this ? scroll_dist : scroll_dist=0);
+ }
+ else if(select ==1) Out->TextCursor(text, MyPos, NULL, &CursorPos,
+ scroll_et == this ? scroll_dist : (scroll_dist=0)+2);
+ }
break;
case 2: //inactive spreadsheet cell
- if((type & 0xff) == ET_FORMULA) Align = TXA_VTOP | TXA_HRIGHT;
+ if((type & 0xff) == ET_FORMULA) Align = TXA_VCENTER | TXA_HRIGHT;
if(crb.x > rb.x) {
crb.x = rb.x; crb.y = rb.y;
}
if(CurrText == this) FindType();
bgLine = &ETbgnn; bgFill = &ETfbnn; TextCol = 0x00000000L;
- Redraw(Out, true);
+ if(Out) Redraw(Out, true);
break;
case 10: //value filled in by external app.
if(text && text[0]) {
type = ET_VALUE;
- Align = TXA_VTOP | TXA_HRIGHT;
+ Align = TXA_VCENTER | TXA_HRIGHT;
sscanf(text, "%lf", &Value);
}
break;
@@ -177,16 +195,18 @@ EditText::Redraw(anyOutput *Out, bool display)
RECT rc;
POINT MyPos;
char *txt, tmptxt[80];
- int i, j, w, h, o_crbx;
+ int w, h, o_crbx;
bool b_clip = false;
anyOutput *opc;
anyResult *fmres;
+ if(!parent && disp) Out = disp;
+ if(loc.x <1 || rb.x < 1 || loc.y <1 || rb.y <1) return false;
o_crbx = crb.x; crb.x = rb.x; crb.y = rb.y;
if (Out) {
+ if (m1 >m2) Swap(m1, m2);
if(((type & 0xff) == ET_UNKNOWN) && text && text[0]) FindType();
- Out->TxtSet.Align = Align;
- Out->TxtSet.ColTxt = TextCol;
+ Out->TxtSet.Align = Align; Out->TxtSet.ColTxt = TextCol;
Out->TxtSet.ColBg = bgLine->color;
if(text && text[0]) {
Out->oGetTextExtent(text, strlen(text), &w, &h);
@@ -198,28 +218,28 @@ EditText::Redraw(anyOutput *Out, bool display)
}
Out->SetFill(bgFill); Out->SetLine(bgLine);
rc.left = loc.x; rc.right = crb.x;
- rc.top = loc.y; rc.bottom = crb.y;
+ rc.top = loc.y+1; rc.bottom = crb.y-2;
Out->oRectangle(loc.x, loc.y, crb.x-1, crb.y-1);
- if(!text && (type & 0xff) == ET_VALUE){
+ if((!text || !text[0]) && (type & 0xff) == ET_VALUE){
sprintf(tmptxt, "%g", Value);
- text = strdup(tmptxt);
+ if(text = (char*)realloc(text, strlen(tmptxt)+2)) strcpy(text, tmptxt);
+ CursorPos = 0;
}
+ if(ftext) free(ftext); ftext = 0L;
if(text && text[0]){
if((type & 0xff) == ET_FORMULA && (bgLine == &ETbgnn || bgLine == &ETbgmn)) {
- Out->TxtSet.Align = TXA_HLEFT;
+ Out->TxtSet.Align = TXA_HLEFT | TXA_VCENTER;
if(type & ET_CIRCULAR) strcpy (tmptxt, "#CIRC.");
else if((fmres = do_formula((DataObj*)parent, text+1)) && fmres->type != ET_ERROR) {
- b_clip = false; //DEBUG: assume column wide enough for number
+ b_clip = false;
if(fmres->type == ET_VALUE) {
sprintf(tmptxt, "%g", Value = fmres->value);
- for(i=j=0; i < 20; i++) {
- while(i>3 && tmptxt[i] == '0' && tmptxt[j-2] == 'e') i++;
- tmptxt[j++] = tmptxt[i];
- }
- tmptxt[j] = 0;
- Out->TxtSet.Align = TXA_HRIGHT;
+ fit_num_rect(Out, rb.x - loc.x, tmptxt);
+ Out->TxtSet.Align = TXA_HRIGHT | TXA_VCENTER;
}
else if(fmres->type == ET_TEXT) {
+ if(ftext) free (ftext); ftext = 0L;
+ if(fmres->text) ftext = strdup(fmres->text);
if(fmres->text && strlen(fmres->text)<sizeof(tmptxt)) strcpy(tmptxt, fmres->text);
else if(fmres->text) sprintf(tmptxt,"#SIZE");
else tmptxt[0] = 0;
@@ -229,21 +249,36 @@ EditText::Redraw(anyOutput *Out, bool display)
else sprintf(tmptxt, "#ERROR");
txt = tmptxt;
}
+ else if((type &0xff) == ET_VALUE) {
+ Out->oGetTextExtent(text, strlen(text), &w, &h);
+ if(w >= (rb.x - loc.x-8) && (bgLine == &ETbgnn || bgLine == &ETbgmn)) {
+ sprintf(tmptxt, "%g", Value);
+ fit_num_rect(Out, rb.x - loc.x, tmptxt);
+ txt = tmptxt; b_clip = false;
+ }
+ else txt = text;
+ }
+ else if((type & 0xff) == ET_TEXT) {
+ if(text && text[0] == '\'' && (bgLine == &ETbgnn || bgLine == &ETbgmn)) {
+ txt = text+1;
+ }
+ else txt = text;
+ }
else txt = text;
- MyPos.y = loc.y;
+ MyPos.y = (loc.y+rb.y)>>1;
if(Out->TxtSet.Align & TXA_HRIGHT) { //right justified text
- MyPos.x = crb.x-2;
+ MyPos.x = crb.x-4;
}
else { //left justified text
- MyPos.x = loc.x +2;
+ MyPos.x = loc.x+4;
}
- if(b_clip && (opc = NewBitmapClass(w+22, h+2, Out->hres, Out->vres))){
+ if(b_clip && (opc = NewBitmapClass(w+22, rb.y-loc.y, Out->hres, Out->vres))){
if(scroll_et != this || parent) {
scroll_et = this; scroll_dist = 0;
}
opc->Erase(bgFill->color);
- opc->SetTextSpec(&Out->TxtSet); opc->TxtSet.Align = TXA_HLEFT | TXA_VTOP;
- opc->oTextOut(2, 0, txt, strlen(txt));
+ opc->SetTextSpec(&Out->TxtSet); opc->TxtSet.Align = TXA_HLEFT | TXA_VCENTER;
+ opc->oTextOut(4,(rb.y-loc.y)>>1, txt, strlen(txt));
if(!parent && CursorPos) {
Out->oGetTextExtent(txt, CursorPos, &w, &h);
while((scroll_dist + w)>(rc.right-rc.left-10)) scroll_dist -=10;
@@ -252,20 +287,24 @@ EditText::Redraw(anyOutput *Out, bool display)
}
else scroll_dist=0;
Out->CopyBitmap(rc.left+1, rc.top+1, opc, 1-scroll_dist, 1,
- rc.right-rc.left-2, rc.bottom-rc.top-2, false);
+ rc.right-rc.left-4, rc.bottom-rc.top-2, false);
DelBitmapClass(opc);
}
else {
+ if(display && hasMark() && mx1 > loc.x && mx2 < crb.x) {
+ Out->SetFill(&yFill); Out->SetLine(&yLine);
+ Out->oRectangle(mx1, rc.top, mx2, rc.bottom);
+ Out->SetFill(bgFill); Out->SetLine(bgLine);
+ }
scroll_dist = 0;
- Out->oTextOut(MyPos.x, loc.y, txt, 0);
+ Out->oTextOut(MyPos.x, MyPos.y, txt, 0);
}
}
if(display) {
if(!(Out->UpdateRect(&rc, false))) return false;
- if(m1 != m2 && m1 >=0 && m2 >=0) {
- if (m1 >m2) Swap(m1, m2);
+ if(hasMark() && mx1 > loc.x && mx2 < rb.x) {
rc.left = mx1; rc.right = mx2;
- Out->ShowMark(&rc, MRK_INVERT);
+ Out->UpdateRect(&rc, true);
Out->MrkMode = MRK_NONE;
}
}
@@ -282,6 +321,7 @@ EditText::Mark(anyOutput *Out, int mark)
DWORD ocol = TextCol;
m1 = m2 = -1;
+ if(!parent) return;
switch (mark){
case 0: //normal not active
bgLine = &ETbgnn; bgFill = &ETfbnn; TextCol = 0x00000000L;
@@ -290,13 +330,19 @@ EditText::Mark(anyOutput *Out, int mark)
bgLine = &ETbgna; bgFill = &ETfbna; TextCol = 0x00000000L;
break;
case 2: //mark not active
- bgLine = &ETbgmn; bgFill = &ETfbmn; TextCol = 0x00ffffffL;
+ bgLine = &ETbgmn; bgFill = &ETfbmn; TextCol = 0x00c00000L;
break;
case 3: //mark active
bgLine = &ETbgma; bgFill = &ETfbma; TextCol = 0x00ff0000L;
break;
}
+ if(!mark || mark == 2) {
+ loc.y--; rb.y++;
+ }
Redraw(Out, true);
+ if(!mark || mark == 2) {
+ loc.y++; rb.y--;
+ }
bgLine = ol; bgFill = of; TextCol = ocol;
}
@@ -309,10 +355,12 @@ EditText::Command(int cmd, anyOutput *Out, void *data_obj)
static RECT rMark;
bool bRet;
char *tag1, *tag2;
+ unsigned char *pt;
MyPos.y = loc.y;
- MyPos.x = Align & TXA_HRIGHT ? crb.x - 2 : loc.x + 2;
+ MyPos.x = Align & TXA_HRIGHT ? crb.x - 4 : loc.x + 4;
if(!(text)) return false;
+ if(!parent && disp) Out = disp; //Dialog !
switch(cmd) {
case CMD_MRK_DIRTY:
type = ET_UNKNOWN;
@@ -325,10 +373,11 @@ EditText::Command(int cmd, anyOutput *Out, void *data_obj)
((DataObj*)parent)->Command(CMD_MRK_DIRTY, Out, 0L);
}
else return Command(CMD_REDRAW, Out, data_obj);
+ return true;
case CMD_SETFONT:
if (!text || !text[0]) return false;
type = ET_TEXT;
- if(m1 > -1 && m2 > -1) {
+ if(hasMark()) {
Undo.TextCell(this, Out, text, &CursorPos, &m1, &m2, parent, 0L);
switch (*((int*)data_obj)) {
case FONT_HELVETICA:
@@ -356,7 +405,7 @@ EditText::Command(int cmd, anyOutput *Out, void *data_obj)
for( ; TmpTxt[i++] = text[w]; w++);
m1 += (w = strlen(tag1)); m2 += w; CursorPos += w;
CleanTags(TmpTxt, &m1, &m2, &CursorPos);
- free(text); text = strdup(TmpTxt);
+ if(text = (char*)realloc(text, strlen(TmpTxt)+2)) strcpy(text, TmpTxt);
Command(CMD_REDRAW, Out, 0L);
return true;
}
@@ -364,7 +413,7 @@ EditText::Command(int cmd, anyOutput *Out, void *data_obj)
case CMD_SETSTYLE:
if (!text || !text[0]) return false;
type = ET_TEXT;
- if(m1 > -1 && m2 > -1) {
+ if(hasMark()) {
Undo.TextCell(this, Out, text, &CursorPos, &m1, &m2, parent, 0L);
switch (*((int*)data_obj)) {
case TXS_BOLD:
@@ -404,12 +453,28 @@ EditText::Command(int cmd, anyOutput *Out, void *data_obj)
for( ; TmpTxt[i++] = text[w]; w++);
m1 += (w = strlen(tag1)); m2 += w; CursorPos += w;
CleanTags(TmpTxt, &m1, &m2, &CursorPos);
- free(text); text = strdup(TmpTxt);
+ if(text = (char*)realloc(text, strlen(TmpTxt)+2)) strcpy(text, TmpTxt);
Command(CMD_REDRAW, Out, 0L);
return true;
}
return false;
+ case CMD_ADDTXT:
+ if(data_obj && *((char*)data_obj) && text &&
+ (type == ET_TEXT || type == ET_UNKNOWN || type == ET_FORMULA)){
+ if(hasMark()) Command(CMD_DELETE, 0L, 0L);
+ else Undo.TextCell(this, Out, text, &CursorPos, &m1, &m2, parent, 0L);
+ if(m1 > -1 && m2 > -1) Command(CMD_DELETE, 0L, 0L);
+ for(i = 0; i < CursorPos && text[i]; i++) TmpTxt[i] = text[i];
+ j = i + sprintf(TmpTxt+i, "%s", (char*)data_obj);
+ if(text[i]) sprintf(TmpTxt+j, "%s", text+i);
+ if(text = (char*)realloc(text, strlen(TmpTxt)+2)) strcpy(text, TmpTxt);
+ CursorPos += strlen((char*)data_obj);
+ Out->Focus();
+ Update(1, Out, 0L);
+ }
+ return true;
case CMD_BACKSP:
+ if(!text) return false;
if(CursorPos <=0){
Out->TextCursor(text, MyPos, (POINT *) NULL, &CursorPos,
scroll_et == this ? scroll_dist : scroll_dist=0);
@@ -418,12 +483,22 @@ EditText::Command(int cmd, anyOutput *Out, void *data_obj)
Undo.TextCell(this, Out, text, &CursorPos, &m1, &m2, parent, 0L);
CursorPos--; //continue as if delete
case CMD_DELETE:
+ if(!text) return false;
+ if(parent) {
+ ((DataObj*)parent)->Command(CMD_ETRACC, text[0] == '=' ? this : 0L, 0L);
+ }
if(cmd == CMD_DELETE) Undo.TextCell(this, Out, text, &CursorPos, &m1, &m2, parent, 0L);
+ if(parent) {
+ ((DataObj*)parent)->Command(CMD_MRK_DIRTY, 0L, 0L);
+ ((DataObj*)parent)->Command(CMD_SAVEPOS, 0L, 0L);
+ }
bRet = false;
- if(m1 > -1 && m2 > -1) { //delete marked part of text
+ if(!text || !text[0]) {
+ type = ET_UNKNOWN; CursorPos = 0;
+ }
+ if(hasMark()) { //delete marked part of text
if (!text || !text[0]) return false;
if(m1 > m2) Swap(m1, m2);
- if(parent) ((DataObj*)parent)->Command(CMD_MRK_DIRTY, 0L, 0L);
if(m2 >= (short int)strlen(text)) text[m1] = 0;
else strcpy(text+m1, text+m2);
CursorPos = m1;
@@ -431,22 +506,62 @@ EditText::Command(int cmd, anyOutput *Out, void *data_obj)
if(Out) Redraw(Out, (bRet = true));
}
else if(text[CursorPos]) {
- if(parent) ((DataObj*)parent)->Command(CMD_MRK_DIRTY, 0L, 0L);
strcpy(text + CursorPos, text + CursorPos + 1);
+ if(!text || !text[0]) {
+ type = ET_UNKNOWN; CursorPos = 0;
+ }
if(Out)Redraw(Out, (bRet = true));
}
if(Out)Out->TextCursor(text, MyPos, (POINT *) NULL, &CursorPos,
scroll_et == this ? scroll_dist : scroll_dist=0);
return bRet;
+ case CMD_COPY:
+ if(text && text[0]) {
+ rMark.left = loc.x+2; rMark.right = rb.x-2;
+ rMark.top = loc.y+1; rMark.bottom = rb.y-2;
+ if(m1 != m2 && m1 >=0 && m2 >=0) {
+ if (m1 >m2) Swap(m1, m2);
+ rMark.left = mx1; rMark.right = mx2;
+ if(Out) Out->UpdateRect(&rMark, false);
+ CopyText(text+m1, m2-m1);
+ if(Out) {
+ Out->MrkMode = MRK_NONE;
+ ShowCopyMark(Out, &rMark, 1);
+ Out->UpdateRect(&rMark, true);
+ }
+ return false;
+ }
+ CopyText(text, strlen(text));
+ if(Out)Out->UpdateRect(&rMark, true);
+ return false;
+ }
+ return false;
+ case CMD_PASTE:
+ if(pt = PasteText()) {
+ Undo.TextCell(this, Out, text, &CursorPos, &m1, &m2, parent, 0L);
+ for(i = 0; pt[i] > 0x20 && i < 81; i++) this->AddChar(pt[i], 0L, 0L);
+ if(Out) Redraw(Out, true); free(pt);
+ if(parent && text) {
+ ((DataObj*)parent)->Command(CMD_ETRACC, text[0] == '=' ? this : 0L, 0L);
+ }
+ if(i) return true;
+ }
+ return false;
case CMD_SHIFTRIGHT:
if(CursorPos == m1 && text[m1]) m1++;
else if(CursorPos == m2 && text[m2]) m2++;
else if(text[CursorPos]){
m1 = CursorPos; m2 = CursorPos+1;
}
+ if(parent && text) {
+ ((DataObj*)parent)->Command(CMD_ETRACC, text[0] == '=' ? this : 0L, 0L);
+ }
if(text[CursorPos]) CursorPos++;
else return false;
case CMD_SHIFTLEFT:
+ if(parent && text) {
+ ((DataObj*)parent)->Command(CMD_ETRACC, text[0] == '=' ? this : 0L, 0L);
+ }
if (!(CursorPos)) return false;
case CMD_REDRAW:
if(cmd == CMD_SHIFTLEFT) {
@@ -462,10 +577,10 @@ EditText::Command(int cmd, anyOutput *Out, void *data_obj)
w = h = 0;
if(Align & TXA_HRIGHT) { //right justified text
Out->oGetTextExtent(text, 0, &w, &h);
- mx1 = crb.x-2 - w;
+ mx1 = crb.x-4 - w;
}
else { //left justified text
- mx1 = loc.x +2;
+ mx1 = loc.x +4;
}
Out->oGetTextExtent(text, m1, &w, &h);
mx1 += (m1 ? w : 0);
@@ -478,6 +593,9 @@ EditText::Command(int cmd, anyOutput *Out, void *data_obj)
return true;
case CMD_CURRLEFT:
m1 = m2 = -1;
+ if(parent && text) {
+ ((DataObj*)parent)->Command(CMD_ETRACC, text[0] == '=' ? this : 0L, 0L);
+ }
if(CursorPos >0) {
CursorPos--;
if(Redraw(Out, true) && Out->TextCursor(text, MyPos, (POINT *) NULL,
@@ -485,14 +603,17 @@ EditText::Command(int cmd, anyOutput *Out, void *data_obj)
else return false;
}
else if (data_obj) {
- MyPos.x = loc.x-2; MyPos.y = (rb.y+loc.y)/2;
+ MyPos.x = loc.x-4; MyPos.y = (rb.y+loc.y)/2;
if(((DataObj*)data_obj)->Select(&MyPos))return true;
- MyPos.x = loc.x+2;
+ MyPos.x = loc.x+4;
((DataObj*)data_obj)->Select(&MyPos);
}
return false;
case CMD_CURRIGHT:
m1 = m2 = -1;
+ if(parent && text) {
+ ((DataObj*)parent)->Command(CMD_ETRACC, text[0] == '=' ? this : 0L, 0L);
+ }
if(text[CursorPos]){
CursorPos++;
if(Redraw(Out, true) && Out->TextCursor(text, MyPos, (POINT *) NULL,
@@ -500,13 +621,20 @@ EditText::Command(int cmd, anyOutput *Out, void *data_obj)
else return false;
}
else if (data_obj) {
- MyPos.x = rb.x+2; MyPos.y = (rb.y+loc.y)/2; crb.x = rb.x;
+ MyPos.x = rb.x+4; MyPos.y = (rb.y+loc.y)/2; crb.x = rb.x;
if(((DataObj*)data_obj)->Select(&MyPos)) return true;
- MyPos.x = rb.x-2;
+ MyPos.x = rb.x-4;
((DataObj*)data_obj)->Select(&MyPos);
}
return false;
+ case CMD_UPDATE:
+ m1 = m2 = -1;
+ Redraw(Out, true);
+ return true;
case CMD_POS_FIRST: case CMD_POS_LAST:
+ if(parent && text) {
+ ((DataObj*)parent)->Command(CMD_ETRACC, text[0] == '=' ? this : 0L, 0L);
+ }
CursorPos = (cmd == CMD_POS_LAST && text && text[0]) ? strlen(text) : 0;
m1 = m2 = -1;
Redraw(Out, true);
@@ -518,11 +646,11 @@ EditText::Command(int cmd, anyOutput *Out, void *data_obj)
//the following calculation of the cursor position is crude
//it is based on a aspect of 2:1 for digits
if(Align & TXA_HRIGHT) //right justified text
- MyPos.x = rb.x-2-((rb.y-loc.y-4)*(strlen(text)-CursorPos))/2;
- else MyPos.x = loc.x+2+((rb.y-loc.y-4)*CursorPos)/2;
+ MyPos.x = rb.x-4-((rb.y-loc.y-4)*(strlen(text)-CursorPos))/2;
+ else MyPos.x = loc.x+4+((rb.y-loc.y-4)*CursorPos)/2;
MyPos.y = (cmd == CMD_CURRUP) ? loc.y-2 : rb.y+2;
- if(MyPos.x < loc.x) MyPos.x = loc.x +2;
- if(MyPos.x > rb.x) MyPos.x = rb.x -2;
+ if(MyPos.x < loc.x) MyPos.x = loc.x +4;
+ if(MyPos.x > rb.x) MyPos.x = rb.x -4;
if(((DataObj*)data_obj)->Select(&MyPos))return true;
MyPos.y = rb.y;
((DataObj*)data_obj)->Select(&MyPos);
@@ -537,19 +665,23 @@ EditText::Command(int cmd, anyOutput *Out, void *data_obj)
return true;
}
if(mev->Action == MOUSE_LBDOUBLECLICK) {
- rMark.top = loc.y; rMark.bottom = rb.y;
+ rMark.top = loc.y+1; rMark.bottom = rb.y-2;
if(!Out->oGetTextExtent(text, strlen(text), &w, &h)) return false;
m1 = 0; m2 = strlen(text);
if(Align & TXA_HRIGHT) { //right justfied text
- rMark.right = crb.x -2; rMark.left = crb.x - w - 2;
+ rMark.right = crb.x -4; rMark.left = crb.x - w - 4;
}
else { //left justified text
- rMark.left = loc.x +2; rMark.right = rMark.left +w;
+ rMark.left = loc.x +4; rMark.right = rMark.left +w;
+ }
+ mx1 = rMark.left; mx2 = rMark.right;
+ Redraw(Out, true);
+ if(parent && text) {
+ ((DataObj*)parent)->Command(CMD_ETRACC, text[0] == '=' ? this : 0L, 0L);
}
- Out->UpdateRect(&rMark,true);
return true;
}
- MyPos.x = Align & TXA_HRIGHT ? mev->x + 2 : mev->x - 2;
+ MyPos.x = Align & TXA_HRIGHT ? mev->x + 4 : mev->x - 4;
MyPos.y = mev->y;
Out->TxtSet.Align = Align;
j = Out->CalcCursorPos(text, Align & TXA_HRIGHT ? crb :loc, &MyPos);
@@ -557,14 +689,14 @@ EditText::Command(int cmd, anyOutput *Out, void *data_obj)
if(Align & TXA_HRIGHT) { //right justfied text
if((i = strlen(text)-j)){
if(!Out->oGetTextExtent(text+j, i, &w, &h)) return false;
- w = crb.x - w - 2;
+ w = crb.x - w - 4;
}
else w = crb.x-1;
}
else { //left justified text
if(!j) w = 0;
else if(!Out->oGetTextExtent(text, j, &w, &h))return false;
- w += (loc.x+2);
+ w += (loc.x+4);
}
if(m1 == m2 && m1 == -1) {
mx1 = (short)(rMark.left = w);
@@ -574,13 +706,12 @@ EditText::Command(int cmd, anyOutput *Out, void *data_obj)
m2 = j;
if(m2 >= 0)Out->UpdateRect(&rMark, false);
mx2 = (short)(rMark.right = w);
- rMark.top = loc.y;
- rMark.bottom = rb.y;
+ rMark.top = loc.y+1; rMark.bottom = rb.y-2;
if(rMark.right < crb.x && rMark.right > loc.x &&
rMark.left > loc.x && rMark.left < crb.x)
Out->UpdateRect(&rMark,true);
}
- if(m1 >= 0 && m2 >= 0 && m1 != m2 && parent)
+ if(hasMark() && parent)
//remove range-mark of data
((DataObj*)parent)->Command(CMD_UNLOCK, 0L, 0L);
return true;
@@ -618,10 +749,7 @@ EditText::GetValue(double *v)
type &= ~ET_BUSY;
return false;
}
- else if(parent) {
- ((DataObj*)parent)->Command(CMD_ERROR, (void*)"circular reference in formula", 0L);
- type |= ET_CIRCULAR;
- }
+ else type |= ET_CIRCULAR;
*v = Value;
return true;
}
@@ -629,25 +757,31 @@ EditText::GetValue(double *v)
}
bool
-EditText::GetText(char *t, int size)
+EditText::GetText(char *tx, int size)
{
- if(text) {
- if((int)strlen(text) < size) strcpy(t, text);
+ char *t;
+
+ if(text && text[0]) {
+ if(text[0] =='\'' && text[1]) t = text + 1;
+ else t = text;
+ }
+ else t = 0L;
+ if(t) {
+ if((int)strlen(t) < size) strcpy(tx, t);
else {
- memcpy(t, &text, size-1); t[size-1] = 0;
+ memcpy(tx, text, size-1); tx[size-1] = 0;
}
return true;
}
if((type & 0xff) == ET_VALUE) {
- sprintf(TmpTxt, "%lf", Value);
- text = strdup(TmpTxt);
- return GetText(t, size);
+ if(text = (char*)realloc(text, 20)) sprintf(text, "%g", Value);
+ if(text && text[0]) return(GetText(tx, size));
}
return false;
}
bool
-EditText::GetResult(anyResult *r)
+EditText::GetResult(anyResult *r, bool use_last)
{
anyResult * res;
@@ -671,6 +805,15 @@ EditText::GetResult(anyResult *r)
return true;
}
if((type & 0xff) == ET_FORMULA){
+ if(use_last) {
+ if(ftext) {
+ r->text = ftext; r->value = 0.0; r->type = ET_TEXT;
+ }
+ else {
+ r->text = 0L; r->value = Value; r->type = ET_VALUE;
+ }
+ return true;
+ }
if(!(type & ET_BUSY)){
type |= ET_BUSY;
if(res = do_formula((DataObj*)parent, text+1)) {
@@ -683,8 +826,8 @@ EditText::GetResult(anyResult *r)
type &= ~ET_BUSY;
return false;
}
- else if(parent) {
- ((DataObj*)parent)->Command(CMD_ERROR, (void*)"circular reference in formula", 0L);
+ else {
+ type |= ET_CIRCULAR;
r->text = "#CIRC."; r->value = 0.0; r->type = ET_TEXT;
return true;
}
@@ -696,9 +839,7 @@ EditText::GetResult(anyResult *r)
bool
EditText::SetValue(double v)
{
- if(text){
- free(text); text = 0L;
- }
+ if(text) text[0] = 0;
Value = v; type = ET_VALUE;
return true;
}
@@ -706,11 +847,10 @@ EditText::SetValue(double v)
bool
EditText::SetText(char *t)
{
- if(text){
- free(text); text = 0L;
- }
Value = 0.0; type = ET_UNKNOWN;
- if(t && t[0]) text = strdup(t);
+ bgLine = &ETbgnn; bgFill = &ETfbnn; TextCol = 0x00000000L;
+ if(t && t[0] && (text = (char*)realloc(text, strlen(t)+2))) strcpy(text, t);
+ else if (text) text[0] = 0;
return false;
}
@@ -777,23 +917,23 @@ void
EditText::FindType()
{
if(text && text[0] == '=') {
- Align = TXA_VTOP | TXA_HRIGHT;
+ Align = TXA_VCENTER | TXA_HRIGHT;
type = ET_FORMULA;
}
else if(text && (Txt2Flt(text, &Value))) {
- Align = TXA_VTOP | TXA_HRIGHT;
+ Align = TXA_VCENTER | TXA_HRIGHT;
type = ET_VALUE;
}
else if (text && text[0]) {
- Align = TXA_VTOP | TXA_HLEFT;
+ Align = TXA_VCENTER | TXA_HLEFT;
type = ET_TEXT;
}
else if ((type && 0xff) == ET_VALUE) {
- Align = TXA_VTOP | TXA_HRIGHT;
+ Align = TXA_VCENTER | TXA_HRIGHT;
type = ET_VALUE;
}
else {
- Align = TXA_VTOP | TXA_HRIGHT;
+ Align = TXA_VCENTER | TXA_HRIGHT;
type = ET_UNKNOWN;
}
}
@@ -827,6 +967,7 @@ static tag_info tags[] = {
{"<bullet3>", 0, 0, -1, 3}, {"<bullet4>", 0, 0, -1, 4},
{"<bullet5>", 0, 0, -1, 5}, {"<bullet6>", 0, 0, -1, 6},
{"<bullet7>", 0, 0, -1, 7}, {"<bullet8>", 0, 0, -1, 8},
+ {"<bullet9>", 0, 0, -1, 9}, {"<bullet10>", 0, 0, -1, 10},
{"<white>", 0, 0, -1, 100}, {"<black>", 0, 0, -1, 101},
{"<red>", 0, 0, -1, 102}, {"<blue>", 0, 0, -1, 103},
{"<green>", 0, 0, -1, 104}, {"<yellow>", 0, 0, -1, 105},
@@ -935,13 +1076,16 @@ fmtText::oGetTextExtent(anyOutput *o, int *width, int *height, int cb)
o->SetTextSpec(&td2);
l += strlen(tags[n].tag);
}
- if(split_text[i].txt){
+ if(split_text[i].txt && split_text[i].txt[0]){
l1 = l; l += strlen(split_text[i].txt);
if (l1 >= cb) break;
o->oGetTextExtent(split_text[i].txt, l >= cb ? cb-l1 : 0, &w1, &h1);
- w += w1; if(!i) h = h1;
+ w += w1; h = h1 > h ? h1 : h;
if (l >= cb) break;
}
+ if(tags[n].font == -1 && tags[n].op > 0 && tags[n].op < 100) {
+ w += o->un2ix(td2.fSize/2.0);
+ }
}
*width = w; *height = h; o->SetTextSpec(&td1);
return true;
@@ -1065,19 +1209,24 @@ fmtText::DrawBullet(anyOutput *o, int x, int y, int type, double size, DWORD lc,
o->SetLine(&ld); o->SetFill(&fd);
o->oRectangle(x-is, y-is, x+is, y+is);
break;
- case 5: case 6: case 7: case 8:
- if(type == 6 || type == 8) fd.color = ld.color;
- pts[0].x = pts[3].x = x - is; pts[1].x = x; pts[2].x = x+is;
+ case 5: case 6: case 7: case 8: case 9: case 10:
+ if(type == 6 || type == 8 || type == 10) fd.color = ld.color;
+ pts[0].x = pts[3].x = pts[4].x = x - is;
+ pts[1].x = x; pts[2].x = x+is;
if(type == 5 || type == 6) {
pts[0].y = pts[2].y = pts[3].y = y+o->un2iy(size*0.19439);
pts[1].y = y-o->un2iy(size*0.38878);
}
+ else if(type == 9 || type ==10) {
+ pts[0].y = pts[2].y = pts[4].y = y;
+ pts[1].y = y - is; pts[3].y = y + is; pts[3].x = x;
+ }
else {
pts[0].y = pts[2].y = pts[3].y = y-o->un2iy(size*0.19439);
pts[1].y = y+o->un2iy(size*0.38878);
}
o->SetLine(&ld); o->SetFill(&fd);
- o->oPolygon(pts, 4);
+ o->oPolygon(pts, type < 9 ? 4 : 5);
break;
}
}
@@ -1120,7 +1269,7 @@ fmtText::DrawFormatted(anyOutput *o)
x1 -= iround(o->un2fix(td2.fSize)*si);
}
switch (tags[n].op) {
- case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
+ case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10:
DrawBullet(o, x1, y1, tags[n].op, td2.fSize, td2.ColTxt, 0x00ffffff);
w = o->un2ix(td2.fSize/2.0);
x = iround(fx += (w*csi)); y = iround(fy -= (w*si));
@@ -1173,7 +1322,7 @@ DataObj::Init(int nR, int nC)
FlushData(); return false;
}
if(etRows[i]) for(j = 0; j < cCols; j++) {
- etRows[i][j] = new EditText(this, 0L);
+ etRows[i][j] = new EditText(this, 0L, i, j);
}
}
return true;
@@ -1220,10 +1369,10 @@ DataObj::GetTextPtr(int row, int col)
}
bool
-DataObj::GetResult(anyResult *r, int row, int col)
+DataObj::GetResult(anyResult *r, int row, int col, bool use_last)
{
if(row < 0 || row >= cRows || col < 0 || col >= cCols) return false;
- if(etRows[row][col]) return etRows[row][col]->GetResult(r);
+ if(etRows[row][col]) return etRows[row][col]->GetResult(r, use_last);
return false;
}
@@ -1252,32 +1401,49 @@ DataObj::FlushData()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Store Data Object as strings: less memory required than with DataObj
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-StrData::StrData(DataObj *par)
+StrData::StrData(DataObj *par, RECT *rc)
{
- int r, c;
- char *tx;
+ int r1, c1, r2, c2, w, h;
+ char **tx;
- pw = ph = w = h = 0; str_data = 0L;
- if(src = par) {
- src->GetSize(&pw, & ph);
+ pw = ph = 0; str_data = 0L;
+ drc.left = drc.right = drc.top = drc.bottom = 0;
+ if(!(src = par)) return;
+ src->GetSize(&pw, & ph);
+ if(rc) {
+ if(0>(h = (rc->bottom - rc->top)) || 0>(w = (rc->right - rc->left))) return;
+ if(!(str_data = (char***)calloc(h+1, sizeof(char**))))return;
+ drc.left = rc->left; drc.right = rc->right;
+ drc.top = rc->top; drc.bottom = rc->bottom;
+ for (r1 = 0, r2 = drc.top; r1 <= h; r1++, r2++) {
+ if(!(str_data[r1] = (char**)malloc((w+1) * sizeof(char*)))) break;
+ for(c1 = 0, c2= drc.left; c1 <= w; c1++, c2++) {
+ tx = src->GetTextPtr(r2, c2);
+ str_data[r1][c1] = tx && *tx && *tx[0] ? strdup(*tx) : 0L;
+ }
+ }
+ }
+ else {
if(!(str_data = (char***)calloc(ph, sizeof(char**))))return;
- for (r = 0; r < ph; r++) {
- if(!(str_data[r] = (char**)malloc(pw * sizeof(char*)))) break;
- for(c = 0; c < pw; c++) {
- str_data[r][c] = (tx = *(src->GetTextPtr(r, c))) && tx[0] ? strdup(tx) : 0L;
+ for (r1 = 0; r1 < ph; r1++) {
+ if(!(str_data[r1] = (char**)malloc(pw * sizeof(char*)))) break;
+ for(c1 = 0; c1 < pw; c1++) {
+ tx = src->GetTextPtr(r1, c1);
+ str_data[r1][c1] = tx && *tx && *tx[0] ? strdup(*tx) : 0L;
}
}
+ drc.right = pw-1; drc.bottom = ph-1;
}
- w = pw; h = ph;
}
StrData::~StrData()
{
- int r, c;
+ int r, c, w, h;
- if(str_data) for (r = 0; r < h; r++) {
+ w = drc.right-drc.left; h = drc.bottom-drc.top;
+ if(str_data) for (r = 0; r <= h; r++) {
if(str_data[r]) {
- for(c = 0; c < w; c++) if(str_data[r][c]) free(str_data[r][c]);
+ for(c = 0; c <= w; c++) if(str_data[r][c]) free(str_data[r][c]);
free(str_data[r]);
}
}
@@ -1294,12 +1460,13 @@ StrData::GetSize(int *uw, int *uh)
void
StrData::RestoreData(DataObj *dest)
{
- int r, c;
+ int r1, c1, r2, c2;
- if(!dest || !str_data || !w || ! h) return;
- for (r = 0; r < h; r++) {
- if(str_data[r]) {
- for(c = 0; c < w; c++) dest->SetText(r, c, str_data[r][c]);
+ if(!dest || !str_data) return;
+ for (r1 = 0, r2 = drc.top; r2 <= drc.bottom; r1++, r2++) {
+ if(str_data[r1]) {
+ for(c1 = 0, c2 = drc.left; c2 <= drc.right; c1++, c2++)
+ dest->SetText(r2, c2, str_data[r1][c1]);
}
}
return;
@@ -1508,11 +1675,10 @@ notary::FreeStack()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
AccRange::AccRange(char *asc)
{
- int i, j;
+ int i, j, l;
- if(asc && *asc){
- i = strlen(asc)+2;
- txt = (char *)malloc(i);
+ if(asc && *asc && (l=strlen(asc)) >1){
+ txt = (char *)malloc(l+2);
for(i = j = 0; i< (int)strlen(asc); i++)
if(asc[i] > 32) txt[j++] = asc[i];
txt[j] = 0;
@@ -1566,6 +1732,26 @@ AccRange::GetNext(int *x, int *y)
}
bool
+AccRange::NextRow(int *y)
+{
+ if(cy <= y2) {
+ *y = cy; cy++; return true;
+ }
+ else if(txt[curridx] && Parse(curridx)) return NextRow(y);
+ return false;
+}
+
+bool
+AccRange::NextCol(int *x)
+{
+ if(cx <= x2) {
+ *x = cx; cx++; return true;
+ }
+ else if(txt[curridx] && Parse(curridx)) return NextCol(x);
+ return false;
+}
+
+bool
AccRange::IsInRange(int x, int y)
{
if(txt && Reset()) do {
@@ -1582,6 +1768,7 @@ AccRange::BoundRec(RECT *rec)
while((curridx < (int)strlen(txt)) && Parse(curridx)) {
UpdateMinMaxRect(rec, x1, y1); UpdateMinMaxRect(rec, x2, y2);
}
+ Reset();
return true;
}
return false;
@@ -1597,15 +1784,15 @@ AccRange::Reset()
bool
AccRange::Parse(int start)
{
- int i, step, *v;
+ int i, l, step, *v;
i = start;
if(!txt) return false;
- if(txt[i] == ';') i++;
+ if(txt[i] == ';' || txt[i] == ',') i++;
if(!txt[i]) return false;
step = x1 = y1 = x2 = y2 = 0;
v = &x1;
- for ( ; i < (int)strlen(txt)+1; i++) {
+ for (l=strlen(txt)+1 ; i < l; i++) {
if(txt[i] == '$') i++;
switch(step) {
case 0:
@@ -1648,8 +1835,8 @@ AccRange::Parse(int start)
x2 = x1; y2 = y1;
}
if(x2<x1) Swap(x1,x2); if(y2<y1) Swap(y1,y2);
- if(y1 >0) y1--; if(y2 >0) y2--;
- if(x1 >0) x1--; if(x2 >0) x2--;
+ if(y1 >=0) y1--; if(y2 >=0) y2--;
+ if(x1 >=0) x1--; if(x2 >=0) x2--;
curridx = i;
cx = x1; cy = y1;
return true;
@@ -1685,8 +1872,8 @@ Default::Default()
OutLine_0.color = OutLine_1.color = OutLine_2.color = 0x00000000L;
OutLine_0.pattern = OutLine_1.pattern = OutLine_2.pattern = 0L;
pl = pgl = 0L; pg = 0L; pg_fl = 0L; rrect_rad = 0L;
- cdisp = 0L; min4log = 0.000001;
- axis_color = 0x0L;
+ cdisp = 0L; min4log = 0.000001; ss_txt = 0.9;
+ axis_color = 0x0L;
svgAttr = svgScript = currPath = IniFile = 0L;
File1 = File2 = File3 = File4 = File5 = File6 = 0L;
}
@@ -1727,7 +1914,7 @@ Default::GetSize(int select)
case 2: return Line_2.width;
default: return Line_0.width;
}
- case SIZE_TEXT: RetVal = 4.0; break;
+ case SIZE_TEXT: RetVal = _TXH; break;
case SIZE_GRECT_TOP: RetVal = 0.0; break;
case SIZE_GRECT_BOTTOM: RetVal = 110.0; break;
case SIZE_GRECT_LEFT: RetVal = 0.0; break;
@@ -1744,7 +1931,7 @@ Default::GetSize(int select)
default: return Line_0.patlength;
}
case SIZE_AXIS_TICKS: RetVal = 2.0; break;
- case SIZE_TICK_LABELS: RetVal = 4.0; break;
+ case SIZE_TICK_LABELS: RetVal = _TXH; break;
case SIZE_WHISKER:
case SIZE_ERRBAR: RetVal = 3.0; break;
case SIZE_WHISKER_LINE:
@@ -1757,16 +1944,16 @@ Default::GetSize(int select)
default: return OutLine_0.width;
}
case SIZE_BOX:
- case SIZE_BAR: RetVal = 10.0; break;
- case SIZE_BUBBLE_LINE: RetVal = 0.4; break;
- case SIZE_BUBBLE_HATCH_LINE: RetVal = 0.1; break;
- case SIZE_ARROW_LINE: RetVal = 0.4; break;
- case SIZE_ARROW_CAPWIDTH: RetVal = 3.0; break;
- case SIZE_ARROW_CAPLENGTH: RetVal = 4.0; break;
- case SIZE_HAIRLINE: RetVal = 0.1; break;
- case SIZE_SEGLINE: RetVal = 0.4; break;
- case SIZE_CELLWIDTH: RetVal = 20.0; break;
- case SIZE_CELLTEXT: RetVal = 4.5; break;
+ case SIZE_BAR: RetVal = 10.0; break;
+ case SIZE_BUBBLE_LINE: RetVal = 0.4; break;
+ case SIZE_BUBBLE_HATCH_LINE: RetVal = 0.1; break;
+ case SIZE_ARROW_LINE: RetVal = 0.4; break;
+ case SIZE_ARROW_CAPWIDTH: RetVal = 3.0; break;
+ case SIZE_ARROW_CAPLENGTH: RetVal = 4.0; break;
+ case SIZE_HAIRLINE: RetVal = 0.1; break;
+ case SIZE_SEGLINE: RetVal = 0.4; break;
+ case SIZE_CELLWIDTH: RetVal = 20.0; break;
+ case SIZE_CELLTEXT: RetVal = 4.5*ss_txt; break;
case SIZE_RRECT_RAD:
return rrect_rad ? *rrect_rad : GetSize(SIZE_SYMBOL)/2.0;
default: return 0.0;
@@ -2184,7 +2371,7 @@ MemCache::GetField()
UndoObj::UndoObj()
{
buff = buff0 = (UndoInfo**)calloc(UNDO_RING_SIZE, sizeof(UndoInfo*));
- stub1 = ndisp = 0;
+ stub1 = ndisp = 0; busy = false;
pcb = &stub1; cdisp = ldisp = 0L; buffers = 0L;
}
@@ -2313,14 +2500,17 @@ UndoObj::InvalidGO(GraphObj *go)
}
void
-UndoObj::Pop()
+UndoObj::Pop(anyOutput *o)
{
int idx;
- if(*pcb < 1) return;
- idx = ((*pcb-1) & UNDO_IDX_MASK);
- if(buff[idx]) FreeInfo(&buff[idx]);
- (*pcb)--;
+ if(o) {
+ SetDisp(o);
+ if(*pcb < 1) return;
+ idx = ((*pcb-1) & UNDO_IDX_MASK);
+ if(buff[idx]) FreeInfo(&buff[idx]);
+ (*pcb)--;
+ }
}
void
@@ -2358,6 +2548,7 @@ UndoObj::Restore(bool redraw, anyOutput*o)
return;
}
(*pcb)--;
+ busy = true;
if(buff[idx]) {
flags = buff[idx]->flags;
switch(buff[idx]->cmd) {
@@ -2370,7 +2561,9 @@ UndoObj::Restore(bool redraw, anyOutput*o)
buff[idx]->loc = (void**)((EtBuff*)buff[idx]->data)->DaO->
etRows[((EtBuff*)buff[idx]->data)->row][((EtBuff*)buff[idx]->data)->col];
}
- ((EditText*)buff[idx]->loc)->SetText(((EtBuff*)buff[idx]->data)->txt);
+ if(((EtBuff*)buff[idx]->data)->DaO) (((EtBuff*)buff[idx]->data)->DaO)->SetText(((EtBuff*)buff[idx]->data)->row,
+ ((EtBuff*)buff[idx]->data)->col, ((EtBuff*)buff[idx]->data)->txt);
+ else ((EditText*)buff[idx]->loc)->SetText(((EtBuff*)buff[idx]->data)->txt);
if(((EtBuff*)buff[idx]->data)->txt) free(((EtBuff*)buff[idx]->data)->txt);
*(((EtBuff*)buff[idx]->data)->cur) = ((EtBuff*)buff[idx]->data)->vcur;
*(((EtBuff*)buff[idx]->data)->m1) = ((EtBuff*)buff[idx]->data)->vm1;
@@ -2418,9 +2611,17 @@ UndoObj::Restore(bool redraw, anyOutput*o)
case UNDO_VALDWORD:
*((DWORD*)(buff[idx]->loc)) = *((DWORD*)(buff[idx]->data));
free(buff[idx]->data); break;
+ case UNDO_POINT:
+ memcpy(buff[idx]->loc, buff[idx]->data, sizeof(POINT));
+ free(buff[idx]->data); break;
+ case UNDO_VOIDPTR:
+ *buff[idx]->loc = buff[idx]->data; break;
case UNDO_VALINT:
*((int*)(buff[idx]->loc)) = *((int*)(buff[idx]->data));
free(buff[idx]->data); break;
+ case UNDO_VALLONG:
+ *((long*)(buff[idx]->loc)) = *((long*)(buff[idx]->data));
+ free(buff[idx]->data); break;
case UNDO_OBJCONF_1: //single object restore
UpdGOfromMem((GraphObj *)buff[idx]->loc, (unsigned char *)buff[idx]->data);
free(buff[idx]->data); break;
@@ -2437,9 +2638,10 @@ UndoObj::Restore(bool redraw, anyOutput*o)
memcpy(buff[idx]->loc, buff[idx]->data, sizeof(fRECT));
free(buff[idx]->data); break;
case UNDO_STRING:
- if(*(buff[idx]->loc)) free(*(buff[idx]->loc));
- CurrGO = buff[idx]->owner;
- *(buff[idx]->loc) = buff[idx]->data; break;
+ if(*(buff[idx]->loc) && buff[idx]->data)
+ strcpy ((char*)(*buff[idx]->loc), (char*)(buff[idx]->data));
+ if(buff[idx]->data) free(buff[idx]->data);
+ CurrGO = buff[idx]->owner; break;
case UNDO_ROTDEF:
memcpy(*(buff[idx]->loc), buff[idx]->data, 6 * sizeof(double));
free(buff[idx]->data); break;
@@ -2493,6 +2695,7 @@ UndoObj::Restore(bool redraw, anyOutput*o)
else {
InfoBox("The UNDO-cache is empty");
}
+ busy = false;
}
void
@@ -2612,6 +2815,23 @@ UndoObj::ValDword(GraphObj *parent, DWORD *val, DWORD flags)
if(0 > NewItem(UNDO_VALDWORD, flags, parent, ptr, (void**)val)) free(ptr);
}
+void
+UndoObj::Point(GraphObj *parent, POINT *pt, anyOutput * o, DWORD flags)
+{
+ void *ptr;
+
+ if(o) SetDisp(o);
+ if(!(ptr = memdup(pt, sizeof(POINT), 0))) return;
+ if(0 > NewItem(UNDO_POINT, flags, parent, ptr, (void**)pt)) free(ptr);
+}
+
+void
+UndoObj::VoidPtr(GraphObj *parent, void **pptr, void *ptr, anyOutput * o, DWORD flags)
+{
+ if(o) SetDisp(o);
+ if(0 > NewItem(UNDO_VOIDPTR, flags, parent, ptr, pptr)) free(ptr);
+}
+
void
UndoObj::ValInt(GraphObj *parent, int *val, DWORD flags)
{
@@ -2622,6 +2842,15 @@ UndoObj::ValInt(GraphObj *parent, int *val, DWORD flags)
}
void
+UndoObj::ValLong(GraphObj *parent, long *val, DWORD flags)
+{
+ void *ptr;
+
+ if(!(ptr = memdup(val, sizeof(long), 0))) return;
+ if(0 > NewItem(UNDO_VALINT, flags, parent, ptr, (void**)val)) free(ptr);
+}
+
+void
UndoObj::ObjConf(GraphObj *go, DWORD flags)
{
long sz;
@@ -2768,14 +2997,13 @@ UndoObj::DataMem(GraphObj *go, void **mem, int size, long *count, DWORD flags)
}
void
-UndoObj::DataObject(GraphObj *go, anyOutput *o, DataObj *d, DWORD flags)
+UndoObj::DataObject(GraphObj *go, anyOutput *o, DataObj *d, RECT *rc, DWORD flags)
{
- int w, h;
StrData *save;
if(!go || !d) return;
if(o) SetDisp(o);
- if(!(d->GetSize(&w, &h)) || !(save = new StrData(d))) return;
+ if(!(save = new StrData(d, rc))) return;
if(0 > NewItem(UNDO_DATA, flags, go, save, (void**)d)) if(save) delete(save);
}
@@ -2792,12 +3020,8 @@ UndoObj::TextCell(EditText *et, anyOutput *o, char *text, int *cur, int *m1, int
if(text && text[0]) ptr->txt = strdup(text);
ptr->cur = cur; ptr->m1 = m1; ptr->m2 = m2;
ptr->vcur = *cur; ptr->vm1 = *m1; ptr->vm2 = *m2;
- ptr->row = 0; ptr->col = 0;
- if(ptr->DaO = (DataObj*)DaO) {
- if(ptr->DaO->Command(CMD_CURRPOS, &cpos, 0L)){
- ptr->row = cpos.y; ptr->col = cpos.x;
- }
- }
+ ptr->row = et->row; ptr->col = et->col;
+ ptr->DaO = (DataObj*)et->parent;
if(0 > NewItem(UNDO_ET, flags, 0L, ptr, (void**)et)) {
if(ptr->txt)free (ptr->txt); free(ptr);
}
@@ -2874,6 +3098,7 @@ UndoObj::FreeInfo(UndoInfo** inf)
case UNDO_MOVE: case UNDO_RECT: case UNDO_STRING:
case UNDO_ROTDEF: case UNDO_LINEDEF: case UNDO_FILLDEF:
case UNDO_LFP3D: case UNDO_FLOAT: case UNDO_SAVVAR:
+ case UNDO_POINT: case UNDO_VALLONG:
free((*inf)->data);
break;
}
diff --git a/Utils.cpp b/Utils.cpp
index 33fc5b2..a3bc6da 100755
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -439,6 +439,43 @@ char **split(char *str, char sep, int *nl)
return ptr;
}
+char *fit_num_rect(anyOutput *o, int max_width, char *num_str)
+{
+ int i, j, k, w, h, slen;
+ char mant[20], expo[20], fmt[10];
+ double num;
+
+ o->oGetTextExtent(num_str, slen = strlen(num_str), &w, &h);
+ if(w < (max_width-5)) return num_str;
+ //first try to remove leading zero from exponent
+ for(i = 0; i < slen; i++) if(num_str[i] == 'e') break;
+ if(num_str[i] == 'e') while (num_str[i+2] == '0') {
+ for(j = i+2; num_str[j]; j++) num_str[j] = num_str[j+1];
+ o->oGetTextExtent(num_str, slen = strlen(num_str), &w, &h);
+ if(w < (max_width-5)) return num_str;
+ }
+ //no success: reduce the number of digit by rounding
+ for(i = k = 0; i <= slen; i++){
+ if(num_str[i] == '.') k = i;
+ if((mant[i] = num_str[i]) == 'e' || mant[i] == 0) break;
+ }
+ if(num_str[i] =='e') mant[i] = 0; k = i - k-1;
+ for(j = 0; num_str[i]; j++, i++) expo[j] = num_str[i]; expo[j] = 0;
+ sscanf(mant, "%lf", &num);
+ if(k >0) do {
+ sprintf(fmt, "%s.%dlf%s", "%", k, expo);
+ sprintf(num_str, fmt, num); k--;
+ o->oGetTextExtent(num_str, slen = strlen(num_str), &w, &h);
+ if(w < (max_width-5)) return num_str;
+ }while (k >= 0);
+ //cannot fit: return hash marks instead
+ for(i = w = 0; w < (max_width-5); i++) {
+ sprintf(num_str+i, "#");
+ o->oGetTextExtent(num_str, slen = strlen(num_str), &w, &h);
+ }
+ num_str[i-1] = 0; return num_str;
+}
+
//----------------------------------------------------------------------------
// bounding rectangle utilities
//----------------------------------------------------------------------------
@@ -936,6 +973,8 @@ void DeleteGO(GraphObj *go)
case GO_OBJTREE: delete((ObjTree*)go); break;
case GO_FREQDIST: delete((FreqDist*)go); break;
case GO_GRID3D: delete((Grid3D*)go); break;
+ case GO_FUNC3D: delete((Func3D*)go); break;
+ case GO_XYSTAT: delete((xyStat*)go); break;
default:
sprintf(TmpTxt, "Cannot delete Object\nwith Id %ld", go->Id);
ErrorBox(TmpTxt);
@@ -944,6 +983,35 @@ void DeleteGO(GraphObj *go)
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//Delete a graphic object from a list
+bool DeleteGOL(GraphObj ***gol, long n, GraphObj *go, anyOutput *o)
+{
+ long i;
+ int c;
+ GraphObj **g, *p;
+
+ if(!gol || !(*gol) || !go || !n) return false;
+ for (i = 0, c = 0, g = *gol; i < n; i++, g++) {
+ if(*g) {
+ c++;
+ if(*g == go) {
+ p = (*g)->parent;
+ if(o) o->HideMark();
+ Undo.DeleteGO(g, 0L, o);
+ if(c == 1) {
+ for (g++, i++ ;i < n; i++, g++) {
+ if(*g) return true;
+ }
+ if(p) Undo.DropMemory(p, (void**) gol, UNDO_CONTINUE);
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//backup file before writing a new one
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool BackupFile(char *FileName)
@@ -1015,6 +1083,16 @@ bool FileExist(char *FileName)
return true;
}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//check Object for certain properties
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+bool IsPlot3D(GraphObj *g)
+{
+ if(g && (g->Id == GO_PLOT3D || g->Id == GO_FUNC3D)) return true;
+ return false;
+}
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//duplicate a block of memory
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1069,6 +1147,7 @@ unsigned int HashValue(unsigned char *str)
if(str[i] > 32) ret = ((str[i]-32) + (ret <<2));
i++;
}while(str[i]);
+ if(i < 4) memcpy(&ret, str, i);
return ret;
}
diff --git a/Version.h b/Version.h
index 5289724..aca17f5 100755
--- a/Version.h
+++ b/Version.h
@@ -16,5 +16,4 @@
// along with RLPlot; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
-#define SZ_VERSION "0.99.14b"
-
+#define SZ_VERSION "1.0"
diff --git a/WinSpec.cpp b/WinSpec.cpp
index fb917e7..ff11d6e 100755
--- a/WinSpec.cpp
+++ b/WinSpec.cpp
@@ -242,6 +242,19 @@ bool YesNoBox(char *Msg)
return false;
}
+int YesNoCancelBox(char *Msg)
+{
+ int res;
+
+ res = MessageBox(0, Msg, "RLPlot", MB_YESNOCANCEL | MB_ICONQUESTION);
+ switch(res) {
+ case IDYES: return 1;
+ case IDNO: return 0;
+ default: return 2;
+ }
+ return 0;
+}
+
void Qt_Box()
{
MessageBox(0, "No Qt installed\nunder Windows", "Error", MB_OK | MB_ICONQUESTION);
@@ -437,6 +450,39 @@ void EmptyClip()
CloseClipboard();
}
+void CopyText(char *txt, int len)
+{
+ HGLOBAL hmem;
+ unsigned char* buf;
+
+ if(!txt || !txt[0]) return;
+ if(!len) len = strlen(txt);
+ OpenClipboard(MainWnd);
+ EmptyClipboard();
+ if(hmem = GlobalAlloc(GMEM_MOVEABLE, len+2)) {
+ if(buf = (unsigned char *)GlobalLock(hmem)) {
+ memcpy(buf, txt, len); buf[len] = 0;
+ GlobalUnlock(hmem);
+ SetClipboardData(CF_TEXT, hmem);
+ }
+ }
+ CloseClipboard();
+}
+
+unsigned char* PasteText()
+{
+ HANDLE hmem = 0;
+ unsigned char *ptr, *ret=0L;
+
+ OpenClipboard(MainWnd);
+ if((hmem = GetClipboardData(CF_TEXT)) && (ptr = (unsigned char*) GlobalLock(hmem))){
+ ret = (unsigned char*) strdup((char*)ptr);
+ }
+ if(hmem) GlobalUnlock(hmem);
+ CloseClipboard();
+ return ret;
+}
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get display (desktop) size
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -822,8 +868,7 @@ BitMapWin::oGetTextExtent(char *text, int cb, int *width, int *height)
d = (TextExtent.cx * ((7.0 + d)/8.0));
TextExtent.cx = iround(d);
}
- *width = TextExtent.cx;
- *height = TextExtent.cy;
+ *width = TextExtent.cx; *height = TextExtent.cy;
return true;
}
@@ -1708,31 +1753,6 @@ void FindBrowser()
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Shutdown or reboot windows
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-void HardExit(bool reboot)
-{
- int tpsize;
- HANDLE hProcess, hAccessToken;
- TOKEN_PRIVILEGES *tp;
-
- hProcess = GetCurrentProcess();
- tpsize = sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES);
- tp = (TOKEN_PRIVILEGES *)malloc(tpsize);
- if(tp){
- tp->PrivilegeCount = 1;
- tp->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- if(LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tp->Privileges[0].Luid)) {
- if(OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hAccessToken))
- AdjustTokenPrivileges(hAccessToken, FALSE, tp, tpsize, NULL, NULL);
- }
- free(tp);
- }
- if(reboot) ExitWindowsEx(EWX_REBOOT | EWX_FORCE, NULL);
- else ExitWindowsEx(EWX_POWEROFF | EWX_FORCE, NULL);
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Windos entry point
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInstance,
@@ -1746,6 +1766,14 @@ WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInstance,
dlgtxtheight = 16;
if(lpCmdLine && lpCmdLine[0] && FileExist(lpCmdLine)) LoadFile = strdup(lpCmdLine);
+ else if(lpCmdLine) { //probably Unicode
+ sprintf(TmpTxt, "%s", lpCmdLine);
+ if(TmpTxt[0] == '"'){
+ strcpy(TmpTxt, TmpTxt+1);
+ if(TmpTxt[0]) TmpTxt[strlen(TmpTxt)-1] = 0;
+ }
+ if(TmpTxt[0]) LoadFile= strdup(TmpTxt);
+ }
hInstance = hInst;
wndclass.style = CS_BYTEALIGNWINDOW | CS_DBLCLKS;
wndclass.lpfnWndProc = WndProc;
@@ -1848,15 +1876,20 @@ void ScrollEvent(bool bVert, HWND hwnd, UINT type, GraphObj *g, OutputWin *w)
pos = si.nPos + LineStep;
break;
case SB_PAGEUP:
- pos = (si.nPos - (int)si.nPage) >= si.nMin ?
- (si.nPos - si.nPage) : si.nMin;
+ if(g->Id == GO_SPREADDATA) {
+ g->Command(CMD_PAGEUP, 0L, w);
+ return;
+ }
+ pos = (si.nPos - (int)si.nPage) >= si.nMin ? (si.nPos - si.nPage) : si.nMin;
break;
case SB_PAGEDOWN:
- pos = ((unsigned)si.nPos + si.nPage*2) < (unsigned)si.nMax ?
- (si.nPos + si.nPage) : (si.nMax - si.nPage+1);
+ if(g->Id == GO_SPREADDATA) {
+ g->Command(CMD_PAGEDOWN, 0L, w);
+ return;
+ }
+ pos = (si.nPos + (int)si.nPage*2) < si.nMax ? (si.nPos + si.nPage) : (si.nMax - si.nPage+1);
break;
- case SB_THUMBTRACK:
- case SB_THUMBPOSITION:
+ case SB_THUMBTRACK: case SB_THUMBPOSITION:
pos = si.nTrackPos;
break;
default:
@@ -1977,20 +2010,17 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
if(CopyWMF && CopyWMF->StartPage()) {
copy_obj->DoPlot(CopyWMF);
CopyWMF->EndPage();
+ delete CopyWMF; CopyWMF = NULL;
}
- delete CopyWMF;
- CopyWMF = NULL;
if(copy_obj->Id == GO_GRAPH || copy_obj->Id == GO_PAGE) copy_obj->DoPlot(0L);
break;
case CF_BITMAP:
if((CopyBMP = new BitMapWin(copy_obj)) && CopyBMP->StartPage()) {
- copy_obj->DoPlot(CopyBMP);
- CopyBMP->EndPage();
+ copy_obj->DoPlot(CopyBMP); CopyBMP->EndPage();
SetClipboardData(CF_BITMAP, CopyBMP->scr);
- CopyBMP->scr = 0L;
+ CopyBMP->scr = 0L; CopyBMP->go = 0L;
+ delete CopyBMP; CopyBMP = NULL;
}
- delete CopyBMP;
- CopyBMP = NULL;
if(copy_obj->Id == GO_GRAPH || copy_obj->Id == GO_PAGE) copy_obj->DoPlot(0L);
break;
case CF_SYLK: case CF_TEXT:
@@ -2007,11 +2037,12 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
wParam &= 0xffff;
if(g && w) switch(wParam) {
case CM_EXIT:
- g->Command(CMD_CAN_DELETE, 0L, 0L);
- SetWindowLong(hwnd, 0, 0L);
- SetWindowLong(hwnd, GWL_USERDATA, 0L);
- w->go = 0L;
- DestroyWindow(hwnd);
+ if(g->Command(CMD_CAN_CLOSE, 0L, 0L)) {
+ SetWindowLong(hwnd, 0, 0L);
+ SetWindowLong(hwnd, GWL_USERDATA, 0L);
+ w->go = 0L;
+ DestroyWindow(hwnd);
+ }
return 0;
case CM_PASTE:
w->MouseCursor(MC_WAIT, true);
@@ -2134,12 +2165,6 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
case CM_ADDROWCOL:
g->Command(CMD_ADDROWCOL, (void *)NULL, w);
return 0;
- case CM_REBOOT:
- HardExit(true);
- return 0;
- case CM_SHUTDOWN:
- HardExit(false);
- return 0;
case CM_DEFAULTS:
g->Command(CMD_CONFIG, 0L, w);
return 0;
@@ -2186,7 +2211,7 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
case CM_UPARRKEY: case CM_DOWNARRKEY: case CM_POS_FIRST:
case CM_POS_LAST: case CM_SHLEFT: case CM_SHRIGHT:
case CM_SHUP: case CM_SHDOWN: case CM_TAB:
- case CM_SHTAB:
+ case CM_SHTAB: case CM_SHPGUP: case CM_SHPGDOWN:
switch(wParam) {
case CM_DELKEY: cc = CMD_DELETE; break;
case CM_LEFTARRKEY: cc = CMD_CURRLEFT; break;
@@ -2201,6 +2226,8 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
case CM_SHDOWN: cc = CMD_SHIFTDOWN; break;
case CM_TAB: cc = CMD_TAB; break;
case CM_SHTAB: cc = CMD_SHTAB; break;
+ case CM_SHPGUP: cc = CMD_SHPGUP; break;
+ case CM_SHPGDOWN: cc = CMD_SHPGDOWN; break;
}
g->Command(cc, (void *)NULL, w);
return 0;
@@ -2210,6 +2237,18 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
case CM_UNDO:
g->Command(CMD_UNDO, 0L, w);
return 0;
+ case CM_INSROW:
+ g->Command(CMD_INSROW, 0L, w);
+ return 0;
+ case CM_INSCOL:
+ g->Command(CMD_INSCOL, 0L, w);
+ return 0;
+ case CM_DELROW:
+ g->Command(CMD_DELROW, 0L, w);
+ return 0;
+ case CM_DELCOL:
+ g->Command(CMD_DELCOL, 0L, w);
+ return 0;
default:
sprintf(TmpTxt, "Command 0x%x (%d)\nreceived", wParam & 0xffff,
wParam & 0xffff);
@@ -2217,13 +2256,13 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
}
return 0;
case WM_CLOSE:
- if(g) {
- g->Command(CMD_CAN_DELETE, 0L, 0L);
+ if(g && g->Command(CMD_CAN_CLOSE, 0L, 0L)) {
SetWindowLong(hwnd, 0, 0L);
SetWindowLong(hwnd, GWL_USERDATA, 0L);
w->go = 0L;
+ DestroyWindow(hwnd);
}
- DestroyWindow(hwnd);
+ else if(!g) DestroyWindow(hwnd);
return 0;
case WM_DESTROY:
if(hwnd == MainWnd)PostQuitMessage(0);
@@ -2276,6 +2315,8 @@ long FAR PASCAL DlgWndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
break;
case WM_CHAR:
if(0x09 == (cc = wParam & 0xff)) break; //ignore Tab
+ if(cc == 0x03) return d->Command(CMD_COPY, 0L, w); //^c copy
+ if(cc == 0x16) return d->Command(CMD_PASTE, 0L, w); //^v paste
if(d && w) d->Command(CMD_ADDCHAR, (void *)(& cc), w);
break;
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
@@ -2355,7 +2396,7 @@ void *CreateDlgWnd(char *title, int x, int y, int width, int height, tag_DlgObj
x, y, width, height, GetFocus(), NULL, hInstance, NULL);
w = new OutputWin(0L, hDlg);
w->units = defs.cUnits;
- if(hDlg && w && w->Erase(0x00c0c0c0L)) {
+ if(hDlg && w && w->Erase(0x00e0e0e0L)) {
SetWindowLong(hDlg, GWL_USERDATA, (long)w);
SetWindowLong(hDlg, 0, (long)d);
ShowWindow(hDlg, SW_SHOW);
@@ -2387,6 +2428,7 @@ void LoopDlgWnd() //keep message processing running
void CloseDlgWnd(void *hDlg)
{
+ HideCopyMark();
if(hDlg) SendMessage((HWND)hDlg, WM_CLOSE, 0, 0);
}
diff --git a/WinSpec.h b/WinSpec.h
index f6a6423..af66052 100755
--- a/WinSpec.h
+++ b/WinSpec.h
@@ -57,6 +57,7 @@ public:
OutputWin(GraphObj *g, HWND hw);
~OutputWin();
bool ActualSize(RECT *rc);
+ void Focus(){if(hWnd) SetFocus(hWnd);};
void Caption(char *txt);
void MouseCursor(int cid, bool force);
bool SetScroll(bool isVert, int iMin, int iMax, int iPSize, int iPos);
diff --git a/exprlp.cpp b/exprlp.cpp
index b374c7f..fbccddb 100755
--- a/exprlp.cpp
+++ b/exprlp.cpp
@@ -11,6 +11,7 @@ int file_fmt = FF_UNKNOWN;
bool bQuiet = false, bSVGtype = false, bDelete = false;
char *szFile1 = 0L, *szFile2 = 0L;
int dlgtxtheight = 12; //stub: not used
+char *name1, *name2; //the filenames
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// direct messages to console
@@ -29,6 +30,28 @@ bool YesNoBox(char *Msg)
{
return false;
}
+
+int YesNoCancelBox(char *Msg)
+{
+ return 0;
+}
+
+void HideCopyMark()
+{
+}
+
+void ShowCopyMark(anyOutput *out, RECT *mrk, int nRec)
+{
+}
+
+void CopyText(char *txt, int len)
+{
+}
+
+unsigned char* PasteText()
+{
+ return 0L;
+}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// STUBS: we do not need dialogs
@@ -168,6 +191,11 @@ bool PlotScatt::PropertyDlg()
{
return false;
}
+
+bool xyStat::PropertyDlg()
+{
+ return false;
+}
bool Regression::PropertyDlg()
{
@@ -262,6 +290,11 @@ bool Chart25D::PropertyDlg()
bool Ribbon25D::PropertyDlg()
{
return false;
+}
+
+bool Func3D::PropertyDlg()
+{
+ return false;
}
bool BubblePlot3D::PropertyDlg()
@@ -314,7 +347,7 @@ bool Page::Configure()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
char *SaveGraphAsName(char *oldname)
{
- return 0L;
+ return name2;
}
char *OpenGraphName(char *oldname)
@@ -356,7 +389,7 @@ bool DelBitmapClass(anyOutput *w)
{
return false;
}
-
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// create a root object to handle I/O
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -367,7 +400,6 @@ public:
bool Command(int cmd, void *tmpl, anyOutput *o);
private:
- char *name1, *name2;
GraphObj *go;
};
@@ -409,6 +441,9 @@ ExpRoot::Command(int cmd, void *tmpl, anyOutput *o)
break;
case FF_EPS:
DoExportEps(go, name2, 0L);
+ break;
+ case FF_RLP:
+ SaveGraphAs(go);
break;
default:
ErrorBox("Unknown file extension or format of destination");
@@ -426,7 +461,7 @@ int Usage()
{
printf("______________________________________________________________\n");
printf("\nexprlp: RLPlot export utility, version %s.\n", SZ_VERSION);
- printf("Copyright (C) 2002-2004 R. Lackner\n");
+ printf("Copyright (C) 2002-2005 R. Lackner\n");
printf("This is free software published under the GNU\n");
printf("general public licence (GPL).\n");
printf("\nUsage: exprlp [options] <input> [options] [<output>]\n");
@@ -479,6 +514,9 @@ int main (int argc, char **argv)
case 'e': case 'E':
file_fmt = FF_EPS;
break;
+ case 'r': case 'R':
+ file_fmt = FF_RLP;
+ break;
case 'w': case 'W':
file_fmt = FF_WMF;
break;
@@ -512,6 +550,7 @@ int main (int argc, char **argv)
if(0==strcmp(".svg", szFile2+i-4)) file_fmt = FF_SVG;
else if(0==strcmp(".wmf", szFile2+i-4)) file_fmt = FF_WMF;
else if(0==strcmp(".eps", szFile2+i-4)) file_fmt = FF_EPS;
+ else if(0==strcmp(".rlp", szFile2+i-4)) file_fmt = FF_RLP;
}
if(file_fmt == FF_UNKNOWN) {
if(szFile1)printf("\n**** Unknown file extension or format ****\n\n");
diff --git a/mfcalc.cpp b/mfcalc.cpp
old mode 100755
new mode 100644
index 8f7f943..9144a14
--- a/mfcalc.cpp
+++ b/mfcalc.cpp
@@ -5,26 +5,38 @@
#define YYBISON 1 /* Identify Bison output. */
#define NUM 257
-#define ARR 258
-#define STR 259
-#define PI 260
-#define E 261
-#define CLVAL 262
-#define VAR 263
-#define FNCT 264
-#define TXT 265
-#define CLAUSE 266
-#define COLR 267
-#define COLC 268
-#define AND 269
-#define OR 270
-#define EQ 271
-#define NE 272
-#define GT 273
-#define GE 274
-#define LT 275
-#define LE 276
-#define NEG 277
+#define STR 258
+#define ARR 259
+#define BLOCK 260
+#define PI 261
+#define E 262
+#define CLVAL 263
+#define PSEP 264
+#define IF 265
+#define ELSE 266
+#define VAR 267
+#define FNCT 268
+#define AFNCT 269
+#define SFNCT 270
+#define FUNC2 271
+#define TXT 272
+#define CLAUSE 273
+#define SER 274
+#define COLR 275
+#define COLC 276
+#define AND 277
+#define OR 278
+#define EQ 279
+#define NE 280
+#define GT 281
+#define GE 282
+#define LT 283
+#define LE 284
+#define NEG 285
+#define INC 286
+#define DEC 287
+#define PINC 288
+#define PDEC 289
/*
@@ -54,16 +66,27 @@
#include <stdio.h>
#include "rlplot.h"
-struct symrec {
+class symrec {
+public:
int type, row, col;
unsigned int h_name;
char *name, *text;
- struct {
- double var;
- double (*fnctptr)(...);
- } value;
- int arg_type;
- struct symrec *next;
+ double (*fnctptr)(...);
+ symrec *next;
+ double var;
+
+ symrec(unsigned int h_n, int typ, symrec *nxt);
+ ~symrec();
+ double GetValue();
+ void GetValue(void *res);
+ double SetValue(double v);
+ void SetValue(void* dest, void* src);
+ void SetName(char *nam);
+ void InitSS();
+
+private:
+ bool isSSval;
+
};
// syntactical information
@@ -86,27 +109,32 @@ typedef struct{
}YYSTYPE;
-static symrec *putsym (unsigned int h_name, int sym_type, int arg_type);
+static symrec *putsym (unsigned int h_name, int sym_type);
static symrec *getsym (unsigned int h_name, char *sym_name = 0L);
static int push(YYSTYPE *res, YYSTYPE *val);
static void store_res(YYSTYPE *res);
static char *PushString(char *text);
static char *add_strings(char *st1, char *st2);
static char *string_value(YYSTYPE *exp);
-static int get_range(YYSTYPE *res, char *first, char *last);
+static double eval(YYSTYPE *sr, YYSTYPE *dst);
+static int range_array(YYSTYPE * res, char *range);
static void exec_clause(YYSTYPE *res);
static YYSTYPE *proc_clause(YYSTYPE *res);
static void yyerror(char *s);
static int yylex(void);
+static double nop() {return 0.0;};
static char res_txt[1000];
static anyResult line_res = {ET_UNKNOWN, 0.0, res_txt};
-static double line_result;
static DataObj *curr_data;
+static char *last_error = 0L; //error text
+static char *last_err_desc = 0L; //short error description
-//the current command buffer
-static char *buffer = 0L;
+static char *buffer = 0L; //the current command buffer
static int buff_pos = 0;
+static bool bRecent = false; //rearrange functions
+static int parse_level = 0; //count reentrances into parser
+#define MAX_PARSE 20 //maximum number of reentances
#include <stdio.h>
#ifndef __cplusplus
@@ -117,23 +145,23 @@ static int buff_pos = 0;
-#define YYFINAL 79
+#define YYFINAL 131
#define YYFLAG -32768
-#define YYNTBASE 36
+#define YYNTBASE 48
-#define YYTRANSLATE(x) ((unsigned)(x) <= 277 ? yytranslate[x] : 40)
+#define YYTRANSLATE(x) ((unsigned)(x) <= 289 ? yytranslate[x] : 54)
static const char yytranslate[] = { 0,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 32,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 44,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 34,
- 35, 28, 27, 13, 26, 2, 29, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 33, 2,
- 12, 2, 17, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 46,
+ 47, 36, 35, 20, 34, 2, 37, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 45, 2,
+ 19, 2, 25, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 31, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 43, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -150,174 +178,245 @@ static const char yytranslate[] = { 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 14, 15, 16, 18, 19,
- 20, 21, 22, 23, 24, 25, 30
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 21, 22, 23, 24, 26, 27, 28, 29,
+ 30, 31, 32, 33, 38, 39, 40, 41, 42
};
#if YYDEBUG != 0
static const short yyprhs[] = { 0,
- 0, 1, 4, 7, 10, 13, 16, 19, 22, 24,
- 28, 32, 36, 38, 40, 42, 44, 46, 48, 52,
- 57, 61, 65, 69, 73, 77, 81, 85, 89, 93,
- 97, 101, 105, 109, 113, 116, 120, 124, 128, 134,
- 140, 146
+ 0, 1, 4, 6, 8, 10, 13, 16, 19, 22,
+ 25, 28, 30, 34, 38, 42, 44, 48, 50, 52,
+ 56, 60, 62, 66, 68, 70, 72, 74, 76, 78,
+ 80, 84, 88, 93, 98, 105, 114, 119, 124, 131,
+ 140, 146, 154, 158, 162, 166, 170, 174, 178, 182,
+ 186, 190, 194, 198, 202, 205, 208, 211, 214, 217,
+ 221, 225, 231, 237, 243
};
static const short yyrhs[] = { -1,
- 36, 37, 0, 32, 33, 0, 39, 32, 0, 39,
- 33, 0, 38, 32, 0, 38, 33, 0, 1, 32,
- 0, 5, 0, 38, 27, 39, 0, 39, 27, 38,
- 0, 38, 27, 38, 0, 3, 0, 11, 0, 8,
- 0, 6, 0, 7, 0, 9, 0, 9, 12, 39,
- 0, 10, 34, 39, 35, 0, 39, 18, 39, 0,
- 39, 19, 39, 0, 39, 20, 39, 0, 39, 21,
- 39, 0, 39, 22, 39, 0, 39, 23, 39, 0,
- 39, 24, 39, 0, 39, 25, 39, 0, 39, 27,
- 39, 0, 39, 26, 39, 0, 39, 28, 39, 0,
- 39, 29, 39, 0, 39, 13, 39, 0, 9, 15,
- 9, 0, 26, 39, 0, 39, 31, 39, 0, 39,
- 14, 39, 0, 34, 39, 35, 0, 39, 17, 39,
- 16, 39, 0, 39, 17, 5, 16, 5, 0, 39,
- 17, 5, 16, 39, 0, 39, 17, 39, 16, 5,
- 0
+ 48, 49, 0, 44, 0, 45, 0, 20, 0, 53,
+ 44, 0, 53, 45, 0, 53, 20, 0, 50, 44,
+ 0, 50, 45, 0, 1, 44, 0, 4, 0, 50,
+ 35, 53, 0, 53, 35, 50, 0, 50, 35, 50,
+ 0, 50, 0, 13, 23, 13, 0, 5, 0, 53,
+ 0, 52, 20, 52, 0, 52, 21, 53, 0, 51,
+ 0, 3, 22, 3, 0, 3, 0, 18, 0, 9,
+ 0, 7, 0, 8, 0, 13, 0, 6, 0, 13,
+ 19, 53, 0, 13, 19, 50, 0, 14, 46, 53,
+ 47, 0, 15, 46, 52, 47, 0, 15, 46, 53,
+ 10, 53, 47, 0, 15, 46, 53, 10, 53, 10,
+ 53, 47, 0, 16, 46, 50, 47, 0, 16, 46,
+ 53, 47, 0, 17, 46, 52, 10, 52, 47, 0,
+ 17, 46, 52, 10, 52, 10, 51, 47, 0, 11,
+ 46, 53, 47, 6, 0, 11, 46, 53, 47, 6,
+ 12, 6, 0, 53, 26, 53, 0, 53, 27, 53,
+ 0, 53, 28, 53, 0, 53, 29, 53, 0, 53,
+ 30, 53, 0, 53, 31, 53, 0, 53, 32, 53,
+ 0, 53, 33, 53, 0, 53, 35, 53, 0, 53,
+ 34, 53, 0, 53, 36, 53, 0, 53, 37, 53,
+ 0, 34, 53, 0, 13, 39, 0, 13, 40, 0,
+ 39, 13, 0, 40, 13, 0, 53, 43, 53, 0,
+ 46, 52, 47, 0, 53, 25, 53, 24, 53, 0,
+ 53, 25, 4, 24, 4, 0, 53, 25, 4, 24,
+ 53, 0, 53, 25, 53, 24, 4, 0
};
#endif
#if YYDEBUG != 0
static const short yyrline[] = { 0,
- 102, 103, 106, 107, 108, 109, 110, 111, 114, 116,
- 117, 118, 121, 122, 123, 124, 125, 126, 127, 129,
- 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
- 141, 142, 144, 145, 146, 147, 148, 149, 150, 151,
- 152, 153
+ 121, 122, 125, 125, 125, 126, 127, 128, 129, 130,
+ 131, 134, 136, 137, 138, 141, 143, 146, 147, 148,
+ 149, 150, 151, 155, 156, 157, 158, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+ 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
+ 183, 184, 185, 186, 188, 189, 190, 191, 192, 193,
+ 194, 195, 196, 197, 198
};
#endif
#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
-static const char * const yytname[] = { "$","error","$undefined.","NUM","ARR",
-"STR","PI","E","CLVAL","VAR","FNCT","TXT","'='","','","CLAUSE","COLR","COLC",
-"'?'","AND","OR","EQ","NE","GT","GE","LT","LE","'-'","'+'","'*'","'/'","NEG",
-"'^'","'\\n'","';'","'('","')'","input","line","str_exp","exp", NULL
+static const char * const yytname[] = { "$","error","$undefined.","NUM","STR",
+"ARR","BLOCK","PI","E","CLVAL","PSEP","IF","ELSE","VAR","FNCT","AFNCT","SFNCT",
+"FUNC2","TXT","'='","','","CLAUSE","SER","COLR","COLC","'?'","AND","OR","EQ",
+"NE","GT","GE","LT","LE","'-'","'+'","'*'","'/'","NEG","INC","DEC","PINC","PDEC",
+"'^'","'\\n'","';'","'('","')'","input","line","str_exp","range","arr","exp", NULL
};
#endif
static const short yyr1[] = { 0,
- 36, 36, 37, 37, 37, 37, 37, 37, 38, 38,
- 38, 38, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39
+ 48, 48, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 50, 50, 50, 50, 51, 51, 52, 52, 52,
+ 52, 52, 52, 53, 53, 53, 53, 53, 53, 53,
+ 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+ 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+ 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+ 53, 53, 53, 53, 53
};
static const short yyr2[] = { 0,
- 0, 2, 2, 2, 2, 2, 2, 2, 1, 3,
- 3, 3, 1, 1, 1, 1, 1, 1, 3, 4,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 2, 3, 3, 3, 5, 5,
- 5, 5
+ 0, 2, 1, 1, 1, 2, 2, 2, 2, 2,
+ 2, 1, 3, 3, 3, 1, 3, 1, 1, 3,
+ 3, 1, 3, 1, 1, 1, 1, 1, 1, 1,
+ 3, 3, 4, 4, 6, 8, 4, 4, 6, 8,
+ 5, 7, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 2, 2, 2, 2, 2, 3,
+ 3, 5, 5, 5, 5
};
static const short yydefact[] = { 1,
- 0, 0, 13, 9, 16, 17, 15, 18, 0, 14,
- 0, 0, 0, 2, 0, 0, 8, 0, 0, 0,
- 35, 3, 0, 0, 6, 7, 0, 0, 0, 0,
+ 0, 0, 24, 12, 30, 27, 28, 26, 0, 29,
+ 0, 0, 0, 0, 25, 5, 0, 0, 0, 3,
+ 4, 0, 2, 0, 0, 11, 0, 0, 56, 57,
+ 0, 0, 0, 0, 55, 58, 59, 24, 18, 29,
+ 16, 22, 0, 19, 0, 9, 10, 8, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 4, 5, 19, 34, 0, 0, 38, 12,
- 10, 33, 37, 0, 0, 21, 22, 23, 24, 25,
- 26, 27, 28, 30, 11, 29, 31, 32, 36, 20,
- 29, 0, 0, 40, 41, 42, 39, 0, 0
+ 0, 0, 6, 7, 0, 32, 31, 0, 0, 19,
+ 0, 0, 0, 0, 0, 0, 0, 0, 61, 15,
+ 13, 0, 0, 43, 44, 45, 46, 47, 48, 49,
+ 50, 52, 14, 51, 53, 54, 60, 0, 33, 34,
+ 0, 37, 38, 0, 51, 23, 17, 20, 21, 0,
+ 0, 41, 0, 0, 63, 64, 65, 62, 0, 0,
+ 35, 0, 39, 42, 0, 0, 0, 36, 40, 0,
+ 0
};
static const short yydefgoto[] = { 1,
- 14, 15, 16
+ 23, 41, 42, 43, 44
};
static const short yypact[] = {-32768,
- 33, -31,-32768,-32768,-32768,-32768,-32768, 0, -26,-32768,
- 115, -19, 115,-32768, -22, 171,-32768, 115, 23, 115,
- 4,-32768, 133, 42,-32768,-32768, 115, 115, 72, 115,
- 115, 115, 115, 115, 115, 115, 115, 115, 42, 115,
- 115, 115,-32768,-32768, 211,-32768, 152, 115,-32768,-32768,
- 230, 246, 261, 47, 192, 109, 109, 29, 29, 29,
- 29, 29, 29, -25,-32768, -25, 4, 4, 4,-32768,
- -25, 81, 94,-32768, 261,-32768, 261, 46,-32768
+ 88, -39,-32768,-32768,-32768,-32768,-32768,-32768, -33, 2,
+ -26, -24, -18, -17,-32768,-32768, 378, 21, 24,-32768,
+-32768, 132,-32768, -27, 419,-32768, 378, 173,-32768,-32768,
+ 378, 132, 173, 132, 3,-32768,-32768, 23,-32768, 0,
+ 8,-32768, -14, 331, 173,-32768,-32768,-32768, 214, 378,
+ 378, 378, 378, 378, 378, 378, 378, 378, 173, 378,
+ 378, 378,-32768,-32768, 126, 8, 331, 167, -11, 400,
+ -32, 208, 4, 378, 67, 58, 132, 378,-32768,-32768,
+ 32, 52, 291, 456, 456, 29, 29, 29, 29, 29,
+ 29, 32,-32768, 32, 3, 3, 3, 72,-32768,-32768,
+ 378,-32768,-32768, 132, 32,-32768,-32768, 59, 440, 255,
+ 296, 69, 372, -9,-32768, 440,-32768, 440, 76, 378,
+-32768, 337,-32768,-32768, 249, 36, 331,-32768,-32768, 84,
+-32768
};
static const short yypgoto[] = {-32768,
--32768, 30, -11
+-32768, 34, -37, -30, -1
};
-#define YYLAST 292
-
-
-static const short yytable[] = { 21,
- 17, 23, 40, 41, 24, 42, 45, 20, 47, 25,
- 26, 18, 51, 22, 19, 52, 53, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
- 69, 46, 78, 2, 42, 3, 71, 4, 5, 6,
- 7, 8, 9, 10, 3, 79, 4, 5, 6, 7,
- 8, 9, 10, 50, 38, 48, 40, 41, 11, 42,
- 75, 77, 72, 0, 12, 0, 13, 11, 65, 0,
- 0, 0, 0, 0, 3, 13, 54, 5, 6, 7,
- 8, 9, 10, 3, 0, 74, 5, 6, 7, 8,
- 9, 10, 0, 0, 0, 0, 3, 11, 76, 5,
- 6, 7, 8, 9, 10, 13, 11, 0, 0, 0,
- 0, 0, 0, 0, 13, 0, 0, 3, 0, 11,
- 5, 6, 7, 8, 9, 10, 0, 13, 32, 33,
- 34, 35, 36, 37, 38, 48, 40, 41, 0, 42,
- 11, 0, 0, 0, 0, 27, 28, 0, 13, 29,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 48,
- 40, 41, 0, 42, 27, 28, 0, 49, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 38, 48, 40,
- 41, 0, 42, 27, 28, 0, 70, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
- 0, 42, 43, 44, 27, 28, 0, 73, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 38, 48, 40,
- 41, 0, 42, 27, 28, 0, 0, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 48, 40, 41,
- 0, 42, 27, 28, 0, 0, 29, 30, 31, 32,
- 33, 34, 35, 36, 37, 38, 0, 40, 41, 28,
- 42, 0, 29, 30, 31, 32, 33, 34, 35, 36,
- 37, 38, 48, 40, 41, 0, 42, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 48, 40, 41,
- 0, 42
+#define YYLAST 499
+
+
+static const short yytable[] = { 25,
+ 122, 69, 45, 73, 26, 77, 78, 45, 77, 78,
+ 77, 78, 27, 104, 102, 35, 46, 47, 28, 31,
+ 28, 32, 76, 77, 78, 65, 67, 33, 34, 68,
+ 70, 72, 79, 36, 24, 100, 37, 123, 29, 30,
+ 29, 30, 45, 81, 75, 62, 108, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 94, 95, 96,
+ 97, 66, 58, 74, 60, 61, 71, 60, 61, 106,
+ 107, 62, 105, 114, 62, 110, 109, 112, 80, 78,
+ 119, 124, 129, 131, 126, 0, 0, 130, 2, 0,
+ 3, 4, 93, 5, 6, 7, 8, 0, 9, 113,
+ 10, 11, 12, 13, 14, 15, 0, 16, 116, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 125, 0,
+ 127, 17, 0, 0, 0, 0, 18, 19, 0, 0,
+ 0, 20, 21, 22, 38, 4, 39, 5, 6, 7,
+ 8, 0, 9, 0, 40, 11, 12, 13, 14, 15,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 74, 60, 61, 0, 0, 17, 0, 0, 62, 0,
+ 18, 19, 98, 0, 0, 3, 4, 22, 5, 6,
+ 7, 8, 0, 9, 0, 10, 11, 12, 13, 14,
+ 15, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 74, 60, 61, 0, 0, 17, 0, 0, 62,
+ 0, 18, 19, 99, 0, 0, 3, 82, 22, 5,
+ 6, 7, 8, 0, 9, 0, 10, 11, 12, 13,
+ 14, 15, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 0, 0, 17, 0, 0,
+ 62, 0, 18, 19, 103, 0, 0, 3, 115, 22,
+ 5, 6, 7, 8, 0, 9, 0, 10, 11, 12,
+ 13, 14, 15, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 74, 60, 61, 0, 0, 17, 0,
+ 0, 62, 0, 18, 19, 128, 0, 0, 3, 117,
+ 22, 5, 6, 7, 8, 0, 9, 0, 10, 11,
+ 12, 13, 14, 15, 111, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 74, 60, 61, 0, 17,
+ 0, 0, 0, 62, 18, 19, 0, 0, 0, 3,
+ 4, 22, 5, 6, 7, 8, 0, 9, 0, 40,
+ 11, 12, 13, 14, 15, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 0, 0,
+ 17, 0, 0, 62, 0, 18, 19, 0, 0, 0,
+ 3, 120, 22, 5, 6, 7, 8, 0, 9, 0,
+ 10, 11, 12, 13, 14, 15, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 74, 60, 61, 101,
+ 0, 17, 0, 0, 62, 0, 18, 19, 121, 0,
+ 0, 0, 0, 22, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 0, 48, 0,
+ 0, 0, 62, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 0, 0, 0, 0,
+ 0, 62, 63, 64, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 74, 60, 61, 0, 0, 0,
+ 0, 0, 62, 52, 53, 54, 55, 56, 57, 58,
+ 74, 60, 61, 0, 0, 0, 0, 0, 62
};
-static const short yycheck[] = { 11,
- 32, 13, 28, 29, 27, 31, 18, 34, 20, 32,
- 33, 12, 24, 33, 15, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
- 42, 9, 0, 1, 31, 3, 48, 5, 6, 7,
- 8, 9, 10, 11, 3, 0, 5, 6, 7, 8,
- 9, 10, 11, 24, 26, 27, 28, 29, 26, 31,
- 72, 73, 16, -1, 32, -1, 34, 26, 39, -1,
- -1, -1, -1, -1, 3, 34, 5, 6, 7, 8,
- 9, 10, 11, 3, -1, 5, 6, 7, 8, 9,
- 10, 11, -1, -1, -1, -1, 3, 26, 5, 6,
- 7, 8, 9, 10, 11, 34, 26, -1, -1, -1,
- -1, -1, -1, -1, 34, -1, -1, 3, -1, 26,
- 6, 7, 8, 9, 10, 11, -1, 34, 20, 21,
- 22, 23, 24, 25, 26, 27, 28, 29, -1, 31,
- 26, -1, -1, -1, -1, 13, 14, -1, 34, 17,
- 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, -1, 31, 13, 14, -1, 35, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
- 29, -1, 31, 13, 14, -1, 35, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- -1, 31, 32, 33, 13, 14, -1, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
- 29, -1, 31, 13, 14, -1, -1, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- -1, 31, 13, 14, -1, -1, 17, 18, 19, 20,
- 21, 22, 23, 24, 25, 26, -1, 28, 29, 14,
- 31, -1, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, -1, 31, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- -1, 31
+static const short yycheck[] = { 1,
+ 10, 32, 35, 34, 44, 20, 21, 35, 20, 21,
+ 20, 21, 46, 10, 47, 17, 44, 45, 19, 46,
+ 19, 46, 23, 20, 21, 27, 28, 46, 46, 31,
+ 32, 33, 47, 13, 1, 47, 13, 47, 39, 40,
+ 39, 40, 35, 45, 22, 43, 77, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 28, 34, 35, 36, 37, 33, 36, 37, 3,
+ 13, 43, 74, 104, 43, 24, 78, 6, 45, 21,
+ 12, 6, 47, 0, 122, -1, -1, 0, 1, -1,
+ 3, 4, 59, 6, 7, 8, 9, -1, 11, 101,
+ 13, 14, 15, 16, 17, 18, -1, 20, 110, 111,
+ -1, -1, -1, -1, -1, -1, -1, -1, 120, -1,
+ 122, 34, -1, -1, -1, -1, 39, 40, -1, -1,
+ -1, 44, 45, 46, 3, 4, 5, 6, 7, 8,
+ 9, -1, 11, -1, 13, 14, 15, 16, 17, 18,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, -1, -1, 34, -1, -1, 43, -1,
+ 39, 40, 47, -1, -1, 3, 4, 46, 6, 7,
+ 8, 9, -1, 11, -1, 13, 14, 15, 16, 17,
+ 18, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, -1, -1, 34, -1, -1, 43,
+ -1, 39, 40, 47, -1, -1, 3, 4, 46, 6,
+ 7, 8, 9, -1, 11, -1, 13, 14, 15, 16,
+ 17, 18, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, -1, -1, 34, -1, -1,
+ 43, -1, 39, 40, 47, -1, -1, 3, 4, 46,
+ 6, 7, 8, 9, -1, 11, -1, 13, 14, 15,
+ 16, 17, 18, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, -1, -1, 34, -1,
+ -1, 43, -1, 39, 40, 47, -1, -1, 3, 4,
+ 46, 6, 7, 8, 9, -1, 11, -1, 13, 14,
+ 15, 16, 17, 18, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, -1, 34,
+ -1, -1, -1, 43, 39, 40, -1, -1, -1, 3,
+ 4, 46, 6, 7, 8, 9, -1, 11, -1, 13,
+ 14, 15, 16, 17, 18, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, -1, -1,
+ 34, -1, -1, 43, -1, 39, 40, -1, -1, -1,
+ 3, 10, 46, 6, 7, 8, 9, -1, 11, -1,
+ 13, 14, 15, 16, 17, 18, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 10,
+ -1, 34, -1, -1, 43, -1, 39, 40, 47, -1,
+ -1, -1, -1, 46, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, -1, 20, -1,
+ -1, -1, 43, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, -1, -1, -1, -1,
+ -1, 43, 44, 45, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, -1, -1, -1,
+ -1, -1, 43, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, -1, -1, -1, -1, -1, 43
};
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
@@ -862,12 +961,6 @@ yyreduce:
switch (yyn) {
-case 4:
-{store_res(&yyvsp[-1]); return 0;;
- break;}
-case 5:
-{store_res(&yyvsp[-1]); return 0;;
- break;}
case 6:
{store_res(&yyvsp[-1]); return 0;;
break;}
@@ -875,111 +968,176 @@ case 7:
{store_res(&yyvsp[-1]); return 0;;
break;}
case 8:
-{yyerrok;;
+{store_res(&yyvsp[-1]); return 0;;
break;}
case 9:
-{yyval.type=STR;;
+{store_res(&yyvsp[-1]); return 0;;
break;}
case 10:
-{yyval.text=add_strings(yyvsp[-2].text, string_value(&yyvsp[0])); yyval.type=STR;;
+{store_res(&yyvsp[-1]); return 0;;
break;}
case 11:
-{yyval.text=add_strings(string_value(&yyvsp[-2]), yyvsp[0].text); yyval.type=STR;;
+{yyerrok;;
break;}
case 12:
-{yyval.text=add_strings(yyvsp[-2].text, yyvsp[0].text); yyval.type=STR;;
+{;;
break;}
case 13:
-{yyval.val = yyvsp[0].val; yyval.type = NUM;;
+{yyval.text=add_strings(yyvsp[-2].text, string_value(&yyvsp[0]));;
break;}
case 14:
-{yyval.val = 0.0;;
+{yyval.text=add_strings(string_value(&yyvsp[-2]), yyvsp[0].text);;
break;}
case 15:
-{yyval.val = syntax_level ? syntax_level->clval : 0.0; ;
+{yyval.text=add_strings(yyvsp[-2].text, yyvsp[0].text);;
break;}
case 16:
-{yyval.val = 3.14159265358979; yyval.type = NUM;;
+{;;
break;}
case 17:
-{yyval.val = 2.71828182845905; yyval.type = NUM;;
- break;}
-case 18:
-{yyval.val = yyvsp[0].tptr->value.var; yyval.type=VAR;
+{if(yyval.text =(char*)malloc(strlen(yyvsp[-2].tptr->name) +strlen(yyvsp[0].tptr->name) + 2)) sprintf(yyval.text, "%s:%s", yyvsp[-2].tptr->name, yyvsp[0].tptr->name);;
break;}
case 19:
-{yyval.val = yyvsp[-2].tptr->value.var = yyvsp[0].val;
- if(yyvsp[-2].tptr->row >=0 && yyvsp[-2].tptr->col >= 0 && curr_data) curr_data->SetValue(yyvsp[-2].tptr->row, yyvsp[-2].tptr->col, yyvsp[0].val);;
+{if(!yyval.a_data) {yyval.a_data = (double*)malloc(sizeof(double)); yyval.a_count = 1; yyval.a_data[0] = yyval.val;};
break;}
case 20:
-{yyval.val = (yyvsp[-3].tptr->arg_type == ARR) ? ((*yyvsp[-3].tptr->value.fnctptr)(proc_clause(&yyvsp[-1]))) :
- (*(yyvsp[-3].tptr->value.fnctptr))(yyvsp[-1].val);;
+{push(&yyval, &yyvsp[0]);;
break;}
case 21:
-{yyval.val = ((yyvsp[-2].val != 0) && (yyvsp[0].val != 0))? 1 : 0;;
+{exec_clause(&yyval);;
break;}
case 22:
-{yyval.val = ((yyvsp[-2].val != 0) || (yyvsp[0].val != 0))? 1 : 0;;
+{range_array(&yyval, yyvsp[0].text);;
break;}
case 23:
-{yyval.val = (yyvsp[-2].val == yyvsp[0].val) ? 1 : 0;;
+{if(yyvsp[-2].val < yyvsp[0].val && (yyval.a_data = (double*)malloc((int)(yyvsp[0].val-yyvsp[-2].val+2)*sizeof(double))))
+ for(yyval.a_count=0; yyvsp[-2].val<=yyvsp[0].val; yyval.a_data[yyval.a_count++] = yyvsp[-2].val, yyvsp[-2].val += 1.0 );;
break;}
case 24:
-{yyval.val = (yyvsp[-2].val != yyvsp[0].val) ? 1 : 0;;
+{yyval.val = yyvsp[0].val; yyval.type = NUM;;
break;}
case 25:
-{yyval.val = (yyvsp[-2].val > yyvsp[0].val) ? 1 : 0;;
+{yyval.val = 0.0;;
break;}
case 26:
-{yyval.val = (yyvsp[-2].val >= yyvsp[0].val) ? 1 : 0;;
+{yyval.val = syntax_level ? syntax_level->clval : 0.0; ;
break;}
case 27:
-{yyval.val = (yyvsp[-2].val < yyvsp[0].val) ? 1 : 0;;
+{yyval.val = _PI; yyval.type = NUM;;
break;}
case 28:
-{yyval.val = (yyvsp[-2].val <= yyvsp[0].val) ? 1 : 0;;
+{yyval.val = 2.71828182845905; yyval.type = NUM;;
break;}
case 29:
-{yyval.val = yyvsp[-2].val + yyvsp[0].val;;
+{yyvsp[0].tptr->GetValue(&yyval);;
break;}
case 30:
-{yyval.val = yyvsp[-2].val - yyvsp[0].val;;
+{eval(&yyvsp[0], &yyval);;
break;}
case 31:
-{yyval.val = yyvsp[-2].val * yyvsp[0].val;;
+{yyvsp[-2].tptr->SetValue(&yyval, &yyvsp[0]);;
break;}
case 32:
-{if(yyvsp[0].val != 0.0) yyval.val = yyvsp[-2].val / yyvsp[0].val;
- else yyval.val = (getsym(HashValue((unsigned char*)"zdiv")))->value.var; ;
+{yyvsp[-2].tptr->SetValue(&yyval, &yyvsp[0]);;
break;}
case 33:
-{push(&yyval, &yyvsp[0]);;
+{yyval.val = ((yyvsp[-3].tptr->fnctptr)(yyvsp[-1].val));;
break;}
case 34:
-{get_range(&yyval, yyvsp[-2].tptr->name, yyvsp[0].tptr->name);;
+{yyval.val = ((yyvsp[-3].tptr->fnctptr)(proc_clause(&yyvsp[-1])));;
break;}
case 35:
-{yyval.val = -yyvsp[0].val;;
+{push(&yyvsp[-2], &yyvsp[0]); yyval.val = ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-2]));;
break;}
case 36:
-{yyval.val = pow(yyvsp[-2].val, yyvsp[0].val);;
+{push(&yyvsp[-4], &yyvsp[-2]); push(&yyvsp[-4], &yyvsp[0]); yyval.val = ((yyvsp[-7].tptr->fnctptr)(&yyvsp[-4]));;
break;}
case 37:
-{yyval.val = yyvsp[-2].val; exec_clause(&yyval);;
+{yyval.val = ((yyvsp[-3].tptr->fnctptr)(&yyvsp[-1], &yyval));;
break;}
case 38:
-{memcpy(&yyval, &yyvsp[-1], sizeof(YYSTYPE));
+{yyvsp[-1].text = string_value(&yyvsp[-1]); yyval.val = ((yyvsp[-3].tptr->fnctptr)(&yyvsp[-1], &yyval));;
break;}
case 39:
-{memcpy(&yyval, yyvsp[-4].val != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE));
+{yyval.val = ((*yyvsp[-5].tptr->fnctptr)(proc_clause(&yyvsp[-3]), proc_clause(&yyvsp[-1]), 0L));;
break;}
case 40:
-{memcpy(&yyval, yyvsp[-4].val != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE));
+{yyval.val = ((*yyvsp[-7].tptr->fnctptr)(proc_clause(&yyvsp[-5]), proc_clause(&yyvsp[-3]), yyvsp[-1].text));;
break;}
case 41:
-{memcpy(&yyval, yyvsp[-4].val != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE));
+{yyval.val = yyvsp[-2].val != 0 ? eval(&yyvsp[0], &yyval) : 0.0;;
break;}
case 42:
+{yyval.val = yyvsp[-4].val != 0 ? eval(&yyvsp[-2], &yyval) : eval(&yyvsp[0], &yyval);;
+ break;}
+case 43:
+{yyval.val = ((yyvsp[-2].val != 0) && (yyvsp[0].val != 0))? 1 : 0;;
+ break;}
+case 44:
+{yyval.val = ((yyvsp[-2].val != 0) || (yyvsp[0].val != 0))? 1 : 0;;
+ break;}
+case 45:
+{yyval.val = (yyvsp[-2].val == yyvsp[0].val) ? 1 : 0;;
+ break;}
+case 46:
+{yyval.val = (yyvsp[-2].val != yyvsp[0].val) ? 1 : 0;;
+ break;}
+case 47:
+{yyval.val = (yyvsp[-2].val > yyvsp[0].val) ? 1 : 0;;
+ break;}
+case 48:
+{yyval.val = (yyvsp[-2].val >= yyvsp[0].val) ? 1 : 0;;
+ break;}
+case 49:
+{yyval.val = (yyvsp[-2].val < yyvsp[0].val) ? 1 : 0;;
+ break;}
+case 50:
+{yyval.val = (yyvsp[-2].val <= yyvsp[0].val) ? 1 : 0;;
+ break;}
+case 51:
+{yyval.val = yyvsp[-2].val + yyvsp[0].val;;
+ break;}
+case 52:
+{yyval.val = yyvsp[-2].val - yyvsp[0].val;;
+ break;}
+case 53:
+{yyval.val = yyvsp[-2].val * yyvsp[0].val;;
+ break;}
+case 54:
+{if(yyvsp[0].val != 0.0) yyval.val = yyvsp[-2].val / yyvsp[0].val;
+ else yyval.val = (getsym(HashValue((unsigned char*)"zdiv")))->GetValue(); ;
+ break;}
+case 55:
+{yyval.val = -yyvsp[0].val;;
+ break;}
+case 56:
+{yyval.val=yyvsp[-1].tptr->GetValue(); yyvsp[-1].tptr->SetValue(yyval.val+1.0); yyval.val -= 1.0; yyval.type = NUM;;
+ break;}
+case 57:
+{yyval.val=yyvsp[-1].tptr->GetValue(); yyvsp[-1].tptr->SetValue(yyval.val-1.0); yyval.val += 1.0; yyval.type = NUM;;
+ break;}
+case 58:
+{yyval.val=yyvsp[0].tptr->GetValue(); yyvsp[0].tptr->SetValue(yyval.val+1.0); yyval.type = NUM;;
+ break;}
+case 59:
+{yyval.val=yyvsp[0].tptr->GetValue(); yyvsp[0].tptr->SetValue(yyval.val-1.0); yyval.type = NUM;;
+ break;}
+case 60:
+{yyval.val = pow(yyvsp[-2].val, yyvsp[0].val);;
+ break;}
+case 61:
+{memcpy(&yyval, &yyvsp[-1], sizeof(YYSTYPE)); yyvsp[-1].a_data = 0L; yyvsp[-1].a_count = 0;;
+ break;}
+case 62:
+{memcpy(&yyval, yyvsp[-4].val != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE));
+ break;}
+case 63:
+{memcpy(&yyval, yyvsp[-4].val != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE));
+ break;}
+case 64:
+{memcpy(&yyval, yyvsp[-4].val != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE));
+ break;}
+case 65:
{memcpy(&yyval, yyvsp[-4].val != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE));
break;}
}
@@ -1206,36 +1364,185 @@ yyerrhandle:
}
-static char *last_error = 0L;
+// The symrec class
+symrec::symrec(unsigned int h_n, int typ, symrec *nxt)
+{
+ h_name = h_n;
+ type = typ;
+ next = nxt;
+ row = col = -1;
+ name = text = 0L;
+ var = 0.0;
+ isSSval = false;
+ fnctptr = (double (*)(...))nop;
+}
+
+symrec::~symrec()
+{
+ if(name) free(name); name = 0L;
+ if(text) free(text); text = 0L;
+}
+
+double
+symrec::GetValue()
+{
+ anyResult ares;
+
+ if(isSSval) {
+ if(row < 0 && col < 0) InitSS();
+ //GetResult( , , ,true) inhibits reentrance into parser !
+ if(curr_data->GetResult(&ares, row, col, parse_level > MAX_PARSE)){
+ return var = ares.value;
+ }
+ isSSval = false;
+ row = col = -1;
+ }
+ return var;
+}
+
+void
+symrec::GetValue(void *re)
+{
+ anyResult ares;
+ YYSTYPE *res = (YYSTYPE*)re;
+
+ if(isSSval) {
+ if(row < 0 && col < 0) InitSS();
+ res->a_data = 0L; res->a_count = 0;
+ //GetResult( , , ,true) inhibits reentrance into parser !
+ if(curr_data->GetResult(&ares, row, col, parse_level > MAX_PARSE)){
+ if(text) free(text); text = 0L;
+ if(ares.type == ET_VALUE) {
+ res->type = VAR; res->val = ares.value;
+ res->text = 0L;
+ }
+ else if(ares.type == ET_TEXT && ares.text) {
+ res->type = STR; res->val = 0.0;
+ text = strdup(ares.text);
+ res->text = text;
+ }
+ else {
+ res->type = NUM; res->val = var;
+ res->text = 0L;
+ }
+ var = res->val;
+ return;
+ }
+ isSSval = false;
+ row = col = -1;
+ }
+ if(text && text[0]) {
+ res->text = strdup(text);
+ res->val = var; res->type = STR;
+ }
+ else {
+ res->type = NUM; res->val = var;
+ res->text = 0L;
+ }
+ res->a_data = 0L; res->a_count = 0L;
+}
+
+double
+symrec::SetValue(double v)
+{
+ if(isSSval) {
+ if(row < 0 && col < 0) InitSS();
+ if(curr_data->SetValue(row, col, v)){
+ if(curr_data) curr_data->Command(CMD_UPDATE, 0L, 0L);
+ return var = v;
+ }
+ isSSval = false;
+ row = col = -1;
+ }
+ return var = v;
+}
+
+void
+symrec::SetValue(void* d, void* s)
+{
+ YYSTYPE *dest = (YYSTYPE*)d;
+ YYSTYPE *src = (YYSTYPE*)s;
+
+ if(isSSval && curr_data) {
+ if(row < 0 && col < 0) InitSS();
+ if(last_err_desc) curr_data->SetText(row, col, last_err_desc);
+ else if(src->type == STR) curr_data->SetText(row, col, src->text);
+ else if(src->type == ARR || (src->a_data)) curr_data->SetText(row, col, "#ARRAY");
+ else if(src->type == VAR && src->tptr->type == TXT) curr_data->SetText(row, col, src->tptr->text);
+ else curr_data->SetValue(row, col, src->val);
+ curr_data->Command(CMD_UPDATE, 0L, 0L);
+ }
+ var = src->val;
+ if(text) free(text); text = 0L;
+ if(src->text && src->text[0]) text = strdup(src->text);
+ GetValue(d);
+ return;
+}
+
+void
+symrec::SetName(char *nam)
+{
+ if(name || !nam || !nam[0]) return;
+ name = strdup(nam);
+ if((name && curr_data) && (isalpha(name[0]) || name[0] == '$') && isdigit(name[strlen(name)-1])) isSSval=true;
+}
+
+void
+symrec::InitSS()
+{
+ AccRange *ar;
+
+ if(row<0 && col<0 &&(ar = new AccRange(name))) {
+ ar->GetFirst(&col, &row);
+ delete(ar);
+ }
+}
+
static void yyerror(char *s)
{
- //Called by yyparse on error
+ //called by yyparse on error
if(curr_data) curr_data->Command(CMD_ERROR, last_error = s, 0L);
else printf("%s\n", s);
}
+static void yyargserr(char *s)
+{
+ //call from function on argument type/number mismatch
+ yyerror(s);
+ last_err_desc = "#ARGS";
+}
+
static void store_res(YYSTYPE *res)
{
- if(res->type == STR) {
- line_result = 0.0;
+ if(last_err_desc) {
+ line_res.type = ET_TEXT;
+ line_res.value = 0.0;
+ strcpy(res_txt, last_err_desc);
+ }
+ else if(res->type == STR) {
line_res.type = ET_TEXT;
- line_res. value = 0.0;
+ line_res.value = 0.0;
if(res->text) strcpy(res_txt, res->text);
}
+ else if((res->type == ARR || (res->a_data)) && res->a_count == 1) {
+ line_res.type = ET_VALUE;
+ line_res.value = res->a_data[0];
+ }
+ else if(res->type == ARR && !(res->a_data) && !(res->a_count)) {
+ line_res.type = ET_VALUE;
+ line_res.value = res->val;
+ }
else if(res->type == ARR || (res->a_data)) {
- line_result = 0.0;
line_res.type = ET_TEXT;
- line_res. value = 0.0;
+ line_res.value = 0.0;
strcpy(res_txt, "#ARRAY");
}
else if(res->tptr && res->tptr->type == TXT) {
- line_result = 0.0;
line_res.type = ET_TEXT;
line_res.value = 0.0;
if(res->tptr->text) strcpy(res_txt, res->tptr->text);
}
else {
- line_result = res->val;
line_res.type = ET_VALUE;
line_res.value = res->val;
}
@@ -1297,6 +1604,35 @@ static void pop_syntax()
}
}
+static double eval(YYSTYPE *sr, YYSTYPE *dst)
+{
+ anyResult *ar;
+
+ if(!sr || !sr->text) return 0.0;
+ parse_level++;
+ ar = do_formula(0L, sr->text);
+ yylval.a_data = 0L; yylval.a_count = 0;
+ switch(ar->type) {
+ case ET_VALUE:
+ dst->type = NUM;
+ dst->val = ar->value;
+ dst->text = 0L;
+ break;
+ case ET_TEXT:
+ dst->type = STR;
+ dst->val = 0.0;
+ dst->text = PushString(ar->text);
+ break;
+ default:
+ dst->type = NUM;
+ dst->val = 0.0;
+ dst->text = 0L;
+ break;
+ }
+ parse_level--;
+ return dst->val;
+}
+
// more functions
static double sign(double v)
{
@@ -1305,6 +1641,19 @@ static double sign(double v)
return 0.0;
}
+static long idum=0;
+
+static double rand(double v)
+{
+ return ran2(&idum);
+}
+
+static double srand(double v)
+{
+ idum = (long)v;
+ return v;
+}
+
static double factorial(double v)
{
return factrl((int)v);
@@ -1312,9 +1661,14 @@ static double factorial(double v)
static void close_arr_func(YYSTYPE *sr)
{
- free(sr->a_data);
+ if(sr->a_data) free(sr->a_data);
sr->a_data = 0L; sr->a_count = 0;
- if(sr->type == ARR) sr->type = NUM;
+}
+
+static double _strlen(YYSTYPE *sr, YYSTYPE *dst)
+{
+ if(!sr || !sr->text) return 0.0;
+ return (double)strlen(sr->text);
}
#undef min
@@ -1322,7 +1676,7 @@ static double min(YYSTYPE *sr)
{
int i;
- if(!sr) return 0.0;
+ if(!sr || !sr->a_count) return 0.0;
if(sr->a_data && sr->a_data){
for(i = 1, sr->val = sr->a_data[0]; i < sr->a_count; i++)
if(sr->a_data[i] < sr->val) sr->val = sr->a_data[i];
@@ -1336,7 +1690,7 @@ static double max(YYSTYPE *sr)
{
int i;
- if(!sr) return 0.0;
+ if(!sr || !sr->a_count) return 0.0;
if(sr->a_data){
for(i = 1, sr->val = sr->a_data[0]; i < sr->a_count; i++)
if(sr->a_data[i] > sr->val) sr->val = sr->a_data[i];
@@ -1362,9 +1716,10 @@ static double sum(YYSTYPE *sr)
if(!sr) return 0.0;
if(sr->a_data){
- for(i = 1, sr->val = sr->a_data[0]; i < sr->a_count; i++) sr->val += sr->a_data[i];
+ for(i = 0, sr->val = 0.0; i < sr->a_count; i++) sr->val += sr->a_data[i];
close_arr_func(sr);
}
+ else sr->val = 0.0;
return sr->val;
}
@@ -1470,14 +1825,159 @@ static double sterr(YYSTYPE *sr)
return sr->val;
}
+static double beta(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2){
+ sr->val = betaf(sr->a_data[0], sr->a_data[1]);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to beta(u, v).");
+ return sr->val;
+}
+
+static double _gammp(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2){
+ sr->val = gammp(sr->a_data[0], sr->a_data[1]);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to gammp(a, x).");
+ return sr->val;
+}
+
+static double _gammq(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2){
+ sr->val = gammq(sr->a_data[0], sr->a_data[1]);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to gammq(a, x).");
+ return sr->val;
+}
+
+static double _betai(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 3){
+ sr->val = betai(sr->a_data[0], sr->a_data[1], sr->a_data[2]);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to betai(x, a, b).");
+ return sr->val;
+}
+
+static double _bincof(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2){
+ sr->val = bincof(sr->a_data[0], sr->a_data[1]);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to bincof(n, k).");
+ return sr->val;
+}
+
+static double binomdist(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 3){
+ sr->val = binomdistf(sr->a_data[0], sr->a_data[1], sr->a_data[2]);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to binomdist(s, n, p).");
+ return sr->val;
+}
+
+static double normdist(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 3){
+ sr->val = norm_dist(sr->a_data[0], sr->a_data[1], sr->a_data[2]);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to normdist(x, mean, SD).");
+ return sr->val;
+}
+
+static double norminv(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 3) {
+ sr->val = distinv(norm_dist,sr->a_data[1], sr->a_data[2], sr->a_data[0], 2.0);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to norminv(p, mean, SD).");
+ return sr->val;
+}
+
+static double chidist(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2){
+ sr->val = chi_dist(sr->a_data[0], sr->a_data[1], 1.0);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to chidist(x, df).");
+ return sr->val;
+}
+
+static double chiinv(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2) {
+ sr->val = distinv(chi_dist,sr->a_data[1], 1.0, sr->a_data[0], 2.0);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to chiinv(p, df).");
+ return sr->val;
+}
+
static double tdist(YYSTYPE *sr)
{
if(!sr) return 0.0;
sr->val = 0.0;
if(sr->a_data && sr->a_count == 2){
- sr->val = t_dist(sr->a_data[0], sr->a_data[1]);
+ sr->val = t_dist(sr->a_data[0], sr->a_data[1], 1.0);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to tdist(x, df).");
+ return sr->val;
+}
+
+static double tinv(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2) {
+ sr->val = distinv(t_dist,sr->a_data[1], 1.0, sr->a_data[0], 2.0);
close_arr_func(sr);
}
+ else yyargserr("Wrong number of arguments\nin call to tinv(p, df).");
+ return sr->val;
+}
+
+static double poisdist(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2){
+ sr->val = pois_dist(sr->a_data[0], sr->a_data[1], 1.0);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to poisdist(x, mean).");
return sr->val;
}
@@ -1489,51 +1989,150 @@ static double fdist(YYSTYPE *sr)
sr->val = f_dist(sr->a_data[0], sr->a_data[1], sr->a_data[2]);
close_arr_func(sr);
}
+ else yyargserr("Wrong number of arguments\nin call to fdist(x, df1, df2).");
return sr->val;
}
+static double finv(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0;
+ if(sr->a_data && sr->a_count == 3){
+ sr->val = distinv(f_dist,sr->a_data[1], sr->a_data[2], sr->a_data[0], 2.0);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to finv(p, df1, df2).");
+ return sr->val;
+}
+
+static double pearson(YYSTYPE *sr1, YYSTYPE *sr2, char *dest)
+{
+ if(!sr1 || !sr2) return 0.0;
+ sr1->val = 0.0;
+ if(sr1->a_data && sr1->a_count > 1 && sr2->a_data && sr1->a_count == sr2->a_count){
+ sr1->val = sr2->val = d_pearson(sr1->a_data, sr2->a_data, sr1->a_count, dest, curr_data);
+ close_arr_func(sr1); close_arr_func(sr2);
+ }
+ else yyargserr("Bad arguments in call to function\npearson(range1; range2 [;\"dest\"]).");
+ return sr1->val;
+}
+
+static double spearman(YYSTYPE *sr1, YYSTYPE *sr2, char *dest)
+{
+ if(!sr1 || !sr2) return 0.0;
+ sr1->val = 0.0;
+ if(sr1->a_data && sr1->a_count > 1 && sr2->a_data && sr1->a_count == sr2->a_count){
+ sr1->val = sr2->val = d_spearman(sr1->a_data, sr2->a_data, sr1->a_count, dest, curr_data);
+ close_arr_func(sr1); close_arr_func(sr2);
+ }
+ else yyargserr("Bad arguments in call to function\nspearman(range1; range2 [;\"dest\"]).");
+ return sr1->val;
+}
+
+static double regression(YYSTYPE *sr1, YYSTYPE *sr2, char *dest)
+{
+ if(!sr1 || !sr2) return 0.0;
+ sr1->val = 0.0;
+ if(!(dest)) yyargserr("No destination range in call to function\nregression(range1; range2; \"dest\").");
+ if(sr1->a_data && sr1->a_count > 1 && sr2->a_data && sr1->a_count == sr2->a_count){
+ sr1->val = sr2->val = d_regression(sr1->a_data, sr2->a_data, sr1->a_count, dest, curr_data);
+ close_arr_func(sr1); close_arr_func(sr2);
+ }
+ else yyargserr("Bad arguments in call to function\nregression(range1; range2; \"dest\").");
+ return sr1->val;
+}
+
+static double ttest(YYSTYPE *sr1, YYSTYPE *sr2, char *dest)
+{
+ if(!sr1 || !sr2) return 0.0;
+ sr1->val = 0.0;
+ if(sr1->a_data && sr1->a_count > 1 && sr2->a_data && sr2->a_count > 1){
+ sr1->val = sr2->val = d_ttest(sr1->a_data, sr2->a_data, sr1->a_count, sr2->a_count, dest, curr_data);
+ close_arr_func(sr1); close_arr_func(sr2);
+ }
+ else yyargserr("Bad arguments in call to function\nttest(range1; range2[;\"dest\"]).");
+ return sr1->val;
+}
+
+static double ftest(YYSTYPE *sr1, YYSTYPE *sr2, char *dest)
+{
+ if(!sr1 || !sr2) return 0.0;
+ sr1->val = 0.0;
+ if(sr1->a_data && sr1->a_count > 1 && sr2->a_data && sr1->a_count > 1){
+ sr1->val = sr2->val = d_ftest(sr1->a_data, sr2->a_data, sr1->a_count, sr2->a_count, dest, curr_data);
+ close_arr_func(sr1); close_arr_func(sr2);
+ }
+ else yyargserr("Bad arguments in call to function\nftest(range1; range2[;\"dest\"]).");
+ return sr1->val;
+}
+
struct init
{
+ int f_type;
unsigned int h_name;
double (*fnct)(double);
- int arg_type;
};
static struct init arith_fncts[] = {
- {HashValue((unsigned char*)"variance"), (double(*)(double))&variance, ARR},
- {HashValue((unsigned char*)"stdev"), (double(*)(double))&stdev, ARR},
- {HashValue((unsigned char*)"sterr"), (double(*)(double))&sterr, ARR},
- {HashValue((unsigned char*)"min"), (double(*)(double))&min, ARR},
- {HashValue((unsigned char*)"max"), (double(*)(double))&max, ARR},
- {HashValue((unsigned char*)"count"), (double(*)(double))&count, ARR},
- {HashValue((unsigned char*)"sum"), (double(*)(double))&sum, ARR},
- {HashValue((unsigned char*)"mean"), (double(*)(double))&mean, ARR},
- {HashValue((unsigned char*)"median"), (double(*)(double))&quartile2, ARR},
- {HashValue((unsigned char*)"quartile1"), (double(*)(double))&quartile1, ARR},
- {HashValue((unsigned char*)"quartile2"), (double(*)(double))&quartile2, ARR},
- {HashValue((unsigned char*)"quartile3"), (double(*)(double))&quartile3, ARR},
- {HashValue((unsigned char*)"gmean"), (double(*)(double))&gmean, ARR},
- {HashValue((unsigned char*)"hmean"), (double(*)(double))&hmean, ARR},
- {HashValue((unsigned char*)"tdist"), (double(*)(double))&tdist, ARR},
- {HashValue((unsigned char*)"fdist"), (double(*)(double))&fdist, ARR},
- {HashValue((unsigned char*)"sign"), sign, VAR},
- {HashValue((unsigned char*)"gammaln"), gammln, VAR},
- {HashValue((unsigned char*)"factorial"), factorial, VAR},
- {HashValue((unsigned char*)"abs"), fabs, VAR},
- {HashValue((unsigned char*)"asin"), asin, VAR},
- {HashValue((unsigned char*)"acos"), acos, VAR},
- {HashValue((unsigned char*)"atan"), atan, VAR},
- {HashValue((unsigned char*)"sinh"), sinh, VAR},
- {HashValue((unsigned char*)"cosh"), cosh, VAR},
- {HashValue((unsigned char*)"tanh"), tanh, VAR},
- {HashValue((unsigned char*)"sin"), sin, VAR},
- {HashValue((unsigned char*)"cos"), cos, VAR},
- {HashValue((unsigned char*)"atan"), atan, VAR},
- {HashValue((unsigned char*)"log10"), log10, VAR},
- {HashValue((unsigned char*)"ln"), log, VAR},
- {HashValue((unsigned char*)"log"), log, VAR},
- {HashValue((unsigned char*)"exp"), exp, VAR},
- {HashValue((unsigned char*)"sqrt"), sqrt, VAR},
+ {FUNC2, HashValue((unsigned char*)"pearson"), (double(*)(double))&pearson},
+ {FUNC2, HashValue((unsigned char*)"spearman"), (double(*)(double))&spearman},
+ {FUNC2, HashValue((unsigned char*)"regression"), (double(*)(double))®ression},
+ {FUNC2, HashValue((unsigned char*)"ttest"), (double(*)(double))&ttest},
+ {FUNC2, HashValue((unsigned char*)"ftest"), (double(*)(double))&ftest},
+ {AFNCT, HashValue((unsigned char*)"variance"), (double(*)(double))&variance},
+ {AFNCT, HashValue((unsigned char*)"stdev"), (double(*)(double))&stdev},
+ {AFNCT, HashValue((unsigned char*)"sterr"), (double(*)(double))&sterr},
+ {AFNCT, HashValue((unsigned char*)"min"), (double(*)(double))&min},
+ {AFNCT, HashValue((unsigned char*)"max"), (double(*)(double))&max},
+ {AFNCT, HashValue((unsigned char*)"count"), (double(*)(double))&count},
+ {AFNCT, HashValue((unsigned char*)"sum"), (double(*)(double))&sum},
+ {AFNCT, HashValue((unsigned char*)"mean"), (double(*)(double))&mean},
+ {AFNCT, HashValue((unsigned char*)"median"), (double(*)(double))&quartile2},
+ {AFNCT, HashValue((unsigned char*)"quartile1"), (double(*)(double))&quartile1},
+ {AFNCT, HashValue((unsigned char*)"quartile2"), (double(*)(double))&quartile2},
+ {AFNCT, HashValue((unsigned char*)"quartile3"), (double(*)(double))&quartile3},
+ {AFNCT, HashValue((unsigned char*)"gmean"), (double(*)(double))&gmean},
+ {AFNCT, HashValue((unsigned char*)"hmean"), (double(*)(double))&hmean},
+ {AFNCT, HashValue((unsigned char*)"tdist"), (double(*)(double))&tdist},
+ {AFNCT, HashValue((unsigned char*)"tinv"), (double(*)(double))&tinv},
+ {AFNCT, HashValue((unsigned char*)"poisdist"), (double(*)(double))&poisdist},
+ {AFNCT, HashValue((unsigned char*)"fdist"), (double(*)(double))&fdist},
+ {AFNCT, HashValue((unsigned char*)"finv"), (double(*)(double))&finv},
+ {AFNCT, HashValue((unsigned char*)"gammp"), (double(*)(double))&_gammp},
+ {AFNCT, HashValue((unsigned char*)"gammq"), (double(*)(double))&_gammq},
+ {AFNCT, HashValue((unsigned char*)"beta"), (double(*)(double))&beta},
+ {AFNCT, HashValue((unsigned char*)"betai"), (double(*)(double))&_betai},
+ {AFNCT, HashValue((unsigned char*)"bincof"), (double(*)(double))&_bincof},
+ {AFNCT, HashValue((unsigned char*)"binomdist"), (double(*)(double))&binomdist},
+ {AFNCT, HashValue((unsigned char*)"normdist"), (double(*)(double))&normdist},
+ {AFNCT, HashValue((unsigned char*)"norminv"), (double(*)(double))&norminv},
+ {AFNCT, HashValue((unsigned char*)"chidist"), (double(*)(double))&chidist},
+ {AFNCT, HashValue((unsigned char*)"chiinv"), (double(*)(double))&chiinv},
+ {SFNCT, HashValue((unsigned char*)"strlen"), (double(*)(double))&_strlen},
+ {SFNCT, HashValue((unsigned char*)"eval"), (double(*)(double))&eval},
+ {FNCT, HashValue((unsigned char*)"erf"), errf},
+ {FNCT, HashValue((unsigned char*)"erfc"), errfc},
+ {FNCT, HashValue((unsigned char*)"sign"), sign},
+ {FNCT, HashValue((unsigned char*)"gammaln"), gammln},
+ {FNCT, HashValue((unsigned char*)"factorial"), factorial},
+ {FNCT, HashValue((unsigned char*)"rand"), rand},
+ {FNCT, HashValue((unsigned char*)"srand"), srand},
+ {FNCT, HashValue((unsigned char*)"floor"), floor},
+ {FNCT, HashValue((unsigned char*)"abs"), fabs},
+ {FNCT, HashValue((unsigned char*)"asin"), asin},
+ {FNCT, HashValue((unsigned char*)"acos"), acos},
+ {FNCT, HashValue((unsigned char*)"atan"), atan},
+ {FNCT, HashValue((unsigned char*)"sinh"), sinh},
+ {FNCT, HashValue((unsigned char*)"cosh"), cosh},
+ {FNCT, HashValue((unsigned char*)"tanh"), tanh},
+ {FNCT, HashValue((unsigned char*)"sin"), sin},
+ {FNCT, HashValue((unsigned char*)"cos"), cos},
+ {FNCT, HashValue((unsigned char*)"atan"), atan},
+ {FNCT, HashValue((unsigned char*)"log10"), log10},
+ {FNCT, HashValue((unsigned char*)"ln"), log},
+ {FNCT, HashValue((unsigned char*)"log"), log},
+ {FNCT, HashValue((unsigned char*)"exp"), exp},
+ {FNCT, HashValue((unsigned char*)"sqrt"), sqrt},
{0, 0, 0}};
// Store strings in a list
@@ -1551,19 +2150,68 @@ static char *PushString(char *text)
}
//The symbol table: a chain of `struct symrec'
-static symrec *sym_table = (symrec *) 0;
+static symrec *sym_table, *sym_tab_first;
+
+//Rearrange function table with previously used functions in front
+void ArrangeFunctions()
+{
+ symrec *ptr, *ptr1, *ptr2, *next;
+
+ for(ptr = sym_table, ptr1 = ptr2 = 0L; (ptr); ) {
+ next = ptr->next;
+ if(ptr->name) {
+ ptr->next = ptr1;
+ ptr1 = ptr;
+ }
+ else {
+ ptr->next = ptr2;
+ ptr2 = ptr;
+ }
+ ptr = next;
+ }
+ for(sym_table = 0L, ptr = ptr2; (ptr); ){
+ next = ptr->next;
+ ptr->next = sym_table;
+ sym_table = ptr;
+ ptr = next;
+ }
+ for(ptr = ptr1; (ptr); ){
+ next = ptr->next;
+ ptr->next = sym_table;
+ sym_table = ptr;
+ ptr = next;
+ }
+ sym_tab_first = sym_table;
+ bRecent = false;
+}
// Put arithmetic functions and predifened variables in table
-static void init_table (void)
+void InitArithFuncs(DataObj *d)
{
int i;
- symrec *ptr;
+ symrec *ptr, *next;
+ if(d) curr_data = d;
+ if(sym_table) {
+ for (ptr = sym_table; ptr != (symrec *) 0;){
+ if(ptr) {
+ next = ptr->next;
+ delete (ptr);
+ }
+ ptr = next;
+ }
+ sym_table = sym_tab_first = (symrec *) 0;
+ }
for (i = 0; arith_fncts[i].h_name; i++) {
- ptr = putsym (arith_fncts[i].h_name, FNCT, arith_fncts[i].arg_type);
- ptr->value.fnctptr = (double (*)(...))arith_fncts[i].fnct;
+ ptr = putsym (arith_fncts[i].h_name, arith_fncts[i].f_type);
+ ptr->fnctptr = (double (*)(...))arith_fncts[i].fnct;
}
- ptr = putsym(HashValue((unsigned char*)"zdiv"), VAR, 0); ptr->value.var = 1.0;
+ ptr = putsym(HashValue((unsigned char*)"zdiv"), VAR); ptr->SetValue(1.0);
+ sym_tab_first = sym_table;
+}
+
+static void init_table (void)
+{
str_list = 0L; n_str = 0;
push_syntax();
}
@@ -1571,18 +2219,7 @@ static void init_table (void)
static void clear_table()
{
int i;
- symrec *ptr, *next;
- for (ptr = sym_table; ptr != (symrec *) 0;){
- if(ptr) {
- if(ptr->name) free(ptr->name);
- if(ptr->text) free(ptr->text);
- next = (symrec*)ptr->next;
- free(ptr);
- }
- ptr = next;
- }
- sym_table = (symrec *) 0;
if(str_list) {
for(i = 0; i < n_str; i++) if(str_list[i]) free(str_list[i]);
free(str_list); str_list = 0L; n_str = 0;
@@ -1591,58 +2228,30 @@ static void clear_table()
}
static symrec *
-putsym (unsigned int h_name, int sym_type, int arg_type)
+putsym (unsigned int h_name, int sym_type)
{
- symrec *ptr;
-
- ptr = (symrec *) malloc (sizeof (symrec));
- ptr->h_name = h_name;
- ptr->type = sym_type;
- ptr->name = ptr->text = 0L;
- ptr->value.var = 0; /* set value to 0 even if fctn. */
- ptr->arg_type = arg_type;
- ptr->col = ptr->row = -1;
- ptr->next = (struct symrec *)sym_table;
- sym_table = ptr;
- return ptr;
+ sym_table = new symrec(h_name, sym_type, sym_table);
+ return sym_table;
}
static symrec *
getsym (unsigned int h_name, char *sym_name)
{
symrec *ptr;
- int row, col;
- AccRange *ar;
- anyResult ares;
if(!h_name) return 0;
- for (ptr = sym_table; ptr != (symrec *) 0; ptr = (symrec *)ptr->next)
+ for (ptr = sym_table; ptr != (symrec *) 0; ptr = (symrec *)ptr->next) {
if (ptr->h_name == h_name){
- if(sym_name && !ptr->name) ptr->name = ptr->name=strdup(sym_name);
- return ptr;
- }
- if((sym_name && curr_data) && (isalpha(sym_name[0]) || sym_name[0] == '$') && isdigit(sym_name[strlen(sym_name)-1])) {
- if((ar = new AccRange(sym_name)) && ar->GetFirst(&col, &row) &&
- (ptr = putsym(h_name, VAR, 0))) {
- ptr->name = strdup(sym_name);
- if(curr_data->GetResult(&ares, row, col)){
- if(ares.type == ET_VALUE) {
- ptr->type = VAR; ptr->value.var = ares.value;
- ptr->text = 0L;
- }
- else if(ares.type == ET_TEXT && ares.text) {
- ptr->type = TXT; ptr->value.var = 0.0;
- ptr->text = strdup(ares.text);
- }
- else {
- ptr->type = VAR; ptr->value.var = 0.0;
- ptr->text = 0L;
- }
+ if(sym_name && !ptr->name) {
+ ptr->SetName(sym_name);
+ bRecent = true;
}
- ptr->row = row; ptr->col = col;
- delete(ar);
return ptr;
}
+ //predefined variables never end on a digit
+ else if(ptr == sym_tab_first) {
+ if(sym_name && isdigit(sym_name[strlen(sym_name)-1])) return 0;
+ }
}
return 0;
}
@@ -1650,7 +2259,7 @@ getsym (unsigned int h_name, char *sym_name)
static int
push(YYSTYPE *res, YYSTYPE *val)
{
- if(val->a_data && val->a_count) {
+ if(val->a_data) {
if(!(res->a_data)) {
if(!(val->a_data=(double*)realloc(val->a_data, (val->a_count+2)*sizeof(double))))return 0;
val->a_data[val->a_count++] = res->val;
@@ -1681,36 +2290,36 @@ push(YYSTYPE *res, YYSTYPE *val)
}
static int
-get_range(YYSTYPE *res, char *first, char *last)
+range_array(YYSTYPE * res, char *range)
{
- char r_txt[40];
AccRange *r;
int row, col;
- double value;
- YYSTYPE tmp;
-
- if(!res || !first || !last || !curr_data) return 0;
- sprintf(r_txt, "%s:%s", first, last);
- if(!(res->a_data ) && (r = new AccRange(r_txt)) && r->GetFirst(&col, &row)) {
- if(!(res->a_data = (double*)malloc(r->CountItems() * sizeof(double)))) return 0;
- res->a_count = 0;
- for( ; r->GetNext(&col, &row); ) {
- if(curr_data->GetValue(row, col, &value)) res->a_data[res->a_count++] = value;
- }
- delete r; return 1;
- }
- if((r = new AccRange(r_txt)) && r->GetFirst(&col, &row)) {
- //it is probably a bit slow to push every element
- tmp.type = NUM;
- for( ; r->GetNext(&col, &row); ) {
- if(curr_data->GetValue(row, col, &value)) {
- tmp.val = value;
- push(res, &tmp);
+ anyResult ares;
+
+ if(!range || !range[0] || !(r = new AccRange(range))) return 0;
+ if(!r->GetFirst(&col, &row) || !(res->a_data = (double*)malloc(r->CountItems() * sizeof(double)))) {
+ delete(r);
+ return 0;
+ }
+ parse_level++;
+ for(res->a_count = 0; r->GetNext(&col, &row); ) {
+ if(curr_data->GetResult(&ares, row, col, parse_level > MAX_PARSE)) {
+ switch(ares.type) {
+ case ET_VALUE:
+ res->a_data[res->a_count++] = ares.value;
+ break;
+ case ET_TEXT:
+ if(ares.text && ares.text[0]) last_err_desc = "#ARGS";
+ break;
+ case ET_ERROR:
+ last_err_desc = "#ARGS";
+ break;
}
}
- delete r; return 1;
}
- return 0;
+ parse_level--;
+ delete(r);
+ return 1;
}
static YYSTYPE *proc_clause(YYSTYPE *res)
@@ -1722,7 +2331,7 @@ static YYSTYPE *proc_clause(YYSTYPE *res)
if(!(syntax_level) || !syntax_level->cl1 || syntax_level->cl2 <= syntax_level->cl1) return res;
if(!res->text) return res;
if(!res->a_data && (res->a_data = (double*)malloc(sizeof(double)))) {
- res->a_data[0] = res->type == VAR && res->tptr ? res->tptr->value.var : res->val;
+ res->a_data[0] = res->type == VAR && res->tptr ? res->tptr->GetValue() : res->val;
res->a_count = 1;
}
else if(!res->a_data) return res;
@@ -1760,13 +2369,13 @@ static void exec_clause(YYSTYPE *res)
struct parse_info {
char *buffer;
int buff_pos;
- double line_result;
DataObj *curr_data;
symrec *sym_table;
YYSTYPE yylval;
struct parse_info *next;
char **str_list;
- int n_str;
+ char *last_err_desc;
+ int n_str, yychar, yynerrs;
};
static parse_info *parse_stack = 0L;
@@ -1774,30 +2383,42 @@ static void push_parser()
{
parse_info *ptr;
+ if(!sym_table) InitArithFuncs(0L);
+ else if(!parse_level && bRecent) ArrangeFunctions();
ptr = (parse_info *) malloc(sizeof(parse_info));
ptr->buffer = buffer; ptr->buff_pos = buff_pos;
- ptr->line_result = line_result; ptr->curr_data = curr_data;
- ptr->sym_table = sym_table; sym_table = 0L;
+ ptr->curr_data = curr_data; ptr->last_err_desc = last_err_desc;
+ ptr->sym_table = sym_table; sym_table = sym_tab_first;
memcpy(&ptr->yylval, &yylval, sizeof(YYSTYPE));
ptr->next = parse_stack;
ptr->str_list = str_list; str_list = 0L;
ptr->n_str = n_str; n_str = 0;
- parse_stack = ptr;
- push_syntax();
+ ptr->yychar = yychar; ptr->yynerrs = yynerrs;
+ parse_stack = ptr; last_err_desc = 0L;
+ parse_level++; //reenter ?
+ push_syntax(); syntax_level->last_tok = 0;
}
static void pop_parser()
{
parse_info *ptr;
+ symrec *n;
if(ptr = parse_stack) {
+ while(sym_table && sym_table != sym_tab_first) {
+ n = sym_table->next;
+ delete(sym_table);
+ sym_table = n;
+ }
+ if(sym_table) sym_table = ptr->sym_table;
parse_stack = ptr->next;
- buffer = ptr->buffer; buff_pos = ptr->buff_pos;
- line_result = ptr->line_result; curr_data = ptr->curr_data;
- sym_table = ptr->sym_table;
+ buffer = ptr->buffer; buff_pos = ptr->buff_pos;
+ curr_data = ptr->curr_data; last_err_desc = ptr->last_err_desc;
memcpy(&yylval, &ptr->yylval, sizeof(YYSTYPE));
- str_list = ptr->str_list; n_str = ptr->n_str;
+ str_list = ptr->str_list; n_str = ptr->n_str;
+ yychar = ptr->yychar; yynerrs = ptr->yynerrs;
free(ptr);
+ parse_level--;
}
pop_syntax();
}
@@ -1805,12 +2426,14 @@ static void pop_parser()
static int is_ttoken(int h_nam)
{
switch(h_nam) {
- case 69: return E;
- case 393: return PI;
+ case 101: return E;
+ case 26992: return PI;
case 28381:
if(syntax_level) syntax_level->cl1 = buff_pos;
return CLAUSE;
- case 20: return CLVAL;
+ case 9252: return CLVAL;
+ case 26217: return IF;
+ case 6033: return ELSE;
}
return 0;
}
@@ -1825,19 +2448,37 @@ static int yylex (void)
while((c = buffer[buff_pos++]) == ' ' || c == '\t'); //get first nonwhite char
if(!c) return 0;
+ //test for block statement
+ if(c == '{') {
+ for(i= 0; i < 79 && ((tok = buffer[buff_pos]) && (tok != '}')); buff_pos++) {
+ tmp_txt[i++] = (char)tok;
+ }
+ if(buffer[buff_pos] == '}')buff_pos++;
+ tmp_txt[i] = 0;
+ yylval.text = PushString(tmp_txt);
+ return yylval.type = BLOCK;
+ }
+ //test for '..' operator
+ if(c == '.' && buffer[buff_pos] == '.') {
+ buff_pos++;
+ return yylval.type = SER;
+ }
//test for number
if(c == '.' || isdigit(c)) {
for(buff_pos--, i = 0; i < 79 && ((c = buffer[buff_pos]) == '.' || isdigit(c)); buff_pos++) {
tmp_txt[i++] = (char)c;
- if(buffer[buff_pos+1] == 'e' && (buffer[buff_pos+2] == '-' || buffer[buff_pos+2] == '+')){
+ if(i && buffer[buff_pos+1] == 'e' && (buffer[buff_pos+2] == '-' || buffer[buff_pos+2] == '+')){
tmp_txt[i++] = buffer[++buff_pos];
tmp_txt[i++] = buffer[++buff_pos];
}
+ if(i && buffer[buff_pos+1] == '.' && buffer[buff_pos+2] == '.') { //operator '..'
+ buff_pos++;
+ break;
+ }
}
tmp_txt[i] = 0;
sscanf(tmp_txt, "%lf", &yylval.val);
- yylval.type = NUM;
- return NUM;
+ return yylval.type = NUM;
}
//test for name or stringtoken
if(isalpha(c) || c=='$') {
@@ -1848,11 +2489,9 @@ static int yylex (void)
h_nam = HashValue((unsigned char*)tmp_txt);
if(tok = is_ttoken(h_nam))
return tok;
- if(!(strcmp(tmp_txt, "pi"))) return PI;
- if(!(strcmp(tmp_txt, "e"))) return E;
if(!(s = getsym(h_nam, tmp_txt))){
- s = putsym(h_nam, VAR, 0);
- s->name = strdup(tmp_txt);
+ s = putsym(h_nam, VAR);
+ s->SetName(tmp_txt);
}
curr_sym = yylval.tptr = s; return s->type;
@@ -1910,6 +2549,17 @@ static int yylex (void)
else if(syntax_level->last_tok == '?') return COLC;
}
break;
+ case ';':
+ if(syntax_level) {
+ if(syntax_level->last_tok == '(') return PSEP;
+ }
+ break;
+ case '+':
+ if(buffer[buff_pos] == '+') tok = INC;
+ break;
+ case '-':
+ if(buffer[buff_pos] == '-') tok = DEC;
+ break;
}
if(tok) {
buff_pos++; return tok;
@@ -1921,10 +2571,10 @@ static int yylex (void)
bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOINT **pts, long *npts, char *param)
{
double x, y;
- symrec *s;
+ symrec *sx, *sy;
lfPOINT *new_points;
long npoints = 0;
- int length;
+ int length, res_mode = 0;
unsigned int hn_x = HashValue((unsigned char *)"x");
unsigned int hn_y = HashValue((unsigned char *)"y");
@@ -1933,6 +2583,7 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
if(!(new_points = (lfPOINT*)calloc((iround(fabs(x2-x1)/fabs(step))+2), sizeof(lfPOINT))))
return false;
if(d) curr_data = d;
+ push_parser();
init_table();
if(param) {
length = strlen(param);
@@ -1948,21 +2599,34 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
free(buffer); buffer = 0L;
}
length = strlen(expr);
- buffer = expr; s = putsym(hn_x, VAR, 0);
+ buffer = expr; sx = putsym(hn_x, VAR);
for(x = x1; step > 0.0 ? x <= x2 : x >= x2; x += step) {
- if(s = getsym(hn_x)){
- s->value.var = x; buff_pos = 0;
+ if(sx){
+ sx->SetValue(x); buff_pos = 0;
do {
yyparse();
}while(buff_pos < length);
- if(s = getsym(hn_y)) y = s->value.var;
- else y = line_result;
- new_points[npoints].fx = (getsym(hn_x))->value.var;
+ switch (res_mode) {
+ case 1:
+ y = sy->GetValue(); break;
+ case 2:
+ y = line_res.value; break;
+ default:
+ if(sy = getsym(hn_y)) {
+ y = sy->GetValue(); res_mode = 1;
+ }
+ else {
+ y = line_res.value; res_mode = 2;
+ }
+ break;
+ }
+ new_points[npoints].fx = (getsym(hn_x))->GetValue();
new_points[npoints++].fy = y;
}
}
*pts = new_points; *npts = npoints;
clear_table();
+ pop_parser();
if(curr_data) {
curr_data->Command(CMD_CLEAR_ERROR, 0L, 0L);
curr_data->Command(CMD_REDRAW, 0L, 0L);
@@ -1970,10 +2634,68 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
return true;
}
+bool do_func3D(DataObj *d, double x1, double x2, double xstep, double z1, double z2, double zstep,
+ char *expr, char *param)
+{
+ int length, nr, nc, r, c, res_mode=0;
+ symrec *sx, *sz, *sy;
+ double x, y, z;
+ unsigned int hn_x = HashValue((unsigned char *)"x");
+ unsigned int hn_y = HashValue((unsigned char *)"y");
+ unsigned int hn_z = HashValue((unsigned char *)"z");
+
+ if(!d || x2 <= x1 || z2 <= z1 || xstep <= 0.0 || zstep <= 0.0) return false;
+ push_parser();
+ init_table();
+ if(param) {
+ length = strlen(param);
+ if(!(buffer = (char*)malloc(length+2))){
+ pop_parser();
+ return false;
+ }
+ strcpy(buffer, param); buffer[length++] = ';';
+ buffer[length] = 0; buff_pos = 0;
+ do {
+ yyparse();
+ }while(buff_pos < length);
+ free(buffer); buffer = 0L;
+ }
+ length = strlen(expr); buffer = expr;
+ sx = putsym(hn_x, VAR); sz = putsym(hn_z, VAR);
+ nr = iround((z2-z1)/zstep)+1; nc = iround((x2-x1)/xstep)+1;
+ d->Init(nr, nc);
+ for(r = 0, x = x1; r < nr; r++, x += xstep) {
+ for(c = 0, z = z1; c < nc; c++, z+= zstep) {
+ sx->SetValue(x); sz->SetValue(z); buff_pos = 0;
+ do {
+ yyparse();
+ }while(buff_pos < length);
+ switch (res_mode) {
+ case 1:
+ y = sy->GetValue(); break;
+ case 2:
+ y = line_res.value; break;
+ default:
+ if(sy = getsym(hn_y)) {
+ y = sy->GetValue(); res_mode = 1;
+ }
+ else {
+ y = line_res.value; res_mode = 2;
+ }
+ break;
+ }
+ d->SetValue(r, c, y);
+ }
+ }
+ clear_table();
+ pop_parser();
+ return true;
+}
+
anyResult *do_formula(DataObj *d, char *expr)
{
int length;
- static anyResult ret;
+ static anyResult ret, *pret = 0L;
if(d) curr_data = d;
ret.type = ET_ERROR; ret.text = 0L;
@@ -1984,22 +2706,26 @@ anyResult *do_formula(DataObj *d, char *expr)
pop_parser();
return &ret;
}
- strcpy(buffer, expr); buffer[length++] = ';';
+ strcpy(buffer, expr); if(buffer[length-1] != ';') buffer[length++] = ';';
buffer[length] = 0; buff_pos = 0;
do {
yyparse();
}while(buff_pos < length);
+ ret.type = ET_ERROR; ret.text = 0L;
if(curr_data && last_error) {
- curr_data->Command(CMD_ERROR, last_error = 0L, 0L);
- return &ret;
+ if(!(strcmp(last_error, "parse error"))) curr_data->Command(CMD_ERROR, 0L, 0L);
+ if(last_err_desc) pret = &line_res;
+ else pret = &ret;
}
+ else pret = &line_res;
+ last_error = last_err_desc = 0L;
free(buffer); buffer = 0L;
clear_table();
pop_parser();
- return &line_res;
+ return pret;
}
-bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy)
+bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy, int r0, int c0)
{
int length, tok, pos, i;
char *res, desc1[2], desc2[2];
@@ -2023,43 +2749,55 @@ bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy)
}
else switch(tok) {
case NUM:
- pos += sprintf(res+pos, "%g ", yylval.val);
+ pos += sprintf(res+pos, "%g", yylval.val);
break;
- case FNCT:
+ case FNCT: case FUNC2: case AFNCT: case SFNCT:
pos += sprintf(res+pos, "%s", curr_sym->name);
break;
- case COLR:
+ case COLR: case COLC:
pos += sprintf(res+pos, ":");
break;
- case COLC:
- pos += sprintf(res+pos, ": ");
+ case PSEP:
+ pos += sprintf(res+pos, ";");
break;
case CLVAL:
- pos += sprintf(res+pos, "$$ ");
+ pos += sprintf(res+pos, "$$");
break;
case CLAUSE:
pos += sprintf(res+pos, " where ");
break;
case VAR:
+ curr_sym->InitSS();
if(curr_sym->col >= 0 && curr_sym->row >= 0) {
desc1[0] = desc1[1] = desc2[0] = desc2[1] = 0;
for(i=strlen(curr_sym->name)-1; i>0 && isdigit(curr_sym->name[i]); i--);
if(curr_sym->name[0] == '$') desc1[0] = '$';
if(curr_sym->name[i] == '$') desc2[0] = '$';
pos += sprintf(res+pos, "%s%s%s%d", desc1,
- Int2ColLabel(desc1[0] ? curr_sym->col : curr_sym->col+dx, false),
- desc2, desc2[0]? curr_sym->row+1 : curr_sym->row+1+dy);
+ Int2ColLabel(desc1[0] || curr_sym->col < c0 ? curr_sym->col : curr_sym->col+dx >=0 ?
+ curr_sym->col+dx > c0 ? curr_sym->col+dx : c0 : 0, false),
+ desc2, desc2[0] || curr_sym->row < r0 ? curr_sym->row+1 : curr_sym->row + dy >= 0 ?
+ curr_sym->row+dy > r0 ? curr_sym->row+1+dy : r0 : 1);
}
else pos += sprintf(res+pos, "%s ", curr_sym->name);
break;
case STR:
pos += sprintf(res+pos, "\"%s\"", yylval.text && yylval.text[0] ? yylval.text : "");
break;
+ case SER:
+ pos += sprintf(res+pos, "..");
+ break;
+ case INC:
+ pos += sprintf(res+pos, "++");
+ break;
+ case DEC:
+ pos += sprintf(res+pos, "--");
+ break;
case PI:
- pos += sprintf(res+pos, "pi ");
+ pos += sprintf(res+pos, "pi");
break;
case E:
- pos += sprintf(res+pos, "e ");
+ pos += sprintf(res+pos, "e");
break;
case AND:
pos += sprintf(res+pos, " && ");
@@ -2074,16 +2812,25 @@ bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy)
pos += sprintf(res+pos, " != ");
break;
case GT:
- pos += sprintf(res+pos, " > ");
+ pos += sprintf(res+pos, ">");
break;
case GE:
- pos += sprintf(res+pos, " >= ");
+ pos += sprintf(res+pos, ">=");
break;
case LT:
- pos += sprintf(res+pos, " < ");
+ pos += sprintf(res+pos, "<");
break;
case LE:
- pos += sprintf(res+pos, " <= ");
+ pos += sprintf(res+pos, "<=");
+ break;
+ case IF:
+ pos += sprintf(res+pos, "if");
+ break;
+ case ELSE:
+ pos += sprintf(res+pos, "else");
+ break;
+ case BLOCK:
+ pos += sprintf(res+pos, "{%s}", yylval.text && yylval.text[0] ? yylval.text : "");
break;
}
}while(buff_pos < length);
@@ -2101,21 +2848,21 @@ static void fcurve(double x, double z, double **a, double *y, double dyda[], int
{
int i, length;
double tmp, y1, y2;
- symrec *symx, *s=0L;
+ symrec *symx, *sy=0L;
unsigned int hn_x = HashValue((unsigned char *)"x");
unsigned int hn_y = HashValue((unsigned char *)"y");
- if(!(symx = getsym(hn_x))) symx = putsym(hn_x, VAR, 0);
+ if(!(symx = getsym(hn_x))) symx = putsym(hn_x, VAR);
//swap parameters to requested set
if(a != parval) for(i = 0; i < ma; i++) {
tmp = *parval[i]; *parval[i] = *a[i]; *a[i] = tmp;
}
//calc result
- symx->value.var = x; buffer = txt_formula;
+ symx->SetValue(x); buffer = txt_formula;
buff_pos = 0; length = strlen(txt_formula);
do { yyparse(); }while(buff_pos < length);
- if(s = getsym(hn_y)) *y = s->value.var;
- else *y = line_result;
+ if(sy = getsym(hn_y)) *y = sy->GetValue();
+ else *y = line_res.value;
if(*y == HUGE_VAL || *y == -HUGE_VAL) {
for(i = 0, *y = 0.0; i < ma; dyda[i++] = 0.0);
return;
@@ -2127,11 +2874,11 @@ static void fcurve(double x, double z, double **a, double *y, double dyda[], int
*parval[i] = tmp*.995;
buff_pos = 0;
do { yyparse(); }while(buff_pos < length);
- y1 = s ? s->value.var : line_result;
+ y1 = sy ? sy->GetValue() : line_res.value;
*parval[i] = tmp*1.005;
buff_pos = 0;
do { yyparse(); }while(buff_pos < length);
- y2 = s ? s->value.var : line_result;
+ y2 = sy ? sy->GetValue() : line_res.value;
*parval[i] = tmp;
dyda[i] = (y2-y1)*100.0/tmp;
}
@@ -2216,7 +2963,7 @@ int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr,
parsym = (symrec**)malloc((nparam+1)*sizeof(symrec*));
parval = (double**)malloc((nparam+1)*sizeof(double*));
for(i = 0, csr=tab2; csr != tab1 && i < nparam; i++, csr = csr->next){
- parsym[i] = csr; parval[i] = &csr->value.var;
+ parsym[i] = csr; parval[i] = &csr->var;
}
//do iteratations to optimize fit
lista = (int*)malloc(sizeof(int)*nparam);
@@ -2243,7 +2990,7 @@ int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr,
l = sprintf(tmp_txt+j, "\n");
j += l; k = 0;
}
- l += sprintf(tmp_txt+j, "%s%s=%g;", j && k ? " " : "", parsym[i]->name, parsym[i]->value.var);
+ l += sprintf(tmp_txt+j, "%s%s=%g;", j && k ? " " : "", parsym[i]->name, parsym[i]->GetValue());
j += l; k += l;
}
free(*par); *par = strdup(tmp_txt);
@@ -2294,6 +3041,3 @@ int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr,
-
-
-
diff --git a/mfcalc.y b/mfcalc.y
index 9aa1928..1ce5db4 100755
--- a/mfcalc.y
+++ b/mfcalc.y
@@ -26,16 +26,27 @@
#include <stdio.h>
#include "rlplot.h"
-struct symrec {
+class symrec {
+public:
int type, row, col;
unsigned int h_name;
char *name, *text;
- struct {
- double var;
- double (*fnctptr)(...);
- } value;
- int arg_type;
- struct symrec *next;
+ double (*fnctptr)(...);
+ symrec *next;
+ double var;
+
+ symrec(unsigned int h_n, int typ, symrec *nxt);
+ ~symrec();
+ double GetValue();
+ void GetValue(void *res);
+ double SetValue(double v);
+ void SetValue(void* dest, void* src);
+ void SetName(char *nam);
+ void InitSS();
+
+private:
+ bool isSSval;
+
};
// syntactical information
@@ -58,36 +69,42 @@ typedef struct{
}YYSTYPE;
-static symrec *putsym (unsigned int h_name, int sym_type, int arg_type);
+static symrec *putsym (unsigned int h_name, int sym_type);
static symrec *getsym (unsigned int h_name, char *sym_name = 0L);
static int push(YYSTYPE *res, YYSTYPE *val);
static void store_res(YYSTYPE *res);
static char *PushString(char *text);
static char *add_strings(char *st1, char *st2);
static char *string_value(YYSTYPE *exp);
-static int get_range(YYSTYPE *res, char *first, char *last);
+static double eval(YYSTYPE *sr, YYSTYPE *dst);
+static int range_array(YYSTYPE * res, char *range);
static void exec_clause(YYSTYPE *res);
static YYSTYPE *proc_clause(YYSTYPE *res);
static void yyerror(char *s);
static int yylex(void);
+static double nop() {return 0.0;};
static char res_txt[1000];
static anyResult line_res = {ET_UNKNOWN, 0.0, res_txt};
-static double line_result;
static DataObj *curr_data;
+static char *last_error = 0L; //error text
+static char *last_err_desc = 0L; //short error description
-//the current command buffer
-static char *buffer = 0L;
+static char *buffer = 0L; //the current command buffer
static int buff_pos = 0;
+static bool bRecent = false; //rearrange functions
+static int parse_level = 0; //count reentrances into parser
+#define MAX_PARSE 20 //maximum number of reentances
%}
-%token <val> NUM ARR STR PI E CLVAL
-%token <tptr> VAR FNCT TXT
-%type <val> exp str_exp
+%token <val> NUM STR ARR BLOCK PI E CLVAL PSEP IF ELSE
+%token <tptr> VAR FNCT AFNCT SFNCT FUNC2 TXT
+%type <val> exp str_exp arr
%right '='
%left ',' /* list separator */
%left CLAUSE /* clause (where) operator */
+%left SER
%right COLR COLC /* range sep., conditional sep. */
%right '?' /* conditional assignment */
%left AND OR
@@ -95,6 +112,8 @@ static int buff_pos = 0;
%left '-' '+'
%left '*' '/'
%left NEG /* negation-unary minus */
+%left INC DEC /* increment, decrement */
+%left PINC PDEC /* pre- increment, decrement */
%right '^' /* exponentiation */
/* Grammar follows */
@@ -103,31 +122,56 @@ input: /* empty string */
| input line
;
-line: '\n' ';'
+line: '\n' | ';' | ','
| exp '\n' {store_res(&yyvsp[-1]); return 0;}
| exp ';' {store_res(&yyvsp[-1]); return 0;}
+ | exp ',' {store_res(&yyvsp[-1]); return 0;}
| str_exp '\n' {store_res(&yyvsp[-1]); return 0;}
| str_exp ';' {store_res(&yyvsp[-1]); return 0;}
| error '\n' {yyerrok;}
;
str_exp:
- STR {yyval.type=STR;}
- |str_exp '+' exp {yyval.text=add_strings(yyvsp[-2].text, string_value(&yyvsp[0])); yyval.type=STR;}
- |exp '+' str_exp {yyval.text=add_strings(string_value(&yyvsp[-2]), yyvsp[0].text); yyval.type=STR;}
- |str_exp '+' str_exp {yyval.text=add_strings(yyvsp[-2].text, yyvsp[0].text); yyval.type=STR;}
+ STR {;}
+ |str_exp '+' exp {yyval.text=add_strings(yyvsp[-2].text, string_value(&yyvsp[0]));}
+ |exp '+' str_exp {yyval.text=add_strings(string_value(&yyvsp[-2]), yyvsp[0].text);}
+ |str_exp '+' str_exp {yyval.text=add_strings(yyvsp[-2].text, yyvsp[0].text);}
+;
+
+range:
+ str_exp {;}
+ |VAR COLR VAR {if(yyval.text =(char*)malloc(strlen($1->name) +strlen($3->name) + 2)) sprintf(yyval.text, "%s:%s", $1->name, $3->name);}
+;
+
+arr: ARR
+ |exp {if(!yyval.a_data) {yyval.a_data = (double*)malloc(sizeof(double)); yyval.a_count = 1; yyval.a_data[0] = yyval.val;}}
+ |arr ',' arr {push(&yyval, &yyvsp[0]);}
+ |arr CLAUSE exp {exec_clause(&yyval);}
+ |range {range_array(&yyval, yyvsp[0].text);}
+ |NUM SER NUM {if($1 < $3 && (yyval.a_data = (double*)malloc((int)($3-$1+2)*sizeof(double))))
+ for(yyval.a_count=0; $1<=$3; yyval.a_data[yyval.a_count++] = $1, $1 += 1.0 );}
;
exp: NUM {$$ = $1; yyval.type = NUM;}
|TXT {$$ = 0.0;}
|CLVAL {$$ = syntax_level ? syntax_level->clval : 0.0; }
- |PI {$$ = 3.14159265358979; yyval.type = NUM;}
+ |PI {$$ = _PI; yyval.type = NUM;}
|E {$$ = 2.71828182845905; yyval.type = NUM;}
- |VAR {$$ = $1->value.var; yyval.type=VAR}
- |VAR '=' exp {$$ = $1->value.var = $3;
- if($1->row >=0 && $1->col >= 0 && curr_data) curr_data->SetValue($1->row, $1->col, $3);}
- |FNCT '(' exp ')' {$$ = ($1->arg_type == ARR) ? ((*$1->value.fnctptr)(proc_clause(&yyvsp[-1]))) :
- (*($1->value.fnctptr))($3);}
+ |VAR {$1->GetValue(&yyval);}
+ |BLOCK {eval(&yyvsp[0], &yyval);}
+ |VAR '=' exp {$1->SetValue(&yyval, &yyvsp[0]);}
+ |VAR '=' str_exp {$1->SetValue(&yyval, &yyvsp[0]);}
+ |FNCT '(' exp ')' {$$ = (($1->fnctptr)($3));}
+ |AFNCT '(' arr ')' {$$ = (($1->fnctptr)(proc_clause(&yyvsp[-1])));}
+ |AFNCT '(' exp PSEP exp ')' {push(&yyvsp[-2], &yyvsp[0]); $$ = (($1->fnctptr)(&yyvsp[-2]));}
+ |AFNCT '(' exp PSEP exp PSEP exp ')' {push(&yyvsp[-4], &yyvsp[-2]); push(&yyvsp[-4], &yyvsp[0]); $$ = (($1->fnctptr)(&yyvsp[-4]));}
+ |SFNCT '(' str_exp ')' {$$ = (($1->fnctptr)(&yyvsp[-1], &yyval));}
+ |SFNCT '(' exp ')' {yyvsp[-1].text = string_value(&yyvsp[-1]); $$ = (($1->fnctptr)(&yyvsp[-1], &yyval));}
+ |FUNC2 '(' arr PSEP arr ')' {$$ = ((*$1->fnctptr)(proc_clause(&yyvsp[-3]), proc_clause(&yyvsp[-1]), 0L));}
+ |FUNC2 '(' arr PSEP arr PSEP range')'
+ {$$ = ((*$1->fnctptr)(proc_clause(&yyvsp[-5]), proc_clause(&yyvsp[-3]), yyvsp[-1].text));}
+ |IF '(' exp ')' BLOCK {$$ = $3 != 0 ? eval(&yyvsp[0], &yyval) : 0.0;}
+ |IF '(' exp ')' BLOCK ELSE BLOCK {$$ = $3 != 0 ? eval(&yyvsp[-2], &yyval) : eval(&yyvsp[0], &yyval);}
|exp AND exp {$$ = (($1 != 0) && ($3 != 0))? 1 : 0;}
|exp OR exp {$$ = (($1 != 0) || ($3 != 0))? 1 : 0;}
|exp EQ exp {$$ = ($1 == $3) ? 1 : 0;}
@@ -140,13 +184,14 @@ exp: NUM {$$ = $1; yyval.type = NUM;}
|exp '-' exp {$$ = $1 - $3;}
|exp '*' exp {$$ = $1 * $3;}
|exp '/' exp {if($3 != 0.0) $$ = $1 / $3;
- else $$ = (getsym(HashValue((unsigned char*)"zdiv")))->value.var; }
- |exp ',' exp {push(&yyval, &yyvsp[0]);}
- |VAR COLR VAR {get_range(&yyval, $1->name, $3->name);}
+ else $$ = (getsym(HashValue((unsigned char*)"zdiv")))->GetValue(); }
|'-' exp %prec NEG {$$ = -$2;}
+ |VAR INC {$$=$1->GetValue(); $1->SetValue($$+1.0); $$ -= 1.0; yyval.type = NUM;}
+ |VAR DEC {$$=$1->GetValue(); $1->SetValue($$-1.0); $$ += 1.0; yyval.type = NUM;}
+ |INC VAR %prec PINC {$$=$2->GetValue(); $2->SetValue($$+1.0); yyval.type = NUM;}
+ |DEC VAR %prec PDEC {$$=$2->GetValue(); $2->SetValue($$-1.0); yyval.type = NUM;}
|exp '^' exp {$$ = pow($1, $3);}
- |exp CLAUSE exp {$$ = $1; exec_clause(&yyval);}
- |'(' exp ')' {memcpy(&yyval, &yyvsp[-1], sizeof(YYSTYPE))}
+ |'(' arr ')' {memcpy(&yyval, &yyvsp[-1], sizeof(YYSTYPE)); yyvsp[-1].a_data = 0L; yyvsp[-1].a_count = 0;}
|exp '?' exp COLC exp {memcpy(&yyval, $1 != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE))}
|exp '?' STR COLC STR {memcpy(&yyval, $1 != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE))}
|exp '?' STR COLC exp {memcpy(&yyval, $1 != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE))}
@@ -154,36 +199,185 @@ exp: NUM {$$ = $1; yyval.type = NUM;}
;
%%
-static char *last_error = 0L;
+// The symrec class
+symrec::symrec(unsigned int h_n, int typ, symrec *nxt)
+{
+ h_name = h_n;
+ type = typ;
+ next = nxt;
+ row = col = -1;
+ name = text = 0L;
+ var = 0.0;
+ isSSval = false;
+ fnctptr = (double (*)(...))nop;
+}
+
+symrec::~symrec()
+{
+ if(name) free(name); name = 0L;
+ if(text) free(text); text = 0L;
+}
+
+double
+symrec::GetValue()
+{
+ anyResult ares;
+
+ if(isSSval) {
+ if(row < 0 && col < 0) InitSS();
+ //GetResult( , , ,true) inhibits reentrance into parser !
+ if(curr_data->GetResult(&ares, row, col, parse_level > MAX_PARSE)){
+ return var = ares.value;
+ }
+ isSSval = false;
+ row = col = -1;
+ }
+ return var;
+}
+
+void
+symrec::GetValue(void *re)
+{
+ anyResult ares;
+ YYSTYPE *res = (YYSTYPE*)re;
+
+ if(isSSval) {
+ if(row < 0 && col < 0) InitSS();
+ res->a_data = 0L; res->a_count = 0;
+ //GetResult( , , ,true) inhibits reentrance into parser !
+ if(curr_data->GetResult(&ares, row, col, parse_level > MAX_PARSE)){
+ if(text) free(text); text = 0L;
+ if(ares.type == ET_VALUE) {
+ res->type = VAR; res->val = ares.value;
+ res->text = 0L;
+ }
+ else if(ares.type == ET_TEXT && ares.text) {
+ res->type = STR; res->val = 0.0;
+ text = strdup(ares.text);
+ res->text = text;
+ }
+ else {
+ res->type = NUM; res->val = var;
+ res->text = 0L;
+ }
+ var = res->val;
+ return;
+ }
+ isSSval = false;
+ row = col = -1;
+ }
+ if(text && text[0]) {
+ res->text = strdup(text);
+ res->val = var; res->type = STR;
+ }
+ else {
+ res->type = NUM; res->val = var;
+ res->text = 0L;
+ }
+ res->a_data = 0L; res->a_count = 0L;
+}
+
+double
+symrec::SetValue(double v)
+{
+ if(isSSval) {
+ if(row < 0 && col < 0) InitSS();
+ if(curr_data->SetValue(row, col, v)){
+ if(curr_data) curr_data->Command(CMD_UPDATE, 0L, 0L);
+ return var = v;
+ }
+ isSSval = false;
+ row = col = -1;
+ }
+ return var = v;
+}
+
+void
+symrec::SetValue(void* d, void* s)
+{
+ YYSTYPE *dest = (YYSTYPE*)d;
+ YYSTYPE *src = (YYSTYPE*)s;
+
+ if(isSSval && curr_data) {
+ if(row < 0 && col < 0) InitSS();
+ if(last_err_desc) curr_data->SetText(row, col, last_err_desc);
+ else if(src->type == STR) curr_data->SetText(row, col, src->text);
+ else if(src->type == ARR || (src->a_data)) curr_data->SetText(row, col, "#ARRAY");
+ else if(src->type == VAR && src->tptr->type == TXT) curr_data->SetText(row, col, src->tptr->text);
+ else curr_data->SetValue(row, col, src->val);
+ curr_data->Command(CMD_UPDATE, 0L, 0L);
+ }
+ var = src->val;
+ if(text) free(text); text = 0L;
+ if(src->text && src->text[0]) text = strdup(src->text);
+ GetValue(d);
+ return;
+}
+
+void
+symrec::SetName(char *nam)
+{
+ if(name || !nam || !nam[0]) return;
+ name = strdup(nam);
+ if((name && curr_data) && (isalpha(name[0]) || name[0] == '$') && isdigit(name[strlen(name)-1])) isSSval=true;
+}
+
+void
+symrec::InitSS()
+{
+ AccRange *ar;
+
+ if(row<0 && col<0 &&(ar = new AccRange(name))) {
+ ar->GetFirst(&col, &row);
+ delete(ar);
+ }
+}
+
static void yyerror(char *s)
{
- //Called by yyparse on error
+ //called by yyparse on error
if(curr_data) curr_data->Command(CMD_ERROR, last_error = s, 0L);
else printf("%s\n", s);
}
+static void yyargserr(char *s)
+{
+ //call from function on argument type/number mismatch
+ yyerror(s);
+ last_err_desc = "#ARGS";
+}
+
static void store_res(YYSTYPE *res)
{
- if(res->type == STR) {
- line_result = 0.0;
+ if(last_err_desc) {
line_res.type = ET_TEXT;
- line_res. value = 0.0;
+ line_res.value = 0.0;
+ strcpy(res_txt, last_err_desc);
+ }
+ else if(res->type == STR) {
+ line_res.type = ET_TEXT;
+ line_res.value = 0.0;
if(res->text) strcpy(res_txt, res->text);
}
+ else if((res->type == ARR || (res->a_data)) && res->a_count == 1) {
+ line_res.type = ET_VALUE;
+ line_res.value = res->a_data[0];
+ }
+ else if(res->type == ARR && !(res->a_data) && !(res->a_count)) {
+ line_res.type = ET_VALUE;
+ line_res.value = res->val;
+ }
else if(res->type == ARR || (res->a_data)) {
- line_result = 0.0;
line_res.type = ET_TEXT;
- line_res. value = 0.0;
+ line_res.value = 0.0;
strcpy(res_txt, "#ARRAY");
}
else if(res->tptr && res->tptr->type == TXT) {
- line_result = 0.0;
line_res.type = ET_TEXT;
line_res.value = 0.0;
if(res->tptr->text) strcpy(res_txt, res->tptr->text);
}
else {
- line_result = res->val;
line_res.type = ET_VALUE;
line_res.value = res->val;
}
@@ -245,6 +439,35 @@ static void pop_syntax()
}
}
+static double eval(YYSTYPE *sr, YYSTYPE *dst)
+{
+ anyResult *ar;
+
+ if(!sr || !sr->text) return 0.0;
+ parse_level++;
+ ar = do_formula(0L, sr->text);
+ yylval.a_data = 0L; yylval.a_count = 0;
+ switch(ar->type) {
+ case ET_VALUE:
+ dst->type = NUM;
+ dst->val = ar->value;
+ dst->text = 0L;
+ break;
+ case ET_TEXT:
+ dst->type = STR;
+ dst->val = 0.0;
+ dst->text = PushString(ar->text);
+ break;
+ default:
+ dst->type = NUM;
+ dst->val = 0.0;
+ dst->text = 0L;
+ break;
+ }
+ parse_level--;
+ return dst->val;
+}
+
// more functions
static double sign(double v)
{
@@ -253,6 +476,19 @@ static double sign(double v)
return 0.0;
}
+static long idum=0;
+
+static double rand(double v)
+{
+ return ran2(&idum);
+}
+
+static double srand(double v)
+{
+ idum = (long)v;
+ return v;
+}
+
static double factorial(double v)
{
return factrl((int)v);
@@ -260,9 +496,14 @@ static double factorial(double v)
static void close_arr_func(YYSTYPE *sr)
{
- free(sr->a_data);
+ if(sr->a_data) free(sr->a_data);
sr->a_data = 0L; sr->a_count = 0;
- if(sr->type == ARR) sr->type = NUM;
+}
+
+static double _strlen(YYSTYPE *sr, YYSTYPE *dst)
+{
+ if(!sr || !sr->text) return 0.0;
+ return (double)strlen(sr->text);
}
#undef min
@@ -270,7 +511,7 @@ static double min(YYSTYPE *sr)
{
int i;
- if(!sr) return 0.0;
+ if(!sr || !sr->a_count) return 0.0;
if(sr->a_data && sr->a_data){
for(i = 1, sr->val = sr->a_data[0]; i < sr->a_count; i++)
if(sr->a_data[i] < sr->val) sr->val = sr->a_data[i];
@@ -284,7 +525,7 @@ static double max(YYSTYPE *sr)
{
int i;
- if(!sr) return 0.0;
+ if(!sr || !sr->a_count) return 0.0;
if(sr->a_data){
for(i = 1, sr->val = sr->a_data[0]; i < sr->a_count; i++)
if(sr->a_data[i] > sr->val) sr->val = sr->a_data[i];
@@ -310,9 +551,10 @@ static double sum(YYSTYPE *sr)
if(!sr) return 0.0;
if(sr->a_data){
- for(i = 1, sr->val = sr->a_data[0]; i < sr->a_count; i++) sr->val += sr->a_data[i];
+ for(i = 0, sr->val = 0.0; i < sr->a_count; i++) sr->val += sr->a_data[i];
close_arr_func(sr);
}
+ else sr->val = 0.0;
return sr->val;
}
@@ -418,14 +660,159 @@ static double sterr(YYSTYPE *sr)
return sr->val;
}
+static double beta(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2){
+ sr->val = betaf(sr->a_data[0], sr->a_data[1]);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to beta(u, v).");
+ return sr->val;
+}
+
+static double _gammp(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2){
+ sr->val = gammp(sr->a_data[0], sr->a_data[1]);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to gammp(a, x).");
+ return sr->val;
+}
+
+static double _gammq(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2){
+ sr->val = gammq(sr->a_data[0], sr->a_data[1]);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to gammq(a, x).");
+ return sr->val;
+}
+
+static double _betai(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 3){
+ sr->val = betai(sr->a_data[0], sr->a_data[1], sr->a_data[2]);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to betai(x, a, b).");
+ return sr->val;
+}
+
+static double _bincof(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2){
+ sr->val = bincof(sr->a_data[0], sr->a_data[1]);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to bincof(n, k).");
+ return sr->val;
+}
+
+static double binomdist(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 3){
+ sr->val = binomdistf(sr->a_data[0], sr->a_data[1], sr->a_data[2]);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to binomdist(s, n, p).");
+ return sr->val;
+}
+
+static double normdist(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 3){
+ sr->val = norm_dist(sr->a_data[0], sr->a_data[1], sr->a_data[2]);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to normdist(x, mean, SD).");
+ return sr->val;
+}
+
+static double norminv(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 3) {
+ sr->val = distinv(norm_dist,sr->a_data[1], sr->a_data[2], sr->a_data[0], 2.0);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to norminv(p, mean, SD).");
+ return sr->val;
+}
+
+static double chidist(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2){
+ sr->val = chi_dist(sr->a_data[0], sr->a_data[1], 1.0);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to chidist(x, df).");
+ return sr->val;
+}
+
+static double chiinv(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2) {
+ sr->val = distinv(chi_dist,sr->a_data[1], 1.0, sr->a_data[0], 2.0);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to chiinv(p, df).");
+ return sr->val;
+}
+
static double tdist(YYSTYPE *sr)
{
if(!sr) return 0.0;
sr->val = 0.0;
if(sr->a_data && sr->a_count == 2){
- sr->val = t_dist(sr->a_data[0], sr->a_data[1]);
+ sr->val = t_dist(sr->a_data[0], sr->a_data[1], 1.0);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to tdist(x, df).");
+ return sr->val;
+}
+
+static double tinv(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2) {
+ sr->val = distinv(t_dist,sr->a_data[1], 1.0, sr->a_data[0], 2.0);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to tinv(p, df).");
+ return sr->val;
+}
+
+static double poisdist(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2){
+ sr->val = pois_dist(sr->a_data[0], sr->a_data[1], 1.0);
close_arr_func(sr);
}
+ else yyargserr("Wrong number of arguments\nin call to poisdist(x, mean).");
return sr->val;
}
@@ -437,51 +824,150 @@ static double fdist(YYSTYPE *sr)
sr->val = f_dist(sr->a_data[0], sr->a_data[1], sr->a_data[2]);
close_arr_func(sr);
}
+ else yyargserr("Wrong number of arguments\nin call to fdist(x, df1, df2).");
return sr->val;
}
+static double finv(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0;
+ if(sr->a_data && sr->a_count == 3){
+ sr->val = distinv(f_dist,sr->a_data[1], sr->a_data[2], sr->a_data[0], 2.0);
+ close_arr_func(sr);
+ }
+ else yyargserr("Wrong number of arguments\nin call to finv(p, df1, df2).");
+ return sr->val;
+}
+
+static double pearson(YYSTYPE *sr1, YYSTYPE *sr2, char *dest)
+{
+ if(!sr1 || !sr2) return 0.0;
+ sr1->val = 0.0;
+ if(sr1->a_data && sr1->a_count > 1 && sr2->a_data && sr1->a_count == sr2->a_count){
+ sr1->val = sr2->val = d_pearson(sr1->a_data, sr2->a_data, sr1->a_count, dest, curr_data);
+ close_arr_func(sr1); close_arr_func(sr2);
+ }
+ else yyargserr("Bad arguments in call to function\npearson(range1; range2 [;\"dest\"]).");
+ return sr1->val;
+}
+
+static double spearman(YYSTYPE *sr1, YYSTYPE *sr2, char *dest)
+{
+ if(!sr1 || !sr2) return 0.0;
+ sr1->val = 0.0;
+ if(sr1->a_data && sr1->a_count > 1 && sr2->a_data && sr1->a_count == sr2->a_count){
+ sr1->val = sr2->val = d_spearman(sr1->a_data, sr2->a_data, sr1->a_count, dest, curr_data);
+ close_arr_func(sr1); close_arr_func(sr2);
+ }
+ else yyargserr("Bad arguments in call to function\nspearman(range1; range2 [;\"dest\"]).");
+ return sr1->val;
+}
+
+static double regression(YYSTYPE *sr1, YYSTYPE *sr2, char *dest)
+{
+ if(!sr1 || !sr2) return 0.0;
+ sr1->val = 0.0;
+ if(!(dest)) yyargserr("No destination range in call to function\nregression(range1; range2; \"dest\").");
+ if(sr1->a_data && sr1->a_count > 1 && sr2->a_data && sr1->a_count == sr2->a_count){
+ sr1->val = sr2->val = d_regression(sr1->a_data, sr2->a_data, sr1->a_count, dest, curr_data);
+ close_arr_func(sr1); close_arr_func(sr2);
+ }
+ else yyargserr("Bad arguments in call to function\nregression(range1; range2; \"dest\").");
+ return sr1->val;
+}
+
+static double ttest(YYSTYPE *sr1, YYSTYPE *sr2, char *dest)
+{
+ if(!sr1 || !sr2) return 0.0;
+ sr1->val = 0.0;
+ if(sr1->a_data && sr1->a_count > 1 && sr2->a_data && sr2->a_count > 1){
+ sr1->val = sr2->val = d_ttest(sr1->a_data, sr2->a_data, sr1->a_count, sr2->a_count, dest, curr_data);
+ close_arr_func(sr1); close_arr_func(sr2);
+ }
+ else yyargserr("Bad arguments in call to function\nttest(range1; range2[;\"dest\"]).");
+ return sr1->val;
+}
+
+static double ftest(YYSTYPE *sr1, YYSTYPE *sr2, char *dest)
+{
+ if(!sr1 || !sr2) return 0.0;
+ sr1->val = 0.0;
+ if(sr1->a_data && sr1->a_count > 1 && sr2->a_data && sr1->a_count > 1){
+ sr1->val = sr2->val = d_ftest(sr1->a_data, sr2->a_data, sr1->a_count, sr2->a_count, dest, curr_data);
+ close_arr_func(sr1); close_arr_func(sr2);
+ }
+ else yyargserr("Bad arguments in call to function\nftest(range1; range2[;\"dest\"]).");
+ return sr1->val;
+}
+
struct init
{
+ int f_type;
unsigned int h_name;
double (*fnct)(double);
- int arg_type;
};
static struct init arith_fncts[] = {
- {HashValue((unsigned char*)"variance"), (double(*)(double))&variance, ARR},
- {HashValue((unsigned char*)"stdev"), (double(*)(double))&stdev, ARR},
- {HashValue((unsigned char*)"sterr"), (double(*)(double))&sterr, ARR},
- {HashValue((unsigned char*)"min"), (double(*)(double))&min, ARR},
- {HashValue((unsigned char*)"max"), (double(*)(double))&max, ARR},
- {HashValue((unsigned char*)"count"), (double(*)(double))&count, ARR},
- {HashValue((unsigned char*)"sum"), (double(*)(double))&sum, ARR},
- {HashValue((unsigned char*)"mean"), (double(*)(double))&mean, ARR},
- {HashValue((unsigned char*)"median"), (double(*)(double))&quartile2, ARR},
- {HashValue((unsigned char*)"quartile1"), (double(*)(double))&quartile1, ARR},
- {HashValue((unsigned char*)"quartile2"), (double(*)(double))&quartile2, ARR},
- {HashValue((unsigned char*)"quartile3"), (double(*)(double))&quartile3, ARR},
- {HashValue((unsigned char*)"gmean"), (double(*)(double))&gmean, ARR},
- {HashValue((unsigned char*)"hmean"), (double(*)(double))&hmean, ARR},
- {HashValue((unsigned char*)"tdist"), (double(*)(double))&tdist, ARR},
- {HashValue((unsigned char*)"fdist"), (double(*)(double))&fdist, ARR},
- {HashValue((unsigned char*)"sign"), sign, VAR},
- {HashValue((unsigned char*)"gammaln"), gammln, VAR},
- {HashValue((unsigned char*)"factorial"), factorial, VAR},
- {HashValue((unsigned char*)"abs"), fabs, VAR},
- {HashValue((unsigned char*)"asin"), asin, VAR},
- {HashValue((unsigned char*)"acos"), acos, VAR},
- {HashValue((unsigned char*)"atan"), atan, VAR},
- {HashValue((unsigned char*)"sinh"), sinh, VAR},
- {HashValue((unsigned char*)"cosh"), cosh, VAR},
- {HashValue((unsigned char*)"tanh"), tanh, VAR},
- {HashValue((unsigned char*)"sin"), sin, VAR},
- {HashValue((unsigned char*)"cos"), cos, VAR},
- {HashValue((unsigned char*)"atan"), atan, VAR},
- {HashValue((unsigned char*)"log10"), log10, VAR},
- {HashValue((unsigned char*)"ln"), log, VAR},
- {HashValue((unsigned char*)"log"), log, VAR},
- {HashValue((unsigned char*)"exp"), exp, VAR},
- {HashValue((unsigned char*)"sqrt"), sqrt, VAR},
+ {FUNC2, HashValue((unsigned char*)"pearson"), (double(*)(double))&pearson},
+ {FUNC2, HashValue((unsigned char*)"spearman"), (double(*)(double))&spearman},
+ {FUNC2, HashValue((unsigned char*)"regression"), (double(*)(double))®ression},
+ {FUNC2, HashValue((unsigned char*)"ttest"), (double(*)(double))&ttest},
+ {FUNC2, HashValue((unsigned char*)"ftest"), (double(*)(double))&ftest},
+ {AFNCT, HashValue((unsigned char*)"variance"), (double(*)(double))&variance},
+ {AFNCT, HashValue((unsigned char*)"stdev"), (double(*)(double))&stdev},
+ {AFNCT, HashValue((unsigned char*)"sterr"), (double(*)(double))&sterr},
+ {AFNCT, HashValue((unsigned char*)"min"), (double(*)(double))&min},
+ {AFNCT, HashValue((unsigned char*)"max"), (double(*)(double))&max},
+ {AFNCT, HashValue((unsigned char*)"count"), (double(*)(double))&count},
+ {AFNCT, HashValue((unsigned char*)"sum"), (double(*)(double))&sum},
+ {AFNCT, HashValue((unsigned char*)"mean"), (double(*)(double))&mean},
+ {AFNCT, HashValue((unsigned char*)"median"), (double(*)(double))&quartile2},
+ {AFNCT, HashValue((unsigned char*)"quartile1"), (double(*)(double))&quartile1},
+ {AFNCT, HashValue((unsigned char*)"quartile2"), (double(*)(double))&quartile2},
+ {AFNCT, HashValue((unsigned char*)"quartile3"), (double(*)(double))&quartile3},
+ {AFNCT, HashValue((unsigned char*)"gmean"), (double(*)(double))&gmean},
+ {AFNCT, HashValue((unsigned char*)"hmean"), (double(*)(double))&hmean},
+ {AFNCT, HashValue((unsigned char*)"tdist"), (double(*)(double))&tdist},
+ {AFNCT, HashValue((unsigned char*)"tinv"), (double(*)(double))&tinv},
+ {AFNCT, HashValue((unsigned char*)"poisdist"), (double(*)(double))&poisdist},
+ {AFNCT, HashValue((unsigned char*)"fdist"), (double(*)(double))&fdist},
+ {AFNCT, HashValue((unsigned char*)"finv"), (double(*)(double))&finv},
+ {AFNCT, HashValue((unsigned char*)"gammp"), (double(*)(double))&_gammp},
+ {AFNCT, HashValue((unsigned char*)"gammq"), (double(*)(double))&_gammq},
+ {AFNCT, HashValue((unsigned char*)"beta"), (double(*)(double))&beta},
+ {AFNCT, HashValue((unsigned char*)"betai"), (double(*)(double))&_betai},
+ {AFNCT, HashValue((unsigned char*)"bincof"), (double(*)(double))&_bincof},
+ {AFNCT, HashValue((unsigned char*)"binomdist"), (double(*)(double))&binomdist},
+ {AFNCT, HashValue((unsigned char*)"normdist"), (double(*)(double))&normdist},
+ {AFNCT, HashValue((unsigned char*)"norminv"), (double(*)(double))&norminv},
+ {AFNCT, HashValue((unsigned char*)"chidist"), (double(*)(double))&chidist},
+ {AFNCT, HashValue((unsigned char*)"chiinv"), (double(*)(double))&chiinv},
+ {SFNCT, HashValue((unsigned char*)"strlen"), (double(*)(double))&_strlen},
+ {SFNCT, HashValue((unsigned char*)"eval"), (double(*)(double))&eval},
+ {FNCT, HashValue((unsigned char*)"erf"), errf},
+ {FNCT, HashValue((unsigned char*)"erfc"), errfc},
+ {FNCT, HashValue((unsigned char*)"sign"), sign},
+ {FNCT, HashValue((unsigned char*)"gammaln"), gammln},
+ {FNCT, HashValue((unsigned char*)"factorial"), factorial},
+ {FNCT, HashValue((unsigned char*)"rand"), rand},
+ {FNCT, HashValue((unsigned char*)"srand"), srand},
+ {FNCT, HashValue((unsigned char*)"floor"), floor},
+ {FNCT, HashValue((unsigned char*)"abs"), fabs},
+ {FNCT, HashValue((unsigned char*)"asin"), asin},
+ {FNCT, HashValue((unsigned char*)"acos"), acos},
+ {FNCT, HashValue((unsigned char*)"atan"), atan},
+ {FNCT, HashValue((unsigned char*)"sinh"), sinh},
+ {FNCT, HashValue((unsigned char*)"cosh"), cosh},
+ {FNCT, HashValue((unsigned char*)"tanh"), tanh},
+ {FNCT, HashValue((unsigned char*)"sin"), sin},
+ {FNCT, HashValue((unsigned char*)"cos"), cos},
+ {FNCT, HashValue((unsigned char*)"atan"), atan},
+ {FNCT, HashValue((unsigned char*)"log10"), log10},
+ {FNCT, HashValue((unsigned char*)"ln"), log},
+ {FNCT, HashValue((unsigned char*)"log"), log},
+ {FNCT, HashValue((unsigned char*)"exp"), exp},
+ {FNCT, HashValue((unsigned char*)"sqrt"), sqrt},
{0, 0, 0}};
// Store strings in a list
@@ -499,19 +985,68 @@ static char *PushString(char *text)
}
//The symbol table: a chain of `struct symrec'
-static symrec *sym_table = (symrec *) 0;
+static symrec *sym_table, *sym_tab_first;
+
+//Rearrange function table with previously used functions in front
+void ArrangeFunctions()
+{
+ symrec *ptr, *ptr1, *ptr2, *next;
+
+ for(ptr = sym_table, ptr1 = ptr2 = 0L; (ptr); ) {
+ next = ptr->next;
+ if(ptr->name) {
+ ptr->next = ptr1;
+ ptr1 = ptr;
+ }
+ else {
+ ptr->next = ptr2;
+ ptr2 = ptr;
+ }
+ ptr = next;
+ }
+ for(sym_table = 0L, ptr = ptr2; (ptr); ){
+ next = ptr->next;
+ ptr->next = sym_table;
+ sym_table = ptr;
+ ptr = next;
+ }
+ for(ptr = ptr1; (ptr); ){
+ next = ptr->next;
+ ptr->next = sym_table;
+ sym_table = ptr;
+ ptr = next;
+ }
+ sym_tab_first = sym_table;
+ bRecent = false;
+}
// Put arithmetic functions and predifened variables in table
-static void init_table (void)
+void InitArithFuncs(DataObj *d)
{
int i;
- symrec *ptr;
+ symrec *ptr, *next;
+ if(d) curr_data = d;
+ if(sym_table) {
+ for (ptr = sym_table; ptr != (symrec *) 0;){
+ if(ptr) {
+ next = ptr->next;
+ delete (ptr);
+ }
+ ptr = next;
+ }
+ sym_table = sym_tab_first = (symrec *) 0;
+ }
for (i = 0; arith_fncts[i].h_name; i++) {
- ptr = putsym (arith_fncts[i].h_name, FNCT, arith_fncts[i].arg_type);
- ptr->value.fnctptr = (double (*)(...))arith_fncts[i].fnct;
+ ptr = putsym (arith_fncts[i].h_name, arith_fncts[i].f_type);
+ ptr->fnctptr = (double (*)(...))arith_fncts[i].fnct;
}
- ptr = putsym(HashValue((unsigned char*)"zdiv"), VAR, 0); ptr->value.var = 1.0;
+ ptr = putsym(HashValue((unsigned char*)"zdiv"), VAR); ptr->SetValue(1.0);
+ sym_tab_first = sym_table;
+}
+
+static void init_table (void)
+{
str_list = 0L; n_str = 0;
push_syntax();
}
@@ -519,18 +1054,7 @@ static void init_table (void)
static void clear_table()
{
int i;
- symrec *ptr, *next;
- for (ptr = sym_table; ptr != (symrec *) 0;){
- if(ptr) {
- if(ptr->name) free(ptr->name);
- if(ptr->text) free(ptr->text);
- next = (symrec*)ptr->next;
- free(ptr);
- }
- ptr = next;
- }
- sym_table = (symrec *) 0;
if(str_list) {
for(i = 0; i < n_str; i++) if(str_list[i]) free(str_list[i]);
free(str_list); str_list = 0L; n_str = 0;
@@ -539,58 +1063,30 @@ static void clear_table()
}
static symrec *
-putsym (unsigned int h_name, int sym_type, int arg_type)
+putsym (unsigned int h_name, int sym_type)
{
- symrec *ptr;
-
- ptr = (symrec *) malloc (sizeof (symrec));
- ptr->h_name = h_name;
- ptr->type = sym_type;
- ptr->name = ptr->text = 0L;
- ptr->value.var = 0; /* set value to 0 even if fctn. */
- ptr->arg_type = arg_type;
- ptr->col = ptr->row = -1;
- ptr->next = (struct symrec *)sym_table;
- sym_table = ptr;
- return ptr;
+ sym_table = new symrec(h_name, sym_type, sym_table);
+ return sym_table;
}
static symrec *
getsym (unsigned int h_name, char *sym_name)
{
symrec *ptr;
- int row, col;
- AccRange *ar;
- anyResult ares;
if(!h_name) return 0;
- for (ptr = sym_table; ptr != (symrec *) 0; ptr = (symrec *)ptr->next)
+ for (ptr = sym_table; ptr != (symrec *) 0; ptr = (symrec *)ptr->next) {
if (ptr->h_name == h_name){
- if(sym_name && !ptr->name) ptr->name = ptr->name=strdup(sym_name);
- return ptr;
- }
- if((sym_name && curr_data) && (isalpha(sym_name[0]) || sym_name[0] == '$') && isdigit(sym_name[strlen(sym_name)-1])) {
- if((ar = new AccRange(sym_name)) && ar->GetFirst(&col, &row) &&
- (ptr = putsym(h_name, VAR, 0))) {
- ptr->name = strdup(sym_name);
- if(curr_data->GetResult(&ares, row, col)){
- if(ares.type == ET_VALUE) {
- ptr->type = VAR; ptr->value.var = ares.value;
- ptr->text = 0L;
- }
- else if(ares.type == ET_TEXT && ares.text) {
- ptr->type = TXT; ptr->value.var = 0.0;
- ptr->text = strdup(ares.text);
- }
- else {
- ptr->type = VAR; ptr->value.var = 0.0;
- ptr->text = 0L;
- }
+ if(sym_name && !ptr->name) {
+ ptr->SetName(sym_name);
+ bRecent = true;
}
- ptr->row = row; ptr->col = col;
- delete(ar);
return ptr;
}
+ //predefined variables never end on a digit
+ else if(ptr == sym_tab_first) {
+ if(sym_name && isdigit(sym_name[strlen(sym_name)-1])) return 0;
+ }
}
return 0;
}
@@ -598,7 +1094,7 @@ getsym (unsigned int h_name, char *sym_name)
static int
push(YYSTYPE *res, YYSTYPE *val)
{
- if(val->a_data && val->a_count) {
+ if(val->a_data) {
if(!(res->a_data)) {
if(!(val->a_data=(double*)realloc(val->a_data, (val->a_count+2)*sizeof(double))))return 0;
val->a_data[val->a_count++] = res->val;
@@ -629,36 +1125,36 @@ push(YYSTYPE *res, YYSTYPE *val)
}
static int
-get_range(YYSTYPE *res, char *first, char *last)
+range_array(YYSTYPE * res, char *range)
{
- char r_txt[40];
AccRange *r;
int row, col;
- double value;
- YYSTYPE tmp;
-
- if(!res || !first || !last || !curr_data) return 0;
- sprintf(r_txt, "%s:%s", first, last);
- if(!(res->a_data ) && (r = new AccRange(r_txt)) && r->GetFirst(&col, &row)) {
- if(!(res->a_data = (double*)malloc(r->CountItems() * sizeof(double)))) return 0;
- res->a_count = 0;
- for( ; r->GetNext(&col, &row); ) {
- if(curr_data->GetValue(row, col, &value)) res->a_data[res->a_count++] = value;
- }
- delete r; return 1;
- }
- if((r = new AccRange(r_txt)) && r->GetFirst(&col, &row)) {
- //it is probably a bit slow to push every element
- tmp.type = NUM;
- for( ; r->GetNext(&col, &row); ) {
- if(curr_data->GetValue(row, col, &value)) {
- tmp.val = value;
- push(res, &tmp);
+ anyResult ares;
+
+ if(!range || !range[0] || !(r = new AccRange(range))) return 0;
+ if(!r->GetFirst(&col, &row) || !(res->a_data = (double*)malloc(r->CountItems() * sizeof(double)))) {
+ delete(r);
+ return 0;
+ }
+ parse_level++;
+ for(res->a_count = 0; r->GetNext(&col, &row); ) {
+ if(curr_data->GetResult(&ares, row, col, parse_level > MAX_PARSE)) {
+ switch(ares.type) {
+ case ET_VALUE:
+ res->a_data[res->a_count++] = ares.value;
+ break;
+ case ET_TEXT:
+ if(ares.text && ares.text[0]) last_err_desc = "#ARGS";
+ break;
+ case ET_ERROR:
+ last_err_desc = "#ARGS";
+ break;
}
}
- delete r; return 1;
}
- return 0;
+ parse_level--;
+ delete(r);
+ return 1;
}
static YYSTYPE *proc_clause(YYSTYPE *res)
@@ -670,7 +1166,7 @@ static YYSTYPE *proc_clause(YYSTYPE *res)
if(!(syntax_level) || !syntax_level->cl1 || syntax_level->cl2 <= syntax_level->cl1) return res;
if(!res->text) return res;
if(!res->a_data && (res->a_data = (double*)malloc(sizeof(double)))) {
- res->a_data[0] = res->type == VAR && res->tptr ? res->tptr->value.var : res->val;
+ res->a_data[0] = res->type == VAR && res->tptr ? res->tptr->GetValue() : res->val;
res->a_count = 1;
}
else if(!res->a_data) return res;
@@ -708,13 +1204,13 @@ static void exec_clause(YYSTYPE *res)
struct parse_info {
char *buffer;
int buff_pos;
- double line_result;
DataObj *curr_data;
symrec *sym_table;
YYSTYPE yylval;
struct parse_info *next;
char **str_list;
- int n_str;
+ char *last_err_desc;
+ int n_str, yychar, yynerrs;
};
static parse_info *parse_stack = 0L;
@@ -722,30 +1218,42 @@ static void push_parser()
{
parse_info *ptr;
+ if(!sym_table) InitArithFuncs(0L);
+ else if(!parse_level && bRecent) ArrangeFunctions();
ptr = (parse_info *) malloc(sizeof(parse_info));
ptr->buffer = buffer; ptr->buff_pos = buff_pos;
- ptr->line_result = line_result; ptr->curr_data = curr_data;
- ptr->sym_table = sym_table; sym_table = 0L;
+ ptr->curr_data = curr_data; ptr->last_err_desc = last_err_desc;
+ ptr->sym_table = sym_table; sym_table = sym_tab_first;
memcpy(&ptr->yylval, &yylval, sizeof(YYSTYPE));
ptr->next = parse_stack;
ptr->str_list = str_list; str_list = 0L;
ptr->n_str = n_str; n_str = 0;
- parse_stack = ptr;
- push_syntax();
+ ptr->yychar = yychar; ptr->yynerrs = yynerrs;
+ parse_stack = ptr; last_err_desc = 0L;
+ parse_level++; //reenter ?
+ push_syntax(); syntax_level->last_tok = 0;
}
static void pop_parser()
{
parse_info *ptr;
+ symrec *n;
if(ptr = parse_stack) {
+ while(sym_table && sym_table != sym_tab_first) {
+ n = sym_table->next;
+ delete(sym_table);
+ sym_table = n;
+ }
+ if(sym_table) sym_table = ptr->sym_table;
parse_stack = ptr->next;
- buffer = ptr->buffer; buff_pos = ptr->buff_pos;
- line_result = ptr->line_result; curr_data = ptr->curr_data;
- sym_table = ptr->sym_table;
+ buffer = ptr->buffer; buff_pos = ptr->buff_pos;
+ curr_data = ptr->curr_data; last_err_desc = ptr->last_err_desc;
memcpy(&yylval, &ptr->yylval, sizeof(YYSTYPE));
- str_list = ptr->str_list; n_str = ptr->n_str;
+ str_list = ptr->str_list; n_str = ptr->n_str;
+ yychar = ptr->yychar; yynerrs = ptr->yynerrs;
free(ptr);
+ parse_level--;
}
pop_syntax();
}
@@ -753,12 +1261,14 @@ static void pop_parser()
static int is_ttoken(int h_nam)
{
switch(h_nam) {
- case 69: return E;
- case 393: return PI;
+ case 101: return E;
+ case 26992: return PI;
case 28381:
if(syntax_level) syntax_level->cl1 = buff_pos;
return CLAUSE;
- case 20: return CLVAL;
+ case 9252: return CLVAL;
+ case 26217: return IF;
+ case 6033: return ELSE;
}
return 0;
}
@@ -773,19 +1283,37 @@ static int yylex (void)
while((c = buffer[buff_pos++]) == ' ' || c == '\t'); //get first nonwhite char
if(!c) return 0;
+ //test for block statement
+ if(c == '{') {
+ for(i= 0; i < 79 && ((tok = buffer[buff_pos]) && (tok != '}')); buff_pos++) {
+ tmp_txt[i++] = (char)tok;
+ }
+ if(buffer[buff_pos] == '}')buff_pos++;
+ tmp_txt[i] = 0;
+ yylval.text = PushString(tmp_txt);
+ return yylval.type = BLOCK;
+ }
+ //test for '..' operator
+ if(c == '.' && buffer[buff_pos] == '.') {
+ buff_pos++;
+ return yylval.type = SER;
+ }
//test for number
if(c == '.' || isdigit(c)) {
for(buff_pos--, i = 0; i < 79 && ((c = buffer[buff_pos]) == '.' || isdigit(c)); buff_pos++) {
tmp_txt[i++] = (char)c;
- if(buffer[buff_pos+1] == 'e' && (buffer[buff_pos+2] == '-' || buffer[buff_pos+2] == '+')){
+ if(i && buffer[buff_pos+1] == 'e' && (buffer[buff_pos+2] == '-' || buffer[buff_pos+2] == '+')){
tmp_txt[i++] = buffer[++buff_pos];
tmp_txt[i++] = buffer[++buff_pos];
}
+ if(i && buffer[buff_pos+1] == '.' && buffer[buff_pos+2] == '.') { //operator '..'
+ buff_pos++;
+ break;
+ }
}
tmp_txt[i] = 0;
sscanf(tmp_txt, "%lf", &yylval.val);
- yylval.type = NUM;
- return NUM;
+ return yylval.type = NUM;
}
//test for name or stringtoken
if(isalpha(c) || c=='$') {
@@ -796,11 +1324,9 @@ static int yylex (void)
h_nam = HashValue((unsigned char*)tmp_txt);
if(tok = is_ttoken(h_nam))
return tok;
- if(!(strcmp(tmp_txt, "pi"))) return PI;
- if(!(strcmp(tmp_txt, "e"))) return E;
if(!(s = getsym(h_nam, tmp_txt))){
- s = putsym(h_nam, VAR, 0);
- s->name = strdup(tmp_txt);
+ s = putsym(h_nam, VAR);
+ s->SetName(tmp_txt);
}
curr_sym = yylval.tptr = s; return s->type;
@@ -858,6 +1384,17 @@ static int yylex (void)
else if(syntax_level->last_tok == '?') return COLC;
}
break;
+ case ';':
+ if(syntax_level) {
+ if(syntax_level->last_tok == '(') return PSEP;
+ }
+ break;
+ case '+':
+ if(buffer[buff_pos] == '+') tok = INC;
+ break;
+ case '-':
+ if(buffer[buff_pos] == '-') tok = DEC;
+ break;
}
if(tok) {
buff_pos++; return tok;
@@ -869,10 +1406,10 @@ static int yylex (void)
bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOINT **pts, long *npts, char *param)
{
double x, y;
- symrec *s;
+ symrec *sx, *sy;
lfPOINT *new_points;
long npoints = 0;
- int length;
+ int length, res_mode = 0;
unsigned int hn_x = HashValue((unsigned char *)"x");
unsigned int hn_y = HashValue((unsigned char *)"y");
@@ -881,6 +1418,7 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
if(!(new_points = (lfPOINT*)calloc((iround(fabs(x2-x1)/fabs(step))+2), sizeof(lfPOINT))))
return false;
if(d) curr_data = d;
+ push_parser();
init_table();
if(param) {
length = strlen(param);
@@ -896,21 +1434,34 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
free(buffer); buffer = 0L;
}
length = strlen(expr);
- buffer = expr; s = putsym(hn_x, VAR, 0);
+ buffer = expr; sx = putsym(hn_x, VAR);
for(x = x1; step > 0.0 ? x <= x2 : x >= x2; x += step) {
- if(s = getsym(hn_x)){
- s->value.var = x; buff_pos = 0;
+ if(sx){
+ sx->SetValue(x); buff_pos = 0;
do {
yyparse();
}while(buff_pos < length);
- if(s = getsym(hn_y)) y = s->value.var;
- else y = line_result;
- new_points[npoints].fx = (getsym(hn_x))->value.var;
+ switch (res_mode) {
+ case 1:
+ y = sy->GetValue(); break;
+ case 2:
+ y = line_res.value; break;
+ default:
+ if(sy = getsym(hn_y)) {
+ y = sy->GetValue(); res_mode = 1;
+ }
+ else {
+ y = line_res.value; res_mode = 2;
+ }
+ break;
+ }
+ new_points[npoints].fx = (getsym(hn_x))->GetValue();
new_points[npoints++].fy = y;
}
}
*pts = new_points; *npts = npoints;
clear_table();
+ pop_parser();
if(curr_data) {
curr_data->Command(CMD_CLEAR_ERROR, 0L, 0L);
curr_data->Command(CMD_REDRAW, 0L, 0L);
@@ -918,10 +1469,68 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
return true;
}
+bool do_func3D(DataObj *d, double x1, double x2, double xstep, double z1, double z2, double zstep,
+ char *expr, char *param)
+{
+ int length, nr, nc, r, c, res_mode=0;
+ symrec *sx, *sz, *sy;
+ double x, y, z;
+ unsigned int hn_x = HashValue((unsigned char *)"x");
+ unsigned int hn_y = HashValue((unsigned char *)"y");
+ unsigned int hn_z = HashValue((unsigned char *)"z");
+
+ if(!d || x2 <= x1 || z2 <= z1 || xstep <= 0.0 || zstep <= 0.0) return false;
+ push_parser();
+ init_table();
+ if(param) {
+ length = strlen(param);
+ if(!(buffer = (char*)malloc(length+2))){
+ pop_parser();
+ return false;
+ }
+ strcpy(buffer, param); buffer[length++] = ';';
+ buffer[length] = 0; buff_pos = 0;
+ do {
+ yyparse();
+ }while(buff_pos < length);
+ free(buffer); buffer = 0L;
+ }
+ length = strlen(expr); buffer = expr;
+ sx = putsym(hn_x, VAR); sz = putsym(hn_z, VAR);
+ nr = iround((z2-z1)/zstep)+1; nc = iround((x2-x1)/xstep)+1;
+ d->Init(nr, nc);
+ for(r = 0, x = x1; r < nr; r++, x += xstep) {
+ for(c = 0, z = z1; c < nc; c++, z+= zstep) {
+ sx->SetValue(x); sz->SetValue(z); buff_pos = 0;
+ do {
+ yyparse();
+ }while(buff_pos < length);
+ switch (res_mode) {
+ case 1:
+ y = sy->GetValue(); break;
+ case 2:
+ y = line_res.value; break;
+ default:
+ if(sy = getsym(hn_y)) {
+ y = sy->GetValue(); res_mode = 1;
+ }
+ else {
+ y = line_res.value; res_mode = 2;
+ }
+ break;
+ }
+ d->SetValue(r, c, y);
+ }
+ }
+ clear_table();
+ pop_parser();
+ return true;
+}
+
anyResult *do_formula(DataObj *d, char *expr)
{
int length;
- static anyResult ret;
+ static anyResult ret, *pret = 0L;
if(d) curr_data = d;
ret.type = ET_ERROR; ret.text = 0L;
@@ -932,22 +1541,26 @@ anyResult *do_formula(DataObj *d, char *expr)
pop_parser();
return &ret;
}
- strcpy(buffer, expr); buffer[length++] = ';';
+ strcpy(buffer, expr); if(buffer[length-1] != ';') buffer[length++] = ';';
buffer[length] = 0; buff_pos = 0;
do {
yyparse();
}while(buff_pos < length);
+ ret.type = ET_ERROR; ret.text = 0L;
if(curr_data && last_error) {
- curr_data->Command(CMD_ERROR, last_error = 0L, 0L);
- return &ret;
+ if(!(strcmp(last_error, "parse error"))) curr_data->Command(CMD_ERROR, 0L, 0L);
+ if(last_err_desc) pret = &line_res;
+ else pret = &ret;
}
+ else pret = &line_res;
+ last_error = last_err_desc = 0L;
free(buffer); buffer = 0L;
clear_table();
pop_parser();
- return &line_res;
+ return pret;
}
-bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy)
+bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy, int r0, int c0)
{
int length, tok, pos, i;
char *res, desc1[2], desc2[2];
@@ -971,43 +1584,55 @@ bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy)
}
else switch(tok) {
case NUM:
- pos += sprintf(res+pos, "%g ", yylval.val);
+ pos += sprintf(res+pos, "%g", yylval.val);
break;
- case FNCT:
+ case FNCT: case FUNC2: case AFNCT: case SFNCT:
pos += sprintf(res+pos, "%s", curr_sym->name);
break;
- case COLR:
+ case COLR: case COLC:
pos += sprintf(res+pos, ":");
break;
- case COLC:
- pos += sprintf(res+pos, ": ");
+ case PSEP:
+ pos += sprintf(res+pos, ";");
break;
case CLVAL:
- pos += sprintf(res+pos, "$$ ");
+ pos += sprintf(res+pos, "$$");
break;
case CLAUSE:
pos += sprintf(res+pos, " where ");
break;
case VAR:
+ curr_sym->InitSS();
if(curr_sym->col >= 0 && curr_sym->row >= 0) {
desc1[0] = desc1[1] = desc2[0] = desc2[1] = 0;
for(i=strlen(curr_sym->name)-1; i>0 && isdigit(curr_sym->name[i]); i--);
if(curr_sym->name[0] == '$') desc1[0] = '$';
if(curr_sym->name[i] == '$') desc2[0] = '$';
pos += sprintf(res+pos, "%s%s%s%d", desc1,
- Int2ColLabel(desc1[0] ? curr_sym->col : curr_sym->col+dx, false),
- desc2, desc2[0]? curr_sym->row+1 : curr_sym->row+1+dy);
+ Int2ColLabel(desc1[0] || curr_sym->col < c0 ? curr_sym->col : curr_sym->col+dx >=0 ?
+ curr_sym->col+dx > c0 ? curr_sym->col+dx : c0 : 0, false),
+ desc2, desc2[0] || curr_sym->row < r0 ? curr_sym->row+1 : curr_sym->row + dy >= 0 ?
+ curr_sym->row+dy > r0 ? curr_sym->row+1+dy : r0 : 1);
}
else pos += sprintf(res+pos, "%s ", curr_sym->name);
break;
case STR:
pos += sprintf(res+pos, "\"%s\"", yylval.text && yylval.text[0] ? yylval.text : "");
break;
+ case SER:
+ pos += sprintf(res+pos, "..");
+ break;
+ case INC:
+ pos += sprintf(res+pos, "++");
+ break;
+ case DEC:
+ pos += sprintf(res+pos, "--");
+ break;
case PI:
- pos += sprintf(res+pos, "pi ");
+ pos += sprintf(res+pos, "pi");
break;
case E:
- pos += sprintf(res+pos, "e ");
+ pos += sprintf(res+pos, "e");
break;
case AND:
pos += sprintf(res+pos, " && ");
@@ -1022,16 +1647,25 @@ bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy)
pos += sprintf(res+pos, " != ");
break;
case GT:
- pos += sprintf(res+pos, " > ");
+ pos += sprintf(res+pos, ">");
break;
case GE:
- pos += sprintf(res+pos, " >= ");
+ pos += sprintf(res+pos, ">=");
break;
case LT:
- pos += sprintf(res+pos, " < ");
+ pos += sprintf(res+pos, "<");
break;
case LE:
- pos += sprintf(res+pos, " <= ");
+ pos += sprintf(res+pos, "<=");
+ break;
+ case IF:
+ pos += sprintf(res+pos, "if");
+ break;
+ case ELSE:
+ pos += sprintf(res+pos, "else");
+ break;
+ case BLOCK:
+ pos += sprintf(res+pos, "{%s}", yylval.text && yylval.text[0] ? yylval.text : "");
break;
}
}while(buff_pos < length);
@@ -1049,21 +1683,21 @@ static void fcurve(double x, double z, double **a, double *y, double dyda[], int
{
int i, length;
double tmp, y1, y2;
- symrec *symx, *s=0L;
+ symrec *symx, *sy=0L;
unsigned int hn_x = HashValue((unsigned char *)"x");
unsigned int hn_y = HashValue((unsigned char *)"y");
- if(!(symx = getsym(hn_x))) symx = putsym(hn_x, VAR, 0);
+ if(!(symx = getsym(hn_x))) symx = putsym(hn_x, VAR);
//swap parameters to requested set
if(a != parval) for(i = 0; i < ma; i++) {
tmp = *parval[i]; *parval[i] = *a[i]; *a[i] = tmp;
}
//calc result
- symx->value.var = x; buffer = txt_formula;
+ symx->SetValue(x); buffer = txt_formula;
buff_pos = 0; length = strlen(txt_formula);
do { yyparse(); }while(buff_pos < length);
- if(s = getsym(hn_y)) *y = s->value.var;
- else *y = line_result;
+ if(sy = getsym(hn_y)) *y = sy->GetValue();
+ else *y = line_res.value;
if(*y == HUGE_VAL || *y == -HUGE_VAL) {
for(i = 0, *y = 0.0; i < ma; dyda[i++] = 0.0);
return;
@@ -1075,11 +1709,11 @@ static void fcurve(double x, double z, double **a, double *y, double dyda[], int
*parval[i] = tmp*.995;
buff_pos = 0;
do { yyparse(); }while(buff_pos < length);
- y1 = s ? s->value.var : line_result;
+ y1 = sy ? sy->GetValue() : line_res.value;
*parval[i] = tmp*1.005;
buff_pos = 0;
do { yyparse(); }while(buff_pos < length);
- y2 = s ? s->value.var : line_result;
+ y2 = sy ? sy->GetValue() : line_res.value;
*parval[i] = tmp;
dyda[i] = (y2-y1)*100.0/tmp;
}
@@ -1164,7 +1798,7 @@ int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr,
parsym = (symrec**)malloc((nparam+1)*sizeof(symrec*));
parval = (double**)malloc((nparam+1)*sizeof(double*));
for(i = 0, csr=tab2; csr != tab1 && i < nparam; i++, csr = csr->next){
- parsym[i] = csr; parval[i] = &csr->value.var;
+ parsym[i] = csr; parval[i] = &csr->var;
}
//do iteratations to optimize fit
lista = (int*)malloc(sizeof(int)*nparam);
@@ -1191,7 +1825,7 @@ int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr,
l = sprintf(tmp_txt+j, "\n");
j += l; k = 0;
}
- l += sprintf(tmp_txt+j, "%s%s=%g;", j && k ? " " : "", parsym[i]->name, parsym[i]->value.var);
+ l += sprintf(tmp_txt+j, "%s%s=%g;", j && k ? " " : "", parsym[i]->name, parsym[i]->GetValue());
j += l; k += l;
}
free(*par); *par = strdup(tmp_txt);
@@ -1242,6 +1876,3 @@ int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr,
-
-
-
diff --git a/rlp_math.cpp b/rlp_math.cpp
index 9420d89..7428003 100755
--- a/rlp_math.cpp
+++ b/rlp_math.cpp
@@ -21,6 +21,8 @@
#include <stdlib.h>
#define SWAP(a,b) {double temp=(a);(a)=(b);(b)=temp;}
+#define _PREC 1.0e-12
+
static char *MRQ_error = 0L;
//---------------------------------------------------------------------------
@@ -230,6 +232,7 @@ void SortArray(int n, double *vals)
int l, j, ir, i;
double rra, *ra = vals-1;
+ if(n < 2 || !vals) return;
l=(n >> 1) + 1; ir = n;
for( ; ; ) {
if(l > 1) rra = ra[--l];
@@ -250,6 +253,99 @@ void SortArray(int n, double *vals)
ra[i] = rra;
}
}
+
+//sorts array v1 making the corresponding rearrangement of v2
+void SortArray2(int n, double *v1, double *v2)
+{
+ int l, j, ir, i;
+ double rra, rrb, *ra = v1-1, *rb = v2-1;
+
+ if(n < 2 || !v1 || !v2) return;
+ l=(n >> 1) + 1; ir = n;
+ for( ; ; ) {
+ if(l > 1) {
+ rra = ra[--l]; rrb = rb[l];
+ }
+ else {
+ rra = ra[ir]; rrb = rb[ir];
+ ra[ir] = ra[1]; rb[ir] = rb[1];
+ if(--ir == 1) {
+ ra[1] = rra; rb[1] = rrb;
+ return;
+ }
+ }
+ i = l; j = l << 1;
+ while (j <= ir) {
+ if (j < ir && ra[j] < ra[j+1]) ++j;
+ if (rra < ra[j]) {
+ ra[i] = ra[j]; rb[i] = rb[j];
+ j += (i=j);
+ }
+ else j = ir + 1;
+ }
+ ra[i] = rra; rb[i] = rrb;
+ }
+}
+
+//Use heap sort to sort elements of an xy array
+void SortFpArray(int n, lfPOINT *vals)
+{
+ int l, j, ir, i;
+ lfPOINT rra, *ra = vals-1;
+
+ if(n < 2) return;
+ l=(n >> 1) + 1; ir = n;
+ for( ; ; ) {
+ if(l > 1) {
+ rra.fx = ra[--l].fx; rra.fy = ra[l].fy;
+ }
+ else {
+ rra.fx = ra[ir].fx; rra.fy = ra[ir].fy;
+ ra[ir].fx = ra[1].fx; ra[ir].fy = ra[1].fy;
+ if(--ir == 1) {
+ ra[1].fx = rra.fx; ra[1].fy = rra.fy;
+ return;
+ }
+ }
+ i = l; j = l << 1;
+ while (j <= ir) {
+ if (j < ir && ra[j].fx < ra[j+1].fx) ++j;
+ if (rra.fx < ra[j].fx) {
+ ra[i].fx = ra[j].fx; ra[i].fy = ra[j].fy;
+ j += (i=j);
+ }
+ else j = ir + 1;
+ }
+ ra[i].fx = rra.fx; ra[i].fy = rra.fy;
+ }
+}
+
+//---------------------------------------------------------------------------
+// Cubic Spline Interpolation
+// Ref.: W.H. Press, B.P. Flannery, S.A. Teukolsky, W.T. Vetterling (1989),
+// Numerical Rcipies in C. The Art of Scientific Computing,
+// Cambridge University Press, ISBN 0-521-35465, pp. 96 ff.
+void spline(lfPOINT *v, int n, double *y2)
+{
+ int i, k;
+ double p, qn, sig, un, *u;
+
+ u = (double *)malloc(n * sizeof(double));
+ y2[0] = u[0] = 0.0;
+ for(i = 1; i < (n-1); i++) {
+ sig = (v[i].fx-v[i-1].fx)/(v[i+1].fx-v[i-1].fx);
+ p = sig*y2[i-1]+2.0; y2[i]=(sig-1.0)/p;
+ u[i]=(v[i+1].fy-v[i].fy)/(v[i+1].fx-v[i].fx)-(v[i].fy-v[i-1].fy)/(v[i].fx-v[i-1].fx);
+ u[i]=(6.0*u[i]/(v[i+1].fx-v[i-1].fx)-sig*u[i-1])/p;
+ }
+ qn = un = 0.0;
+ y2[n-1] = (un - qn * u[n-2])/(qn*y2[n-2]+1.0);
+ for(k = n-2; k >= 0; k--) {
+ y2[k] = y2[k]*y2[k+1]+u[k];
+ }
+ free(u);
+}
+
//---------------------------------------------------------------------------
// Special Functions
// Ref.: W.H. Press, B.P. Flannery, S.A. Teukolsky, W.T. Vetterling (1989),
@@ -259,14 +355,12 @@ void SortArray(int n, double *vals)
// The Gamma Function: return the ln(G(xx)) for xx > 0
double gammln(double xx)
{
- double x, tmp, ser, pi=3.14159265358979;
+ double x, tmp, ser;
static double cof[6] = {76.18009173, -86.50532033, 24.01409822,
-1.231739516, 0.120858003e-2, -0.536382e-5};
int j;
- if(xx < 0) return 0.0;
- if(xx < 1.0) //reflect
- return log((pi*(1.0-xx))/(exp(gammln(2.0-xx))*sin(pi*(1.0-xx))));
+ if(xx < 0.0) return 0.0;
x = xx-1; tmp = x + 5.5; tmp -= (x + 0.5)*log(tmp);
for (j = 0, ser = 1.0; j <= 5; j++) {
x += 1.0; ser += cof[j]/x;
@@ -289,6 +383,85 @@ double factrl(int n)
return a[n];
}
+//returns the incomplete gamma function evaluated by its series representation
+void gser(double *gamser, double a, double x, double *gln)
+{
+ int n;
+ double sum, del, ap;
+
+ *gln = gammln(a);
+ if(x <= 0) {
+ *gamser = 0.0; return;
+ }
+ else {
+ ap = a; del = sum = 1.0/a;
+ for(n = 1; n <= 100; n++) {
+ ap += 1.0; del *= x/ap; sum += del;
+ if(fabs(del) <= fabs(sum) * _PREC) {
+ *gamser = sum * exp(-x + a * log(x)-(*gln));
+ return;
+ }
+ }
+ // maximum number of iterations exceeded
+ *gamser = sum * exp(-x + a * log(x)-(*gln));
+ }
+
+}
+
+//returns the incomplete gamma function evaluated by its continued fraction representation
+void gcf(double *gammcf, double a, double x, double *gln)
+{
+ int n;
+ double gold=0.0, g, fac=1.0, b1=1.0, b0=0.0, anf, ana, an, a1, a0=1.0;
+
+ *gln=gammln(a); a1=x;
+ for(n=1; n <= 100; n++) {
+ an = (double)n; ana = an -a; a0 = (a1 + a0 * ana) * fac;
+ b0 = (b1 + b0 * ana) *fac; anf = an * fac;
+ a1 = x * a0 + anf * a1; b1 = x * b0 + anf * b1;
+ if(a1) {
+ fac = 1.0 / a1; g = b1 * fac;
+ if(fabs((g-gold)/g) <= _PREC) {
+ *gammcf = exp(-x + a * log(x) -(*gln)) * g;
+ return;
+ }
+ gold = g;
+ }
+ }
+ // maximum number of iterations exceeded
+ *gammcf = exp(-x + a * log(x) -(*gln)) * gold;
+}
+
+//returns the incomplete gamma function P(a,x)
+double gammp(double a, double x)
+{
+ double gamser, gammcf, gln;
+
+ if(x < 0.0 || a <= 0.0) return 0.0;
+ if(x < (a+1.0)) {
+ gser(&gamser, a, x, &gln); return gamser;
+ }
+ else {
+ gcf(&gammcf, a, x, &gln); return 1.0-gammcf;
+ }
+ return 0.0;
+}
+
+//returns the complementary incomplete gamma function Q(a,x)
+double gammq(double a, double x)
+{
+ double gamser, gammcf, gln;
+
+ if(x < 0.0 || a <= 0.0) return 0.0;
+ if(x < (a+1.0)) {
+ gser(&gamser, a, x, &gln); return 1.0-gamser;
+ }
+ else {
+ gcf(&gammcf, a, x, &gln); return gammcf;
+ }
+ return 0.0;
+}
+
//continued fraction for incomplete beta function, used by betai()
double betacf(double a, double b, double x)
{
@@ -305,7 +478,7 @@ double betacf(double a, double b, double x)
aold = az; am = ap/bpp;
bm = bp/bpp; az = app/bpp;
bz = 1.0;
- if(fabs(az-aold) <= (1.0e-12 * fabs(az))) return az; //success: return
+ if(fabs(az-aold) <= (_PREC * fabs(az))) return az; //success: return
}
return az; //fail: iterations exceeded
}
@@ -323,17 +496,147 @@ double betai(double a, double b, double x)
else return 1.0 - bt * betacf(b, a, 1.0 - x)/b;
}
-double t_dist(double t, double df)
+//the binomial coefficient
+double bincof(double n, double k)
+{
+ if(n<0 || k<0 || k > n) return 0.0;
+ return exp(gammln(n+1.0) - gammln(k+1.0) - gammln(n-k+1.0));
+}
+
+//the cumulative binomial distribution
+double binomdistf(double k, double n, double p)
+{
+ if(k > n || n < 0.0 || p < 0.0 || p >1.0) return 0.0;
+ return betai(n-k, k+1, p);
+}
+
+//the beta function
+double betaf(double z, double w)
+{
+ return exp(gammln(z)+gammln(w)-gammln(z+w));
+}
+
+//the error function: not all compilers have a built in erf()
+double errf(double x)
+{
+ return x < 0.0 ? -gammp(0.5, x*x) : gammp(0.5, x*x);
+}
+
+//the complementary error function
+double errfc(double x)
+{
+ double t, z, ans;
+
+ z = fabs(x);
+ t = 1.0/(1.0+0.5*z);
+ ans = t * exp(-z*z-1.26551223+t*(1.00002368+t*(0.37409196+t*(0.09678418+
+ t*(-0.18628806+t*(0.27886807+t*(-1.13520398+t*(1.48851587+
+ t*(-0.82215223+t*0.17087277)))))))));
+ return x >= 0.0 ? ans : 2.0-ans;
+}
+
+//cumulative normal distribution
+double norm_dist(double x, double m, double s)
+{
+ return 0.5 + errf((x - m)/(s * _SQRT2))/2.0;
+}
+
+//chi square distribution
+double chi_dist(double x, double df, double)
+{
+ return gammq(df/2.0, x/2);
+}
+
+//t-distribution
+double t_dist(double t, double df, double)
{
return betai(df/2.0, 0.5, (df/(df+t*t)));
}
+//poisson distribution
+double pois_dist(double x, double m, double)
+{
+ return gammq(x+1.0, m);
+}
+
+//f-distribution
double f_dist(double f, double df1, double df2)
{
return betai(df2/2.0, df1/2.0, df2/(df2+df1*f));
}
//---------------------------------------------------------------------------
+// Inverse of statitistical functions:
+// Use a combination of the Newton-Raphson method and bisection
+// Ref.: W.H. Press, B.P. Flannery, S.A. Teukolsky, W.T. Vetterling (1989),
+// Numerical Rcipies in C. The Art of Scientific Computing,
+// Cambridge University Press, ISBN 0-521-35465, pp. 273 ff.
+
+// funcd supplies the function value fn and the derivative df of the function sf at x
+void funcd(double x, double *fn, double *df, double (*sf)(double, double, double),
+ double df1, double df2, double p)
+{
+ double y1, y2;
+
+ *fn = (sf)(x, df1, df2);
+ y1 = (sf)(x * 0.995, df1, df2);
+ y2 = (sf)(x * 1.005, df1, df2);
+ *df = (y2-y1)*100.0/x;
+ *fn = *fn - p;
+}
+
+//distinv does actual bisection and Newton-Raphson root finding
+double distinv(double (*sf)(double, double, double), double df1, double df2, double p, double x0)
+{
+ int j;
+ double df, dx, dxold, f, fh, fl;
+ double swap, temp, xh, xl, rts;
+ double x1 = 0.0001, x2 = 10000;
+ char info[80];
+
+ funcd(x1, &fl, &df, sf, df1, df2, p);
+ funcd(x2, &fh, &df, sf, df1, df2, p);
+ for(j = 0; fl*fh >= 0 && j < 10; j++) {
+ x1 /= 2.0; x2 *= 2.0;
+ funcd(x1, &fl, &df, sf, df1, df2, p);
+ funcd(x2, &fh, &df, sf, df1, df2, p);
+ }
+ if(fl*fh >= 0) {
+ sprintf(info, "Value for inverse distribution\nmust be between %g and %g!", x1, x2);
+ InfoBox(info);
+ return 0.0;
+ }
+ if(fl < 0.0) {
+ xl = x1; xh = x2;
+ }
+ else {
+ xh = x1; xl = x2;
+ swap = fl; fl = fh; fh = swap;
+ }
+ rts = x0; dxold = fabs(x2-x1); dx = dxold;
+ funcd(rts, &f, &df, sf, df1, df2, p);
+ for(j = 1; j <= 100; j++) {
+ if((((rts-xh)*df-f)*((rts-xl)*df-f) >= 0.0) || (fabs(2.0*f) > fabs(dxold * df))) {
+ dxold = dx; dx = 0.5 * (xh-xl); rts = xl + dx;
+ if(xl == rts) return rts;
+ }
+ else {
+ dxold = dx; dx = f/df; temp = rts; rts -= dx;
+ if(temp == rts) return rts;
+ }
+ if(fabs(dx) < _PREC) return rts;
+ funcd(rts, &f, &df, sf, df1, df2, p);
+ if(f < 0.0) {
+ xl = rts; fl = f;
+ }
+ else {
+ xh = rts; fh = f;
+ }
+ }
+ return 0.0;
+}
+
+//---------------------------------------------------------------------------
//some statistical basics
//do quartiles, median of data
void d_quartile(int n, double *v, double *q1, double *q2, double *q3)
@@ -409,3 +712,204 @@ double d_hmean(int n, double *v)
}
return (n/sum);
}
+
+//---------------------------------------------------------------------------
+// Pearsons linear correlation
+// Ref.: W.H. Press, B.P. Flannery, S.A. Teukolsky, W.T. Vetterling (1989),
+// Numerical Rcipies in C. The Art of Scientific Computing,
+// Cambridge University Press, ISBN 0-521-35465, pp. 503 ff.
+double d_pearson(double *x, double *y, int n, char *dest, DataObj *data)
+{
+ int j, r, c;
+ double yt, xt, t, df, res[3];
+ double syy=0.0, sxy=0.0, sxx=0.0, ay=0.0, ax=0.0;
+ AccRange *rD;
+
+ for(j = 0; j < n; j++) { // find means
+ ax += x[j]; ay += y[j];
+ }
+ ax /= n; ay /= n;
+ for(j = 0; j < n; j++) { // correlation
+ xt = x[j] - ax; yt = y[j] - ay;
+ sxx += xt*xt; syy += yt*yt; sxy += xt * yt;
+ }
+ res[0] = sxy/sqrt(sxx*syy); //pearsons r
+ if(dest) {
+ res[1] = 0.5 * log((1.0+res[0]+_PREC)/(1.0-res[0]+_PREC)); //Fishers z-transform
+ df = n-2;
+ t = res[0]*sqrt(df/((1.0-res[0]+_PREC)*(1.0+res[0]+_PREC))); //Student's t
+ res[2] = betai(0.5*df, 0.5, df/(df+t*t)); //probability
+ }
+ if((dest) && (data) && (rD = new AccRange(dest))) {
+ rD->GetFirst(&c, &r);
+ for(j = 0; j < 3 && rD->GetNext(&c, &r); j++) {
+ data->SetValue(r, c, res[j]);
+ }
+ data->Command(CMD_UPDATE, 0L, 0L);
+ delete rD;
+ }
+ return res[0];
+}
+
+//---------------------------------------------------------------------------
+// Spearman rank-order correlation
+// Ref.: W.H. Press, B.P. Flannery, S.A. Teukolsky, W.T. Vetterling (1989),
+// Numerical Recipies in C. The Art of Scientific Computing,
+// Cambridge University Press, ISBN 0-521-35465, pp. 507 ff.
+
+//Given a sorted array w, crank replaces the elements by their rank
+void crank(int n, double *w0, double *s)
+{
+ int j=1, ji, jt;
+ double t, rank, *w = w0-1;
+
+ *s = 0.0;
+ while (j < n) {
+ if(w[j+1] != w[j]) {
+ w[j] = j; ++j;
+ }
+ else {
+ for(jt = j+1; jt <= n; jt++)
+ if(w[jt] != w[j]) break;
+ rank = 0.5 * (j+jt-1);
+ for(ji = j; ji <= (jt-1); ji++) w[ji] = rank;
+ t = jt -j;
+ *s += t*t*t -t;
+ j = jt;
+ }
+ }
+ if(j == n) w[n] = n;
+}
+
+//the actual rank correlation
+double d_spearman(double *x, double *y, int n, char *dest, DataObj *data)
+{
+ int j, r, c;
+ double vard, t, sg, sf, fac, en3n, en, df, aved, tmp;
+ double res[5];
+ AccRange *rD;
+
+ SortArray2(n, x, y); crank(n, x, &sf);
+ SortArray2(n, y, x); crank(n, y, &sg);
+ for(j = 0, res[0] = 0.0; j < n; j++) res[0] += ((tmp = (x[j]-y[j]))*tmp);
+ en = n; en3n = en*en*en -en;
+ aved = en3n/6.0 - (sf+sg)/12.0;
+ fac = (1.0-sf/en3n)*(1.0-sg/en3n);
+ vard = ((en-1.0)*en*en*((en+1.0)*(en+1.0))/36.0)*fac;
+ vard = ((en-1.0)*en*en*((tmp = (en+1.0))*tmp)/36.0)*fac;
+ res[1] = (res[0]-aved)/sqrt(vard);
+ res[2] = errfc(fabs(res[1])/_SQRT2);
+ res[3] = (1.0-(6.0/en3n)*(res[0]+0.5*(sf+sg)))/fac;
+ t = res[3]*sqrt((en-2.0)/((res[3]+1.0)*(1.0-res[3])));
+ df = en-2.0;
+ res[4] = betai(0.5*df, 0.5, df/(df+t*t));
+ if((dest) && (data) && (rD = new AccRange(dest))) {
+ rD->GetFirst(&c, &r);
+ for(j = 0; j < 5 && rD->GetNext(&c, &r); j++) {
+ data->SetValue(r, c, res[j]);
+ }
+ data->Command(CMD_UPDATE, 0L, 0L);
+ delete rD;
+ }
+ return res[3];
+}
+
+//linear regression
+double d_regression(double *x, double *y, int n, char *dest, DataObj *data)
+{
+ double sx, sy, dx, dy, sxy, sxx, syy, sdy;
+ double res[10]; // slope, intercept, mean x, mean y, SE of slope,
+ // variance(x), variance(y), variance(fit), F of regression
+ int i, j, r, c;
+ AccRange *rD;
+
+ if(n < 2) return 0.0;
+ for(i = 0, sx = sy = 0.0; i < n; i++) {
+ sx += x[i]; sy += y[i];
+ }
+ res[2] = sx /n; res[3] = sy/n;
+ sxy = sxx = syy = 0.0;
+ for(i = 0; i < n; i++) {
+ dx = x[i]-res[2]; dy = y[i]-res[3];
+ sxx += (dx*dx); syy += (dy*dy); sxy += (dx*dy);
+ }
+ res[0] = sxy / sxx; res[1] = res[3] - res[0] * res[2];
+ for(i = 0, sdy = 0.0; i < n; i++) {
+ dy = y[i] - (res[1] + x[i] *res[0]);
+ sdy += (dy * dy);
+ }
+ sdy = sdy/(n-2); res[4] = sqrt(sdy/sxx);
+ res[5] = sxx/(n-1); res[6] = syy/(n-1); res[7] = sdy;
+ res[8] = sxy/sdy*sxy/sxx;
+ if((dest) && (data) && (rD = new AccRange(dest))) {
+ rD->GetFirst(&c, &r);
+ for(j = 0; j < 9 && rD->GetNext(&c, &r); j++) {
+ data->SetValue(r, c, res[j]);
+ }
+ data->Command(CMD_UPDATE, 0L, 0L);
+ delete rD;
+ }
+ return n;
+}
+
+//t-test
+double d_ttest(double *x, double *y, int n1, int n2, char *dest, DataObj *data)
+{
+ int i, r, c;
+ double sx, sy, mx, my, d, df, p;
+ double res[9]; // mean1, SD1, n1, mean2, SD2, n2, p if variances equal,
+ AccRange *rD; // corrected df, corrected p
+
+ for(i=0, sx = 0.0; i < n1; sx += x[i], i++); mx = sx/n1;
+ for(i=0, sy = 0.0; i < n2; sy += y[i], i++); my = sy/n2;
+ for(i=0, sx = 0.0; i < n1; sx += ((d=(x[i]-mx))*d), i++);
+ for(i=0, sy = 0.0; i < n2; sy += ((d=(y[i]-my))*d), i++);
+ d = ((sx+sy)/(n1+n2-2)) * ((double)(n1+n2)/(double)(n1*n2));
+ d = (mx-my)/sqrt(d); //Student's t
+
+ //Welch's correction for differences in variance
+ df = (sx/(double)n1)*(sx/(double)n1)/(double)(n1+1)+(sy/(double)n2)*(sy/(double)n2)/(double)(n2+1);
+ df = (sx/(double)n1+sy/(double)n2)*(sx/(double)n1+sy/(double)n2)/df;
+ df -= 2.0;
+ p = betai(df/2.0, 0.5, (df/(df+d*d)));
+ if((dest) && (data) && (rD = new AccRange(dest))) {
+ res[0] = mx; res[1] = sqrt(sx/(double)(n1-1)); res[2] = n1;
+ res[3] = my; res[4] = sqrt(sy/(double)(n2-1)); res[5] = n2;
+ res[7] = df; df = (n1-1) + (n2-1); res[6] = betai(df/2.0, 0.5, (df/(df+d*d)));
+ res[8] = p;
+ rD->GetFirst(&c, &r);
+ for(i = 0; i < 9 && rD->GetNext(&c, &r); i++) {
+ data->SetValue(r, c, res[i]);
+ }
+ data->Command(CMD_UPDATE, 0L, 0L);
+ delete rD;
+ }
+ return p;
+}
+
+//f-test
+double d_ftest(double *x, double *y, int n1, int n2, char *dest, DataObj *data)
+{
+ int i, r, c;
+ double sx, sy, mx, my, d, df1, df2, p;
+ double res[6]; // mean1, SD1, n1, mean2, SD2, n2
+ AccRange *rD;
+
+ for(i=0, sx = 0.0; i < n1; sx += x[i], i++); mx = sx/n1;
+ for(i=0, sy = 0.0; i < n2; sy += y[i], i++); my = sy/n2;
+ for(i=0, sx = 0.0; i < n1; sx += ((d=(x[i]-mx))*d), i++); sx /= (n1-1);
+ for(i=0, sy = 0.0; i < n2; sy += ((d=(y[i]-my))*d), i++); sy /= (n2-1);
+ d = sx/sy; df1 = n1-1; df2 = n2-1;
+ p= 2.0 * betai(df2/2.0, df1/2.0, df2/(df2+df1*d));
+ if((dest) && (data) && (rD = new AccRange(dest))) {
+ res[0] = mx; res[1] = sqrt(sx); res[2] = n1;
+ res[3] = my; res[4] = sqrt(sy); res[5] = n2;
+ rD->GetFirst(&c, &r);
+ for(i = 0; i < 6 && rD->GetNext(&c, &r); i++) {
+ data->SetValue(r, c, res[i]);
+ }
+ data->Command(CMD_UPDATE, 0L, 0L);
+ delete rD;
+ }
+ return p;
+}
diff --git a/rlplot.cpp b/rlplot.cpp
index 0de7a6b..0c1fdd5 100755
--- a/rlplot.cpp
+++ b/rlplot.cpp
@@ -95,13 +95,14 @@ ssButton::ssButton(GraphObj *par, int x, int y, int w, int h):GraphObj(par, 0L)
SetMinMaxRect(&rDims, x, y, x+w, y+h);
Line.width = 0.0f; Line.patlength = 1.0f;
Line.color = 0x00000000L; Line.pattern = 0x00000000L;
- Fill.type = FILL_NONE; Fill.color = 0x00d8d8d8L;
+ Fill.type = FILL_NONE; Fill.color = 0x00e8e8e8L;
Fill.scale = 1.0; Fill.hatch = NULL;
TextDef.ColTxt = 0x00000000L; TextDef.ColBg = 0x00ffffffL;
TextDef.fSize = 4.0; TextDef.RotBL = TextDef.RotCHAR = 0.0;
TextDef.iSize = 0; TextDef.Align = TXA_HLEFT | TXA_VTOP;
TextDef.Mode = TXM_TRANSPARENT; TextDef.Style = TXS_NORMAL;
- TextDef.Font = FONT_HELVETICA; TextDef.text = 0L;
+ TextDef.Font = FONT_HELVETICA; TextDef.text = 0L;
+ bSelected = false;
}
ssButton::~ssButton()
@@ -114,9 +115,8 @@ ssButton::DoPlot(anyOutput *o)
{
POINT pts[3];
- Line.color = 0x00000000L;
- o->SetLine(&Line);
- o->SetFill(&Fill);
+ Line.color = 0x00000000L; Fill.color = bSelected ? 0x00ffffff : 0x00e8e8e8L;
+ o->SetLine(&Line); o->SetFill(&Fill);
if(bLBdown){
o->oRectangle(rDims.left, rDims.top, rDims.right, rDims.bottom);
}
@@ -163,7 +163,12 @@ ssButton::Command(int cmd, void *tmpl, anyOutput *o)
strcpy((char*)tmpl, TextDef.text);
return true;
}
- return false;
+ return false;
+ case CMD_SELECT:
+ if(tmpl && *((int*)tmpl)) bSelected = true;
+ else bSelected = false;
+ if(o) DoPlot(o);
+ return true;
case CMD_SETTEXT:
if(TextDef.text) free(TextDef.text);
if(tmpl) TextDef.text = strdup((char*)tmpl);
@@ -1029,14 +1034,12 @@ Symbol::DoPlot(anyOutput *target)
target->oRectangle(ix-rx, iy-ry, ix+rx+1, iy+ry+1, name);
break;
case SYM_TRIAU: //triangles up and down, open or closed
- case SYM_TRIAUF:
- case SYM_TRIAD:
- case SYM_TRIADF:
+ case SYM_TRIAUF: case SYM_TRIAD: case SYM_TRIADF:
rx = target->un2ix(size/1.48503);
ry = target->un2iy(size/1.48503);
target->SetFill(&cf);
pts[0].x = pts[3].x = ix - rx; pts[1].x = ix; pts[2].x = ix+rx;
- if(type == SYM_TRIAU || type == SYM_TRIAUF) {
+ if(atype == SYM_TRIAU || atype == SYM_TRIAUF) { //patch by anonymous
pts[0].y = pts[2].y = pts[3].y = iy+target->un2iy(size*0.38878f);
pts[1].y = iy-target->un2iy(size*0.77756f);
}
@@ -1047,8 +1050,7 @@ Symbol::DoPlot(anyOutput *target)
target->oPolygon(pts, 4);
rx--; ry--;
break;
- case SYM_DIAMOND:
- case SYM_DIAMONDF:
+ case SYM_DIAMOND: case SYM_DIAMONDF:
rx = target->un2ix(size/1.59588f);
ry = target->un2iy(size/1.59588f);
target->SetFill(&cf);
@@ -1061,8 +1063,7 @@ Symbol::DoPlot(anyOutput *target)
break;
case SYM_STAR: //star is a combination of + and x symbols
case SYM_PLUS: //draw a + sign
- case SYM_HLINE:
- case SYM_VLINE:
+ case SYM_HLINE: case SYM_VLINE:
rx = target->un2ix(size/2.0f);
ry = target->un2iy(size/2.0f);
pts[0].x = pts[1].x = ix;
@@ -1070,10 +1071,10 @@ Symbol::DoPlot(anyOutput *target)
if(type != SYM_HLINE) target->oPolyline(pts, 2);
pts[0].x = ix -rx; pts[1].x = ix + rx +1;
pts[0].y = pts[1].y = iy;
- if(type != SYM_VLINE) target->oPolyline(pts, 2);
- if(type == SYM_VLINE){ rx = 2; break;}
- if(type == SYM_HLINE){ ry = 2; break;}
- if(type == SYM_PLUS) break; //continue with x symbol for star
+ if(atype != SYM_VLINE) target->oPolyline(pts, 2);
+ if(atype == SYM_VLINE){ rx = 2; break;}
+ if(atype == SYM_HLINE){ ry = 2; break;}
+ if(atype == SYM_PLUS) break; //continue with x symbol for star
case SYM_CROSS: //draw a x symbol
rx = target->un2ix(size/2.5);
ry = target->un2iy(size/2.5);
@@ -1139,14 +1140,11 @@ Symbol::Command(int cmd, void *tmpl, anyOutput *o)
//fall through if its new
case CMD_SYMTEXT: case CMD_SETTEXT:
if(!SymTxt && (SymTxt = (TextDEF *) calloc(1, sizeof(TextDEF)))) {
- SymTxt->ColTxt = SymLine.color;
- SymTxt->fSize = size*1.5;
+ SymTxt->ColTxt = SymLine.color; SymTxt->fSize = size*1.5;
SymTxt->ColBg = parent ? parent->GetColor(COL_BG) : 0x00ffffffL;
SymTxt->Align = TXA_VCENTER | TXA_HCENTER;
- SymTxt->Style = TXS_NORMAL;
- SymTxt->Mode = TXM_TRANSPARENT;
- SymTxt->Font = FONT_HELVETICA;
- SymTxt->text = 0L;
+ SymTxt->Style = TXS_NORMAL; SymTxt->Mode = TXM_TRANSPARENT;
+ SymTxt->Font = FONT_HELVETICA; SymTxt->text = 0L;
}
if(!SymTxt) return false;
if(tmpl) {
@@ -1162,8 +1160,7 @@ Symbol::Command(int cmd, void *tmpl, anyOutput *o)
if(!SymTxt || !tmpl) return false;
memcpy(tmpl, SymTxt, sizeof(TextDEF));
return true;
- case CMD_SYMTEXTDEF:
- case CMD_SETTEXTDEF:
+ case CMD_SYMTEXTDEF: case CMD_SETTEXTDEF:
if(!tmpl)return false;
if(SymTxt) tmptxt = SymTxt->text;
else tmptxt = 0L;
@@ -1171,12 +1168,11 @@ Symbol::Command(int cmd, void *tmpl, anyOutput *o)
memcpy(SymTxt, tmpl, sizeof(TextDEF));
SymTxt->text = tmptxt;
return true;
- case CMD_SYM_RANGETEXT:
- case CMD_RANGETEXT:
+ case CMD_SYM_RANGETEXT: case CMD_RANGETEXT:
if(!data || !tmpl) return false;
if(!(tmptxt = (char*)malloc(500)))return false;
if((ac = new AccRange((char*)tmpl)) && ac->GetFirst(&c, &r)) {
- for(i = 0; i <= idx; i++) ac->GetNext(&c, &r);
+ for(i = 0, tmptxt[0] = 0; i <= idx; i++) ac->GetNext(&c, &r);
data->GetText(r, c, tmptxt, 500);
delete(ac);
}
@@ -1363,6 +1359,10 @@ Bubble::Command(int cmd, void *tmpl, anyOutput *o)
if(ssRef) free(ssRef); ssRef = 0L;
if(name)free(name); name = 0L;
return true;
+ case CMD_LEGEND:
+ if(!tmpl || ((GraphObj*)tmpl)->Id != GO_LEGEND) return false;
+ ((Legend*)tmpl)->HasFill(&BubbleLine, &BubbleFill);
+ break;
case CMD_MOUSE_EVENT:
mev = (MouseEvent *) tmpl;
switch (mev->Action) {
@@ -1429,15 +1429,28 @@ Bubble::Command(int cmd, void *tmpl, anyOutput *o)
case CMD_BUBBLE_LINE:
if(tmpl) memcpy(&BubbleLine, tmpl, sizeof(LineDEF));
return true;
- case CMD_AUTOSCALE:
- if(parent && parent->Id >= GO_PLOT && parent->Id < GO_GRAPH) {
- ((Plot*)parent)->CheckBounds(fPos.fx, fPos.fy);
- return true;
- }
+ case CMD_AUTOSCALE:
+ return DoAutoscale(o);
break;
}
return false;
}
+
+bool
+Bubble::DoAutoscale(anyOutput *o)
+{
+ double dx, dy;
+
+ switch(type & 0x0f0) {
+ case BUBBLE_XAXIS: case BUBBLE_YAXIS:
+ dx = dy = fs/2.0; break;
+ case BUBBLE_UNITS:
+ dx = fPos.fx/20; dy = fPos.fy/20; break;
+ }
+ ((Plot*)parent)->CheckBounds(fPos.fx+dx, fPos.fy-dy);
+ ((Plot*)parent)->CheckBounds(fPos.fx-dx, fPos.fy+dy);
+ return true;
+}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Bars are graphic objects
@@ -1471,6 +1484,7 @@ Bar::Bar(int src):GraphObj(0L, 0L)
Bar::~Bar()
{
+ if(mo) DelBitmapClass(mo); mo = 0L;
Command(CMD_FLUSH, 0L, 0L);
}
@@ -1600,6 +1614,19 @@ Bar::DoPlot(anyOutput *target)
else target->oRectangle(pts[0].x, pts[0].y, pts[1].x, pts[1].y, name);
SetMinMaxRect(&rDims, pts[0].x, pts[0].y, pts[1].x, pts[1].y);
}
+
+void
+Bar::DoMark(anyOutput *o, bool mark)
+{
+ if(mark){
+ memcpy(&mrc, &rDims, sizeof(RECT));
+ IncrementMinMaxRect(&mrc, 3);
+ mo = GetRectBitmap(&mrc, o);
+ o->CopyBitmap(mrc.left, mrc.top, mo, 0, 0, mrc.right-mrc.left, mrc.bottom - mrc.top, true);
+ o->UpdateRect(&mrc, false);
+ }
+ else RestoreRectBitmap(&mo, &mrc, o);
+}
bool
Bar::Command(int cmd, void *tmpl, anyOutput *o)
@@ -1622,8 +1649,7 @@ Bar::Command(int cmd, void *tmpl, anyOutput *o)
switch (mev->Action) {
case MOUSE_LBUP:
if(IsInRect(&rDims, mev->x, mev->y) && !CurrGO) {
- o->ShowMark(&rDims, MRK_INVERT);
- CurrGO = this;
+ o->ShowMark(CurrGO = this, MRK_GODRAW);
return true;
}
break;
@@ -1746,17 +1772,20 @@ DataLine::DoPlot(anyOutput *target)
lfPOINT fip;
POINT pn, *tmppts;
- if(!Values || nPntSet < 1) return;
+ if(!Values || nPntSet < 1) return;
+ if (nPntSet >= nPnt) nPntSet = nPnt-1;
if(mo) DelBitmapClass(mo); mo = 0L;
- if(pts) free(pts);
- if(type & 0xff) pts = (POINT *)malloc(sizeof(POINT)*(nPntSet+2)*2);
+ if(pts) free(pts); pts = 0L;
+ if((type & 0xff) == 9 || (type & 0xff) == 10) //splines
+ pts = (POINT *)malloc(sizeof(POINT)*1000);
+ else if(type & 0xff) pts = (POINT *)malloc(sizeof(POINT)*(nPntSet+2)*2);
else pts = (POINT *)malloc(sizeof(POINT)*(nPntSet+2));
- if(!pts)return;
+ if(!pts) return;
if(max.fx > min.fx && max.fy > min.fy) dirty = false;
- else if(dirty)Command(CMD_AUTOSCALE, 0L, target);
+ else if(dirty) Command(CMD_AUTOSCALE, 0L, target);
cp = 0;
- switch(type & 0xf) {
- case 0:
+ switch(type & 0x0f) {
+ case 0: default:
for (i = 0; i <= nPntSet; i++){
target->fp2fip(Values+i, &fip);
pn.x = iround(fip.fx); pn.y = iround(fip.fy);
@@ -1846,6 +1875,9 @@ DataLine::DoPlot(anyOutput *target)
pn.y += (pn.y - iround(fip.fy))>>1;
AddToPolygon(&cp, pts, &pn);
}
+ break;
+ case 9: case 10:
+ DrawSpline(target);
break;
}
if(cp < 2) return;
@@ -1890,7 +1922,7 @@ DataLine::Command(int cmd, void *tmpl, anyOutput *o)
mev = (MouseEvent *) tmpl;
switch (mev->Action) {
case MOUSE_LBUP:
- if(!IsInRect(&rDims, p1.x= mev->x, p1.y= mev->y) || CurrGO || !o || nPntSet <2)
+ if(!IsInRect(&rDims, p1.x= mev->x, p1.y= mev->y) || CurrGO || !o || nPntSet <1)
return false;
if(isPolygon && IsInPolygon(&p1, pts, cp)) bFound = true;
if(bFound || IsCloseToPL(p1,pts,cp))
@@ -1900,7 +1932,12 @@ DataLine::Command(int cmd, void *tmpl, anyOutput *o)
case CMD_SET_DATAOBJ:
Id = isPolygon ? GO_DATAPOLYGON : GO_DATALINE;
data = (DataObj*)tmpl;
- return true;
+ return true;
+ case CMD_MRK_DIRTY:
+ dirty= true;
+ case CMD_REDRAW:
+ if(parent) return parent->Command(cmd, tmpl, 0L);
+ return false;
case CMD_LEGEND:
if(tmpl && ((GraphObj*)tmpl)->Id == GO_LEGEND) {
if(Id == GO_DATALINE) ((Legend*)tmpl)->HasFill(&LineDef, 0L);
@@ -1909,11 +1946,13 @@ DataLine::Command(int cmd, void *tmpl, anyOutput *o)
case CMD_SET_LINE:
if(tmpl) memcpy(&LineDef, tmpl, sizeof(LineDEF));
return true;
- case CMD_UPDATE:
+ case CMD_UPDATE:
+ Undo.DataMem(this, (void**)&Values, nPnt * sizeof(lfPOINT), &nPnt, UNDO_CONTINUE);
+ Undo.ValLong(this, &nPntSet, UNDO_CONTINUE);
SetValues();
return true;
case CMD_AUTOSCALE:
- if(nPntSet < 2 || !Values) return false;
+ if(nPntSet < 1 || !Values) return false;
if(parent && parent->Id >= GO_PLOT && parent->Id < GO_GRAPH) {
if(dirty) {
min.fx = max.fx = Values[0].fx; min.fy = max.fy = Values[0].fy;
@@ -1941,7 +1980,7 @@ DataLine::SetValues()
int i, j, k, l, m, n;
double x, y;
char *yref1 = 0L, *yref2 = 0L;
- lfPOINT *tmpValues = 0L;
+ lfPOINT *tmpValues = Values;
if(!ssXref || !ssYref) return;
if(!(yref1 = strdup(ssYref)))return;
@@ -1953,7 +1992,6 @@ DataLine::SetValues()
}
}
nPnt = nPntSet = 0;
- if(Values) free(Values); Values = 0L;
min.fx = min.fy = HUGE_VAL; max.fx = max.fy = -HUGE_VAL;
rX = new AccRange(ssXref); rY1 = new AccRange(yref1);
if(!rX || !rY1){
@@ -1962,7 +2000,7 @@ DataLine::SetValues()
return;
}
if(yref2 &&((nPnt = rX->CountItems()) == (rY1->CountItems()))) {
- if(!(Values = (lfPOINT *)calloc(nPnt*2+2, sizeof(lfPOINT)))) return;
+ if(!(Values = (lfPOINT *)realloc(Values, ((nPnt*2+2) * sizeof(lfPOINT))))) return;
if(!(rY2 = new AccRange(yref2))) {
if(yref1) free(yref1); if(yref2) free(yref2);
if(rX) delete(rX); if(rY1) delete(rY1);
@@ -1983,7 +2021,7 @@ DataLine::SetValues()
}
else {
if((nPnt = rX->CountItems()) != (rY1->CountItems())) return;
- if(!(Values = (lfPOINT *)calloc(nPnt+2, sizeof(lfPOINT)))) return;
+ if(!(Values = (lfPOINT *)realloc(Values, (nPnt+2) * sizeof(lfPOINT)))) return;
if(rX->GetFirst(&i, &j) && rY1->GetFirst(&k, &l) &&
rX->GetNext(&i, &j) && rY1->GetNext(&k, &l)) do {
if(data->GetValue(j, i, &x) && data->GetValue(l, k, &y)){
@@ -1992,21 +2030,87 @@ DataLine::SetValues()
}while(rX->GetNext(&i, &j) && rY1->GetNext(&k, &l));
}
nPnt = nPntSet; nPntSet--; dirty = true;
- Command(CMD_AUTOSCALE, 0L, 0L);
- if(tmpValues = (lfPOINT *)realloc(Values, (nPnt+2)*sizeof(lfPOINT)))
- Values = tmpValues;
+ Command(CMD_AUTOSCALE, 0L, 0L);
+ if(tmpValues && Values != tmpValues) Undo.InvalidGO(this);
if(rX) delete(rX); if(rY1) delete(rY1); if(rY2) delete(rY2);
if(yref1) free(yref1); if(yref2) free(yref2);
}
void
DataLine::LineData(lfPOINT *val, long nval)
-{
- if(Values)free(Values); Values = 0L;
- if(pts) free(pts); pts = 0L;
- Values = val; dirty = true;
- nPnt = nval; nPntSet = nPnt-1;
+{
+ lfPOINT *ov = Values;
+
+ if(!val || nval <2) return;
+ if(nval > nPnt && nPnt > 1 && Values){
+ if(!(Values = (lfPOINT *)realloc(Values, ((nval*2+2) * sizeof(lfPOINT))))) return;
+ if(ov != Values) Undo.InvalidGO(this);
+ }
+ else if(!Undo.busy) Undo.DataMem(this, (void**)&Values, nPnt * sizeof(lfPOINT), &nPnt, UNDO_CONTINUE);
+ memcpy(Values, val, nval * sizeof(lfPOINT));
+ if(pts) free(pts); pts = 0L; dirty = true;
+ free(val); nPnt = nval; nPntSet = nPnt-1;
}
+
+void
+DataLine::DrawSpline(anyOutput *target)
+{
+ int i, j, k, klo, khi, ptsize = 1000;
+ double *y2, min, max, x, y, h, b, a;
+ POINT pn;
+ lfPOINT *scvals;
+
+ if(!(y2 = (double*)malloc(sizeof(double)*(nPnt)))) return;
+ if(!(scvals = (lfPOINT*)malloc(sizeof(lfPOINT)*(nPnt)))){
+ free(y2);
+ return;
+ }
+ if((type & 0x0f) == 9 || (type & 0x0f) == 10) {
+ if((type & 0x0f) == 9) for(i = 0; i < nPnt; i++) {
+ scvals[i].fx = target->fx2fix(Values[i].fx);
+ scvals[i].fy = target->fy2fiy(Values[i].fy);
+ }
+ else for(i = 0; i < nPnt; i++) {
+ scvals[i].fy = target->fx2fix(Values[i].fx);
+ scvals[i].fx = target->fy2fiy(Values[i].fy);
+ }
+ SortFpArray(nPnt, scvals);
+ min = scvals[0].fx; max = scvals[nPnt-1].fx;
+ for(i = j = 0; i < (nPnt-1); i++, j++) {
+ y = scvals[i].fy; scvals[j].fx = scvals[i].fx;
+ for(k = 1; scvals[i+1].fx == scvals[i].fx; k++) {
+ y += scvals[i+1].fy; i++;
+ }
+ scvals[j].fy = y/((double)k);
+ }
+ if(scvals[i].fx > scvals[i-1].fx) {
+ scvals[j].fx = scvals[i].fx; scvals[j].fy = scvals[i].fy;
+ j++;
+ }
+ spline(scvals, j, y2);
+ h = scvals[1].fx - scvals[0].fx; // klo and khi bracket the input value of x
+ for(x = min, klo = 0, i = khi = 1; x < max && i < j; x += 1.0) {
+ while(x > scvals[i].fx) {
+ klo++; khi++; i++;
+ h = scvals[khi].fx - scvals[klo].fx;
+ }
+ a = (scvals[khi].fx - x) / h; b = (x - scvals[klo].fx) / h;
+ y = a * scvals[klo].fy + b * scvals[khi].fy + ((a*a*a - a) * y2[klo] + (b*b*b - b) * y2[khi]) * (h*h)/6.0;
+ if((type & 0x0f) == 9) {
+ pn.x = iround(x); pn.y = iround(y);
+ }
+ else {
+ pn.x = iround(y); pn.y = iround(x);
+ }
+ if(cp >= ptsize) {
+ ptsize += 1000;
+ pts = (POINT*)realloc(pts, sizeof(POINT)*ptsize);
+ }
+ AddToPolygon(&cp, pts, &pn);
+ }
+ }
+ free(y2); free(scvals);
+}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// DataPolygon is a graphic object based on DataLine
@@ -2536,8 +2640,7 @@ ErrorBar::ErrorBar(int src):GraphObj(0L, 0L)
ErrorBar::~ErrorBar()
{
- if(ssRef) free(ssRef);
- ssRef = 0L;
+ if(ssRef) free(ssRef); ssRef = 0L;
}
bool
@@ -2714,6 +2817,9 @@ ErrorBar::Command(int cmd, void *tmpl, anyOutput *o)
return true;
}
return false;
+ case CMD_ERR_TYPE:
+ if(tmpl) type = *((int*)tmpl);
+ return true;
case CMD_AUTOSCALE:
if(parent && parent->Id >= GO_PLOT && parent->Id < GO_GRAPH) {
switch(type) {
@@ -3115,12 +3221,12 @@ bool
Box::SetSize(int select, double value)
{
switch(select & 0xfff) {
- case SIZE_BOX_LINE:
- Outline.width = value;
- return true;
- case SIZE_BOX:
- size = value;
- return true;
+ case SIZE_BOX_LINE: Outline.width = value; return true;
+ case SIZE_BOX: size = value; return true;
+ case SIZE_XPOS: pos1.fx = value; return true;
+ case SIZE_XPOS+1: pos2.fx = value; return true;
+ case SIZE_YPOS: pos1.fy = value; return true;
+ case SIZE_YPOS+1: pos2.fy = value; return true;
}
return false;
}
@@ -3162,7 +3268,7 @@ Box::DoPlot(anyOutput *o)
pts[2].y = o->fy2iy(pos2.fy - dy); pts[3].y = o->fy2iy(pos1.fy - dy);
}
else if(type & BAR_RELWIDTH) {
- if(!parent) return;
+ if(!parent || (pos1.fy == pos2.fy && pos1.fx == pos2.fx)) return;
fsize = parent->GetSize(pos1.fy == pos2.fy ? SIZE_BOXMINY : SIZE_BOXMINX);
fsize = fsize * size /200.0;
dx = si * fsize; dy = csi * fsize;
@@ -3261,8 +3367,20 @@ Box::Command(int cmd, void *tmpl, anyOutput *o)
break;
case CMD_AUTOSCALE:
if(parent && parent->Id >= GO_PLOT && parent->Id < GO_GRAPH) {
- ((Plot*)parent)->CheckBounds(pos1.fx, pos1.fy);
- ((Plot*)parent)->CheckBounds(pos2.fx, pos2.fy);
+ if(type & BAR_WIDTHDATA) {
+ if(pos1.fy != pos2.fy) {
+ ((Plot*)parent)->CheckBounds(pos1.fx+size, pos1.fy);
+ ((Plot*)parent)->CheckBounds(pos2.fx-size, pos2.fy);
+ }
+ else {
+ ((Plot*)parent)->CheckBounds(pos1.fx, pos1.fy+size);
+ ((Plot*)parent)->CheckBounds(pos2.fx, pos2.fy-size);
+ }
+ }
+ else {
+ ((Plot*)parent)->CheckBounds(pos1.fx, pos1.fy);
+ ((Plot*)parent)->CheckBounds(pos2.fx, pos2.fy);
+ }
return true;
}
break;
@@ -3488,8 +3606,7 @@ DropLine::DropLine(int src):GraphObj(0L, 0L)
DropLine::~DropLine()
{
if(bModified) Undo.InvalidGO(this);
- if(ssRef) free(ssRef);
- ssRef = 0L;
+ if(ssRef) free(ssRef); ssRef = 0L;
}
void
@@ -3793,9 +3910,10 @@ Sphere::DoPlot(anyOutput *o)
rx = ry = iround(size * 0.5 * o->ddy); break;
case 3:
rx = ry = iround(size * 0.5 * o->ddz); break;
- default:
+ default:
+ type = 0;
+ case 5:
rx = o->un2ix(size/2.0); ry = o->un2iy(size/2.0);
- type = 0;
break;
}
rDims.left = ix - rx; rDims.right = ix + rx;
@@ -3825,6 +3943,10 @@ Sphere::Command(int cmd, void *tmpl, anyOutput *o)
scl = 0L; nscl = 0;
}
return true;
+ case CMD_LEGEND:
+ if(!tmpl || ((GraphObj*)tmpl)->Id != GO_LEGEND) return false;
+ ((Legend*)tmpl)->HasFill(&Line, &Fill);
+ break;
case CMD_SYM_FILL:
if(tmpl) memcpy(&Fill, tmpl, sizeof(FillDEF));
return true;
@@ -4112,6 +4234,7 @@ plane::DoPlot(anyOutput *o)
bDrawDone = true; return;
}
if(lines) {
+ if(Line.width == 0.0) return;
//draw line segments for vertical plane
for(i = 0; i < n_lines; i++) if(lines[i]) lines[i]->DoPlot(o);
bDrawDone = true; return;
@@ -4149,7 +4272,8 @@ plane::Command(int cmd, void *tmpl, anyOutput *o)
case CMD_REDRAW:
if(bDrawDone) return false;
bDrawDone = true;
- if(o && data && nldata){
+ if(o && nldata){
+ if(Line.width == 0.0) Line.color = Fill.color;
o->SetLine(&Line); o->SetFill(&Fill);
for(i = 0; i < nli; i++){
if(nldata[i] > 2 && (pt = (POINT*)malloc(nldata[i]*sizeof(POINT)))){
@@ -4289,11 +4413,12 @@ plane::DoClip(GraphObj *co)
int i, j, tnpt;
bool is_valid = false;
- if(co->parent == parent && co->Id == GO_PLANE) {
- //if both planes have the same parent it means they are part of one object
- // do not clip!
- return;
- }
+ //if two planes have the same parent it means they are part of one object
+ // do not clip!
+ if(co->parent == parent && co->Id == GO_PLANE) return;
+ if(co->Id == GO_PLANE && parent->parent->Id == GO_GRID3D
+ && co->parent->parent == parent->parent) return;
+
cliprc.left = iround(co->GetSize(SIZE_MIN_X));
cliprc.right = iround(co->GetSize(SIZE_MAX_X));
cliprc.top = iround(co->GetSize(SIZE_MIN_Y));
@@ -5472,7 +5597,8 @@ Line3D::Line3D(GraphObj *par, DataObj *d, char *rx, char *ry, char *rz)
bModified = false;
}
-Line3D::Line3D(GraphObj *par, DataObj *d, fPOINT3D *pt, int n_pt)
+Line3D::Line3D(GraphObj *par, DataObj *d, fPOINT3D *pt, int n_pt, int xc1, int xr1, int yc1, int yr1,
+ int zc1, int zr1, int xc2, int xr2, int yc2, int yr2, int zc2, int zr2)
:GraphObj(par, d)
{
FileIO(INIT_VARS);
@@ -5481,6 +5607,18 @@ Line3D::Line3D(GraphObj *par, DataObj *d, fPOINT3D *pt, int n_pt)
nPts = n_pt;
ls = (line_segment **)calloc(nPts-1, sizeof(line_segment*));
}
+ if(xc1 >= 0 || xr1 >= 0 || yc1 >= 0 || yr1 >= 0 || zc1 >= 0 || zr1 >= 0 ||
+ xc2 >= 0 || xr2 >= 0 || yc2 >= 0 || yr2 >= 0 || zc2 >= 0 || zr2 >= 0) {
+ if(ssRef = (POINT*)malloc(sizeof(POINT)*6)) {
+ ssRef[0].x = xc1; ssRef[0].y = xr1;
+ ssRef[1].x = yc1; ssRef[1].y = yr1;
+ ssRef[2].x = zc1; ssRef[2].y = zr1;
+ ssRef[3].x = xc2; ssRef[3].y = xr2;
+ ssRef[4].x = yc2; ssRef[4].y = yr2;
+ ssRef[5].x = zc2; ssRef[5].y = zr2;
+ cssRef = 6;
+ }
+ }
Id = GO_LINE3D;
bModified = false;
}
@@ -5503,12 +5641,13 @@ Line3D::~Line3D()
for(i = 0; i < (nPts-1); i++) if(ls[i]) delete(ls[i]);
free(ls);
}
- if(pts && npts) free(pts); pts = 0L; npts = 0;
+ if(pts && npts) free(pts); pts = 0L; npts = 0; cssRef = 0;
if(x_range) free(x_range); x_range = 0L;
if(y_range) free(y_range); y_range = 0L;
if(z_range) free(z_range); z_range = 0L;
if(values) free(values); values = 0L;
- if(mo) DelBitmapClass(mo); mo = 0L;
+ if(ssRef) free(ssRef); ssRef = 0L;
+ if(mo) DelBitmapClass(mo); mo = 0L;
}
void
@@ -5597,7 +5736,19 @@ Line3D::Command(int cmd, void *tmpl, anyOutput *o)
}
return false;
case CMD_UPDATE:
- DoUpdate();
+ if(parent && parent->Id != GO_GRID3D) {
+ Undo.DataMem(this, (void**)&values, nPts * sizeof(fPOINT3D), &nPts, UNDO_CONTINUE);
+ }
+ if(ssRef && cssRef >5 && data && nPts == 2) {
+ data->GetValue(ssRef[0].y, ssRef[0].x, &values[0].fx);
+ data->GetValue(ssRef[1].y, ssRef[1].x, &values[0].fy);
+ data->GetValue(ssRef[2].y, ssRef[2].x, &values[0].fz);
+ data->GetValue(ssRef[3].y, ssRef[3].x, &values[1].fx);
+ data->GetValue(ssRef[4].y, ssRef[4].x, &values[1].fy);
+ data->GetValue(ssRef[5].y, ssRef[5].x, &values[1].fz);
+ return true;
+ }
+ else DoUpdate();
case CMD_AUTOSCALE:
if(parent && parent->Id > GO_PLOT && parent->Id < GO_GRAPH){
if(min.fx == max.fx || min.fy == max.fy){ //z's may be equal !
@@ -5909,9 +6060,11 @@ Label::Command(int cmd, void *tmpl, anyOutput *o)
if(ssRef && cssRef >2 && data) {
data->GetValue(ssRef[0].y, ssRef[0].x, &fPos.fx);
data->GetValue(ssRef[1].y, ssRef[1].x, &fPos.fy);
- if(data->GetText(ssRef[2].y, ssRef[2].x, TmpTxt, TMP_TXT_SIZE)) {
- if(TextDef.text) free(TextDef.text);
- TextDef.text = strdup(TmpTxt);
+ if(data->GetText(ssRef[2].y, ssRef[2].x, TmpTxt, TMP_TXT_SIZE)) {
+ Undo.String(this, &TextDef.text, UNDO_CONTINUE);
+ TextDef.text = (char*)realloc(TextDef.text, strlen(TmpTxt)+2);
+ if(TmpTxt[0]) strcpy(TextDef.text, TmpTxt);
+ else TextDef.text[0] = 0;
}
return true;
}
@@ -6139,8 +6292,9 @@ Label::CalcCursorPos(int x, int y, anyOutput *o)
if(parent && parent->Id != GO_MLABEL) o->SetTextSpec(&TextDef);
x1 = ((pts[3].x + pts[4].x)>>1); y1 = ((pts[3].y + pts[4].y)>>1);
ix = ((j=(x1-x))*j); ix += ((j=(y1-y))*j); ix = isqr(ix);
- for(i = 1, x1 = 0; TextDef.text[i-1]; i++) {
- o->oGetTextExtent(TextDef.text, i, &x2, &h);
+ for(i = 1, x1 = 0; TextDef.text[i-1]; i++) {
+ if(fmt_txt)fmt_txt->oGetTextExtent(o, &x2, &h,i);
+ else o->oGetTextExtent(TextDef.text, i, &x2, &h);
if(x1 <= ix && x2 >= ix) {
if((ix-x1) < (x2-ix)) CursorPos = i-1;
else CursorPos = i;
@@ -6215,7 +6369,7 @@ mLabel::mLabel(GraphObj *par, DataObj *d, double x, double y, TextDEF *td, char
memcpy(&TextDef, td, sizeof(TextDEF));
TextDef.text = 0L; fPos.fx = x; fPos.fy = y;
- Lines = 0L; flags = flg;
+ Lines = 0L; flags = flg; lspc = 1.0;
fDist.fx = 0.0; fDist.fy = 0.0;
CurrGO = CurrLabel = 0L;
if(txt && (Lines = (Label**)calloc(2, sizeof(Label*)))) {
@@ -6241,7 +6395,7 @@ mLabel::mLabel(GraphObj *par, DataObj *d, double x, double y, TextDEF *td, char
memcpy(&TextDef, td, sizeof(TextDEF));
TextDef.text = 0L; fPos.fx = x; fPos.fy = y;
Lines = 0L; flags = 0L; Id = GO_MLABEL;
- fDist.fx = 0.0; fDist.fy = 0.0;
+ fDist.fx = 0.0; fDist.fy = 0.0; lspc = 1.0;
CurrGO = CurrLabel = 0L;
if(txt){
if((llist=split(txt,'\n',&nll)) && nll && (Lines=(Label**)calloc(nll, sizeof(Label*)))){
@@ -6287,6 +6441,8 @@ mLabel::GetSize(int select)
break;
case SIZE_MIN_Z: case SIZE_MAX_Z: case SIZE_ZPOS:
return curr_z;
+ case SIZE_LSPC:
+ return lspc;
}
return 0.0;
}
@@ -6315,6 +6471,9 @@ mLabel::SetSize(int select, double value)
Lines[i]->SetSize(select, value);
}
return is3D = true;
+ case SIZE_LSPC:
+ undo_flags = CheckNewFloat(&lspc, lspc, value, this, undo_flags);
+ return true;
}
return false;
}
@@ -6355,9 +6514,10 @@ mLabel::DoPlot(anyOutput *o)
else if(TextDef.Align & TXA_VCENTER) dh = ((double)(nLines-1))/2.0;
else dh = 0.0; dh *= TextDef.fSize;
cPos.fx -= o->un2fix(dh*si); cPos.fy -= o->un2fiy(dh*csi);
- memcpy(&cPos1, &cPos, sizeof(lfPOINT));
- dist.fx = floor(o->un2fix(TextDef.fSize * si * 1.1));
- dist.fy = floor(o->un2fiy(TextDef.fSize * csi * 1.1));
+ memcpy(&cPos1, &cPos, sizeof(lfPOINT));
+ if(lspc < 0.5 || lspc > 5) lspc = 1.0;
+ dist.fx = floor(o->un2fix(TextDef.fSize * si * 1.1 * lspc));
+ dist.fy = floor(o->un2fiy(TextDef.fSize * csi * 1.1 * lspc));
o->SetTextSpec(&TextDef);
rDims.left = rDims.top = rDims.right = rDims.bottom = 0;
for(i = 0; i < nLines; i++) if(Lines[i]){
@@ -6470,12 +6630,11 @@ mLabel::Command(int cmd, void *tmpl, anyOutput *o)
TextDef.text = 0L;
return true;
case CMD_SET_DATAOBJ:
- if(Lines) for(i = 0; i< nLines; i++)
- if(Lines[i]) Lines[i]->Command(cmd, tmpl, o);
+ if(Lines) {
+ for(i = 0; i< nLines; i++) if(Lines[i]) Lines[i]->Command(cmd, tmpl, o);
+ }
Id = GO_MLABEL;
data = (DataObj*)tmpl;
- if(Lines) for(i = 0; i< nLines; i++)
- if(Lines[i])Lines[i]->Command(cmd, tmpl, o);
return true;
case CMD_AUTOSCALE:
if(parent && parent->Id >= GO_PLOT && parent->Id < GO_GRAPH
@@ -7495,6 +7654,7 @@ LegItem::Command(int cmd, void *tmpl, anyOutput *o)
}
break;
case CMD_SET_DATAOBJ:
+ if(Desc) Desc->Command(cmd, tmpl, o);
Id = GO_LEGITEM;
data = (DataObj *)tmpl;
return true;
@@ -7521,7 +7681,7 @@ bool
LegItem::HasSym(LineDEF *ld, GraphObj *sy)
{
if(sy && !Sym) return false;
- if(sy->Id == GO_SYMBOL && (Sym->type & 0xfff) != (Sym->type & 0xfff)) return false;
+ if(sy->Id == GO_SYMBOL && (sy->type & 0xfff) != (Sym->type & 0xfff)) return false;
if(sy && Sym) {
if(Sym->GetSize(SIZE_SYMBOL) != sy->GetSize(SIZE_SYMBOL)) return false;
if(Sym->GetSize(SIZE_SYM_LINE) != sy->GetSize(SIZE_SYM_LINE)) return false;
@@ -7983,6 +8143,16 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
if(!o) o = CurrDisp;
switch (cmd){
+ case CMD_CAN_CLOSE:
+ HideTextCursor();
+ if(bModified) {
+ bModified = false;
+ sprintf(TmpTxt, "%s has not been saved.\nDo you want to save it now?", name);
+ i = YesNoCancelBox(TmpTxt);
+ if(i == 2) return false;
+ else if(i == 1) if(! SaveGraphAs(this)) return false;
+ }
+ //fall through
case CMD_CAN_DELETE:
HideTextCursor();
if(bModified) {
@@ -8088,7 +8258,7 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
if(tmpl == (void*)Axes[i]){
Axes[i]->DoMark(CurrDisp, false); return true;
}
- else if(Axes[i]->Id == GO_AXIS) {
+ else if(Axes[i] && Axes[i]->Id == GO_AXIS) {
if(Axes[i]->Command(cmd, tmpl, o)) return true;
}
}
@@ -8169,7 +8339,8 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
else {
if(type == GT_3D && Plots){
for(i = 0; i < NumPlots; i++)
- if(Plots[i] && Plots[i]->Id == GO_PLOT3D) return Plots[i]->Command(cmd, tmpl, o);
+ if(Plots[i] && (Plots[i]->Id == GO_PLOT3D || Plots[i]->Id == GO_FUNC3D))
+ return Plots[i]->Command(cmd, tmpl, o);
}
else if(AddAxis()) {
Command(CMD_REDRAW, tmpl, o);
@@ -8214,7 +8385,8 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
if(data) data->Command(CMD_UPDHISTORY, 0L, 0L);
return true;
case CMD_UPDATE:
- Command(CMD_TOOLMODE, 0L, o);
+ Command(CMD_TOOLMODE, 0L, o);
+ Undo.SetDisp(CurrDisp);
if(parent && parent->Id != GO_PAGE){
Undo.ValInt(this, &ToolMode, 0L); //stub, all plots have UNDO_CONTINUE
}
@@ -8285,9 +8457,12 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
else if(Id == GO_GRAPH) {
if(type == GT_3D && Plots){
for(i = 0; i < NumPlots; i++) {
- if(Plots[i] && Plots[i]->Id == GO_PLOT3D)
- return Plots[i]->Command(cmd, tmpl, CurrDisp);
- }
+ if(Plots[i] && (Plots[i]->Id == GO_PLOT3D || Plots[i]->Id == GO_FUNC3D)) {
+ if(Plots[i]->Command(cmd, tmpl, CurrDisp)) return Command(CMD_REDRAW, 0L, o);
+ else return false;
+ }
+ }
+ return false;
}
else return AddPlot(0x0);
}
@@ -8315,7 +8490,7 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
else {
if(type == GT_3D && Plots) {
for(i = 0; i < NumPlots; i++) {
- if(Plots[i] && Plots[i]->Id == GO_PLOT3D)
+ if(Plots[i] && (Plots[i]->Id == GO_PLOT3D || Plots[i]->Id == GO_FUNC3D))
return Plots[i]->Command(cmd, tmpl, CurrDisp);
}
}
@@ -8344,16 +8519,13 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
if(Plots) {
Plots[0] = (Plot *)tmpl;
switch(Plots[0]->Id) {
- case GO_PIECHART:
- case GO_RINGCHART:
- case GO_STARCHART:
+ case GO_PIECHART: case GO_RINGCHART: case GO_STARCHART:
type = GT_CIRCCHART;
break;
case GO_POLARPLOT:
type = GT_POLARPLOT;
break;
- case GO_SCATT3D:
- case GO_PLOT3D:
+ case GO_SCATT3D: case GO_PLOT3D: case GO_FUNC3D:
type = GT_3D;
break;
default:
@@ -8455,15 +8627,16 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
Command(CMD_MOUSE_EVENT, mev, CurrDisp);
mev->Action = MOUSE_LBDOUBLECLICK;
}
- if(CurrGO) {
+ else if(CurrGO->Id < GO_PLOT) {
if(CurrGO->PropertyDlg()) {
bModified = true;
return Command(CMD_REDRAW, 0L, o);
- }
+ }
}
+ else if(CurrGO->Command(CMD_CONFIG, 0L, o)) return Command(CMD_REDRAW, 0L, o);
else if (Id == GO_PAGE) return Command(CMD_CONFIG, 0L, o);
else o->HideMark();
- CurrGO = TrackGO = 0L; CurrLabel = 0L;
+ TrackGO = 0L; CurrLabel = 0L;
return false;
case MOUSE_LBUP:
Undo.SetDisp(o);
@@ -8508,7 +8681,8 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
for(i = 0; Plots && i < NumPlots; i++) if(Plots[i]) {
((ObjTree*)tmpl)->Command(CMD_UPDATE, Plots[i], 0L);
if(Plots[i]->Id == GO_STACKBAR || Plots[i]->Id == GO_GRAPH ||
- Plots[i]->Id == GO_PLOT3D || Plots[i]->Id == GO_POLARPLOT) Plots[i]->Command(cmd, tmpl, o);
+ Plots[i]->Id == GO_PLOT3D || Plots[i]->Id == GO_POLARPLOT ||
+ Plots[i]->Id == GO_FUNC3D) Plots[i]->Command(cmd, tmpl, o);
}
return true;
}
@@ -9519,7 +9693,7 @@ ObjTree::DoPlot(anyOutput *o)
if(!o || !list) return;
o->Erase(0x00ffffffL);
ix = 10; iy = 0;
- for(i = 0; i < count; i++, iy += TextDef.iSize) {
+ for(i = 0; i < count; i++, iy += (TextDef.iSize+_SBINC)) {
if(list[i]) {
curr_obj = list[i]; n = 0;
if(i) while(curr_obj && curr_obj != list[0]) {
diff --git a/rlplot.h b/rlplot.h
index ca03fa0..b942817 100755
--- a/rlplot.h
+++ b/rlplot.h
@@ -24,15 +24,22 @@
#define Swap(a,b) {a^=b;b^=a;a^=b;}
inline int iround(double a) {return a < 0.0 ?(int)(a-0.499) : (int)(a+0.499);}
-inline int WriteFloatToBuff(char *buff, double val) {return sprintf(buff, " %g", val);}
+inline int WriteFloatToBuff(char *buff, double val) {return sprintf(buff, " %g", val);}
+
+#define _PI 3.1415926535897932384626433832795028841971693993751
+#define _SQRT2 1.4142135623730950488016887242096980785696718753769
#ifdef _WINDOWS
#include <windows.h>
#define w_char unsigned short
+#define _SBINC 1 //scrollbox extra space/line
+#define _TXH 4.0 //graph text default size in mm
#else
#define DWORD unsigned long
#define w_char unsigned short
+#define _SBINC 8 //scrollbox extra space/line
+#define _TXH 3.0 //graph text default size in mm
typedef struct tagPOINT { // pt
long x;
@@ -69,7 +76,7 @@ enum {SIZE_MINE, SIZE_SYMBOL, SIZE_SYM_LINE, SIZE_DATA_LINE, SIZE_TEXT,
SIZE_A, SIZE_B, SIZE_MX, SIZE_MY, SIZE_MIN_Z, SIZE_MAX_Z, SIZE_MIN_X, SIZE_MAX_X,
SIZE_MIN_Y, SIZE_MAX_Y, SIZE_TICK_ANGLE, SIZE_RRECT_RAD, SIZE_XCENT, SIZE_YCENT,
SIZE_ZCENT, SIZE_DRADIUS, SIZE_CURSORPOS, SIZE_CURSOR_XMIN, SIZE_CURSOR_YMIN,
- SIZE_CURSOR_XMAX, SIZE_CURSOR_YMAX, SIZE_XSTEP};
+ SIZE_CURSOR_XMAX, SIZE_CURSOR_YMAX, SIZE_XSTEP, SIZE_LSPC};
enum {COL_SYM_LINE, COL_SYM_FILL, COL_DATA_LINE, COL_TEXT, COL_BG,
COL_AXIS, COL_BAR_LINE, COL_BAR_FILL, COL_ERROR_LINE, COL_BUBBLE_LINE,
COL_BUBBLE_FILLLINE, COL_BUBBLE_FILL, COL_ARROW, COL_WHISKER, COL_BOX_LINE,
@@ -89,12 +96,12 @@ enum {CMD_NONE, CMD_ADDCHAR, CMD_SETFOCUS, CMD_KILLFOCUS, CMD_DELETE,
CMD_BUBBLE_ATTRIB, CMD_BUBBLE_FILL, CMD_BUBBLE_LINE, CMD_DL_LINE,
CMD_DL_TYPE, CMD_SEG_FILL, CMD_SEG_LINE, CMD_SELECT, CMD_MOVE, CMD_CUT,
CMD_SETSCROLL, CMD_SETHPOS, CMD_SETVPOS, CMD_PG_FILL, CMD_BOUNDS,
- CMD_SHIFT_OUT, CMD_CAN_DELETE, CMD_RESET_LINE, CMD_SET_TICKSTYLE,
+ CMD_SHIFT_OUT, CMD_CAN_DELETE, CMD_CAN_CLOSE, CMD_RESET_LINE, CMD_SET_TICKSTYLE,
CMD_GET_GRIDLINE, CMD_SET_GRIDLINE, CMD_SET_GRIDTYPE, CMD_TLB_TXTDEF,
CMD_DROP_LABEL, CMD_DROP_OBJECT, CMD_PAGEUP, CMD_PAGEDOWN, CMD_AUTOSCALE,
CMD_MRK_DIRTY, CMD_SETNAME, CMD_TOOLMODE, CMD_DROPFILE, CMD_AXIS, CMD_INIT,
CMD_GET_CELLDIMS, CMD_SET_CELLDIMS, CMD_TEXTSIZE, CMD_PASTE_TSV, CMD_PASTE_XML,
- CMD_PASTE_CSV, CMD_COPY_TSV, CMD_COPY_XML, CMD_COPY_SYLK, CMD_QUERY_COPY,
+ CMD_PASTE_SSV, CMD_PASTE_CSV, CMD_COPY_TSV, CMD_COPY_XML, CMD_COPY_SYLK, CMD_QUERY_COPY,
CMD_MOUSECURSOR, CMD_NEWPAGE, CMD_MINRC, CMD_MAXRC,CMD_SETCHILD, CMD_SYM_FILL,
CMD_LINEUP, CMD_LINEDOWN, CMD_CONFIG, CMD_FINDTEXT, CMD_MOVE_TOP, CMD_MOVE_UP,
CMD_MOVE_DOWN, CMD_MOVE_BOTTOM, CMD_UPDATE, CMD_CURRPOS, CMD_POS_FIRST, CMD_POS_LAST,
@@ -103,10 +110,11 @@ enum {CMD_NONE, CMD_ADDCHAR, CMD_SETFOCUS, CMD_KILLFOCUS, CMD_DELETE,
CMD_ZOOM, CMD_CLIP, CMD_STARTLINE, CMD_ADDTOLINE, CMD_REQ_POINT, CMD_DRAW_LATER,
CMD_SEG_MOVEABLE, CMD_ARROW_ORG3D, CMD_MUTATE, CMD_PRINT, CMD_UPDHISTORY, CMD_ALLTEXT,
CMD_SET_LINE, CMD_SAVE_SYMBOLS, CMD_SAVE_TICKS, CMD_SAVE_BARS, CMD_SAVE_BARS_CONT,
- CMD_SAVE_ERRS, CMD_SAVE_ARROWS, CMD_SAVE_DROPLINES, CMD_UNLOCK, CMD_SYMTEXT_UNDO,
+ CMD_SAVE_ERRS, CMD_SAVE_ARROWS, CMD_SAVE_DROPLINES, CMD_SAVE_LABELS, CMD_UNLOCK, CMD_SYMTEXT_UNDO,
CMD_FILLRANGE, CMD_BUSY, CMD_ERROR, CMD_CLEAR_ERROR, CMD_SETPARAM, CMD_SETFUNC,
CMD_HIDE_MARK, CMD_LEGEND, CMD_FILENAME, CMD_LAYERS, CMD_OBJTREE, CMD_TEXTDEF,
- CMD_HASSTACK, CMD_WRITE_GRAPHS, CMD_SETFONT, CMD_SETSTYLE};
+ CMD_HASSTACK, CMD_WRITE_GRAPHS, CMD_SETFONT, CMD_SETSTYLE, CMD_COPY, CMD_PASTE,
+ CMD_INSROW, CMD_INSCOL, CMD_DELROW, CMD_DELCOL, CMD_ADDTXT, CMD_ETRACC, CMD_SHPGUP, CMD_SHPGDOWN};
enum {SYM_CIRCLE, SYM_CIRCLEF, SYM_RECT, SYM_RECTF, SYM_TRIAU, SYM_TRIAUF,
SYM_TRIAD, SYM_TRIADF, SYM_DIAMOND, SYM_DIAMONDF, SYM_PLUS, SYM_CROSS,
SYM_STAR, SYM_HLINE, SYM_VLINE, SYM_TEXT, SYM_POS_PARENT = 0x1000};
@@ -123,7 +131,8 @@ enum {GO_UNKNOWN, GO_AXIS, GO_TICK, GO_GRIDLINE, GO_SYMBOL, GO_BUBBLE, GO_BAR,
GO_PLOT = 0x100, GO_PLOTSCATT, GO_REGRESSION, GO_BARCHART, GO_BUBBLEPLOT,
GO_BOXPLOT, GO_DENSDISP, GO_STACKBAR, GO_STACKPG, GO_WATERFALL, GO_POLARPLOT,
GO_PIECHART, GO_RINGCHART, GO_GROUP, GO_STARCHART, GO_SCATT3D, GO_PLOT3D,
- GO_RIBBON, GO_LIMITS, GO_FUNCTION, GO_FITFUNC, GO_FREQDIST, GO_GRID3D,
+ GO_RIBBON, GO_LIMITS, GO_FUNCTION, GO_FITFUNC, GO_FREQDIST, GO_GRID3D, GO_FUNC3D,
+ GO_XYSTAT,
GO_GRAPH = 0x200, GO_PAGE, GO_SPREADDATA = 0x300, GO_DEFRW};
enum {FILL_NONE, FILL_HLINES, FILL_VLINES, FILL_HVCROSS, FILL_DLINEU, FILL_DLINED,
FILL_DCROSS, FILL_STIPPLE1, FILL_STIPPLE2, FILL_STIPPLE3, FILL_STIPPLE4,
@@ -145,7 +154,7 @@ enum {MENU_NONE, MENU_SPREAD, MENU_GRAPH, MENU_PAGE};
enum {GT_UNKNOWN, GT_STANDARD, GT_CIRCCHART, GT_POLARPLOT, GT_3D};
enum {ICO_NONE, ICO_INFO, ICO_ERROR, ICO_RLPLOT, ICO_QT};
enum {FF_UNKNOWN, FF_CSV, FF_TSV, FF_XML, FF_SYLK, FF_RLP, FF_SVG, FF_EPS,
- FF_WMF, FF_RLW};
+ FF_WMF, FF_RLW, FF_SSV};
enum {LB_X_DATA = 0x01, LB_X_PARENT = 0x02, LB_Y_DATA = 0x10, LB_Y_PARENT = 0x20};
enum {BUBBLE_CIRCLE = 0x000, BUBBLE_SQUARE = 0x001, BUBBLE_UPTRIA = 0x002,
BUBBLE_DOWNTRIA = 0x003, BUBBLE_UNITS = 0x000, BUBBLE_XAXIS = 0x010,
@@ -153,6 +162,7 @@ enum {BUBBLE_CIRCLE = 0x000, BUBBLE_SQUARE = 0x001, BUBBLE_UPTRIA = 0x002,
BUBBLE_AREA = 0x200};
enum {DH_UNKNOWN, DH_12, DH_22, DH_19, DH_29, DH_39, DH_49, DH_59, DH_69, DH_79,
DH_89, DH_99, DH_18, DH_28, DH_38, DH_48, DH_58, DH_68, DH_78, DH_88, DH_DATA};
+enum {FE_NONE = 0x1000, FE_PARENT, FE_PLOT, FE_FLUSH, FE_DELOBJ, FE_REPLGO, FE_MUTATE};
//drop line styles
#define DL_LEFT 0x001
@@ -314,7 +324,9 @@ public:
~AccRange();
int CountItems();
bool GetFirst(int *x, int *y);
- bool GetNext(int *x, int *y);
+ bool GetNext(int *x, int *y);
+ bool NextRow(int *y);
+ bool NextCol(int *x);
bool IsInRange(int x, int y);
bool BoundRec(RECT *rec);
@@ -385,7 +397,8 @@ public:
double fix2un(double fix);
double fiy2un(double fiy);
virtual bool SetLine(LineDEF *lDef){return false;};
- bool GetLine(LineDEF *lDef);
+ bool GetLine(LineDEF *lDef);
+ virtual void Focus() {return;};
virtual void Caption(char *txt){return;};
virtual void MouseCursor(int cid, bool force){return;};
virtual bool SetScroll(bool, int, int, int, int){return false;};
@@ -427,12 +440,13 @@ enum {ET_UNKNOWN, ET_VALUE, ET_TEXT, ET_FORMULA, ET_ERROR, ET_BUSY=0x100,
class EditText {
public:
- char *text;
- int Align, type;
- void *parent; //points to a data object: defined below
+ char *text, *ftext;
+ int Align, type, row, col;
+ void *parent; //points to a data object: defined below
+ anyOutput *disp;
+ double Value;
- EditText(void *par, POINT where, POINT right, char *msg);
- EditText(void *par, char *msg);
+ EditText(void *par, char *msg, int r, int c);
~EditText();
bool AddChar(int c, anyOutput *Out, void *data_obj);
void Update(int select, anyOutput *Out, POINT *MousePos);
@@ -441,7 +455,7 @@ public:
bool Command(int cmd, anyOutput *Out, void *data_obj);
bool GetValue(double *v);
bool GetText(char *t, int size);
- bool GetResult(anyResult *r);
+ bool GetResult(anyResult *r, bool use_last = false);
bool SetValue(double v);
bool SetText(char *t);
bool GetItem(char *text, int size);
@@ -452,6 +466,7 @@ public:
bool isValue();
bool isFormula();
bool isInRect(POINT *p) {return (p->x>loc.x && p->x<crb.x && p->y>loc.y && p->y<rb.y);};
+ bool hasMark() {return (m1 != m2 && m1 >= 0 && m2 >= 0);};
private:
LineDEF *bgLine;
@@ -459,7 +474,6 @@ private:
int length, CursorPos, m1, m2, mx1, mx2;
POINT loc, rb, crb;
DWORD TextCol;
- double Value;
void FindType();
};
@@ -508,7 +522,7 @@ public:
virtual bool GetValue(int row, int col, double *v);
virtual bool GetText(int row, int col, char *txt, int len);
char ** GetTextPtr(int row, int col);
- virtual bool GetResult(anyResult *r, int row, int col);
+ virtual bool GetResult(anyResult *r, int row, int col, bool use_last = false);
virtual bool GetSize(int *width, int *height);
virtual bool Select(POINT *p){return false;};
virtual bool WriteData(char *FileName) {return false;};
@@ -522,13 +536,14 @@ public:
class StrData {
public:
- StrData(DataObj *par);
+ StrData(DataObj *par, RECT *rc = 0L);
~StrData();
bool GetSize(int *w, int *h);
void StrData::RestoreData(DataObj *dest);
private:
- int pw, ph, h, w;
+ int pw, ph;
+ RECT drc;
DataObj *src;
char ***str_data;
};
@@ -622,7 +637,7 @@ public:
bool Command(int cmd, void *tmpl, anyOutput *o);
private:
- bool bLBdown;
+ bool bLBdown, bSelected;
TextDEF TextDef;
LineDEF Line;
FillDEF Fill;
@@ -747,7 +762,9 @@ public:
bool PropertyDlg();
bool FileIO(int rw);
-private:
+private:
+ bool DoAutoscale(anyOutput *o);
+
lfPOINT fPos;
double fs;
LineDEF BubbleLine, BubbleFillLine;
@@ -767,11 +784,14 @@ public:
bool SetSize(int select, double value);
bool SetColor(int select, DWORD col);
void DoPlot(anyOutput *target);
+ void DoMark(anyOutput *o, bool mark);
bool Command(int cmd, void *tmpl, anyOutput *o);
bool PropertyDlg();
bool FileIO(int rw);
private:
+ anyOutput *mo;
+ RECT mrc;
double size;
LineDEF BarLine, HatchLine;
FillDEF BarFill;
@@ -806,7 +826,8 @@ public:
void FileValues(char *name, int type, double start, double step);
void SetValues();
- void LineData(lfPOINT *val, long nval);
+ void LineData(lfPOINT *val, long nval);
+ void DrawSpline(anyOutput *target);
};
class DataPolygon:public DataLine{
@@ -1208,7 +1229,10 @@ public:
LineDEF Line;
Line3D(GraphObj *par, DataObj *d, char *rx, char *ry, char *rz);
- Line3D::Line3D(GraphObj *par, DataObj *d, fPOINT3D *pt, int n_pt);
+ Line3D(GraphObj *par, DataObj *d, fPOINT3D *pt, int n_pt, int xc1 = -1,
+ int xr1 = -1, int yc1 = -1, int yr1 = -1, int zc1 = -1, int zr1 = -1,
+ int xc2 = -1, int xr2 = -1, int yc2 = -1, int yr2 = -1, int zc2 = -1,
+ int zr2 = -1);
Line3D(int src);
~Line3D();
void DoPlot(anyOutput *o);
@@ -1221,8 +1245,10 @@ private:
line_segment **ls;
fPOINT3D *values, min, max;
POINT *pts;
+ long nPts, npts;
char *x_range, *y_range, *z_range;
- long nPts, npts;
+ POINT *ssRef;
+ long cssRef;
bool bModified;
anyOutput *mo;
RECT mrc;
@@ -1289,7 +1315,7 @@ public:
private:
lfPOINT fPos, fDist, cPos, cPos1, dist;
- double si, csi, curr_z;
+ double si, csi, curr_z, lspc;
DWORD flags, undo_flags;
TextDEF TextDef;
long nLines;
@@ -1480,6 +1506,16 @@ public:
class PlotScatt:public Plot{
public:
+ char *xRange, *yRange;
+ long nPoints;
+ int DefSym;
+ lfPOINT BarDist;
+ Bar **Bars;
+ Symbol **Symbols;
+ DataLine *TheLine;
+ ErrorBar **Errors;
+ Label **Labels;
+
PlotScatt(GraphObj *par, DataObj *d, DWORD presel);
PlotScatt(GraphObj *par, DataObj *d, int cBars, Bar **bars);
PlotScatt(GraphObj *par, DataObj *d, int nPts, Symbol **sym, DataLine *lin);
@@ -1489,30 +1525,39 @@ public:
bool SetSize(int select, double value);
bool SetColor(int select, DWORD col);
void DoPlot(anyOutput *target);
- bool Command(int cmd, void *tmpl, anyOutput *o);
+ virtual bool Command(int cmd, void *tmpl, anyOutput *o);
virtual bool PropertyDlg();
void RegGO(void *n);
- bool FileIO(int rw);
+ virtual bool FileIO(int rw);
+
+ bool ForEach(int cmd, void *tmp, anyOutput *o);
private:
DWORD DefSel;
- lfPOINT BarDist;
- char *xRange, *yRange, *ErrRange, *LbRange;
- int DefSym;
- long nPoints;
- Bar **Bars;
- Symbol **Symbols;
- DataLine *TheLine;
- ErrorBar **Errors;
+ char *ErrRange, *LbRange;
Arrow **Arrows;
DropLine **DropLines;
- Label **Labels;
bool CreateBarChart();
- enum {FE_NONE = 0x1000, FE_PARENT, FE_PLOT, FE_FLUSH, FE_DELOBJ,
- FE_REPLGO, FE_MUTATE};
- bool ForEach(int cmd, void *tmp, anyOutput *o);
-};
+};
+
+class xyStat:public PlotScatt{
+public:
+ xyStat(GraphObj *par, DataObj *d);
+ xyStat(int src);
+ ~xyStat();
+ bool Command(int cmd, void *tmpl, anyOutput *o);
+ bool PropertyDlg();
+ virtual bool FileIO(int rw);
+
+ void CreateData();
+
+private:
+ double ci;
+ DataObj *curr_data;
+ char *case_prefix;
+
+};
class BarChart:public PlotScatt{
public:
@@ -1624,14 +1669,21 @@ public:
bool Command(int cmd, void *tmpl, anyOutput *o);
bool PropertyDlg();
void RegGO(void *n);
- bool FileIO(int rw);
+ bool FileIO(int rw);
+
+ bool ForEach(int cmd, void *tmp, anyOutput *o);
+ void CreateData();
private:
- long nPoints;
+ char *xRange, *yRange, *case_prefix;
+ long nPoints;
+ double ci_box, ci_err;
+ DataObj *curr_data;
lfPOINT BoxDist;
Box **Boxes;
Whisker **Whiskers;
- Symbol **Symbols;
+ Symbol **Symbols;
+ Label **Labels;
DataLine *TheLine;
};
@@ -1722,7 +1774,7 @@ public:
void DoUpdate();
private:
- int nPts;
+ long nPts;
char *ssRefA, *ssRefR;
lfPOINT CtDef;
double FacRad;
@@ -1787,9 +1839,11 @@ private:
class Grid3D:public Plot {
public:
- Grid3D(GraphObj *par, DataObj *d);
+ Grid3D(GraphObj *par, DataObj *d, int sel, double x1=0.0, double xstep=1.0, double z1=0.0, double zstep=1.0);
Grid3D(int src);
~Grid3D();
+ bool SetSize(int select, double value);
+ bool SetColor(int select, DWORD col);
void DoPlot(anyOutput *o);
bool Command(int cmd, void *tmpl, anyOutput *o);
void RegGO(void *n);
@@ -1798,10 +1852,12 @@ public:
void CreateObs();
private:
- long nLines;
+ long nLines, nPlanes;
fPOINT3D start, step;
LineDEF Line;
+ FillDEF Fill;
Line3D **lines;
+ Plane3D **planes;
};
class Scatt3D:public Plot{
@@ -2024,6 +2080,7 @@ public:
Axis **Axes;
GraphObj **plots;
double *RotDef;
+ fPOINT3D cub1, cub2, rotC;
Plot3D(GraphObj *par, DataObj *d, DWORD flags);
Plot3D(int src);
@@ -2032,10 +2089,10 @@ public:
bool SetColor(int select, DWORD col);
void DoPlot(anyOutput *o);
void DoMark(anyOutput *o, bool mark);
- bool Command(int cmd, void *tmpl, anyOutput *o);
- bool PropertyDlg();
- void RegGO(void *n);
- bool FileIO(int rw);
+ virtual bool Command(int cmd, void *tmpl, anyOutput *o);
+ virtual bool PropertyDlg();
+ virtual void RegGO(void *n);
+ virtual bool FileIO(int rw);
void * ObjThere(int x, int y);
void Track(POINT *p, anyOutput *o);
@@ -2050,7 +2107,7 @@ private:
long nObs, nmaxObs;
DWORD crea_flags;
Drag3D *drag;
- fPOINT3D cub1, cub2, rotC, cu1, cu2, rc;
+ fPOINT3D cu1, cu2, rc;
obj_desc **dispObs;
bool AddPlot(int family);
@@ -2082,6 +2139,28 @@ public:
~BubblePlot3D();
bool PropertyDlg();
};
+
+class Func3D:public Plot3D {
+public:
+ Func3D(GraphObj *par, DataObj *d);
+ Func3D(int src);
+ ~Func3D();
+ bool Command(int cmd, void *tmpl, anyOutput *o);
+ bool PropertyDlg();
+ void RegGO(void *n);
+ bool FileIO(int rw);
+
+private:
+ bool Update();
+
+ double x1, x2, xstep, z1, z2, zstep;
+ int g_idx;
+ LineDEF Line;
+ FillDEF Fill;
+ char *param, *cmdxy;
+ DataObj *gda;
+ Grid3D *gob;
+};
class Graph:public GraphObj{
public:
@@ -2188,7 +2267,7 @@ public:
char DecPoint[2], ColSep[2];
char *svgAttr, *svgScript, *currPath, *IniFile;
char *File1, *File2, *File3, *File4, *File5, *File6;
- double min4log;
+ double min4log, ss_txt;
RECT clipRC;
Default();
@@ -2259,11 +2338,11 @@ public:
#define UNDO_STORESET 0x1000
class UndoObj {
enum {UNDO_UNDEFINED, UNDO_DEL_GO, UNDO_GOLIST, UNDO_DROPMEM,
- UNDO_VALDWORD, UNDO_VALINT, UNDO_OBJCONF, UNDO_OBJCONF_1,
- UNDO_LFP, UNDO_MOVE, UNDO_RECT, UNDO_STRING, UNDO_ROTDEF,
- UNDO_SETGO, UNDO_LINEDEF, UNDO_FILLDEF, UNDO_AXISDEF,
- UNDO_LFP3D, UNDO_FLOAT, UNDO_MEM, UNDO_MUTATE, UNDO_DROPGOLIST,
- UNDO_TEXTDEF, UNDO_SAVVAR, UNDO_DATA, UNDO_ET};
+ UNDO_VALDWORD, UNDO_VALINT, UNDO_VALLONG, UNDO_OBJCONF, UNDO_OBJCONF_1,
+ UNDO_LFP, UNDO_POINT, UNDO_VOIDPTR, UNDO_MOVE, UNDO_RECT,
+ UNDO_STRING, UNDO_ROTDEF, UNDO_SETGO, UNDO_LINEDEF, UNDO_FILLDEF,
+ UNDO_AXISDEF, UNDO_LFP3D, UNDO_FLOAT, UNDO_MEM, UNDO_MUTATE,
+ UNDO_DROPGOLIST, UNDO_TEXTDEF, UNDO_SAVVAR, UNDO_DATA, UNDO_ET};
typedef struct _UndoInfo {
int cmd;
DWORD flags;
@@ -2294,14 +2373,16 @@ class UndoObj {
public:
int *pcb;
+ anyOutput *cdisp, *ldisp;
+ bool busy;
- UndoObj();
+ UndoObj();
~UndoObj();
void Flush();
void SetDisp(anyOutput *o);
void KillDisp(anyOutput *o);
void InvalidGO(GraphObj *go);
- void Pop();
+ void Pop(anyOutput *o);
void Restore(bool redraw, anyOutput *o);
void ListGOmoved(GraphObj **oldlist, GraphObj **newlist, long size);
void DeleteGO(GraphObj **go, DWORD flags, anyOutput *o);
@@ -2310,8 +2391,11 @@ public:
void DropListGO(GraphObj *parent, GraphObj ***go, long *count, DWORD flags);
void DropMemory(GraphObj *parent, void **mem, DWORD flags);
void SavVarBlock(GraphObj *parent, void **mem, DWORD flags);
- void ValDword(GraphObj *parent, DWORD *val, DWORD flags);
+ void ValDword(GraphObj *parent, DWORD *val, DWORD flags);
+ void Point(GraphObj *parent, POINT *pt, anyOutput * o, DWORD flags);
+ void VoidPtr(GraphObj *parent, void **pptr, void *ptr, anyOutput * o, DWORD flags);
void ValInt(GraphObj *parent, int *val, DWORD flags);
+ void ValLong(GraphObj *parent, long *val, DWORD flags);
void ObjConf(GraphObj *go, DWORD flags);
int SaveLFP(GraphObj *go, lfPOINT *lfp, DWORD flags);
void MoveObj(GraphObj *go, lfPOINT *lfp, DWORD flags);
@@ -2326,13 +2410,12 @@ public:
void ValLFP3D(GraphObj *go, fPOINT3D *lfp, DWORD flags);
void ValFloat(GraphObj *parent, double *val, DWORD flags);
void DataMem(GraphObj *go, void **mem, int size, long *count, DWORD flags);
- void DataObject(GraphObj *go, anyOutput *o, DataObj *d, DWORD flags);
+ void DataObject(GraphObj *go, anyOutput *o, DataObj *d, RECT *rc, DWORD flags);
void TextCell(EditText *et, anyOutput *o, char *text, int *cur, int *m1, int *m2, void* DaO, DWORD flags);
private:
UndoInfo **buff, **buff0;
int stub1, ndisp;
- anyOutput *cdisp, *ldisp;
UndoBuff **buffers;
int NewItem(int cmd, DWORD flags, GraphObj *owner, void *data, void **loc);
@@ -2353,6 +2436,7 @@ char *OpenDataName(char *oldname);
void InfoBox(char *Msg);
void ErrorBox(char *Msg);
bool YesNoBox(char *Msg);
+int YesNoCancelBox(char *Msg);
void Qt_Box();
void HideTextCursor();
void HideTextCursorObj(anyOutput *out);
@@ -2361,6 +2445,8 @@ void HideCopyMark();
void ShowCopyMark(anyOutput *out, RECT *mrk, int nRec);
void InitTextCursor(bool init);
void EmptyClip();
+void CopyText(char *txt, int len);
+unsigned char* PasteText();
void GetDesktopSize(int *width, int *height);
void FindBrowser();
void LoopDlgWnd();
@@ -2386,8 +2472,7 @@ void GetNewFill(FillDEF *oldfill);
void ShowBanner(bool show);
void RLPlotInfo();
bool DoSpShSize(DataObj *dt);
-bool FillSsRange(DataObj *d, char **range);
-bool GetCopyRange(RECT *rc, DataObj *d);
+bool FillSsRange(DataObj *d, char **range, GraphObj *msg_go);
bool GetBitmapRes(double *res, double *width, double *height, char *header);
void OD_scheme(int, void *, RECT *, anyOutput *, void *, int);
FillDEF *GetSchemeFill(int *i);
@@ -2419,6 +2504,7 @@ double NiceValue(double fv);
char *Int2ColLabel(int nr, bool uc);
char *str2xml(char *str);
char **split(char *str, char sep, int *nl);
+char *fit_num_rect(anyOutput *o, int max_width, char *num_str);
void SetMinMaxRect(RECT *rc, int x1, int y1, int x2, int y2);
void UpdateMinMaxRect(RECT *rc, int x, int y);
void IncrementMinMaxRect(RECT *rc, int i);
@@ -2438,10 +2524,12 @@ unsigned long isqr(unsigned long n);
bool MatMul(double a[3][3], double b[3][3], double c[3][3]);
char *GetNumFormat(double Magn);
void DeleteGO(GraphObj *go);
+bool DeleteGOL(GraphObj ***gol, long n, GraphObj *go, anyOutput *o);
bool BackupFile(char *FileName);
bool IsRlpFile(char *FileName);
bool IsXmlFile(char *FileName);
bool FileExist(char *FileName);
+bool IsPlot3D(GraphObj *g);
void *memdup(void *ptr, int cb_old, int cb_new);
double sininv(double val);
double trig2deg(double si, double csi);
@@ -2474,8 +2562,10 @@ void DoExportTif(GraphObj *g, char *FileName, DWORD flags);
//prototypes mfcalc.cpp
bool do_xyfunc(DataObj *, double, double, double, char *, lfPOINT **, long *, char *);
+bool do_func3D(DataObj *d, double x1, double x2, double xstep, double z1, double z2, double zstep,
+ char *expr, char *param);
anyResult *do_formula(DataObj *, char *);
-bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy);
+bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy, int r0, int c0);
int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr,
double conv, int maxiter, double *chi_2);
@@ -2485,11 +2575,31 @@ void free_dmatrix(double **m, int nrl, int nrh, int ncl, int);
bool mrqmin(double *, double *, double *, int, double **, int, int *, int, double **, double **, double *,
void (*funcs)(double, double, double **, double *, double *, int), double *);
bool Check_MRQerror();
+void SortFpArray(int n, lfPOINT *vals);
+void spline(lfPOINT *v, int n, double *y2);
double gammln(double xx);
double factrl(int n);
-double t_dist(double t, double df);
+double gammp(double a, double x);
+double gammq(double a, double x);
+double betai(double a, double b, double x);
+double bincof(double n, double k);
+double binomdistf(double k, double n, double p);
+double betaf(double z, double w);
+double errf(double x);
+double errfc(double x);
+double norm_dist(double x, double m, double s);
+double chi_dist(double x, double df, double);
+double t_dist(double t, double df, double);
+double pois_dist(double x, double m, double);
double f_dist(double f, double df1, double df2);
+double distinv(double (*sf)(double, double, double), double df1, double df2, double p, double x0);
void d_quartile(int n, double *v, double *q1, double *q2, double *q3);
double d_amean(int n, double *v);
double d_gmean(int n, double *v);
double d_hmean(int n, double *v);
+double d_pearson(double *x, double *y, int n, char *dest, DataObj *data);
+double d_spearman(double *x, double *y, int n, char *dest, DataObj *data);
+double d_regression(double *x, double *y, int n, char *dest, DataObj *data);
+double d_ttest(double *x, double *y, int n1, int n2, char *dest, DataObj *data);
+double d_ftest(double *x, double *y, int n1, int n2, char *dest, DataObj *data);
+
diff --git a/rlplot.spec b/rlplot.spec
index aaaff29..315c497 100755
--- a/rlplot.spec
+++ b/rlplot.spec
@@ -1,5 +1,5 @@
Name: rlplot
-Version: 0.99.12b
+Version: 1.0
Release: 1
Summary: A plotting program to create high quality graphs from data.
License: GPL
@@ -41,6 +41,9 @@ rm -rf "$RPM_BUILD_ROOT"
%{_bindir}/exprlp
%changelog
+* Wed Sep 07 2005 Reinhard Lackner
+- release 1.0
+
* Tue Dec 21 2004 Reinhard Lackner
- release canditate 2, version 0.99.12b
@@ -60,3 +63,4 @@ rm -rf "$RPM_BUILD_ROOT"
+
diff --git a/spreadwi.cpp b/spreadwi.cpp
index 40e32b8..734c7b8 100755
--- a/spreadwi.cpp
+++ b/spreadwi.cpp
@@ -32,13 +32,15 @@
#include <unistd.h>
#endif
-extern const LineDEF BlackLine;
+extern const LineDEF GrayLine;
extern EditText *CurrText;
extern char *LoadFile;
extern char TmpTxt[];
extern Default defs;
extern UndoObj Undo;
+
static ReadCache *Cache = 0L;
+static TextDEF ssText;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get item from *.csv file
@@ -73,10 +75,10 @@ bool GetItemCSV(char *Text, int cbText)
// process a memory block (i.e. clipboard data) as if file input
int ProcMemData(GraphObj *g, unsigned char *ptr, bool dispatch)
{
- int i, RetVal = FF_UNKNOWN, nt, nl, nc, cc;
+ int i, RetVal = FF_UNKNOWN, nt, nl, nc, ns;
if(ptr) {
- for(i = nt = nl = nc = 0; ptr[i]; i++) {
+ for(i = nt = nl = nc = ns = 0; ptr[i] && nl<100; i++) {
switch(ptr[i]) {
case 0x09: //tab
nt++;
@@ -86,22 +88,29 @@ int ProcMemData(GraphObj *g, unsigned char *ptr, bool dispatch)
break;
case ',':
nc++;
- break;
+ break;
+ case ' ':
+ ns++;
+ break;
}
}
- if(dispatch && i && !nt && !nl)
- for(i = 0; ptr[i]; i++){
- cc = ptr[i];
- g->Command(CMD_ADDCHAR, (void*)(& cc), 0L);
- }
+ if(dispatch && i && !nt && !nl) {
+ if(CurrText){
+ g->Command(CMD_SETFOCUS, 0L, 0L);
+ for(i = 0; ptr[i]; i++) CurrText->AddChar(ptr[i], i? 0L : Undo.cdisp, 0L);
+ g->Command(CMD_REDRAW, 0L, 0L);
+ }
+ }
else if(nt) RetVal = FF_TSV;
else if(nl && ptr[0] == '<') RetVal = FF_XML;
else if(nc == nl && defs.DecPoint[0] == ',') RetVal = FF_TSV;
else if(nl && nc && 0 == (nc % nl)) RetVal = FF_CSV;
+ else if(nl && ns && 0 == (ns % nl)) RetVal = FF_SSV;
else if(nl) RetVal = FF_TSV;
if(dispatch) switch(RetVal) {
case FF_CSV: g->Command(CMD_PASTE_CSV, ptr, 0L); break;
case FF_TSV: g->Command(CMD_PASTE_TSV, ptr, 0L); break;
+ case FF_SSV: g->Command(CMD_PASTE_SSV, ptr, 0L); break;
case FF_XML: g->Command(CMD_PASTE_XML, ptr, 0L); break;
}
}
@@ -117,12 +126,12 @@ public:
POINT ssOrg;
RECT currRC;
- SpreadWin(DataObj *Data);
+ SpreadWin(GraphObj *par, DataObj *Data);
~SpreadWin();
void DoPlot(anyOutput *target);
bool Command(int cmd, void *tmpl, anyOutput *o);
- bool ShowGrid(int CellWidth, int CellHeight, int FirstWidth);
+ bool ShowGrid(int CellWidth, int CellHeight, int FirstWidth, POINT *cpos);
bool PrintData(anyOutput *o);
void WriteGraphXML(unsigned char **ptr, long *cbd);
@@ -130,18 +139,19 @@ private:
int ch, cw, fw; //cell height and width, row button width
bool is_modified;
char *filename;
- TextDEF ssText;
ssButton **cButtons, **rButtons;
- ssButton *aButton;
+ ssButton *aButton;
+ POINT cpos;
DataObj *d;
int NumGraphs;
Graph **g;
};
-SpreadWin::SpreadWin(DataObj *Data):GraphObj(0L, Data)
+SpreadWin::SpreadWin(GraphObj *par, DataObj *Data):GraphObj(par, Data)
{
d = Data; g = 0L; ssOrg.x = ssOrg.y = 0; NumGraphs = 0;
- ch = 19; cw = 76; fw = 32; filename=0L; aButton = 0L;
+ ch = 19; cw = 76; fw = 32; filename=0L; aButton = 0L;
+ w = 0L;
if(w = NewDispClass(this)){
w->hasHistMenu = true;
ssText.RotBL = ssText.RotCHAR = 0.0;
@@ -149,16 +159,16 @@ SpreadWin::SpreadWin(DataObj *Data):GraphObj(0L, Data)
#ifdef _WINDOWS
ssText.iSize = w->un2iy(defs.GetSize(SIZE_CELLTEXT));
#else
- ssText.iSize = w->un2iy(defs.GetSize(SIZE_CELLTEXT)*.8f);
+ ssText.iSize = w->un2iy(defs.GetSize(SIZE_CELLTEXT)*.7);
#endif
- ssText.Align = TXA_VTOP | TXA_HLEFT; ssText.Mode = TXM_TRANSPARENT;
- ssText.Style = TXS_NORMAL; ssText.ColBg = 0x00d8d8d8L;
+ ssText.Align = TXA_VCENTER | TXA_HLEFT; ssText.Mode = TXM_TRANSPARENT;
+ ssText.Style = TXS_NORMAL; ssText.ColBg = 0x00e8e8e8L;
ssText.ColTxt = 0x00000000L; ssText.text = 0L;
ssText.Font = FONT_HELVETICA; w->SetTextSpec(&ssText);
w->SetMenu(MENU_SPREAD); w->FileHistory();
- w->Erase(0x00d8d8d8L); w->Caption("RLPlot data");
+ w->Erase(0x00e8e8e8L); w->Caption("RLPlot data");
cw = w->un2ix(defs.GetSize(SIZE_CELLWIDTH));
- ch = w->un2iy(defs.GetSize(SIZE_CELLTEXT)) + 2;
+ ch = w->un2iy(defs.GetSize(SIZE_CELLTEXT)/defs.ss_txt) + 2;
fw = 32;
}
cButtons = rButtons = 0L;
@@ -169,28 +179,30 @@ SpreadWin::SpreadWin(DataObj *Data):GraphObj(0L, Data)
SpreadWin::~SpreadWin()
{
int i;
-
- if(cButtons) {
- for(i = 0; cButtons[i]; i++) if(cButtons[i]) delete(cButtons[i]);
- free(cButtons);
- }
- if(rButtons) {
- for(i = 0; rButtons[i]; i++) if(rButtons[i]) delete(rButtons[i]);
- free(rButtons);
- }
- if (aButton) delete(aButton);
- if (w) delete w;
- if (g && NumGraphs) {
- for(i = 0; i < NumGraphs; i++) if(g[i]) {
- g[i]->Command(CMD_CAN_DELETE, 0L, 0L);
- delete(g[i]);
+
+ if(parent) {
+ if(cButtons) {
+ for(i = 0; cButtons[i]; i++) if(cButtons[i]) delete(cButtons[i]);
+ free(cButtons);
}
- free (g);
- }
- if(filename) free(filename); filename=0L;
-}
-
-void
+ if(rButtons) {
+ for(i = 0; rButtons[i]; i++) if(rButtons[i]) delete(rButtons[i]);
+ free(rButtons);
+ }
+ if (aButton) delete(aButton);
+ if (w) delete w;
+ if (g && NumGraphs) {
+ for(i = 0; i < NumGraphs; i++) if(g[i]) {
+ g[i]->Command(CMD_CAN_DELETE, 0L, 0L);
+ delete(g[i]);
+ }
+ free (g);
+ }
+ if(filename) free(filename); filename=0L;
+ }
+}
+
+void
SpreadWin::DoPlot(anyOutput *o)
{
o->ActualSize(&currRC);
@@ -205,17 +217,45 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
char *Name;
Graph **g1, *g2;
int i, j, k;
- MouseEvent *mev;
+ MouseEvent *mev;
+ POINT p1;
if(d) {
- switch(cmd) {
- case CMD_UNDO:
- if(w) {
- w->MouseCursor(MC_WAIT, true);
- Undo.Restore(true, w);
- w->MouseCursor(MC_ARROW, true);
+ switch(cmd) {
+ case CMD_CURRPOS:
+ if(tmpl && cButtons && rButtons) {
+ int ac = 1, na = 0;
+ RECT urc;
+ if(((POINT*)tmpl)->x != cpos.x) {
+ for(cpos.x = ((POINT*)tmpl)->x, i = 0; cButtons[i]; i++) {
+ cButtons[i]->Command(CMD_SELECT, (cpos.x == (i+ssOrg.x)) ? &ac : &na, w);
+ }
+ urc.left = cButtons[0]->rDims.left; urc.bottom = cButtons[0]->rDims.bottom;
+ urc.top = cButtons[0]->rDims.top; urc.right = urc.left + cw * (i-1);
+ w->UpdateRect(&urc, false);
+ }
+ if(((POINT*)tmpl)->y != cpos.y) {
+ for(cpos.y = ((POINT*)tmpl)->y, i = 0; rButtons[i]; i++) {
+ rButtons[i]->Command(CMD_SELECT, (cpos.y == (i+ssOrg.y)) ? &ac : &na, w);
+ }
+ urc.left = rButtons[0]->rDims.left; urc.right = rButtons[0]->rDims.right;
+ urc.top = rButtons[0]->rDims.top; urc.bottom = urc.top + ch * (i-1);
+ w->UpdateRect(&urc, false);
+ }
}
- return true;
+ return true;
+ case CMD_CAN_CLOSE:
+ HideTextCursor();
+ for(i = 0; i < NumGraphs; i++) {
+ if((g[i]) && !g[i]->Command(cmd, tmpl, o)) return false;
+ }
+ if(is_modified) {
+ is_modified=false;
+ i = YesNoCancelBox("The spreadsheet has been modified!\n\nDo you want to save it now?");
+ if(i == 2) return false;
+ else if(i == 1) return Command(CMD_SAVEDATAAS, tmpl, o);
+ }
+ //fall through
case CMD_CAN_DELETE:
HideTextCursor();
if(is_modified && YesNoBox("The spreadsheet has been modified!\n\nDo you want to save it now?")){
@@ -226,8 +266,7 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
is_modified=false;
return true;
case CMD_MRK_DIRTY:
- is_modified=true;
- return true;
+ return is_modified = true;
case CMD_WRITE_GRAPHS:
if (g && NumGraphs) WriteGraphXML((unsigned char**)tmpl, (long*)o);
return true;
@@ -252,13 +291,15 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
return true;
case CMD_NEWGRAPH:
if((g2 = new Graph(this, d, 0L)) && g2->PropertyDlg() &&
- Command(CMD_DROP_GRAPH, g2, o))return true;
- else if(g2) DeleteGO(g2);
+ Command(CMD_DROP_GRAPH, g2, o))return Command(CMD_REDRAW, 0L, o);
+ else if(g2) DeleteGO(g2);
+ Undo.SetDisp(w);
return false;
case CMD_NEWPAGE:
if((g2 = new Page(this, d)) &&
- Command(CMD_DROP_GRAPH, g2, o))return true;
+ Command(CMD_DROP_GRAPH, g2, o))return Command(CMD_REDRAW, 0L, o);
else if(g2) DeleteGO(g2);
+ Undo.SetDisp(w);
return false;
case CMD_DELGRAPH:
if (g && NumGraphs) {
@@ -290,18 +331,22 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
if(Name && d->WriteData(Name)) {
if(filename) free(filename);
filename = strdup(Name);
- }
- }
+ }
+ else return false;
+ }
+ else return false;
return true;
- case CMD_DROPFILE:
+ case CMD_DROPFILE:
+ if(!Command(CMD_CAN_CLOSE, 0L, o)) return false;
if(IsRlpFile((char*)tmpl)) return OpenGraph(this, (char*)tmpl, 0L);
else if(d->ReadData((char*)tmpl, 0L, FF_UNKNOWN)){
if(filename) free(filename);
- filename = strdup((char*)tmpl);
+ filename = strdup((char*)tmpl);
return Command(CMD_SETSCROLL, 0L, w);
}
return false;
case CMD_OPEN:
+ if(!Command(CMD_CAN_CLOSE, 0L, o)) return false;
if((Name = OpenDataName(filename)) && Name[0]){
if(o) o->FileHistory();
if(IsRlpFile(Name)) return OpenGraph(this, Name, 0L);
@@ -313,7 +358,7 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
}
return false;
case CMD_ADDROWCOL:
- DoSpShSize(d);
+ if(DoSpShSize(d)) DoPlot(o);
return true;
case CMD_MOUSE_EVENT:
if(o && (mev = (MouseEvent*)tmpl) && mev->y > o->MenuHeight) {
@@ -331,8 +376,8 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
else if(o->MrkMode == MRK_SSB_DRAW) o->HideMark();
}
return d->Command(cmd, tmpl, o);
- case CMD_PASTE_TSV: case CMD_PASTE_XML: case CMD_PASTE_CSV:
- Undo.DataObject(this, w, d, 0L);
+ case CMD_PASTE_TSV: case CMD_PASTE_CSV: case CMD_PASTE_SSV:
+ Undo.DataObject(this, w, d, 0L, 0L);
case CMD_COPY_SYLK: case CMD_ADDCHAR: case CMD_SHIFTUP:
case CMD_COPY_TSV: case CMD_COPY_XML: case CMD_QUERY_COPY:
case CMD_TAB: case CMD_SHTAB: case CMD_SHIFTDOWN:
@@ -340,8 +385,14 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
case CMD_CURRDOWN: case CMD_SHIFTRIGHT: case CMD_POS_FIRST:
case CMD_POS_LAST: case CMD_SHIFTLEFT: case CMD_DELETE:
case CMD_TOOLMODE: case CMD_FILLRANGE: case CMD_CUT:
- case CMD_REDRAW:
- return d->Command(cmd, tmpl, o);
+ case CMD_PASTE_XML: case CMD_DELROW: case CMD_INSROW:
+ case CMD_INSCOL: case CMD_DELCOL: case CMD_UNDO:
+ case CMD_SHPGUP: case CMD_SHPGDOWN:
+ return d->Command(cmd, tmpl, o);
+ case CMD_REDRAW:
+ Undo.SetDisp(w);
+ d->Command(cmd, tmpl, o);
+ return true;
case CMD_SETSCROLL:
HideTextCursor();
o->ActualSize(&currRC);
@@ -352,32 +403,35 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
o->SetScroll(false, 0, i, k, ssOrg.x);
DoPlot(o);
return true;
- case CMD_PAGEUP:
+ case CMD_PAGEUP: case CMD_PAGEDOWN:
k = (currRC.bottom-currRC.top)/ch;
- k = k > 3 ? k-2 : 1;
- ssOrg.y = ssOrg.y > k ? ssOrg.y-k : 0;
- return Command(CMD_SETSCROLL, tmpl, o);
- case CMD_PAGEDOWN:
- k = (currRC.bottom-currRC.top)/ch;
- k = k > 3 ? k-2 : 1;
- d->GetSize(&i, &j);
- ssOrg.y = ssOrg.y < j-k*2 ? ssOrg.y+k : j > k ? j-k : 0;
- return Command(CMD_SETSCROLL, tmpl, o);
+ k = k > 3 ? k-2 : 1;
+ p1.x = fw + 2; p1.y = ch + 2;
+ if(CurrText){
+ p1.x = CurrText->GetX()+2; p1.y = CurrText->GetY()+12;
+ }
+ d->GetSize(&i, &j);
+ if(cmd == CMD_PAGEUP) ssOrg.y = ssOrg.y > k ? ssOrg.y-k : 0;
+ else ssOrg.y = ssOrg.y < j-k*2 ? ssOrg.y+k : j > k ? j-k : 0;
+ Command(CMD_SETSCROLL, tmpl, o);
+ CurrText = 0L; d->Select(&p1);
+ return true;
case CMD_SETHPOS:
ssOrg.x = *((int*)tmpl) >= 0 ? *((long*)tmpl) : 0L;
return Command(CMD_SETSCROLL, tmpl, o);
case CMD_SETVPOS:
ssOrg.y = *((int*)tmpl) >= 0 ? *((long*)tmpl) : 0L;
return Command(CMD_SETSCROLL, tmpl, o);
- case CMD_SETFOCUS:
+ case CMD_SETFOCUS:
+ Undo.SetDisp(w);
return true;
case CMD_KILLFOCUS:
return true;
case CMD_TEXTSIZE:
if(tmpl)ssText.iSize = *((int*)tmpl);
- break;
+ return true;
case CMD_CONFIG:
- return defs.PropertyDlg();
+ return defs.PropertyDlg();
case CMD_NONE:
return true;
case CMD_PRINT:
@@ -388,16 +442,16 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
}
bool
-SpreadWin::ShowGrid(int CellWidth, int CellHeight, int FirstWidth)
+SpreadWin::ShowGrid(int CellWidth, int CellHeight, int FirstWidth, POINT *cp)
{
- int i, c, nr, nc;
+ int i, c, nr, nc, ac = 1, na = 0;
RECT rc;
char text[20];
POINT grid[2];
TextDEF ButtText;
bool redim = false;
-
- //DEBUG: Make sure not to draw the grid much larger than the dektop
+
+ cpos.x = cp->x; cpos.y = cp->y;
if(ch != CellHeight || cw != CellWidth || fw != FirstWidth) redim = true;
ch = CellHeight; cw = CellWidth; fw = FirstWidth;
if(redim){
@@ -430,7 +484,7 @@ SpreadWin::ShowGrid(int CellWidth, int CellHeight, int FirstWidth)
new ssButton(this, 0, i*CellHeight+CellHeight+w->MenuHeight,
FirstWidth, CellHeight);
}
- w->SetLine((LineDEF *)&BlackLine);
+ w->SetLine((LineDEF *)&GrayLine);
d->GetSize(&nc, &nr);
grid[0].x = rc.left+FirstWidth;
i = (nc-ssOrg.x)*CellWidth+FirstWidth;
@@ -440,8 +494,8 @@ SpreadWin::ShowGrid(int CellWidth, int CellHeight, int FirstWidth)
if(rButtons[i]) {
rButtons[i]->Command(CMD_SETTEXTDEF, &ButtText, w);
rButtons[i]->Command(CMD_SETTEXT, text, w);
- rButtons[i]->DoPlot(w);
- w->SetLine((LineDEF *)&BlackLine);
+ rButtons[i]->Command(CMD_SELECT, (cpos.y == (i+ssOrg.y)) ? &ac : &na, w);
+ w->SetLine((LineDEF *)&GrayLine);
}
grid[0].y = grid[1].y = w->MenuHeight + i*CellHeight - 1;
if(i < (2+nr-ssOrg.y)) w->oSolidLine(grid);
@@ -453,8 +507,8 @@ SpreadWin::ShowGrid(int CellWidth, int CellHeight, int FirstWidth)
if(cButtons[i]) {
cButtons[i]->Command(CMD_SETTEXTDEF, &ButtText, w);
cButtons[i]->Command(CMD_SETTEXT, Int2ColLabel(i+ssOrg.x, true), w);
- cButtons[i]->DoPlot(w);
- w->SetLine((LineDEF *)&BlackLine);
+ cButtons[i]->Command(CMD_SELECT, (cpos.x == (i+ssOrg.x)) ? &ac : &na, w);
+ w->SetLine((LineDEF *)&GrayLine);
}
grid[0].x = grid[1].x = i*CellWidth+FirstWidth-1;
if(i <= (nc-ssOrg.x)) w->oSolidLine(grid);
@@ -506,7 +560,7 @@ SpreadWin::PrintData(anyOutput *o)
#ifdef _WINDOWS
td.fSize = defs.GetSize(SIZE_CELLTEXT);
#else
- td.fSize = defs.GetSize(SIZE_CELLTEXT)*.8f;
+ td.fSize = defs.GetSize(SIZE_CELLTEXT)*.8;
#endif
margin.left = iround(o->hres); margin.right = iround(o->hres/2.0);
margin.top = margin.bottom = iround(o->hres);
@@ -563,6 +617,7 @@ SpreadWin::PrintData(anyOutput *o)
ix = margin.left+pfw+pcw + i*pcw - iround(o->hres/20.0);
d->etRows[j+ss_pos.y][i+ss_pos.x]->GetValue(&val);
sprintf(TmpTxt,"%g", val);
+ fit_num_rect(o, pcw - iround(o->hres/30.0), TmpTxt);
}
else if(d->etRows[j+ss_pos.y][i+ss_pos.x]->isValue()){
td.Align = TXA_HRIGHT | TXA_VCENTER;
@@ -647,51 +702,66 @@ SpreadWin::WriteGraphXML(unsigned char **ptr, long *cbd)
// This data object is a spreadsheet
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class SpreadData:public DataObj{
+typedef struct _pos_info {
+ POINT ssOrg, currpos;
+ void *CurrText;};
+
public:
- SpreadData();
+ SpreadData(GraphObj *par);
~SpreadData();
bool Init(int nRows, int nCols);
- bool mpos2dpos(POINT *mp, POINT *dp);
+ bool mpos2dpos(POINT *mp, POINT *dp);
bool Select(POINT *p);
void MarkRange(char *range);
void HideMark(bool cclp);
bool WriteData(char *FileName);
bool AddCols(int nCols);
- bool AddRows(int nRows);
- bool ChangeSize(int nCols, int nRows, bool bUndo);
+ bool AddRows(int nRows);
+ bool ChangeSize(int nCols, int nRows, bool bUndo);
+ bool DeleteCols();
+ bool InsertCols();
+ bool DeleteRows();
+ bool InsertRows();
void DoPlot(anyOutput *o);
bool DelRange();
bool PasteRange(int cmd, char *txt);
- bool InitCopy(int cmd, void *tmpl, anyOutput *o);
+ bool InitCopy(int cmd, void *tmpl, anyOutput *o);
+ bool SavePos();
bool Command(int cmd, void *tmpl, anyOutput *o);
bool ReadData(char *FileName, unsigned char *buffer, int type);
- bool ReadXML(char *file, unsigned char *buffer, int type);
+ bool ReadXML(char *file, unsigned char *buffer, int type, DWORD undo_flags = 0L);
bool ReadTSV(char *file, unsigned char *buffer, int type);
bool MemList(unsigned char **ptr, int type);
private:
- int CellHeight, CellWidth, FirstWidth, r_disp, c_disp;
+ int CellHeight, CellWidth, FirstWidth, r_disp, c_disp, mrk_offs;
RECT rcCopy, cp_src_rec; //bounding rectangle for copy range
- bool bActive, new_mark, bCopyCut;
+ bool bActive, new_mark, bCopyCut, bUpdate, isRowMark, isColMark;
POINT currpos, currpos2;
anyOutput *w;
- SpreadWin *Disp;
+ SpreadWin *Disp;
+ GraphObj *g_parent;
+ EditText *et_racc;
char *m_range, *c_range; //mark and copy ranges
- char *err_msg; //error message
+ char *err_msg, *last_err; //error message
+ _pos_info pos_info; //save position settings
};
-SpreadData::SpreadData()
+SpreadData::SpreadData(GraphObj *par)
{
- Disp = 0L; m_range = 0L; c_range = 0L; w = 0L; err_msg=0;
- CellWidth = CellHeight = FirstWidth = 0;
- currpos.x = currpos.y = r_disp = c_disp = 0;
- bActive = bCopyCut = false;
+ Disp = 0L; m_range = 0L; c_range = 0L; w = 0L; err_msg=last_err = 0L;
+ g_parent = par; CellWidth = CellHeight = FirstWidth = 0;
+ et_racc = 0L;
+ currpos.x = currpos.y = r_disp = c_disp = mrk_offs = 0;
+ bActive = bCopyCut = bUpdate = isRowMark = isColMark = false;
rcCopy.left = rcCopy.right = rcCopy.top = rcCopy.bottom = 0;
cp_src_rec.left = cp_src_rec.right = cp_src_rec.top = cp_src_rec.bottom = 0;
if(defs.IniFile && FileExist(defs.IniFile)) {
OpenGraph(0L, defs.IniFile, 0L);
}
+ pos_info.currpos.x = currpos.x; pos_info.currpos.y = currpos.y;
+ pos_info.CurrText = CurrText;
}
SpreadData::~SpreadData()
@@ -706,52 +776,48 @@ bool
SpreadData::Init(int nRows, int nCols)
{
int i, j;
- POINT p1, p2;
RECT rc;
rcCopy.left = rcCopy.top = 0; rcCopy.bottom = cRows = nRows;
rcCopy.right = cCols = nCols; currpos.x = currpos.y = 0;
new_mark = bCopyCut = false;
if(!Disp) {
- Disp = new SpreadWin(this);
+ Disp = new SpreadWin(g_parent, this);
w = Disp->w;
if(w) {
CellWidth = w->un2ix(defs.GetSize(SIZE_CELLWIDTH));
- CellHeight = w->un2iy(defs.GetSize(SIZE_CELLTEXT)) + 2;
- FirstWidth = 32;
- w->ActualSize(&rc);
- r_disp = (rc.bottom-rc.top)/CellHeight+1;
+ CellHeight = w->un2iy(defs.GetSize(SIZE_CELLTEXT)/defs.ss_txt) + 2;
+ FirstWidth = 32;
+ w->GetSize(&rc);
+ r_disp = (rc.bottom-rc.top)/CellHeight;
c_disp = (rc.right-rc.left)/CellWidth+1;
}
else return false;
- Disp->ShowGrid(CellWidth, CellHeight, FirstWidth);
+ Disp->ShowGrid(CellWidth, CellHeight, FirstWidth, &currpos);
+ pos_info.ssOrg.x = Disp->ssOrg.x; pos_info.ssOrg.y = Disp->ssOrg.y;
+ pos_info.CurrText = CurrText;
}
if(etRows)FlushData();
etRows = (EditText ***)calloc (cRows, sizeof(EditText **));
- if(etRows) for(i = 0, p1.x = FirstWidth, p1.y = CellHeight + w->MenuHeight; i < cRows; i++) {
+ if(etRows) for(i = 0; i < cRows; i++) {
etRows[i] = (EditText **)calloc(cCols, sizeof(EditText *));
- p2.y = p1.y + CellHeight;
if(etRows[i]) for(j = 0; j < cCols; j++) {
- p2.x = p1.x + CellWidth;
#ifdef _DEBUG
char text[20];
sprintf (text, "%.2f", i*10.0 + j);
- etRows[i][j] = new EditText(this, p1, p2, text);
+ etRows[i][j] = new EditText(this, text, i, j);
#else
- etRows[i][j] = new EditText(this, p1, p2, 0L);
+ etRows[i][j] = new EditText(this, 0L, i, j);
#endif
- if(etRows[i][j]) etRows[i][j]->Redraw(w, false);
- p1.x += CellWidth;
}
- p1.y += CellHeight;
- p1.x = FirstWidth;
}
if (LoadFile) {
strcpy(TmpTxt, LoadFile); //we will reenter by recursion !
free(LoadFile);
LoadFile = 0L;
Disp->Command(CMD_DROPFILE, TmpTxt, w);
- }
+ }
+ else DoPlot(w);
return true;
}
@@ -764,7 +830,7 @@ SpreadData::mpos2dpos(POINT *mp, POINT *dp)
Disp->Command(CMD_SETSCROLL, 0L, w);
mp->x += CellWidth;
}
- if(mp->y < (w->MenuHeight + CellHeight+10) && mp->y > (w->MenuHeight + CellHeight) && Disp->ssOrg.y >0) {
+ if(mp->y < (w->MenuHeight + CellHeight+9) && mp->y > (w->MenuHeight + CellHeight) && Disp->ssOrg.y >0) {
Disp->ssOrg.y -= 1;
if(CurrText) CurrText->Update(2, w, mp); CurrText = 0L;
Disp->Command(CMD_SETSCROLL, 0L, w);
@@ -789,13 +855,15 @@ SpreadData::mpos2dpos(POINT *mp, POINT *dp)
if(dp->y >= cRows) dp->y = cRows-1;
if(dp->x >= cCols) dp->x = cCols-1;
return true;
-}
-
+}
+
bool
SpreadData::Select(POINT *p)
{
if(CurrText && CurrText->isInRect(p)){
CurrText->Update(1, w, p);
+ Disp->Command(CMD_CURRPOS, &currpos, w);
+ if(CurrText->isFormula() && CurrText->hasMark()) et_racc = CurrText;
return true;
}
mpos2dpos(p, &currpos);
@@ -808,6 +876,7 @@ SpreadData::Select(POINT *p)
DoPlot(w);
CurrText->Update(1, w, p);
}
+ Disp->Command(CMD_CURRPOS, &currpos, w);
return true;
}
}
@@ -819,7 +888,7 @@ void
SpreadData::MarkRange(char *range)
{
AccRange *nr, *oldr;
- int r, c;
+ int r, c;
oldr = nr = 0L;
if(m_range && range && !strcmp(m_range, range)) return; //no change
@@ -836,12 +905,13 @@ SpreadData::MarkRange(char *range)
if(nr && nr->GetFirst(&c, &r)) {
for( ; nr->GetNext(&c, &r); ) {
if(r >= Disp->ssOrg.y && r < (r_disp +Disp->ssOrg.y) && c >= Disp->ssOrg.x
- && c < (c_disp + Disp->ssOrg.x))
+ && c < (c_disp + Disp->ssOrg.x) && r < cRows && c < cCols)
etRows[r][c]->Mark(w, etRows[r][c] != CurrText ? 2 : 3);
}
- }
- if (m_range) free(m_range); m_range = 0L;
- if(range) m_range = strdup(range);
+ }
+ if(range && (m_range = (char*)realloc(m_range, strlen(range)+6)))
+ strcpy(m_range, range);
+ else if (m_range) m_range[0] = 0;
if(oldr) delete(oldr); if(nr) delete(nr);
new_mark = true;
}
@@ -859,7 +929,7 @@ SpreadData::HideMark(bool cclp)
DoPlot(w);
}
if(cclp) EmptyClip();
- new_mark = bCopyCut = false;
+ new_mark = false;
}
bool
@@ -927,16 +997,16 @@ SpreadData::ReadData(char *FileName, unsigned char *buffer, int type)
bool success;
POINT pt;
- if(FileName) { //read disk file
+ if(FileName) { //read disk file
+ Disp->Command(CMD_CAN_DELETE, 0L, 0L);
if(0 == strcmp(".xml", FileName+strlen(FileName)-4) ||
0 == strcmp(".XML", FileName+strlen(FileName)-4) ||
0 == strcmp(".rlw", FileName+strlen(FileName)-4) ||
0 == strcmp(".RLW", FileName+strlen(FileName)-4) ||
IsXmlFile(FileName)){
- if(ReadXML(FileName, buffer, type)){
+ if(ReadXML(FileName, buffer, type, 0L)){
rcCopy.left = rcCopy.top = 0;
- rcCopy.right = cCols;
- rcCopy.bottom = cRows;
+ rcCopy.right = cCols; rcCopy.bottom = cRows;
return true;
}
return false;
@@ -945,8 +1015,7 @@ SpreadData::ReadData(char *FileName, unsigned char *buffer, int type)
0 == strcmp(".TSV", FileName+strlen(FileName)-4)){
if(ReadTSV(FileName, buffer, type)){
rcCopy.left = rcCopy.top = 0;
- rcCopy.right = cCols;
- rcCopy.bottom = cRows;
+ rcCopy.right = cCols; rcCopy.bottom = cRows;
return true;
}
return false;
@@ -965,7 +1034,7 @@ SpreadData::ReadData(char *FileName, unsigned char *buffer, int type)
case FF_TSV:
return ReadTSV(FileName, buffer, type);
case FF_XML:
- return ReadXML(FileName, buffer, type);
+ return ReadXML(FileName, buffer, type, 0L);
case FF_CSV:
if(!(Cache = new MemCache(buffer))) return false;
break;
@@ -1021,33 +1090,16 @@ SpreadData::AddCols(int nCols)
{
EditText **NewRow;
int i, j;
- POINT p1, p2;
- if (nCols <= cCols) return false;
- if(etRows && etRows[0] && etRows[0][cCols-1]) {
- p1.x = p2.x = (CellWidth + etRows[0][cCols-1]->GetX());
- p1.y = p2.y = etRows[0][cCols-1]->GetY();
- p2.x += CellWidth; p2.y += CellHeight;
- }
- else return false;
+ if (nCols <= cCols || !etRows || !etRows[0] || !etRows[0][cCols-1]) return false;
for(i = 0; i < cRows; i++) {
- NewRow = (EditText **)realloc(etRows[i], nCols * sizeof(EditText *));
- if(NewRow) {
+ if(NewRow = (EditText **)realloc(etRows[i], nCols * sizeof(EditText*))){
for(j = cCols; j < nCols; j++) {
- NewRow[j] = new EditText(this, p1, p2, NULL);
- p1.x += CellWidth; p2.x += CellWidth;
+ NewRow[j] = new EditText(this, 0L, i, j);
}
etRows[i] = NewRow;
}
- else { //memory allocation error
- cCols = nCols;
- //DEBUG: we should warn the user that not all cells are available
- // or even better we remove some columns up to i rows
- return false;
- }
- p1.x = p2.x = (CellWidth + etRows[0][cCols-1]->GetX());
- p2.x += CellWidth; p2.y += CellHeight;
- p1.y += CellHeight;
+ else return false; //memory allocation error
}
cCols = nCols;
return true;
@@ -1056,35 +1108,22 @@ SpreadData::AddCols(int nCols)
bool
SpreadData::AddRows(int nRows)
{
- int i, j, x;
- POINT p1, p2;
+ int i, j;
EditText ***NewRows;
- if (nRows <= cRows) return false;
- i = cRows-1;
- if(etRows && etRows[i] && etRows[i][0]) {
- x = p1.x = p2.x = etRows[i][0]->GetX(); p1.y = etRows[i][0]->GetY();
- p1.y += CellHeight; p2.y = p1.y + CellHeight;
- p2.x += CellWidth;
- }
- else return false;
+ if (nRows <= cRows || !etRows || !etRows[cRows-1] || !etRows[cRows-1][0] ) return false;
NewRows = (EditText ***)realloc(etRows, nRows * sizeof(EditText **));
if(NewRows) etRows = NewRows;
- else return false; //memory allocation error
+ else return false; //memory allocation error
for(i = cRows; i < nRows; i++){
etRows[i] = (EditText **)calloc(cCols, sizeof(EditText *));
if(etRows[i]) {
- for(j = 0; j < cCols; j++) {
- etRows[i][j] = new EditText(this, p1, p2, NULL);
- p1.x += CellWidth; p2.x += CellWidth;
- }
+ for(j = 0; j < cCols; j++) etRows[i][j] = new EditText(this, 0L, i, j);
}
else { //memory allocation error
cRows = i-1;
return false;
}
- p1.y += CellHeight; p2.y += CellHeight;
- p1.x = p2.x = x; p2.x += CellWidth;
}
cRows = nRows;
return true;
@@ -1097,7 +1136,7 @@ SpreadData::ChangeSize(int nCols, int nRows, bool bUndo)
bool RetVal = true;
if(nCols == cCols && nRows == cRows) return true;
- if(bUndo) Undo.DataObject(Disp, w, this, 0L);
+ if(bUndo) Undo.DataObject(Disp, w, this, 0L, 0L);
if(nRows && nRows < cRows) {
for (i = nRows; i < cRows; i++) {
if(etRows[i]) for (j = 0; j < cCols; j++) {
@@ -1126,11 +1165,305 @@ SpreadData::ChangeSize(int nCols, int nRows, bool bUndo)
if(i > FirstWidth) FirstWidth = i;
Disp->Command(CMD_SETSCROLL, 0L, w);
}
- rcCopy.left = rcCopy.right = 0;
- rcCopy.right = cCols;
- rcCopy.bottom = cRows;
return RetVal;
}
+
+bool
+SpreadData::DeleteCols()
+{
+ int i, j, r0, c0, c1, c2, cn, dc, nc;
+ RECT rc;
+ lfPOINT *cs;
+
+ AccRange * ar;
+ if(!isColMark || !m_range || !m_range[0]){
+ InfoBox("No columns selected!");
+ return false;
+ }
+ Undo.DataObject(Disp, w, this, 0L, 0L);
+ Undo.String(0L, &m_range, UNDO_CONTINUE);
+ if(!(ar = new AccRange(m_range))) return false;
+ ar->BoundRec(&rc);
+ if(!(cs = (lfPOINT*)malloc((rc.right-rc.left+2)*sizeof(lfPOINT)))) {
+ delete ar; return false;
+ }
+ if(!(ar->GetFirst(&c0, &r0))) {
+ free(cs); delete ar; return false;
+ }
+ ar->NextCol(&c1); cn = c1; nc = 0;
+ do {
+ for(c0 = c1 = c2 = cn; ar->NextCol(&c2); ) {
+ if(c2 > c1+1 || c2 < c0) break;
+ c1 = c2;
+ }
+ dc = c1-c0+1; cn = c2;
+ cs[nc].fx = c0; cs[nc].fy = c1; nc++;
+ }while(c2!=c1);
+ SortFpArray(nc, cs); nc--;
+ do {
+ c0 = (int)cs[nc].fx; c1 = (int)cs[nc].fy; dc = c1-c0+1;
+ for(i = 0; i < cRows; i++) {
+ for(j = c0+dc; j <cCols; j++) {
+ if(etRows && etRows[i] && etRows[i][j] && etRows[i][j-dc]) {
+ switch(etRows[i][j]->type) {
+ default:
+ etRows[i][j-dc]->SetText(etRows[i][j]->text);
+ break;
+ case ET_VALUE:
+ etRows[i][j-dc]->SetText(etRows[i][j]->text);
+ etRows[i][j-dc]->Value = etRows[i][j]->Value;
+ etRows[i][j-dc]->type = ET_VALUE;
+ break;
+ case ET_FORMULA:
+ MoveFormula(this, etRows[i][j]->text, TmpTxt, -dc, 0, -1, c0);
+ etRows[i][j-dc]->SetText(TmpTxt); etRows[i][j]->type = ET_FORMULA;
+ break;
+ }
+ }
+ }
+ }
+ for(i = 0; i < cRows; i++) {
+ if(etRows[i]){
+ for(j = cCols-dc; j < cCols; j++) if(etRows[i][j]) {
+ delete(etRows[i][j]);
+ etRows[i][j] = 0L;
+ }
+ }
+ }
+ cCols -= dc;
+ MoveFormula(this, m_range, TmpTxt, -dc, 0, -1, c0+1);
+ strcpy(m_range, TmpTxt); nc--;
+ for(i = 0; i < c0; i++) for(j = 0; j < c0; j++) {
+ if(etRows && etRows[i] && etRows[i][j] && etRows[i][j]->type == ET_FORMULA) {
+ MoveFormula(this, etRows[i][j]->text, TmpTxt, -dc, 0, -1, c0);
+ etRows[i][j]->SetText(TmpTxt); etRows[i][j]->type = ET_FORMULA;
+ }
+ }
+ }while(nc >= 0);
+ delete ar;
+ Disp->Command(CMD_SETSCROLL, 0L, w); Disp->Command(CMD_MRK_DIRTY, 0L, w);
+ return true;
+}
+
+bool
+SpreadData::InsertCols()
+{
+ int i, j, r0, c0, c1, c2, cn, dc, nc;
+ RECT rc;
+ lfPOINT *cs;
+
+ AccRange * ar;
+ if(!isColMark || !m_range || !m_range[0]){
+ InfoBox("No columns selected!");
+ return false;
+ }
+ Undo.DataObject(Disp, w, this, 0L, 0L);
+ Undo.String(0L, &m_range, UNDO_CONTINUE);
+ if(!(ar = new AccRange(m_range))) return false;
+ ar->BoundRec(&rc);
+ if(!(cs = (lfPOINT*)malloc((rc.right-rc.left+2)*sizeof(lfPOINT)))) {
+ delete ar; return false;
+ }
+ if(!(ar->GetFirst(&c0, &r0))) {
+ free(cs); delete ar; return false;
+ }
+ ar->NextCol(&c1); cn = c1; nc = 0;
+ do {
+ for(c0 = c1 = c2 = cn; ar->NextCol(&c2); ) {
+ if(c2 > c1+1 || c2 < c0) break;
+ c1 = c2;
+ }
+ dc = c1-c0+1; cn = c2;
+ cs[nc].fx = c0; cs[nc].fy = c1; nc++;
+ }while(c2!=c1);
+ SortFpArray(nc, cs); nc--;
+ do {
+ c0 = (int)cs[nc].fx; c1 = (int)cs[nc].fy; dc = c1-c0+1;
+ if(AddCols(cCols + dc)) for(i = 0; i < cRows; i++) {
+ for(j = cCols-1; j >= c0+dc; j--) {
+ if(etRows && etRows[i] && etRows[i][j] && etRows[i][j-dc]) {
+ switch(etRows[i][j-dc]->type) {
+ default:
+ etRows[i][j]->SetText(etRows[i][j-dc]->text);
+ break;
+ case ET_VALUE:
+ etRows[i][j]->SetText(etRows[i][j-dc]->text);
+ etRows[i][j]->Value = etRows[i][j-dc]->Value;
+ etRows[i][j]->type = ET_VALUE;
+ break;
+ case ET_FORMULA:
+ MoveFormula(this, etRows[i][j-dc]->text, TmpTxt, dc, 0, -1, c0);
+ etRows[i][j]->SetText(TmpTxt); etRows[i][j]->type = ET_FORMULA;
+ break;
+ }
+ etRows[i][j-dc]->SetText("");
+ }
+ }
+ }
+ MoveFormula(this, m_range, TmpTxt, dc, 0, -1, c0);
+ strcpy(m_range, TmpTxt); nc--;
+ for(i = 0; i < c0; i++) for(j = 0; j < c0; j++) {
+ if(etRows && etRows[i] && etRows[i][j] && etRows[i][j]->type == ET_FORMULA) {
+ MoveFormula(this, etRows[i][j]->text, TmpTxt, dc, 0, -1, c0);
+ etRows[i][j]->SetText(TmpTxt); etRows[i][j]->type = ET_FORMULA;
+ }
+ }
+ }while(nc >= 0);
+ delete ar;
+ Disp->Command(CMD_SETSCROLL, 0L, w); Disp->Command(CMD_MRK_DIRTY, 0L, w);
+ return true;
+}
+
+bool
+SpreadData::DeleteRows()
+{
+ int i, j, r0, c0, r1, r2, rn, dr, nr;
+ AccRange * ar;
+ RECT rc;
+ lfPOINT *rs;
+
+ if(!isRowMark || !m_range || !m_range[0]){
+ InfoBox("No rows selected!");
+ return false;
+ }
+ Undo.DataObject(Disp, w, this, 0L, 0L);
+ Undo.String(0L, &m_range, UNDO_CONTINUE);
+ if(!(ar = new AccRange(m_range))) return false;
+ ar->BoundRec(&rc);
+ if(!(rs = (lfPOINT*)malloc((rc.bottom-rc.top+2)*sizeof(lfPOINT)))) {
+ delete ar; return false;
+ }
+ if(!(ar->GetFirst(&c0, &r0))) {
+ free(rs); delete ar; return false;
+ }
+ ar->NextRow(&r1); rn = r1; nr = 0;
+ do {
+ for(r0 = r1 = r2 = rn;ar->NextRow(&r2); ) {
+ if(r2 > r1+1 || r2 < r0) break;
+ r1 = r2;
+ }
+ dr = r1-r0+1; rn = r2;
+ rs[nr].fx = r0; rs[nr].fy = r1; nr++;
+ }while(r2!=r1);
+ SortFpArray(nr, rs); nr--;
+ do {
+ r0 = (int)rs[nr].fx; r1 = (int)rs[nr].fy; dr = r1-r0+1;
+ for(i = r0+dr; i < cRows; i++) {
+ for(j = 0; j < cCols; j++) {
+ if(etRows && etRows[i-dr] && etRows[i-dr][j] && etRows[i] && etRows[i][j]) {
+ switch(etRows[i][j]->type) {
+ default:
+ etRows[i-dr][j]->SetText(etRows[i][j]->text);
+ break;
+ case ET_VALUE:
+ etRows[i-dr][j]->SetText(etRows[i][j]->text);
+ etRows[i-dr][j]->Value = etRows[i][j]->Value;
+ etRows[i-dr][j]->type = ET_VALUE;
+ break;
+ case ET_FORMULA:
+ MoveFormula(this, etRows[i][j]->text, TmpTxt, 0, -dr, r0, -1);
+ etRows[i-dr][j]->SetText(TmpTxt); etRows[i-dr][j]->type = ET_FORMULA;
+ break;
+ }
+ }
+ }
+ }
+ for(i = cRows-1; i >= cRows-dr; i--) {
+ if(etRows[i]){
+ for(j = 0; j < cCols; j++) if(etRows[i][j]) delete(etRows[i][j]);
+ free(etRows[i]);
+ }
+ }
+ cRows -= dr;
+ MoveFormula(this, m_range, TmpTxt, 0, -dr, r0+1, -1);
+ strcpy(m_range, TmpTxt); nr--;
+ for(i = 0; i < r0; i++) for(j = 0; j < cCols; j++) {
+ if(etRows && etRows[i] && etRows[i][j] && etRows[i][j]->type == ET_FORMULA) {
+ MoveFormula(this, etRows[i][j]->text, TmpTxt, 0, -dr, r0, -1);
+ etRows[i][j]->SetText(TmpTxt); etRows[i][j]->type = ET_FORMULA;
+ }
+ }
+ }while(nr >= 0);
+ delete ar;
+ if(w) {
+ Disp->Command(CMD_SETSCROLL, 0L, w); Disp->Command(CMD_MRK_DIRTY, 0L, w);
+ }
+ return true;
+}
+
+bool
+SpreadData::InsertRows()
+{
+ int i, j, r0, c0, r1, r2, rn, dr, nr;
+ AccRange * ar;
+ RECT rc;
+ lfPOINT *rs;
+
+ if(!isRowMark || !m_range || !m_range[0]){
+ InfoBox("No rows selected!");
+ return false;
+ }
+ Undo.DataObject(Disp, w, this, 0L, 0L);
+ Undo.String(0L, &m_range, UNDO_CONTINUE);
+ if(!(ar = new AccRange(m_range))) return false;
+ ar->BoundRec(&rc);
+ if(!(rs = (lfPOINT*)malloc((rc.bottom-rc.top+2)*sizeof(lfPOINT)))) {
+ delete ar; return false;
+ }
+ if(!(ar->GetFirst(&c0, &r0))) {
+ free(rs); delete ar; return false;
+ }
+ ar->NextRow(&r1); rn = r1; nr = 0;
+ do {
+ for(r0 = r1 = r2 = rn;ar->NextRow(&r2); ) {
+ if(r2 > r1+1 || r2 < r0) break;
+ r1 = r2;
+ }
+ dr = r1-r0+1; rn = r2;
+ rs[nr].fx = r0; rs[nr].fy = r1; nr++;
+ }while(r2!=r1);
+ SortFpArray(nr, rs); nr--;
+ do {
+ r0 = (int)rs[nr].fx; r1 = (int)rs[nr].fy; dr = r1-r0+1;
+ if(AddRows(cRows + dr)) for(i = cRows-1; i >= r0+dr; i--) {
+ for(j = 0; j < cCols; j++) {
+ if(etRows && etRows[i-dr] && etRows[i-dr][j] && etRows[i] && etRows[i][j]) {
+ switch(etRows[i-dr][j]->type) {
+ default:
+ etRows[i][j]->SetText(etRows[i-dr][j]->text);
+ break;
+ case ET_VALUE:
+ etRows[i][j]->SetText(etRows[i-dr][j]->text);
+ etRows[i][j]->Value = etRows[i-dr][j]->Value;
+ etRows[i][j]->type = ET_VALUE;
+ break;
+ case ET_FORMULA:
+ MoveFormula(this, etRows[i-dr][j]->text, TmpTxt, 0, dr, r0, -1);
+ etRows[i][j]->SetText(TmpTxt); etRows[i][j]->type = ET_FORMULA;
+ break;
+ }
+ etRows[i-dr][j]->SetText("");
+ }
+ }
+ }
+ MoveFormula(this, m_range, TmpTxt, 0, dr, r0, -1);
+ strcpy(m_range, TmpTxt); nr--;
+ for(i = 0; i < r0; i++) for(j = 0; j < cCols; j++) {
+ if(etRows && etRows[i] && etRows[i][j] && etRows[i][j]->type == ET_FORMULA) {
+ MoveFormula(this, etRows[i][j]->text, TmpTxt, 0, dr, r0, -1);
+ etRows[i][j]->SetText(TmpTxt); etRows[i][j]->type = ET_FORMULA;
+ }
+ }
+ }while(nr >= 0);
+ delete ar;
+ if(w) {
+ sprintf(TmpTxt, "%d00", cRows);
+ w->oGetTextExtent(TmpTxt, 0, &i, &j);
+ if(i > FirstWidth) FirstWidth = i;
+ Disp->Command(CMD_SETSCROLL, 0L, w); Disp->Command(CMD_MRK_DIRTY, 0L, w);
+ }
+ return true;
+}
void
SpreadData::DoPlot(anyOutput *o)
@@ -1140,34 +1473,51 @@ SpreadData::DoPlot(anyOutput *o)
AccRange *ar;
if(!w || !Disp) return;
- w->Erase(0x00d8d8d8L); w->ActualSize(&rc);
- r_disp = (rc.bottom-rc.top)/CellHeight+1;
+ w->Erase(0x00e8e8e8L); w->ActualSize(&rc);
+ w->SetTextSpec(&ssText); et_racc = 0L;
+ r_disp = (rc.bottom-rc.top)/CellHeight;
c_disp = (rc.right-rc.left)/CellWidth+1;
- Disp->ShowGrid(CellWidth, CellHeight, FirstWidth);
+ Disp->ShowGrid(CellWidth, CellHeight, FirstWidth, &currpos);
rc.top = w->MenuHeight; rc.bottom = rc.top + CellHeight;
- for(i = 0; i < (cRows - Disp->ssOrg.y) && i < r_disp; i++) {
+ for(i = 0; i <= (cRows - Disp->ssOrg.y) && i <= r_disp; i++) {
rc.left = FirstWidth; rc.right = rc.left + CellWidth;
rc.top += CellHeight; rc.bottom += CellHeight;
- for(j = 0; j< (cCols - Disp->ssOrg.x) && j < cCols; j++) {
+ for(j = 0; j <= (cCols - Disp->ssOrg.x) && j <= c_disp; j++) {
r = i + Disp->ssOrg.y; c = j + Disp->ssOrg.x;
if(r < cRows && r >= 0 && c < cCols && c >=0 && etRows[r][c]){
- etRows[r][c]->SetRec(&rc); etRows[r][c]->Redraw(w, false);
+ etRows[r][c]->SetRec(&rc); etRows[r][c]->Update(2, 0L, 0L);
+ etRows[r][c]->Redraw(w, false);
}
rc.left += CellWidth; rc.right += CellWidth;
- }
+ }
}
+ if(bUpdate) {
+ for(i = 0; i <= (cRows - Disp->ssOrg.y) && i <= r_disp; i++) {
+ for(j = 0; j <= (cCols - Disp->ssOrg.x) && j <= c_disp; j++) {
+ r = i + Disp->ssOrg.y; c = j + Disp->ssOrg.x;
+ if(r < cRows && r >= 0 && c < cCols && c >=0 && etRows[r][c]){
+ etRows[r][c]->Redraw(w, false);
+ }
+ }
+ }
+ }
+ if(CurrText && CurrText->row >= Disp->ssOrg.y && CurrText->row < (Disp->ssOrg.y + r_disp)
+ && CurrText->col >= Disp->ssOrg.x && CurrText->col < (Disp->ssOrg.x +c_disp))
+ CurrText->Update(1, w, 0L);
+ bUpdate = false;
if(m_range && (ar = new AccRange(m_range)) && ar->GetFirst(&c, &r)) {
for( ; ar->GetNext(&c, &r); ) {
- if(r >= Disp->ssOrg.y && r < (r_disp + Disp->ssOrg.y) && c >= Disp->ssOrg.x
+ if(r >= Disp->ssOrg.y && r < (r_disp + Disp->ssOrg.y) && c >= Disp->ssOrg.x
+ && r < cRows && c < cCols
&& c < (c_disp + Disp->ssOrg.x) && etRows[r] && etRows[r][c])
etRows[r][c]->Mark(w, etRows[r][c] != CurrText ? 2 : 3);
}
delete (ar);
- }
+ }
if(c_range) InitCopy(0, 0L, w); //move animated rectangle
- w->ActualSize(&rc); w->UpdateRect(&rc, false);
- if(err_msg) {
- ErrorBox(err_msg); err_msg = 0L;
+ w->ActualSize(&rc); rc.bottom += CellHeight; w->UpdateRect(&rc, false);
+ if(err_msg && (!last_err || strcmp(err_msg,last_err))) {
+ ErrorBox(last_err = err_msg);
}
}
@@ -1175,24 +1525,22 @@ bool
SpreadData::DelRange()
{
AccRange *ar;
- int r, c;
-
- if(m_range && (ar = new AccRange(m_range)) && ar->GetFirst(&c, &r)) {
- Undo.DataObject(Disp, w, this, 0L);
- for( ; ar->GetNext(&c, &r); ) {
- if(r < cRows && c < cCols){
- if(CurrText && r == currpos.y && c == currpos.x) {
- CurrText->Update(2, 0L, 0L);
- CurrText = 0L;
- }
- if(etRows[r][c] && etRows[r][c]->text){
- etRows[r][c]->SetText("");
- }
+ int r, c;
+ RECT rec;
+
+ if(m_range && (ar = new AccRange(m_range)) && ar->GetFirst(&c, &r)) {
+ ar->BoundRec(&rec);
+ Undo.DataObject(Disp, w, this, &rec, 0L);
+ while(ar->GetNext(&c, &r)) {
+ if(r >= 0 && r < cRows && c >= 0 && c < cCols){
+ if(etRows[r][c] && etRows[r][c]->text) etRows[r][c]->SetText("");
}
}
delete (ar); HideTextCursor();
- }
+ }
HideMark(false);
+ if(CurrText) CurrText->Update(1, w, 0L);
+ bCopyCut = false;
return true;
}
@@ -1200,17 +1548,18 @@ bool
SpreadData::PasteRange(int cmd, char *txt)
{
AccRange *cr;
- int r, c;
+ int i, r, c;
RECT mrk_range;
if(new_mark && m_range && (cr = new AccRange(m_range)) && cr->GetFirst(&c, &r)) {
cr->BoundRec(&mrk_range);
- for( ; cr->GetNext(&c, &r); ) if(c >= 0 && c < cCols && r >= 0 && r < cRows){
+ for(i = 0 ; cr->GetNext(&c, &r); i++) if(c >= 0 && c < cCols && r >= 0 && r < cRows){
currpos.x = c; currpos.y = r;
switch(cmd){
- case CMD_PASTE_TSV: ReadTSV(0L, (unsigned char*)txt, FF_TSV); break;
- case CMD_PASTE_XML: ReadXML(0L, (unsigned char*)txt, FF_XML); break;
- case CMD_PASTE_CSV: ReadData(0L, (unsigned char*)txt, FF_CSV); break;
+ case CMD_PASTE_TSV: ReadTSV(0L, (unsigned char*)txt, FF_TSV); break;
+ case CMD_PASTE_SSV: ReadTSV(0L, (unsigned char*)txt, FF_SSV); break;
+ case CMD_PASTE_XML: ReadXML(0L, (unsigned char*)txt, FF_XML, i ? UNDO_CONTINUE : 0L); break;
+ case CMD_PASTE_CSV: ReadData(0L, (unsigned char*)txt, FF_CSV); break;
}
if((mrk_range.right - mrk_range.left) == (cp_src_rec.right - cp_src_rec.left) &&
(mrk_range.bottom - mrk_range.top) == (cp_src_rec.bottom - cp_src_rec.top)) break;
@@ -1222,12 +1571,14 @@ SpreadData::PasteRange(int cmd, char *txt)
else switch(cmd){
case CMD_PASTE_TSV:
return ReadTSV(0L, (unsigned char*)txt, FF_TSV);
+ case CMD_PASTE_SSV:
+ return ReadTSV(0L, (unsigned char*)txt, FF_SSV);
case CMD_PASTE_XML:
- return ReadXML(0L, (unsigned char*)txt, FF_XML);
+ return ReadXML(0L, (unsigned char*)txt, FF_XML, 0L);
case CMD_PASTE_CSV:
return ReadData(0L, (unsigned char*)txt, FF_CSV);
}
- return false;
+ return bCopyCut = false;
}
bool
@@ -1241,7 +1592,7 @@ SpreadData::InitCopy(int cmd, void *tmpl, anyOutput *o)
if(cmd) {
bCopyCut = (cmd == CMD_CUT);
if(rcCopy.right > cCols) rcCopy.right = cCols;
- if(rcCopy.bottom > cRows) rcCopy.bottom = cRows;
+ if(rcCopy.bottom > cRows) rcCopy.bottom = cRows;
new_mark = false;
if(m_range && m_range[0]) {
if(c_range) free(c_range); c_range = strdup(m_range);
@@ -1249,13 +1600,16 @@ SpreadData::InitCopy(int cmd, void *tmpl, anyOutput *o)
ar->BoundRec(&rcCopy);
delete ar; bRet = true;;
}
- }
- else if(GetCopyRange(&rcCopy, this)){
- //The range is stored in TmpTxt
- if(!TmpTxt[0]) return false;
- if(m_range) free(m_range); if(c_range) free(c_range);
- c_range = strdup(TmpTxt); m_range = strdup(TmpTxt);
- DoPlot(o); bRet = true;
+ }
+ else if (CurrText) {
+ if(CurrText->hasMark()) return CurrText->Command(CMD_COPY, o, 0L);
+ else {
+ if(m_range) free(m_range); m_range=0L;
+ sprintf(TmpTxt, "%s%d:%s%d", Int2ColLabel(currpos.x, false), currpos.y+1,
+ Int2ColLabel(currpos.x, false), currpos.y+1);
+ m_range = strdup(TmpTxt); DoPlot(o);
+ return InitCopy(cmd, tmpl, o);
+ }
}
}
if(bRet || !cmd) { //calculate animated mark
@@ -1271,14 +1625,38 @@ SpreadData::InitCopy(int cmd, void *tmpl, anyOutput *o)
}
else return bRet;
c = rcCopy.right < (Disp->ssOrg.x + c_disp) ? rcCopy.right : Disp->ssOrg.x + c_disp;
- r = rcCopy.bottom < (Disp->ssOrg.y + r_disp)? rcCopy.bottom : Disp->ssOrg.y + r_disp;
+ r = rcCopy.bottom < (Disp->ssOrg.y + r_disp)? rcCopy.bottom : Disp->ssOrg.y + r_disp;
+ if(r >= cRows) r = cRows-1; if(c >= cCols) c = cRows -1;
if(etRows[r][c]){
rc_band.right = etRows[r][c]->GetX()+CellWidth;
- rc_band.bottom = etRows[r][c]->GetY()+CellHeight;
+ rc_band.bottom = etRows[r][c]->GetY()+CellHeight;
+ if(rc_band.left >= rc_band.right) rc_band.right = rc_band.left + CellWidth;
+ if(rc_band.top >= rc_band.bottom) rc_band.bottom = rc_band.top + CellHeight;
ShowCopyMark(o, &rc_band, 1);
}
}
return bRet;
+}
+
+bool
+SpreadData::SavePos()
+{
+ bool bRet = false;
+
+ if(pos_info.currpos.x != currpos.x || pos_info.currpos.y != pos_info.currpos.y
+ || CurrText != pos_info.CurrText) {
+ Undo.Point(Disp, &currpos, w, UNDO_CONTINUE);
+ Undo.VoidPtr(Disp, (void**)&CurrText, 0L, 0L, UNDO_CONTINUE);
+ }
+ if(pos_info.ssOrg.x != Disp->ssOrg.x || pos_info.ssOrg.y != Disp->ssOrg.y) {
+ Swap(pos_info.ssOrg.x, Disp->ssOrg.x ); Swap(pos_info.ssOrg.y, Disp->ssOrg.y );
+ Undo.Point(Disp, &Disp->ssOrg, w, UNDO_CONTINUE);
+ Swap(pos_info.ssOrg.x, Disp->ssOrg.x ); Swap(pos_info.ssOrg.y, Disp->ssOrg.y );
+ }
+ pos_info.currpos.x = currpos.x; pos_info.currpos.y = currpos.y;
+ pos_info.ssOrg.x = Disp->ssOrg.x; pos_info.ssOrg.y = Disp->ssOrg.y;
+ pos_info.CurrText = CurrText;
+ return bRet;
}
bool
@@ -1297,11 +1675,13 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
if((mev->StateFlags & 1) || mev->Action == MOUSE_LBUP) {
mpos2dpos(&p, &cp);
if(cp.y >= cRows || cp.x >= cCols || cp.y < 0 || cp.x < 0) return false;
- }
+ }
switch (mev->Action) {
- case MOUSE_LBDOWN:
- bActive = true;
- if(CurrText && !CurrText->isInRect(&p)){
+ case MOUSE_LBDOWN:
+ if(m_range && (mev->StateFlags & 0x08)) mrk_offs = strlen(m_range);
+ else mrk_offs = 0;
+ bActive = true; new_mark = false;
+ if(!et_racc && CurrText && !CurrText->isInRect(&p)){
CurrText->Update(2, w, &p); CurrText = 0L;
DoPlot(w);
}
@@ -1316,20 +1696,20 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
if(mev->Action == MOUSE_MOVE && (mev->StateFlags & 1)
&& !(CurrText && CurrText->isInRect(&p))) {
//mark rectangular range
- if(!m_range && CurrText) {
+ if(!et_racc && !m_range && CurrText) {
CurrText->Update(2, w, &p); CurrText = 0L;
}
- if(p.x < FirstWidth || p.y < (w->MenuHeight+CellHeight)) {
- i = sprintf(TmpTxt, "%s%d:", Int2ColLabel(p.x < FirstWidth ? 0 : currpos.x, false),
+ if(p.x < FirstWidth || p.y < (w->MenuHeight+CellHeight)) {
+ i = sprintf(TmpTxt+mrk_offs, "%s%s%d:", mrk_offs? ";" : "", Int2ColLabel(p.x < FirstWidth ? 0 : currpos.x, false),
p.y < (w->MenuHeight+CellHeight) ? 0 : currpos.y+1);
- sprintf(TmpTxt+i, "%s%d", Int2ColLabel(p.x < FirstWidth ? cCols-1 : cp.x, false),
+ sprintf(TmpTxt+mrk_offs+i, "%s%d", Int2ColLabel(p.x < FirstWidth ? cCols-1 : cp.x, false),
p.y < (w->MenuHeight+CellHeight) ? cRows : cp.y+1);
}
else {
- i = sprintf(TmpTxt, "%s%d:", Int2ColLabel(currpos.x, false), currpos.y+1);
- sprintf(TmpTxt+i, "%s%d", Int2ColLabel(cp.x, false), cp.y+1);
+ i = sprintf(TmpTxt+mrk_offs, "%s%s%d:", mrk_offs? ";" : "", Int2ColLabel(currpos.x, false), currpos.y+1);
+ sprintf(TmpTxt+mrk_offs+i, "%s%d", Int2ColLabel(cp.x, false), cp.y+1);
}
- if(!CurrText)MarkRange(TmpTxt);
+ if(!CurrText || et_racc)MarkRange(TmpTxt);
return true;
}
if(mev->Action == MOUSE_LBDOUBLECLICK) bActive = false;
@@ -1341,31 +1721,51 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
return etRows[cp.y][cp.x]->Command(CMD_MOUSE_EVENT, o, (DataObj *)mev);
return false;
case MOUSE_LBUP:
- if(bActive){
- if(p.x < FirstWidth || p.y < (w->MenuHeight+CellHeight)) {
+ if(bActive){
+ isRowMark = p.x < FirstWidth;
+ isColMark = p.y < (w->MenuHeight+CellHeight);
+ if(isRowMark || isColMark) {
if(p.x < FirstWidth) {
currpos.x = 0; cp.x = cCols-1;
}
if(p.y < (w->MenuHeight+CellHeight)) {
currpos.y = 0; cp.y = cRows-1;
}
- i = sprintf(TmpTxt, "%s%d:", Int2ColLabel(currpos.x, false), currpos.y+1);
- sprintf(TmpTxt+i, "%s%d", Int2ColLabel(cp.x, false), cp.y+1);
+ i = sprintf(TmpTxt+mrk_offs, "%s%s%d:", mrk_offs? ";" : "", Int2ColLabel(currpos.x, false), currpos.y+1);
+ sprintf(TmpTxt+mrk_offs+i, "%s%d", Int2ColLabel(cp.x, false), cp.y+1);
MarkRange(TmpTxt);
currpos2.x = cp.x; currpos2.y = cp.y + 1;
+ }
+ else if((m_range) && !new_mark) HideMark(false);
+ if(et_racc) {
+ CurrText = et_racc;
+ if(m_range && m_range[0]) {
+ CurrText->Command(CMD_ADDTXT, o, (DataObj*) m_range);
+ }
+ else if(!m_range) {
+ m_range = (char*)malloc(10);
+ sprintf(m_range, "%s%d%", Int2ColLabel(currpos.x, false), currpos.y+1);
+ CurrText->Command(CMD_ADDTXT, o, (DataObj*) m_range);
+ free(m_range); m_range = 0L;
+ }
}
- if(m_range) {
+ else if(m_range) {
CurrText = etRows[currpos.y][currpos.x]; CurrText->Update(1, w, &p);
DoPlot(w);
- currpos2.x = cp.x; currpos2.y = cp.y;
+ currpos2.x = cp.x; currpos2.y = cp.y;
}
else return Select(&p);
}
}
break;
- case CMD_PASTE_TSV: case CMD_PASTE_XML: case CMD_PASTE_CSV:
- if(PasteRange(cmd, (char*)tmpl)) return Disp->Command(CMD_SETSCROLL, 0L, w);
+ case CMD_PASTE_TSV: case CMD_PASTE_XML: case CMD_PASTE_CSV: case CMD_PASTE_SSV:
+ if(PasteRange(cmd, (char*)tmpl))
+ return Disp->Command(CMD_SETSCROLL, 0L, w);
return false;
+ case CMD_ETRACC:
+ et_racc = (EditText*) tmpl;
+ if(CurrText && CurrText->parent != this) CurrText = 0L;
+ return true;
case CMD_CURRPOS:
if(tmpl) {
if(((POINT*)tmpl)->x < 0 && ((POINT*)tmpl)->y < 0) {
@@ -1380,41 +1780,51 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
break;
case CMD_ERROR:
err_msg = (char*)tmpl;
- break;
+ break;
+ case CMD_UPDATE:
+ bUpdate = true;
+ break;
+ case CMD_SAVEPOS:
+ return SavePos();
case CMD_CLEAR_ERROR:
- err_msg = 0L;
+ err_msg = last_err = 0L;
break;
- case CMD_TOOLMODE:
+ case CMD_TOOLMODE: //ESC pressed
HideMark(true);
- if(CurrText) CurrText->Update(2, w, 0L);
- if(CurrText) CurrText->Update(1, w, 0L);
+ if(CurrText){
+ CurrText->Update(2, w, 0L); CurrText->Update(1, w, 0L);
+ }
+ et_racc = 0L;
break;
case CMD_UPDHISTORY:
if(w) w->FileHistory();
break;
case CMD_MRK_DIRTY:
+ move_cr = CMD_CURRDOWN;
+ last_err = 0L;
if(Disp) return Disp->Command(cmd, tmpl, o);
return false;
- case CMD_ADDCHAR:
+ case CMD_ADDCHAR:
if(CurrText){
if(currpos.y < Disp->ssOrg.y) {
- Disp->ssOrg.y = currpos.y; DoPlot(o);
+ Disp->ssOrg.y = currpos.y; Disp->Command(CMD_SETSCROLL, 0L, w);
}
else if(currpos.y > (Disp->ssOrg.y + r_disp -3)) {
Disp->ssOrg.y = currpos.y - (r_disp-3);
- if(Disp->ssOrg.y < 0) Disp->ssOrg.y = 0; DoPlot(o);
+ if(Disp->ssOrg.y < 0) Disp->ssOrg.y = 0; Disp->Command(CMD_SETSCROLL, 0L, w);
}
if(currpos.x < Disp->ssOrg.x) {
- Disp->ssOrg.x = currpos.x; DoPlot(o);
+ Disp->ssOrg.x = currpos.x; Disp->Command(CMD_SETSCROLL, 0L, w);
}
else if(currpos.x > (Disp->ssOrg.x + c_disp -3)) {
Disp->ssOrg.x = currpos.x - (c_disp-3);
- if(Disp->ssOrg.x < 0) Disp->ssOrg.x = 0; DoPlot(o);
+ if(Disp->ssOrg.x < 0) Disp->ssOrg.x = 0; Disp->Command(CMD_SETSCROLL, 0L, w);
}
currpos2.x = currpos.x; currpos2.y = currpos.y;
i = *((int*)tmpl);
+ Disp->Command(CMD_CURRPOS, &currpos, w);
if(i == 27) return Command(CMD_TOOLMODE, tmpl, o);
- if(i !=3 && i != 22 && i != 24) HideMark(true); //Do not hide upon ^C, ^V, ^X
+ if(i !=3 && i != 22 && i != 24 && i != 26) HideMark(true); //Do not hide upon ^C, ^V, ^X, ^Z
if(i == 13) return CurrText->Command(move_cr, w, this);
switch(i) {
case 8: return CurrText->Command(CMD_BACKSP, w, this); //Backspace
@@ -1425,27 +1835,64 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
currpos.x = currpos2.x = Disp->ssOrg.x; currpos.y = currpos2.y = Disp->ssOrg.y;
if(etRows[currpos.x] && (CurrText = etRows[currpos.x][currpos.y]))
CurrText->Update(1, w, &p);;
- }
+ }
+ Disp->Command(CMD_CURRPOS, &currpos, w);
break;
case CMD_SHIFTUP:
+ if(Disp->ssOrg.y && currpos2.y <= Disp->ssOrg.y) {
+ Disp->ssOrg.y --; Disp->Command(CMD_SETSCROLL, 0L, w);
+ }
currpos2.y -= 2;
case CMD_SHIFTDOWN:
+ if(cmd == CMD_SHIFTDOWN && r_disp > 3 && (currpos2.y-Disp->ssOrg.y) >= (r_disp-3)) {
+ Disp->ssOrg.y ++; Disp->Command(CMD_SETSCROLL, 0L, w);
+ }
currpos2.y ++;
if(currpos2.y >= cRows) currpos2.y --; if(currpos2.y < 0) currpos2.y ++;
//mark rectangular range
i = sprintf(TmpTxt, "%s%d:", Int2ColLabel(currpos.x, false), currpos.y+1);
sprintf(TmpTxt+i, "%s%d", Int2ColLabel(currpos2.x, false), currpos2.y+1);
- MarkRange(TmpTxt);
+ MarkRange(TmpTxt); HideTextCursor();
break;
case CMD_SHIFTRIGHT: case CMD_SHIFTLEFT:
if(!m_range && CurrText && CurrText->Command(cmd, w, this)) break;
+ if(cmd == CMD_SHIFTLEFT && c_disp > 3 && Disp->ssOrg.x && (currpos2.x-Disp->ssOrg.x) < 1) {
+ Disp->ssOrg.x --; Disp->Command(CMD_SETSCROLL, 0L, w);
+ }
+ if(cmd == CMD_SHIFTRIGHT && c_disp > 3 && (currpos2.x-Disp->ssOrg.x) >= (c_disp-3)) {
+ Disp->ssOrg.x ++; Disp->Command(CMD_SETSCROLL, 0L, w);
+ }
if(cmd == CMD_SHIFTLEFT) currpos2.x --;
else currpos2.x ++;
if(currpos2.x >= cCols) currpos2.x --; if(currpos2.x < 0) currpos2.x ++;
//mark rectangular range
i = sprintf(TmpTxt, "%s%d:", Int2ColLabel(currpos.x, false), currpos.y+1);
sprintf(TmpTxt+i, "%s%d", Int2ColLabel(currpos2.x, false), currpos2.y+1);
- MarkRange(TmpTxt);
+ MarkRange(TmpTxt); HideTextCursor();
+ break;
+ case CMD_SHPGUP:
+ if(Disp->ssOrg.y >0) {
+ Disp->ssOrg.y -= (r_disp-2);
+ if(Disp->ssOrg.y < 0) Disp->ssOrg.y = 0;
+ Disp->Command(CMD_SETSCROLL, 0L, w);
+ currpos2.y -= r_disp; if(currpos2.y < 0) currpos2.y = 0;
+ i = sprintf(TmpTxt, "%s%d:", Int2ColLabel(currpos.x, false), currpos.y+1);
+ sprintf(TmpTxt+i, "%s%d", Int2ColLabel(currpos2.x, false), currpos2.y+1);
+ MarkRange(TmpTxt); HideTextCursor();
+ }
+ break;
+ case CMD_SHPGDOWN:
+ i = (Disp->ssOrg.y + 2*r_disp) < cRows ? r_disp-2 : cRows-r_disp - Disp->ssOrg.y+3;
+ if(i > 0) {
+ Disp->ssOrg.y += i; Disp->Command(CMD_SETSCROLL, 0L, w);
+ }
+ if(currpos2.y < (cRows-1)) {
+ currpos2.y += r_disp; if(currpos2.y >= cRows) currpos2.y = cRows-1;
+ //mark rectangular range
+ i = sprintf(TmpTxt, "%s%d:", Int2ColLabel(currpos.x, false), currpos.y+1);
+ sprintf(TmpTxt+i, "%s%d", Int2ColLabel(currpos2.x, false), currpos2.y+1);
+ MarkRange(TmpTxt); HideTextCursor();
+ }
break;
case CMD_CURRIGHT: case CMD_CURRDOWN:
move_cr = cmd;
@@ -1457,6 +1904,7 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
if(cmd == CMD_CURRLEFT && Disp->ssOrg.x && CurrText && (!CurrText->Cursor()) && (currpos.x == Disp->ssOrg.x)) {
Disp->ssOrg.x --; currpos.x --;
CurrText->Update(2, o, 0L);
+ Disp->Command(CMD_CURRPOS, &currpos, w);
if(etRows && etRows[currpos.y] && etRows[currpos.y][currpos.x])
CurrText = etRows[currpos.y][currpos.x];
if(CurrText){
@@ -1471,8 +1919,9 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
if(cmd == CMD_CURRDOWN && r_disp > 3 && (currpos.y-Disp->ssOrg.y) >= (r_disp-3)) {
Disp->ssOrg.y ++; currpos.y ++; DoPlot(o);
}
- if(err_msg) ErrorBox(err_msg); err_msg = 0L;
+ Disp->Command(CMD_CURRPOS, &currpos, w);
HideMark(false);
+ currpos2.x = currpos.x; currpos2.y = currpos.y;
if(CurrText)return CurrText->Command(cmd, w, this);
else {
currpos.x = currpos2.x = Disp->ssOrg.x; currpos.y = currpos2.y = Disp->ssOrg.y;
@@ -1504,10 +1953,23 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
CurrText->Update(1, w, &p);
CurrText->Command(cmd == CMD_TAB ? CMD_POS_FIRST : CMD_POS_LAST, o, this);
}
+ Disp->Command(CMD_CURRPOS, &currpos, w);
return true;
+ case CMD_UNDO:
+ if(w) {
+ w->MouseCursor(MC_WAIT, true);
+ Undo.Restore(true, w);
+ w->MouseCursor(MC_ARROW, true);
+ if(et_racc) {
+ CurrText = et_racc;
+ CurrText->Update(1, w, 0L);
+ }
+ }
+ return true;
case CMD_DELETE:
if(m_range) DelRange();
else if(CurrText) return CurrText->Command(cmd, o, this);
+ Disp->Command(CMD_CURRPOS, &currpos, w);
return true;
case CMD_QUERY_COPY: case CMD_CUT:
return InitCopy(cmd, tmpl, w);
@@ -1522,39 +1984,50 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
FirstWidth = ((int*)tmpl)[0]; CellWidth = ((int*)tmpl)[1];
CellHeight = ((int*)tmpl)[2];
}
- break;
+ break;
case CMD_TEXTSIZE:
- if(tmpl){
- CellHeight = *((int*)tmpl);
- return Disp->Command(cmd, tmpl, o);
- }
+ if(tmpl) return Disp->Command(cmd, tmpl, o);
return false;
case CMD_COPY_TSV:
return MemList((unsigned char**)tmpl, FF_TSV);
case CMD_COPY_SYLK:
return MemList((unsigned char**)tmpl, FF_SYLK);
case CMD_COPY_XML:
- return MemList((unsigned char**)tmpl, FF_XML);
- case CMD_REDRAW: case CMD_DOPLOT:
+ return MemList((unsigned char**)tmpl, FF_XML);
+ case CMD_DOPLOT: case CMD_REDRAW:
+ if(CurrText) CurrText->Update(2, 0L, 0L);
+ if(etRows && etRows[currpos.y] && currpos.y < cRows && currpos.x < cCols)
+ if(CurrText = etRows[currpos.y][currpos.x]) CurrText->Update(1,0L, 0L);
DoPlot(o);
break;
- case CMD_FILLRANGE:
- FillSsRange(this, &m_range);
+ case CMD_FILLRANGE:
+ Undo.SetDisp(w);
+ FillSsRange(this, &m_range, Disp);
DoPlot(o);
- break;
+ Undo.SetDisp(w);
+ break;
+ case CMD_INSROW:
+ return InsertRows();
+ case CMD_INSCOL:
+ return InsertCols();
+ case CMD_DELROW:
+ return DeleteRows();
+ case CMD_DELCOL:
+ return DeleteCols();
}
return true;
}
bool
-SpreadData::ReadXML(char *file, unsigned char *buffer, int type)
+SpreadData::ReadXML(char *file, unsigned char *buffer, int type, DWORD undo_flags)
{
- int i, row, col, tag, cpgr, spgr;
- bool bContinue, bRet = false;
+ int i, row, col, tag, cpgr, spgr, ufl = 0;
+ bool bContinue, bRet = false, bUndo_done = false;
ReadCache *XMLcache;
POINT pt, mov;
char TmpTxt[1024], *tmp_range;
- unsigned char *pgr = 0L;
+ unsigned char *pgr = 0L;
+ RECT rc_undo;
if(file) {
if(!(XMLcache = new ReadCache())) return false;
@@ -1563,7 +2036,8 @@ SpreadData::ReadXML(char *file, unsigned char *buffer, int type)
sprintf(TmpTxt, "Error open file\n\"%s\"", file);
ErrorBox(TmpTxt);
return false;
- }
+ }
+ bUndo_done = true;
if(!Init(1, 1)) goto XMLError;
etRows[0][0]->SetText("");
}
@@ -1585,9 +2059,37 @@ SpreadData::ReadXML(char *file, unsigned char *buffer, int type)
}while(TmpTxt[0] && TmpTxt[0] != '<');
for(i = 1; i < 5; TmpTxt[i++] = XMLcache->Getc());
TmpTxt[i] = 0;
- if(!strcmp("<cell", TmpTxt)) tag = 1;
+ if(!strcmp("<cell", TmpTxt)){
+ if(!bUndo_done) {
+ rc_undo.left = currpos.x;
+ rc_undo.right = cp_src_rec.right - cp_src_rec.left + currpos.x;
+ rc_undo.top = currpos.y;
+ rc_undo.bottom = cp_src_rec.bottom - cp_src_rec.top + currpos.y;
+ if(ufl == 3) Undo.DataObject(Disp, w, this, &rc_undo, undo_flags);
+ bUndo_done = true;
+ }
+ tag = 1;
+ }
else if(!strcmp("<pos1", TmpTxt)) tag = 2;
- else if(!strcmp("<pos2", TmpTxt)) tag = 3;
+ else if(!strcmp("<pos2", TmpTxt)) tag = 3;
+ else if(!strcmp("<RLPl", TmpTxt)) {
+ do {
+ TmpTxt[i++] = XMLcache->Getc();
+ }while(TmpTxt[i-1] > 31 && TmpTxt[i-1] != '>');
+ TmpTxt[i] = 0;
+ row = col = 0;
+ if(TmpTxt[17] = '=' && TmpTxt[13] == 'r') {
+ strcpy(TmpTxt, TmpTxt+19);
+ }
+ else break;
+ sscanf(TmpTxt, "%d", &row);
+ for(i = 0; TmpTxt[i] && TmpTxt[i] != '='; i++);
+ sscanf(TmpTxt+i+2, "%d", &col);
+ if(row && col) {
+ AddCols(col); AddRows(row);
+ }
+ row = col = -1;
+ }
else if(!strcmp("<Grap", TmpTxt)){
while(XMLcache->Getc() != '[');
pgr = (unsigned char*)malloc(spgr = 1000);
@@ -1619,10 +2121,12 @@ SpreadData::ReadXML(char *file, unsigned char *buffer, int type)
}
if(tag ==2) {
mov.x = col; mov.y = row;
- cp_src_rec.left = col; cp_src_rec.top = row;
+ cp_src_rec.left = col; cp_src_rec.top = row;
+ ufl |= 1;
}
else if(tag ==3) {
- cp_src_rec.right = col; cp_src_rec.bottom = row;
+ cp_src_rec.right = col; cp_src_rec.bottom = row;
+ ufl |= 2;
}
else if(row && col) do {
do {
@@ -1639,7 +2143,7 @@ SpreadData::ReadXML(char *file, unsigned char *buffer, int type)
if(col >= cCols)AddCols(col+1);
if(i && etRows[row] && etRows[row][col]) {
if(TmpTxt[0] == '=') {
- MoveFormula(this, TmpTxt, TmpTxt, currpos.x-mov.x, currpos.y-mov.y);
+ MoveFormula(this, TmpTxt, TmpTxt, currpos.x-mov.x, currpos.y-mov.y, -1, -1);
}
etRows[row][col]->SetText(TmpTxt);
etRows[row][col]->Update(20, 0L, &pt);
@@ -1676,7 +2180,7 @@ SpreadData::ReadTSV(char *file, unsigned char *buffer, int type)
if(!Init(1, 1)) goto TSVError;
etRows[0][0]->SetText("");
}
- else if(buffer && type == FF_TSV) {
+ else if(buffer && (type == FF_TSV || type == FF_SSV)) {
if(!(TSVcache = new MemCache(buffer))) return false;
}
else return false;
@@ -1691,10 +2195,12 @@ SpreadData::ReadTSV(char *file, unsigned char *buffer, int type)
if(col == currpos.x) break;
row ++; col = currpos.x; break;
case 0x09: //tab
- col ++; break;
+ col ++; break;
+ case ' ':
+ if(type == FF_SSV) col ++; break;
}
}while(TmpTxt[0] && TmpTxt[0] < 33);
- for(i = 1; (TmpTxt[i] = c = TSVcache->Getc())>=32; i++)
+ for(i = 1; (TmpTxt[i] = c = TSVcache->Getc())>= (type == FF_SSV ? 33 : 32); i++)
if(i >= 4094) i = 4094;
if(TmpTxt[0] && row >= cRows)AddRows(row+1);
if(TmpTxt[0] && col >= cCols)AddCols(col+1);
@@ -1708,6 +2214,8 @@ SpreadData::ReadTSV(char *file, unsigned char *buffer, int type)
row ++; col = currpos.x; break;
case 0x09: //tab
col ++; break;
+ case ' ':
+ if(type == FF_SSV) col ++; break;
}
}
}while(!TSVcache->IsEOF());
@@ -1727,7 +2235,8 @@ SpreadData::MemList(unsigned char **ptr, int type)
double val;
*ptr = (unsigned char *)malloc(size = 10000);
unsigned char *tmpptr;
- bool bLimit = true;
+ bool bLimit = true;
+ AccRange *ar = 0L;
if(!(*ptr))return false;
if(rcCopy.left < 0) rcCopy.left = 0;
@@ -1749,19 +2258,25 @@ SpreadData::MemList(unsigned char **ptr, int type)
cbd = sprintf((char*)*ptr, "<?xml version=\"1.0\"?><!DOCTYPE RLPlot-workbook>\n"
"<RLPlot-data rows=\"%d\" columns=\"%d\" >\n", cRows, cCols);
}
+ if (c_range && c_range[0]) {
+ ar = new AccRange(c_range);
+ if(bCopyCut) Undo.DataObject(Disp, w, this, &rcCopy, 0L);
+ }
for(nl =0, i = rcCopy.top; i <= rcCopy.bottom; i++, nl++) {
for(nc = 0, j = rcCopy.left; j <= rcCopy.right; cb = 0, j++, nc++) {
switch (type) {
case FF_TSV:
if(nl || nc) cb = sprintf(tmptxt,"%s", nc ? "\t" : "\n");
- if(etRows[i] && etRows[i][j] && etRows[i][j]->text){
- for(k = 0; k < 7990 && (etRows[i][j]->text[k]); k++)
- tmptxt[cb++] = etRows[i][j]->text[k];
+ if(etRows[i] && etRows[i][j] && etRows[i][j]->text){
+ if((ar && ar->IsInRange(j,i)) || !ar) {
+ for(k = 0; k < 7990 && (etRows[i][j]->text[k]); k++)
+ tmptxt[cb++] = etRows[i][j]->text[k];
+ }
tmptxt[cb] = 0;
}
break;
case FF_SYLK:
- if(etRows[i] && etRows[i][j] && etRows[i][j]->text){
+ if(etRows[i] && etRows[i][j] && etRows[i][j]->text && ((ar && ar->IsInRange(j,i)) || !ar)){
cb = sprintf(tmptxt, "C;Y%d;X%d;K", nl+1, nc+1);
if(etRows[i][j]->GetValue(&val)){
cb += sprintf(tmptxt+cb, "%lf", val);
@@ -1774,15 +2289,18 @@ SpreadData::MemList(unsigned char **ptr, int type)
cb += sprintf(tmptxt+cb, "%s\n", TmpTxt);
if(cb >= 267) bLimit = false;
}
+ if(bCopyCut) etRows[i][j]->SetText("");
}
break;
case FF_RLW: case FF_XML:
- if(etRows[i] && etRows[i][j] && etRows[i][j]->text){
+ if(etRows[i] && etRows[i][j] && etRows[i][j]->text && ((ar && ar->IsInRange(j,i)) || !ar)
+ && etRows[i][j]->text[0]){
cb = sprintf(tmptxt, " <cell row=\"%d\" column=\"%d\" >\n", nl+1, nc+1);
cb += sprintf(tmptxt+cb, " <text>");
for(k = 0; k < 7880 && (etRows[i][j]->text[k]); k++)
tmptxt[cb++] = etRows[i][j]->text[k];
- cb += sprintf(tmptxt+cb, "</text>\n </cell>\n");
+ cb += sprintf(tmptxt+cb, "</text>\n </cell>\n");
+ if(bCopyCut) etRows[i][j]->SetText("");
}
break;
}
@@ -1810,6 +2328,8 @@ SpreadData::MemList(unsigned char **ptr, int type)
sprintf((char*)*ptr+cbd,"</RLPlot-data>\n");
//note: cbd may be greater than size !
}
+ if(ar) delete ar;
+ bCopyCut = false;
return true;
}
@@ -1818,8 +2338,8 @@ void SpreadMain(bool show)
static SpreadData *w = 0L;
if(show) {
- w = new SpreadData();
- if(!w ||!(w->Init(10, 10))){
+ w = new SpreadData(0L);
+ if(!w ||!(w->Init(50, 10))){
delete w;
w = 0L;
}
@@ -1829,5 +2349,3 @@ void SpreadMain(bool show)
delete(w);
}
}
-
-
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/rlplot.git
More information about the debian-science-commits
mailing list