[rlplot] 13/23: Imported Upstream version 1.3
Andreas Tille
tille at debian.org
Wed Jun 29 09:50:57 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 2f247a842232af5b72135008542a8ff20ab99a02
Author: Andreas Tille <tille at debian.org>
Date: Wed Jun 29 11:43:56 2016 +0200
Imported Upstream version 1.3
---
Axes.cpp | 108 ++--
Export.cpp | 315 ++++++----
Fileio.cpp | 116 +++-
ODbuttons.cpp | 133 ++++-
Output.cpp | 57 +-
PlotObs.cpp | 612 +++++++++++++++----
PropertyDlg.cpp | 894 ++++++++++++++++++++--------
QT_Spec.cpp | 346 ++++++++---
QT_Spec.h | 28 +-
RLPLOT.RC | 14 +-
TheDialog.cpp | 292 +++++----
TheDialog.h | 6 +-
UtilObj.cpp | 319 ++++++++--
Utils.cpp | 164 +++++-
Version.h | 4 +-
WinSpec.cpp | 645 +++++++++++++-------
WinSpec.h | 15 +-
menu.h | 15 +-
mfcalc.cpp | 1769 ++++++++++++++++++++++++++++++++-----------------------
mfcalc.y | 713 +++++++++++++++-------
no_gui.cpp | 27 +-
reports.cpp | 1202 +++++++++++++++++++++++++++----------
rlp_math.cpp | 635 ++++++++++++++++++--
rlplot.cpp | 154 +++--
rlplot.h | 127 +++-
rlplot.spec | 9 +-
spreadwi.cpp | 397 +++++++------
use_gui.cpp | 79 ++-
28 files changed, 6537 insertions(+), 2658 deletions(-)
diff --git a/Axes.cpp b/Axes.cpp
index 559fbc4..b4e13ae 100755
--- a/Axes.cpp
+++ b/Axes.cpp
@@ -1,4 +1,4 @@
-//Axes.cpp, Copyright 2000, 2001, 2002, 2003, 2004 R.Lackner
+//Axes.cpp, Copyright 2000-2007 R.Lackner
//
// This file is part of RLPlot.
//
@@ -269,7 +269,7 @@ GridLine3D:: DoPlot(anyOutput *o)
if(!gl2) gl2 = (POINT3D*)calloc(4, sizeof(POINT3D));
if(!gl3) gl3 = (POINT3D*)calloc(4, sizeof(POINT3D));
if(!ls) ls = (line_segment**)calloc(6, sizeof(line_segment*));
- o->ActualSize(&rDims);
+ if(!(o->ActualSize(&rDims)))return;
Swap(rDims.left, rDims.right); Swap(rDims.top, rDims.bottom);
if(gl1 && gl2 && gl3 && ls) {
for(i = 0; i < 6; i++) if(ls[i]) {
@@ -661,7 +661,7 @@ Tick::Command(int cmd, void *tmpl, anyOutput *o)
LabelDef->Style = TXS_NORMAL;
LabelDef->Mode = TXM_TRANSPARENT;
LabelDef->Font = FONT_HELVETICA;
- LabelDef->text = tmpl && *((char*)tmpl) ? _strdup((char*)tmpl) : 0L;
+ LabelDef->text = tmpl && *((char*)tmpl) ? (char*)memdup(tmpl, (int)strlen((char*)tmpl)+1, 0) : 0L;
label = new Label(this, 0L, fix, fiy, LabelDef, LB_X_PARENT | LB_Y_PARENT);
if(LabelDef->text) free(LabelDef->text);
delete (LabelDef);
@@ -813,6 +813,7 @@ Axis::~Axis()
if(ssMITval) free(ssMITval); ssMATval = ssMATlbl = ssMITval = 0L;
if(axisLabel) DeleteGO(axisLabel); axisLabel = 0L;
if(mo) DelBitmapClass(mo); mo = 0L;
+ if(atv) delete atv; atv = 0L;
}
double
@@ -990,7 +991,7 @@ Axis::DoPlot(anyOutput *o)
memcpy(&tmp_axis, axis, sizeof(AxisDEF));
tmp_axis.loc[0].fx += dx; tmp_axis.loc[1].fx += dx;
tmp_axis.loc[0].fy += dy; tmp_axis.loc[1].fy += dy;
- if(parent->Id == GO_PLOT3D && (axis->flags & AXIS_3D)) {
+ if(IsPlot3D(parent) && (axis->flags & AXIS_3D)) {
//set 3D information in scaleOut
cu1.fx = axis->loc[0].fx +dx; cu1.fy = axis->loc[0].fy +dy;
cu1.fz = axis->loc[0].fz; cu2.fx = axis->loc[1].fx +dx;
@@ -1160,44 +1161,6 @@ Axis::DoPlot(anyOutput *o)
if(Ticks[i]) Ticks[i]->DoPlot(si, csi, o);
}
-void
-Axis::DoMark(anyOutput *o, bool mark)
-{
- LineDEF mrkLine;
- int x1, y1, x2, y2;
- double minw = DefSize(SIZE_DATA_LINE);
-
- if(axis->flags & AXIS_ANGULAR) {
- if(mark) {
- memcpy(&mrc, &rDims, sizeof(RECT));
- IncrementMinMaxRect(&mrc, 6 + o->un2ix(axline.width));
- mo = GetRectBitmap(&mrc, o);
- memcpy(&mrkLine, &axline, sizeof(LineDEF));
- mrkLine.width = axline.width < minw ? minw * 3.0 : axline.width *3.0;;
- x1 = o->co2ix(axis->Center.fx) - o->un2ix(axis->Radius);
- y1 = o->co2iy(axis->Center.fy) - o->un2iy(axis->Radius);
- x2 = o->co2ix(axis->Center.fx) + o->un2ix(axis->Radius);
- y2 = o->co2iy(axis->Center.fy) + o->un2iy(axis->Radius);
- o->SetLine(&mrkLine);
- o->oArc(x1, y1, x2, y2, 4);
- mrkLine.color ^= 0x00ffffffL;
- mrkLine.width = axline.width;
- o->SetLine(&mrkLine);
- o->oArc(x1, y1, x2, y2, 4);
- o->UpdateRect(&mrc, false);
- }
- else RestoreRectBitmap(&mo, &mrc, o);
- return;
- }
- if(mark){
- memcpy(&mrc, &rDims, sizeof(RECT));
- IncrementMinMaxRect(&mrc, 6 + o->un2ix(axline.width));
- mo = GetRectBitmap(&mrc, o);
- InvertLine(pts, 2, &axline, &rDims, o, mark);
- }
- else RestoreRectBitmap(&mo, &mrc, o);
-}
-
bool
Axis::Command(int cmd, void *tmpl, anyOutput *o)
{
@@ -1209,6 +1172,7 @@ Axis::Command(int cmd, void *tmpl, anyOutput *o)
switch (cmd) {
case CMD_SCALE:
+ if(!Ticks && (axis->flags & 0x03) != AXIS_NOTICKS)CreateTicks();
scale = (scaleINFO*)tmpl;
lbdist.fx *= scale->sx.fy; lbdist.fy *= scale->sy.fy;
tlbdist.fx *= scale->sx.fy; tlbdist.fy *= scale->sy.fy;
@@ -1222,7 +1186,6 @@ Axis::Command(int cmd, void *tmpl, anyOutput *o)
axis->Center.fx *= scale->sx.fy; axis->Center.fy *= scale->sy.fy;
axis->Radius *= scale->sy.fy; tlbdef.iSize = 0;
if(axisLabel) axisLabel->Command(cmd, tmpl, o);
- if(!Ticks && (axis->flags & 0x03) != AXIS_NOTICKS)CreateTicks();
if(Ticks) for(i = 0; i < NumTicks; i++) if(Ticks[i]) Ticks[i]->Command(cmd, tmpl, o);
return true;
case CMD_HIDE_MARK:
@@ -1411,9 +1374,9 @@ Axis::SetTick(long idx, double val, DWORD flags, char *txt)
Ticks[idx] = new Tick(this, data, val, flags);
if(!txt) {
WriteNatFloatToBuff(TmpTxt, val);
- l = _strdup(TmpTxt+1);
+ l = (char*)memdup(TmpTxt+1, (int)strlen(TmpTxt+1)+1, 0);
}
- else l = _strdup(txt);
+ else l = (char*)memdup(txt, (int)strlen(txt)+1, 0);
if(!gl_type) {
}
if(Ticks[idx]) {
@@ -1432,10 +1395,12 @@ void
Axis::CreateTicks()
{
int i, n, nstep;
- char *format;
+ char *format, *tick_label;
double fVal, tmp;
DWORD flags;
+ if(axis->min == -HUGE_VAL || axis->min == HUGE_VAL) return;
+ if(axis->max == -HUGE_VAL || axis->max == HUGE_VAL) return;
Command(CMD_FLUSH, 0L, 0L);
if((axis->flags & 0xf000) == AXIS_LOG) { //log-axis
if(axis->Start > defs.min4log) tmp = log10(axis->Start);
@@ -1470,6 +1435,27 @@ Axis::CreateTicks()
}
}
else { //linear axis
+ if(atv && (nstep = atv->Count()) && (Ticks = (Tick**)calloc(nstep+1, sizeof(Tick*)))) {
+ for(NumTicks = i = n = 0; NumTicks < nstep && atv->GetItem(i, &tick_label, &fVal); i++) {
+ SetTick(NumTicks, fVal, axis->flags, tick_label);
+ NumTicks++; n += (int)strlen(tick_label);
+ }
+ type = type;
+#ifdef _WINDOWS
+ if(type == 1 && n > 40) {
+ tlbdef.RotBL = n >100 ? 90.0 : 45.0; tlbdef.Align = TXA_HRIGHT | TXA_VCENTER;
+ tlbdist.fy = sizAxTick; SetSize(SIZE_TLB_YDIST, tlbdist.fy);
+ Command(CMD_TLB_TXTDEF, &tlbdef, 0L);
+ }
+#else
+ if(type == 1 && n > 30) {
+ tlbdef.RotBL = n >70 ? 90.0 : 45.0; tlbdef.Align = TXA_HRIGHT | TXA_VCENTER;
+ tlbdist.fy = sizAxTick; SetSize(SIZE_TLB_YDIST, tlbdist.fy);
+ Command(CMD_TLB_TXTDEF, &tlbdef, 0L);
+ }
+#endif
+ return;
+ }
if((axis->flags & 0xf000) == AXIS_RECI) {
NiceStep(axis, 8);
format = GetNumFormat(floor(log10(axis->Step)));
@@ -1533,12 +1519,13 @@ Axis::ManuTicks(double sa, double st, int n, DWORD flags)
bool
Axis::GetValuePos(double val, double *fix, double *fiy, double *fiz, anyOutput *op)
{
- double tmp1 = 1.0;
+ double temp, tmp1 = 1.0;
int i;
bool bRet = true;
anyOutput *o;
fPOINT3D p1, p2;
lfPOINT fdp, fip;
+ AxisDEF caxis;
*fix = *fiy = *fiz = 0.0;
if(!op || !parent || (val < axis->min && val < axis->max) ||
@@ -1549,14 +1536,25 @@ Axis::GetValuePos(double val, double *fix, double *fiy, double *fiz, anyOutput *
if(axis->owner == this && scaleOut) o = scaleOut;
else o = op;
if(axis->flags & AXIS_3D) {
- p1.fx = GetSize(SIZE_XPOS); p1.fy = GetSize(SIZE_YPOS); p1.fz = GetSize(SIZE_ZPOS);
- tmp1 = defs.cUnits == 1 ? 2.54 : defs.cUnits == 2 ? 1.0 : 25.4;
- tmp1 /= op->VPscale;
- switch(type) {
- case 1: p1.fx += (tmp1 * (op->fx2fix(val)- op->Box1.Xmin)/op->hres); break;
- case 2: p1.fy += (tmp1 * (op->fy2fiy(val)- op->Box1.Ymax)/op->vres); break;
- case 3: p1.fz += (tmp1 * (op->fz2fiz(val)- op->Box1z.fx)/op->hres); break;
- default: return false;
+ //Get a copy of the axis because GetAxisFac() modifies its contents
+ memcpy(&caxis, axis, sizeof(AxisDEF));
+ p1.fx = op->un2fix(axis->loc[1].fx - caxis.loc[0].fx);
+ p1.fy = op->un2fiy(axis->loc[1].fy - caxis.loc[0].fy);
+ p1.fz = op->un2fiz(axis->loc[1].fz - caxis.loc[0].fz);
+ tmp1 = sqrt(p1.fx*p1.fx + p1.fy*p1.fy + p1.fz*p1.fz);
+ p1.fx /= tmp1; p1.fy /= tmp1; p1.fz /= tmp1;
+ tmp1 = GetAxisFac(&caxis, tmp1, (type&0xf)-1);
+ temp = TransformValue(&caxis, val, true);
+ temp = (temp - caxis.min)*tmp1;
+ if(axis->flags & AXIS_INVERT) {
+ p1.fx = op->fix2un(op->un2fix(axis->loc[1].fx) - p1.fx*temp);
+ p1.fy = op->fiy2un(op->un2fiy(axis->loc[1].fy) - p1.fy*temp);
+ p1.fz = op->fix2un(op->un2fiz(axis->loc[1].fz) - p1.fz*temp);
+ }
+ else {
+ p1.fx = op->fix2un(p1.fx*temp+op->un2fix(axis->loc[0].fx));
+ p1.fy = op->fiy2un(p1.fy*temp+op->un2fiy(axis->loc[0].fy));
+ p1.fz = op->fix2un(p1.fz*temp+op->un2fiz(axis->loc[0].fz));
}
op->cvec2ivec(&p1, &p2);
*fix = p2.fx; *fiy = p2.fy; *fiz = p2.fz;
diff --git a/Export.cpp b/Export.cpp
index 7fd0ea2..b47b8ac 100755
--- a/Export.cpp
+++ b/Export.cpp
@@ -1,4 +1,4 @@
-//Export.cpp, Copyright (c) 2002-2006 R.Lackner
+//Export.cpp, Copyright (c) 2002-2007 R.Lackner
//export graph files
//
// This file is part of RLPlot.
@@ -108,7 +108,7 @@ ExportWMF::ExportWMF(GraphObj *g, char *FileName, float res, DWORD flags)
hPen = 0xffff, hBrush = 0xffff, hFont = 0xffff;
hres = vres = res;
go = g;
- if(FileName)name = _strdup(FileName);
+ if(FileName)name = (char*)memdup(FileName, (int)strlen(FileName)+1, 0);
else name = 0L;
oFile = 0;
rec_size = 28;
@@ -239,7 +239,7 @@ ExportWMF::StartPage()
}
VPorg.fy = -un2fiy(go->GetSize(SIZE_GRECT_TOP));
VPorg.fx = -un2fix(go->GetSize(SIZE_GRECT_LEFT));
- _write(oFile, &header, 18);
+ write(oFile, &header, 18);
return true;
}
@@ -248,15 +248,15 @@ ExportWMF::EndPage()
{
unsigned short end_token[3] = {3, 0, 0};
- _write(oFile, &end_token, 6);
- file_size = _lseek(oFile, 0L, SEEK_CUR);
- _lseek(oFile, 0L, SEEK_SET);
+ write(oFile, &end_token, 6);
+ file_size = lseek(oFile, 0L, SEEK_CUR);
+ lseek(oFile, 0L, SEEK_SET);
header.mtSize0 = (file_size>>1)&0xffff;
header.mtSize1 = file_size>>17;
header.mtNoObj = maxGDIobj;
header.mtMaxRec = rec_size;
- _write(oFile, &header, 18);
- oFile = _close(oFile);
+ write(oFile, &header, 18);
+ oFile = close(oFile);
return true;
}
@@ -367,7 +367,7 @@ ExportWMF::wmfCreateSolidBrush(DWORD color)
{
wmfLogBrush lb = {7, 0x2fc, 0, color, 0};
- _write(oFile, &lb, 14);
+ write(oFile, &lb, 14);
currGDIobj++;
maxGDIobj = currGDIobj > maxGDIobj ? currGDIobj : maxGDIobj;
return currGDIobj-1;
@@ -385,7 +385,7 @@ ExportWMF::wmfCreateFontIndirect(short lfHeight, short lfWidth, short lfEscapeme
lfQuality, lfPitchAndFamily, "Arial"};
if(FaceName && FaceName[0]) rlp_strcpy(lf.face, 32, FaceName);
- _write(oFile, &lf, 56);
+ write(oFile, &lf, 56);
currGDIobj++;
maxGDIobj = currGDIobj > maxGDIobj ? currGDIobj : maxGDIobj;
return currGDIobj-1;
@@ -396,7 +396,7 @@ ExportWMF::wmfCreateSolidPen(DWORD color, unsigned short width)
{
wmfLogPen lp = {8, 0x2fa, 0, width, color};
- _write(oFile, &lp, 16);
+ write(oFile, &lp, 16);
currGDIobj++;
maxGDIobj = currGDIobj > maxGDIobj ? currGDIobj : maxGDIobj;
return currGDIobj-1;
@@ -418,7 +418,7 @@ ExportWMF::wmfEllipse(unsigned short ix1, unsigned short iy1, unsigned short ix2
{
wmfRect rc = {7, 0x418, iy2, ix2, iy1, ix1};
- _write(oFile, &rc, 14);
+ write(oFile, &rc, 14);
}
void
@@ -428,11 +428,11 @@ ExportWMF::wmfPolyline(POINT *pts, unsigned short cp)
unsigned short v[2];
int i;
- _write(oFile, &pl, 8);
+ write(oFile, &pl, 8);
for(i = 0; i < cp; i++) {
v[0] = (unsigned short)pts[i].x;
v[1] = (unsigned short)pts[i].y;
- _write(oFile, &v, 4);
+ write(oFile, &v, 4);
}
if(pl.Size > rec_size) rec_size = pl.Size;
}
@@ -444,11 +444,11 @@ ExportWMF::wmfPolygon(POINT *pts, unsigned short cp)
unsigned short v[2];
int i;
- _write(oFile, &pl, 8);
+ write(oFile, &pl, 8);
for(i = 0; i < cp; i++) {
v[0] = (unsigned short)pts[i].x;
v[1] = (unsigned short)pts[i].y;
- _write(oFile, &v, 4);
+ write(oFile, &v, 4);
}
if(pl.Size > rec_size) rec_size = pl.Size;
}
@@ -458,7 +458,7 @@ ExportWMF::wmfRectangle(unsigned short ix1, unsigned short iy1, unsigned short i
{
wmfRect rc = {7, 0x41B, iy2, ix2, iy1, ix1};
- _write(oFile, &rc, 14);
+ write(oFile, &rc, 14);
}
void
@@ -466,7 +466,7 @@ ExportWMF::wmfSelectObject(unsigned short o)
{
wmfObjShort so = {4, 0x12D, o};
- _write(oFile, &so, 8);
+ write(oFile, &so, 8);
}
void
@@ -474,8 +474,8 @@ ExportWMF::wmfSetBkColor(DWORD col)
{
wmfObjCol co = {5, 0x201};
- _write(oFile, &co, 6);
- _write(oFile, &col, 4);
+ write(oFile, &co, 6);
+ write(oFile, &col, 4);
}
void
@@ -484,9 +484,9 @@ ExportWMF::wmfSetBkMode(unsigned m)
wmfObjShort mo = {5, 0x102, m & 0xffff};
unsigned short p;
- _write(oFile, &mo, 8);
+ write(oFile, &mo, 8);
p = m>>16;
- _write(oFile, &p, 2);
+ write(oFile, &p, 2);
}
//cmSetMapMode()
@@ -498,9 +498,9 @@ ExportWMF::wmfSetTextAlign(unsigned a)
wmfObjShort ao = {5, 0x12E, a & 0xffff};
unsigned short p;
- _write(oFile, &ao, 8);
+ write(oFile, &ao, 8);
p = a>>16;
- _write(oFile, &p, 2);
+ write(oFile, &p, 2);
}
void
@@ -508,8 +508,8 @@ ExportWMF::wmfSetTextColor(DWORD col)
{
wmfObjCol tc = {5, 0x209};
- _write(oFile, &tc, 6);
- _write(oFile, &col, 4);
+ write(oFile, &tc, 6);
+ write(oFile, &col, 4);
}
//cmSetWindowExt()
@@ -523,9 +523,9 @@ ExportWMF::wmfTextOut(unsigned short ix1, unsigned short iy1, char *txt, unsigne
le = cb &1 ? cb+1 : cb;
to.Size += le>>1;
- _write(oFile, &to, 8);
- _write(oFile, txt, le);
- _write(oFile, &v, 4);
+ write(oFile, &to, 8);
+ write(oFile, txt, le);
+ write(oFile, &v, 4);
if(to.Size > rec_size) rec_size = to.Size;
}
@@ -535,6 +535,8 @@ void DoExportWmf(GraphObj *g, char *FileName, float res, DWORD flags)
{
ExportWMF *ex;
+
+ InfoBox("The export of Windos metafile (*.wmf) is deprecated.\n\nThis feature will be removed in future\nversions of RLPlot!\n\n");
ex = new ExportWMF(g, FileName, res, flags);
if(ex->StartPage()) {
g->DoPlot(ex);
@@ -567,18 +569,20 @@ public:
bool oRectangle(int x1, int y1, int x2, int y2, char *nam = 0L);
bool oSolidLine(POINT *p);
bool oTextOut(int x, int y, char *txt, int cb);
+ bool oTextOutW(int x, int y, w_char *txt, int cb);
bool oPolygon(POINT *pts, int cp, char * nam = 0L);
private:
- int iLineWidth;
+ int iLineWidth, cb_out;
bool bUseGroupLine, bOutputPending;
GraphObj *go;
char *name, indent[80], output[120], tHatchStyle[80];
FILE *oFile;
DWORD flags;
+ bool com_TextOut(int x, int y, char *txt, int cb);
void Indent(bool ind);
- void AddToOutput(char *txt);
+ void AddToOutput(char *txt, int len);
char *ColName(DWORD col);
};
@@ -590,7 +594,7 @@ ExportSVG::ExportSVG(GraphObj *g, char *FileName, DWORD flg)
dFillCol = 0xffffffffL;
hres = vres = 1000.0f;
go = g;
- if(FileName)name = _strdup(FileName);
+ if(FileName)name = (char*)memdup(FileName, (int)strlen(FileName)+1, 0);
else name = 0L;
oFile = 0L;
flags = flg;
@@ -739,7 +743,7 @@ ExportSVG::oCircle(int x1, int y1, int x2, int y2, char* nam)
bool
ExportSVG::oPolyline(POINT *pts, int cp, char *nam)
{
- int i;
+ int i, cb;
char tmptxt[40];
if(cp < 2) return false;
@@ -756,23 +760,27 @@ ExportSVG::oPolyline(POINT *pts, int cp, char *nam)
else {
if(cp == 2) return oSolidLine(pts);
bOutputPending = false;
- sprintf(output, "<polyline points=\"");
+ cb_out = sprintf(output, "<polyline points=\"");
for(i = 0; i < cp; i++) {
- sprintf(tmptxt, "%d %d ", pts[i].x, pts[i].y);
- AddToOutput(tmptxt);
+ cb = sprintf(tmptxt, "%d %d ", pts[i].x, pts[i].y);
+ AddToOutput(tmptxt, cb);
}
- i = (int)strlen(output);
- if(i) output[i-1] = 0;
- strcat(output, "\"");
+ if(cb_out) output[cb_out-1] = '"';
if(!bUseGroupLine) {
- strcpy(tmptxt, " style = \"fill:none; ");
- AddToOutput(tmptxt);
- sprintf(tmptxt, "; stroke:%s; ", ColName(dLineCol));
- AddToOutput(tmptxt);
- sprintf(tmptxt, "stroke-width:%d\"/>",iLineWidth);
- AddToOutput(tmptxt);
+ cb = rlp_strcpy(tmptxt, 120, " style = \"fill:none; ");
+ AddToOutput(tmptxt, cb);
+ cb = rlp_strcpy(tmptxt, 120, "; stroke:");
+ cb += rlp_strcpy(tmptxt+cb, 120-cb, ColName(dLineCol));
+ cb += rlp_strcpy(tmptxt+cb, 120-cb, "; ");
+ AddToOutput(tmptxt, cb);
+#ifdef USE_WIN_SECURE
+ cb = sprintf_s(tmptxt, 120, "stroke-width:%d\"/>",iLineWidth);
+#else
+ cb = sprintf(tmptxt, "stroke-width:%d\"/>",iLineWidth);
+#endif
+ AddToOutput(tmptxt, cb);
}
- else strcat(output, "/>");
+ else AddToOutput("/>", 2);
fprintf(oFile, "%s%s\n", indent, output);
if(bOutputPending)Indent(false);
}
@@ -818,10 +826,10 @@ ExportSVG::oSolidLine(POINT *p)
}
bool
-ExportSVG::oTextOut(int x, int y, char *txt, int cb)
+ExportSVG::com_TextOut(int x, int y, char *txt, int cb)
{
- int i, j, h, ix, iy, dy;
- char tmptxt[140], *nt;
+ int c, h, ix, iy, dy;
+ char tmptxt[120];
if(!txt || !txt[0]) return false;
else h = TxtSet.iSize;
@@ -839,70 +847,116 @@ ExportSVG::oTextOut(int x, int y, char *txt, int cb)
else if((TxtSet.Align & TXA_VBOTTOM) == TXA_VBOTTOM) dy = -un2iy(TxtSet.fSize*0.6);
else if((TxtSet.Align & TXA_VTOP) == TXA_VTOP) dy = -un2iy(TxtSet.fSize*0.2);
}
- sprintf(output, "<text x=\"%d\" y=\"%d\" dy=\"%d\" ", ix, iy, dy);
+#ifdef USE_WIN_SECURE
+ cb_out = sprintf_s(output, 120, "<text x=\"%d\" y=\"%d\" dy=\"%d\" ", ix, iy, dy);
+#else
+ cb_out = sprintf(output, "<text x=\"%d\" y=\"%d\" dy=\"%d\" ", ix, iy, dy);
+#endif
if(fabs(TxtSet.RotBL) >.01 || fabs(TxtSet.RotCHAR) >.01) {
- sprintf(tmptxt,"transform=\"rotate(%.0f,%d,%d)\" ", -TxtSet.RotBL, ix, iy);
- strcat(output, tmptxt);
+#ifdef USE_WIN_SECURE
+ cb_out += sprintf_s(output+cb_out, 120-cb_out, "transform=\"rotate(%.0f,%d,%d)\" ", -TxtSet.RotBL, ix, iy);
+#else
+ cb_out += sprintf(output+cb_out,"transform=\"rotate(%.0f,%d,%d)\" ", -TxtSet.RotBL, ix, iy);
+#endif
}
- strcpy(tmptxt, "style=\"font-family:");
+ c = rlp_strcpy(tmptxt, 140, "style=\"font-family:");
switch(TxtSet.Font) {
- case FONT_TIMES: strcat(tmptxt, "Times;"); break;
- case FONT_COURIER: strcat(tmptxt, "Courier;"); break;
- default: strcat(tmptxt, "Helvetica;"); break;
+ case FONT_TIMES: c += rlp_strcpy(tmptxt+c, 120-c, "Times;"); break;
+ case FONT_COURIER: c += rlp_strcpy(tmptxt+c, 120-c, "Courier;"); break;
+ default: c += rlp_strcpy(tmptxt+c, 120-c, "Helvetica;"); break;
}
- if(TxtSet.Style & TXS_ITALIC) strcat(tmptxt, " font-style:italic;");
- if(TxtSet.Style & TXS_BOLD) strcat(tmptxt, " font-weight:bold;");
- if(TxtSet.Style & TXS_UNDERLINE) strcat(tmptxt, " text-decoration:underline;");
- AddToOutput(tmptxt);
- sprintf(tmptxt, " fill:%s; stroke:%s; ", ColName(TxtSet.ColTxt),
- ColName(TxtSet.ColTxt));
- AddToOutput(tmptxt);
- sprintf(tmptxt, "font-size:%d; text-anchor:%s \">", h,
+ if(TxtSet.Style & TXS_ITALIC) c += rlp_strcpy(tmptxt+c, 120-c, " font-style:italic;");
+ if(TxtSet.Style & TXS_BOLD) c += rlp_strcpy(tmptxt+c, 120-c, " font-weight:bold;");
+ if(TxtSet.Style & TXS_UNDERLINE) c += rlp_strcpy(tmptxt+c, 120-c, " text-decoration:underline;");
+ AddToOutput(tmptxt, c);
+#ifdef USE_WIN_SECURE
+ c = sprintf_s(tmptxt, 120, " fill:%s; stroke:%s; ", ColName(TxtSet.ColTxt), ColName(TxtSet.ColTxt));
+#else
+ c = sprintf(tmptxt, " fill:%s; stroke:%s; ", ColName(TxtSet.ColTxt), ColName(TxtSet.ColTxt));
+#endif
+ AddToOutput(tmptxt, c);
+#ifdef USE_WIN_SECURE
+ c = sprintf(tmptxt, "font-size:%d; text-anchor:%s \">", h,
+ (TxtSet.Align & TXA_HRIGHT) ? "end" : (TxtSet.Align & TXA_HCENTER) ? "middle":"start");
+#else
+ c = sprintf(tmptxt, "font-size:%d; text-anchor:%s \">", h,
(TxtSet.Align & TXA_HRIGHT) ? "end" : (TxtSet.Align & TXA_HCENTER) ? "middle":"start");
- AddToOutput(tmptxt);
- if(TxtSet.Font == FONT_GREEK) {
- for(i = j = 0; txt[i] && j < 4090; i++) {
- switch(txt[i]) {
+#endif
+ AddToOutput(tmptxt, c);
+ if((strlen(indent)+strlen(txt)+cb_out) <110) cb_out += rlp_strcpy(output+cb_out, 120-cb_out, txt);
+ else {
+ fprintf(oFile, "%s%s\n", indent, output);
+ cb_out=rlp_strcpy(output, 120, txt);
+ }
+ if((strlen(indent) + cb_out) <104)
+ fprintf(oFile, "%s%s</text>\n", indent, output);
+ else {
+ fprintf(oFile, "%s%s\n", indent, output);
+ fprintf(oFile, "</text>\n");
+ }
+ return true;
+}
+
+bool
+ExportSVG::oTextOut(int x, int y, char *txt, int cb)
+{
+ char *nt;
+
+ if(!txt || !txt[0]) return false;
+ nt = str2xml(txt, TxtSet.Font == FONT_GREEK);
+ return com_TextOut(x, y, nt, cb);
+}
+
+bool
+ExportSVG::oTextOutW(int x, int y, w_char *txt, int cb)
+{
+ int i, j;
+ wchar_t wc;
+ char c;
+
+ for(i = j = 0; txt[i]; i++) {
+ switch(txt[i]) {
case '"':
- j += sprintf(TmpTxt+j, """);
+ j += rlp_strcpy(TmpTxt+j, TMP_TXT_SIZE-j, """);
break;
case '&':
- j += sprintf(TmpTxt+j, "&");
+ j += rlp_strcpy(TmpTxt+j, TMP_TXT_SIZE-j, "&");
break;
case '<':
- j += sprintf(TmpTxt+j, "<");
+ j += rlp_strcpy(TmpTxt+j, TMP_TXT_SIZE-j, "<");
break;
case '>':
- j += sprintf(TmpTxt+j, ">");
+ j += rlp_strcpy(TmpTxt+j, TMP_TXT_SIZE-j, ">");
break;
default:
- if(txt[i] >= 'A' && txt[i] <= 'Z') j += sprintf(TmpTxt+j, "&#%d;", txt[i] - 'A' + 0x391);
- else if(txt[i] >= 'a' && txt[i] <= 'z') j += sprintf(TmpTxt+j, "&#%d;", txt[i] - 'a' + 0x3B1);
- else if(txt[i] > 31) TmpTxt[j++] = txt[i];
+ if(txt[i] > 255) {
+#ifdef USE_WIN_SECURE
+ j += sprintf_s(TmpTxt+j, TMP_TXT_SIZE-j, "&#%d;", txt[i]);
+#else
+ j += sprintf(TmpTxt+j, "&#%d;", txt[i]);
+#endif
+ }
+ else if(txt[i] > 127) {
+ c = (char)txt[i];
+ if(mbtowc(&wc, &c, 1) >0)
+#ifdef USE_WIN_SECURE
+ j += sprintf_s(TmpTxt+j, TMP_TXT_SIZE-j, "&#%d;", ((unsigned short)wc));
+#else
+ j += sprintf(TmpTxt+j, "&#%d;", ((unsigned short)wc));
+#endif
+ }
+ else TmpTxt[j++] = (char)txt[i];
break;
- }
}
- nt = TmpTxt;
- }
- else nt = str2xml(txt);
- if((strlen(indent)+strlen(nt)+strlen(output)) <110) strcat(output, nt);
- else {
- fprintf(oFile, "%s%s\n", indent, output);
- strcpy(output, nt);
- }
- if((strlen(indent) + strlen(output)) <104)
- fprintf(oFile, "%s%s</text>\n", indent, output);
- else {
- fprintf(oFile, "%s%s\n", indent, output);
- fprintf(oFile, "</text>\n");
}
- return true;
+ TmpTxt[j++] = 0;
+ return com_TextOut(x, y, TmpTxt, j-1);
}
bool
ExportSVG::oPolygon(POINT *pts, int cp, char *nam)
{
- int i;
+ int i, cb;
char tmptxt[40];
if(cp <3) return false;
@@ -911,21 +965,37 @@ ExportSVG::oPolygon(POINT *pts, int cp, char *nam)
Indent(true);
}
bOutputPending = false;
- sprintf(output, "<polygon%s%s%s points=\"",
+#ifdef USE_WIN_SECURE
+ cb_out = sprintf_s(output, 120, "<polygon%s%s%s points=\"",
nam? " name=\"" : "", nam ? nam : "", nam ? "\"" : "");
+#else
+ cb_out = sprintf(output, "<polygon%s%s%s points=\"",
+ nam? " name=\"" : "", nam ? nam : "", nam ? "\"" : "");
+#endif
for(i = 0; i < cp; i++) {
- sprintf(tmptxt, "%d %d ", pts[i].x, pts[i].y);
- AddToOutput(tmptxt);
+#ifdef USE_WIN_SECURE
+ cb = sprintf_s(tmptxt, 40, "%d %d ", pts[i].x, pts[i].y);
+#else
+ cb = sprintf(tmptxt, "%d %d ", pts[i].x, pts[i].y);
+#endif
+ AddToOutput(tmptxt, cb);
}
- i = (int)strlen(output);
- if(i) output[i-1] = 0;
- strcat(output, "\" ");
- sprintf(tmptxt, "style=\"fill:%s; ", ColName(dFillCol));
- AddToOutput(tmptxt);
- sprintf(tmptxt, "stroke:%s; ", ColName(dLineCol));
- AddToOutput(tmptxt);
- sprintf(tmptxt, "stroke-width:%d\"/>",iLineWidth);
- AddToOutput(tmptxt);
+ if(cb_out) output[cb_out-1] = '"';
+#ifdef USE_WIN_SECURE
+ cb = sprintf(tmptxt, "style=\"fill:%s; ", ColName(dFillCol));
+ AddToOutput(tmptxt, cb);
+ cb = sprintf(tmptxt, "stroke:%s; ", ColName(dLineCol));
+ AddToOutput(tmptxt, cb);
+ cb = sprintf(tmptxt, "stroke-width:%d\"/>",iLineWidth);
+ AddToOutput(tmptxt, cb);
+#else
+ cb = sprintf(tmptxt, "style=\"fill:%s; ", ColName(dFillCol));
+ AddToOutput(tmptxt, cb);
+ cb = sprintf(tmptxt, "stroke:%s; ", ColName(dLineCol));
+ AddToOutput(tmptxt, cb);
+ cb = sprintf(tmptxt, "stroke-width:%d\"/>",iLineWidth);
+ AddToOutput(tmptxt, cb);
+#endif
if(output)fprintf(oFile, "%s%s\n", indent, output);
if(bOutputPending)Indent(false);
if(hgo) {
@@ -953,16 +1023,21 @@ ExportSVG::Indent(bool ind)
}
void
-ExportSVG::AddToOutput(char *txt)
+ExportSVG::AddToOutput(char *txt, int len)
{
- if((strlen(txt) + strlen(output) + strlen(indent)) < 110)strcat(output, txt);
+ if(!txt || !txt[0]) return;
+ if(!len) len = (int)strlen(txt);
+ if((len + cb_out + strlen(indent)) < 110){
+ cb_out += rlp_strcpy(output+cb_out, 120, txt);
+ }
else {
fprintf(oFile, "%s%s\n", indent, output);
if(!bOutputPending) Indent(true);
bOutputPending = true;
- strcpy(output, txt);
+ cb_out = rlp_strcpy(output, 120, txt);
}
}
+
char *
ExportSVG::ColName(DWORD col)
{
@@ -1001,7 +1076,7 @@ void DoExportSvg(GraphObj *g, char *FileName, DWORD flags)
g->DoPlot(ex);
ex->EndPage();
}
- HideTextCursor();
+ HideTextCursor();
delete(ex);
}
@@ -1082,36 +1157,34 @@ ExportEPS::SetFill(FillDEF *fill)
{
if(!fill) return false;
if((fill->type & 0xff) != FILL_NONE) {
- if(!hgo) hgo = new HatchOut(this);
- if(hgo) hgo->SetFill(fill);
+ if(!hgo) hgo = new HatchOut(this); if(hgo) hgo->SetFill(fill);
}
else {
- if(hgo) delete hgo;
- hgo = 0L;
+ if(hgo) delete hgo; hgo = 0L;
}
- dFillCol = fill->color;
- dFillCol2 = fill->color2;
+ dFillCol = fill->color; dFillCol2 = fill->color2;
return true;
}
bool
ExportEPS::SetTextSpec(TextDEF *set)
{
+ int cb;
+
if(set->fSize > 0.0) {
- if((set->Style & TXS_SUPER) || (set->Style & TXS_SUB))
- set->iSize = un2iy(set->fSize * 0.71);
+ if((set->Style & TXS_SUPER) || (set->Style & TXS_SUB)) set->iSize = un2iy(set->fSize * 0.71);
else set->iSize = un2iy(set->fSize);
}
if(!set->iSize) return false;
anyOutput::SetTextSpec(set);
switch(TxtSet.Font) {
- case FONT_TIMES: sprintf(FontName, "(Times"); break;
- case FONT_COURIER: sprintf(FontName, "(Courier"); break;
- default: sprintf(FontName, "(Helvetica"); break; //Helvetica
+ case FONT_TIMES: cb = rlp_strcpy(FontName, 30, "(Times"); break; //Serif
+ case FONT_COURIER: cb = rlp_strcpy(FontName, 30, "(Courier"); break; //fixed spaced
+ default: cb = rlp_strcpy(FontName, 30, "(Helvetica"); break; //Sans Serif
}
- if(TxtSet.Style & TXS_BOLD) strcat(FontName, "-Bold");
- if(TxtSet.Style & TXS_ITALIC) strcat(FontName, "-Italic");
- strcat(FontName, ")"); bFontChange = true;
+ if(TxtSet.Style & TXS_BOLD) cb += rlp_strcpy(FontName+cb, 30-cb, "-Bold");
+ if(TxtSet.Style & TXS_ITALIC) cb += rlp_strcpy(FontName+cb, 30-cb, "-Italic");
+ cb += rlp_strcpy(FontName+cb, 30-cb, ")"); bFontChange = true;
return true;
}
diff --git a/Fileio.cpp b/Fileio.cpp
index 7fa8a37..055dd19 100755
--- a/Fileio.cpp
+++ b/Fileio.cpp
@@ -1,4 +1,4 @@
-//FileIO.cpp, Copyright (c) 2001-2006 R.Lackner
+//FileIO.cpp, Copyright (c) 2001-2007 R.Lackner
//read/write graphic objects
//
// This file is part of RLPlot.
@@ -239,7 +239,7 @@ static void WriteEscString(char *txt)
esc_str[j++] = '\\'; esc_str[j++] = 'n';
break;
default:
- if(txt[i] >= ' ') esc_str[j++] = txt[i];
+ if(((unsigned char*)txt)[i] >= ' ') esc_str[j++] = txt[i];
}
if(j > (esc_str_size -10)) esc_str = (char*)realloc(esc_str, (esc_str_size += 100));
if(j > lim && (l-i) > 3) {
@@ -899,6 +899,7 @@ bool OpenGraph(GraphObj *root, char *name, unsigned char *mem, bool bPaste)
int i, id, lid;
unsigned int hv;
GraphObj *go;
+ scaleINFO sc_info;
LastOpenGO = 0L;
if(Notary || Cache) {
@@ -1004,6 +1005,7 @@ bool OpenGraph(GraphObj *root, char *name, unsigned char *mem, bool bPaste)
case 967843: go = new DefsRW(FILE_READ); break;
case 66848: go = new Func3D(FILE_READ); break;
case 5001225: go = new TextFrame(FILE_READ); break;
+ case 4743132: go = new NormQuant(FILE_READ); break;
default:
#ifdef USE_WIN_SECURE
sprintf_s(debug, 80, "Object %ld in file\n(Class = \"%s\")\nhash #%d\nis unknown.", id, tmp, hv);
@@ -1025,6 +1027,14 @@ bool OpenGraph(GraphObj *root, char *name, unsigned char *mem, bool bPaste)
if((LastOpenGO = go = Notary->PopGO(lid))) {
go->Command(CMD_SET_DATAOBJ, 0L, 0L);
delete Notary; Notary = 0L;
+ if(bPaste && go->Id == GO_GRAPH) {
+ sc_info.sx.fx = -((Graph*)go)->GRect.Xmin; sc_info.sy.fx = -((Graph*)go)->GRect.Ymin;
+ sc_info.sx.fy = sc_info.sy.fy = sc_info.sz.fy = 1.0; sc_info.sz.fx = 0.0;
+ go->Command(CMD_SCALE, &sc_info, 0L);
+ sc_info.sx.fy = sc_info.sy.fy = sc_info.sz.fy = 1.0/go->GetSize(SIZE_SCALE);
+ sc_info.sx.fx = sc_info.sy.fx = sc_info.sz.fx = 0.0;
+ go->Command(CMD_SCALE, &sc_info, 0L);
+ }
if(bPaste && root->Command(CMD_PASTE_OBJ, (void *)go, 0L)) {
// object accepted
}
@@ -2368,7 +2378,8 @@ PlotScatt::FileIO(int rw)
{"dLines", typOBJLST, &DropLines, &nPoints},
{"Labels", typOBJLST, &Labels, &nPoints},
{"x_info", typTEXT, &x_info, 0L},
- {"y_info", typLAST | typTEXT, &y_info, 0L}};
+ {"y_info", typTEXT, &y_info, 0L},
+ {"DataDesc", typLAST | typTEXT, &data_desc, 0L}};
int i;
switch(rw) {
@@ -2489,6 +2500,7 @@ FreqDist::FileIO(int rw)
BarFill.hatch = &HatchLine;
memcpy(&BarLine, defs.GetOutLine(), sizeof(LineDEF));
curr_data=0L; dirty = true;
+ dmin = HUGE_VAL, dmax = -HUGE_VAL;
if(name) {
#ifdef USE_WIN_SECURE
i = sprintf_s(TmpTxt, TMP_TXT_SIZE, "freq. dist. (%s)", name);
@@ -2936,7 +2948,11 @@ Scatt3D::FileIO(int rw)
{"ssRefX", typTEXT, &ssRefX, 0L},
{"ssRefY", typTEXT, &ssRefY, 0L},
{"ssRefZ", typTEXT, &ssRefZ, 0L},
+ {"DataDesc", typTEXT, &data_desc, 0L},
{"hide", typNZINT, &hidden, 0L},
+ {"x_axis", typNZINT, &use_xaxis, 0L},
+ {"y_axis", typNZINT, &use_yaxis, 0L},
+ {"z_axis", typNZINT, &use_zaxis, 0L},
{"Line", typGOBJ, &Line, 0L},
{"Balls", typOBJLST, &Balls, &nBalls},
{"Columns", typOBJLST, &Columns, &nColumns},
@@ -3007,6 +3023,7 @@ Ribbon::FileIO(int rw)
{"ssRefX", typTEXT, &ssRefX, 0L},
{"ssRefY", typTEXT, &ssRefY, 0L},
{"ssRefZ", typTEXT, &ssRefZ, 0L},
+ {"DataDesc", typTEXT, &data_desc, 0L},
{"Line", typLINEDEF, &Line, 0L},
{"Fill", typFILLDEF, &Fill, 0L},
{"values", typFPLST3D, &values, &nVal},
@@ -3058,6 +3075,7 @@ Grid3D::FileIO(int rw)
{
descIO Desc[] = {
{"Type", typNZINT, &type, 0L},
+ {"hide", typNZINT, &hidden, 0L},
{"Start", typPOINT3D, &start, 0L},
{"Step", typPOINT3D, &step, 0L},
{"Line", typLINEDEF, &Line, 0L},
@@ -3234,6 +3252,62 @@ FitFunc::FileIO(int rw)
}
bool
+NormQuant::FileIO(int rw)
+{
+ lfPOINT *dt;
+ long cnt;
+ descIO Desc[] = {
+ {"Type", typNZINT, &type, 0L},
+ {"nData", typINT, &nData, 0L},
+ {"Data", typFPLST, &dt, &cnt},
+ {"ssRef", typTEXT, &ssRef, 0L},
+ {"x_info", typTEXT, &x_info, 0L},
+ {"y_info", typLAST | typTEXT, &y_info, 0L}};
+ int i, j, l;
+
+ if(rw == FILE_WRITE) {
+ if(nData < 4) return false;
+ l = (nData >>1) +1; cnt = l;
+ if(!(dt = (lfPOINT *)calloc(l, sizeof(lfPOINT))))return false;
+ for(i = j = 0; i < nData; i += 2, j++) {
+ dt[j].fx = src_data[i]; dt[j].fy = src_data[i+1];
+ }
+ }
+ else {
+ dt = 0L; cnt = 0;
+ }
+ switch(rw) {
+ case INIT_VARS:
+ InitVarsGO(Desc);
+ sy = new Symbol(this, data, 0.0, 0.0, SYM_CIRCLE);
+ x_vals = y_vals = src_data = 0L;
+ if(name) {
+#ifdef USE_WIN_SECURE
+ i = sprintf_s(TmpTxt, TMP_TXT_SIZE, "normal quantiles (%s)", name);
+#else
+ i = sprintf(TmpTxt, "normal quantiles (%s)", name);
+#endif
+ free(name); name = (char*)memdup(TmpTxt, i+1, 0);
+ }
+ return true;
+ case FILE_READ:
+ ExecInput(Desc);
+ if(dt && cnt > 1 && (src_data = (double*)malloc(nData*sizeof(double)))) {
+ for(i = j = 0, l = nData-1; i < nData; i += 2, j++) {
+ src_data[i] = dt[j].fx; if(i < l) src_data[i+1] = dt[j].fy;
+ }
+ free(dt);
+ }
+ return true;
+ case FILE_WRITE:
+ ExecOutput(Notary->RegisterGO(this), "NormQuant", Desc);
+ free(dt);
+ return true;
+ }
+ return false;
+}
+
+bool
GridLine::FileIO(int rw)
{
descIO Desc[] = {
@@ -3418,13 +3492,11 @@ Axis::FileIO(int rw)
tlbdef.ColTxt = parent ? parent->GetColor(COL_AXIS) : defs.Color(COL_AXIS);
tlbdef.ColBg = parent ? parent->GetColor(COL_BG) : defs.Color(COL_AXIS);
tlbdef.RotBL = tlbdef.RotCHAR = 0.0f;
- tlbdef.fSize = DefSize(SIZE_TICK_LABELS);
- tlbdef.Align = TXA_VCENTER | TXA_HCENTER;
- tlbdef.Style = TXS_NORMAL;
- tlbdef.Mode = TXM_TRANSPARENT;
- tlbdef.Font = FONT_HELVETICA;
- tlbdef.text = 0L; l_segs = 0L; nl_segs = 0;
- drawOut = scaleOut = 0L; bModified = false;
+ tlbdef.fSize = DefSize(SIZE_TICK_LABELS); tlbdef.Align = TXA_VCENTER | TXA_HCENTER;
+ tlbdef.Style = TXS_NORMAL; tlbdef.Mode = TXM_TRANSPARENT;
+ tlbdef.Font = FONT_HELVETICA; atv = 0L;
+ tlbdef.text = 0L; l_segs = 0L; nl_segs = 0;
+ drawOut = scaleOut = 0L; bModified = false;
mrc.left = mrc.right = mrc.top = mrc.bottom = 0;
mo = 0L;
return true;
@@ -3467,6 +3539,7 @@ Plot3D::FileIO(int rw)
{
fPOINT3D rot_vec, rot_ang;
descIO Desc[] = {
+ {"hide", typNZINT, &hidden, 0L},
{"xBounds", typLFPOINT, &xBounds, 0L},
{"yBounds", typLFPOINT, &yBounds, 0L},
{"zBounds", typLFPOINT, &zBounds, 0L},
@@ -3475,6 +3548,9 @@ Plot3D::FileIO(int rw)
{"Center", typPOINT3D, &rotC, 0L},
{"rot_vec", typPOINT3D, &rot_vec, 0L},
{"rot_ang", typPOINT3D, &rot_ang, 0L},
+ {"x_axis", typNZINT, &use_xaxis, 0L},
+ {"y_axis", typNZINT, &use_yaxis, 0L},
+ {"z_axis", typNZINT, &use_zaxis, 0L},
{"Axes", typOBJLST, &Axes, (long*)&nAxes},
{"Plots", typLAST | typOBJLST, &plots, (long*)&nPlots}};
int i;
@@ -3499,6 +3575,7 @@ Plot3D::FileIO(int rw)
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;
+ Sc_Plots = 0L; nscp = 0;
if(name) {
#ifdef USE_WIN_SECURE
i = sprintf_s(TmpTxt, TMP_TXT_SIZE, "3D-root (%s)", name);
@@ -3538,6 +3615,7 @@ Func3D::FileIO(int rw)
fPOINT3D rot_vec, rot_ang;
descIO Desc[] = {
{"Type", typNZINT, &type, 0L},
+ {"hide", typNZINT, &hidden, 0L},
{"xBounds", typLFPOINT, &xBounds, 0L},
{"yBounds", typLFPOINT, &yBounds, 0L},
{"zBounds", typLFPOINT, &zBounds, 0L},
@@ -3546,6 +3624,9 @@ Func3D::FileIO(int rw)
{"Center", typPOINT3D, &rotC, 0L},
{"rot_vec", typPOINT3D, &rot_vec, 0L},
{"rot_ang", typPOINT3D, &rot_ang, 0L},
+ {"x_axis", typNZINT, &use_xaxis, 0L},
+ {"y_axis", typNZINT, &use_yaxis, 0L},
+ {"z_axis", typNZINT, &use_zaxis, 0L},
{"Axes", typOBJLST, &Axes, (long*)&nAxes},
{"Plots", typOBJLST, &plots, (long*)&nPlots},
{"x1", typNZLFLOAT, &x1, 0L},
@@ -3614,6 +3695,7 @@ FitFunc3D::FileIO(int rw)
fPOINT3D rot_vec, rot_ang;
descIO Desc[] = {
{"Type", typNZINT, &type, 0L},
+ {"hide", typNZINT, &hidden, 0L},
{"ssXref", typTEXT, &ssXref, 0L},
{"ssYref", typTEXT, &ssYref, 0L},
{"ssZref", typTEXT, &ssZref, 0L},
@@ -3625,6 +3707,9 @@ FitFunc3D::FileIO(int rw)
{"Center", typPOINT3D, &rotC, 0L},
{"rot_vec", typPOINT3D, &rot_vec, 0L},
{"rot_ang", typPOINT3D, &rot_ang, 0L},
+ {"x_axis", typNZINT, &use_xaxis, 0L},
+ {"y_axis", typNZINT, &use_yaxis, 0L},
+ {"z_axis", typNZINT, &use_zaxis, 0L},
{"Axes", typOBJLST, &Axes, (long*)&nAxes},
{"Plots", typOBJLST, &plots, (long*)&nPlots},
{"x1", typNZLFLOAT, &x1, 0L},
@@ -3821,7 +3906,7 @@ DefsRW::FileIO(int rw)
{
descIO Desc[] = {
{"dUnits", typINT, &defs.dUnits, 0L},
- {"cUnits", typINT, &defs.dUnits, 0L},
+ {"cUnits", typINT, &defs.cUnits, 0L},
{"dtHeight", typINT, &dlgtxtheight, 0L},
{"ss_txt", typLFLOAT, &defs.ss_txt, 0L},
{"fmt_date", typTEXT, &defs.fmt_date, 0L},
@@ -3838,6 +3923,15 @@ DefsRW::FileIO(int rw)
switch(rw) {
case FILE_READ:
ExecInput(Desc);
+ //check for plausibility
+ if(defs.ss_txt < 0.3 || defs.ss_txt > 3.0) defs.ss_txt = 0.9;
+ if(defs.dUnits < 0 || defs.dUnits > 2) defs.dUnits = 0;
+ defs.cUnits = defs.dUnits;
+#ifdef _WINDOWS
+ if(dlgtxtheight < 5 || dlgtxtheight > 60) dlgtxtheight = 16;
+#else
+ if(dlgtxtheight < 5 || dlgtxtheight > 60) dlgtxtheight = 10;
+#endif
return true;
case FILE_WRITE:
Notary = new notary();
diff --git a/ODbuttons.cpp b/ODbuttons.cpp
index 6d64b7d..1c81e4b 100755
--- a/ODbuttons.cpp
+++ b/ODbuttons.cpp
@@ -1,4 +1,4 @@
-//ODbuttons.cpp, Copyright (c) 2001, 2002, 2003, 2004, 2005 R.Lackner
+//ODbuttons.cpp, Copyright (c) 2001-2007 R.Lackner
//Property dialogs for graphic objects
//
// This file is part of RLPlot.
@@ -134,11 +134,12 @@ void OD_LineStyleTempl(int cmd, void *par, RECT *rec, anyOutput *o,
pts[0].y = pts[1].y = pts[4].y = rec->top;
pts[1].x = pts[2].x = rec->right-1;
pts[2].y = pts[3].y = rec->bottom-1;
- o->oPolyline(pts, 5);
- Line.color = 0x00000000L;
- o->SetLine(&Line);
- o->SetFill(&Fill);
+ o->oPolyline(pts, 5); Line.color = 0x00000000L;
+ o->SetLine(&Line); o->SetFill(&Fill);
o->oRectangle(rec->left+3, rec->top+3, rec->right-3, rec->bottom-3);
+ if(cmd == OD_DRAWSELECTED){
+ Fill.color = 0x000000ffL; o->SetFill(&Fill);
+ }
np = 0;
switch(id) {
case 201:
@@ -210,26 +211,40 @@ void OD_LineStyleTempl(int cmd, void *par, RECT *rec, anyOutput *o,
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(ix-3, rec->top + 9, ix+2, rec->top + 14);
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;
+ case 212:
+ for(i = 2; 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));
+ pts[1].y = iy + iround(pow(20.0, 1.0+((double)-i)/50.0) * -cos(((double)i)/4.0));
+ if(i>2)o->oSolidLine(pts);
+ pts[0].y = pts[1].y; pts[0].x = pts[1].x;
+ }
+ o->oCircle(ix-5, iy-4, ix, iy+1); o->oCircle(ix-10, iy-17, ix-5, iy-12);
+#ifdef _WINDOWS
+ o->oCircle(ix-12, iy+9, ix-7, iy+4); o->oCircle(ix+9, iy+7, ix+4, iy+2);
+#else
+ o->oCircle(ix-12, iy+9, ix-7, iy+4); o->oCircle(ix+8, iy+6, ix+4, iy+2);
+#endif
+ break;
}
if(np) o->oPolyline(pts, np);
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);
+ o->oCircle(ix-2, iy-2, ix+3, iy+3);
#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+18, rec->bottom-18);
+ o->oCircle(rec->right-13, rec->top+13, rec->right-18, rec->top+18);
#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+18, rec->bottom-18);
+ o->oCircle(rec->right-14, rec->top+13, rec->right-18, rec->top+18);
#endif
break;
- case 210: case 211:
+ case 210: case 211: case 212:
break;
}
o->UpdateRect(rec, false);
@@ -740,8 +755,30 @@ void OD_PlotTempl(int cmd, void *par, RECT *rec, anyOutput *o,
pts[0].x++; pts[1].x++; pts[0].y = pts[1].y;
}
break;
- case 520:
- case 521:
+ case 506:
+ o->SetLine(&bLine);
+ pts[0].x = rec->left +9; pts[0].y = rec->bottom-5; pts[1].x = pts[0].x+1;
+ for(i = 0; i < (rec->right - rec->left - 18); i++) {
+ r = ((double)(i+rec->left-ix+7))/8.0;
+ pts[1].y = pts[0].y - iround(exp(-r*r)*1.0+5.0);
+ pts[1].y = rec->bottom - iround(errf(r)*16.0+26.0);
+ if (i) o->oSolidLine(pts);
+ pts[0].x++; pts[1].x++; pts[0].y = pts[1].y;
+ }
+ o->SetLine(&rLine);
+ pts[0].x = ix-2; pts[1].x = pts[0].x+1;
+ for(i = 0; i < (rec->right - ix-5); i++) {
+ r = ((double)(i-9))/4.0;
+ pts[1].y = rec->bottom - iround(exp(-r*r)*17.0+7.0);
+ if (i) o->oSolidLine(pts);
+ pts[0].x++; pts[1].x++; pts[0].y = pts[1].y;
+ }
+ o->SetFill(&FillG); o->SetLine(&Line);
+ o->oCircle(ix, iy, ix+5, iy+5);
+ o->oCircle(ix-5, iy+8, ix, iy+13);
+ o->oCircle(ix+5, iy-10, ix+10, iy-5);
+ break;
+ case 520: case 521:
if(id == 521) {
pts[0].x = rec->left+13; pts[0].y = rec->bottom-12;
pts[1].x = rec->left+20; pts[1].y = rec->top+18;
@@ -1321,7 +1358,7 @@ void OD_AxisTempl3D(int cmd, void *par, RECT *rec, anyOutput *o,
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Execute axis templates for new axis as owner drawn buttons
+// 2D Plot: Execute axis templates for new axis as owner drawn buttons
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void OD_NewAxisTempl(int cmd, void *par, RECT *rec, anyOutput *o,
void *data, int id)
@@ -1387,4 +1424,70 @@ void OD_NewAxisTempl(int cmd, void *par, RECT *rec, anyOutput *o,
break;
}
}
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// 3D Plot: Execute axis templates for new axis as owner drawn buttons
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void OD_NewAxisTempl3D(int cmd, void *par, RECT *rec, anyOutput *o,
+ void *data, int id)
+{
+ LineDEF Line = {0.0, 1.0, 0x0L, 0x0L};
+ FillDEF Fill = {FILL_NONE, 0x00ffffffL, 1.0, 0L};
+ POINT spts[24];
+ int i, ix, iy, edge;
+ DWORD col1, col2;
+ switch(cmd) {
+ case OD_DRAWNORMAL:
+ case OD_DRAWSELECTED:
+ Line.color = cmd == OD_DRAWSELECTED ? 0x00000000L : 0x00e8e8e8L;
+ Fill.color = cmd == OD_DRAWSELECTED ? 0x00ffffffL : 0x00e8e8e8L;
+ col1 = cmd == OD_DRAWSELECTED ? 0x008080c0L : 0x00c8c8c8L;
+ col2 = cmd == OD_DRAWSELECTED ? 0x0000ff00L : 0x0000c000L;
+ o->SetLine(&Line);
+ ix = (rec->right + rec->left)>>1; iy = (rec->bottom + rec->top)>>1;
+ spts[0].x = spts[3].x = spts[4].x = rec->left;
+ spts[0].y = spts[1].y = spts[4].y = rec->top;
+ spts[1].x = spts[2].x = rec->right-1; spts[2].y = spts[3].y = rec->bottom-1;
+ o->oPolyline(spts, 5); Line.color = 0x00000000L;
+ o->SetLine(&Line); o->SetFill(&Fill);
+ o->oRectangle(rec->left+3, rec->top+3, rec->right-3, rec->bottom-3);
+ spts[0].x = spts[6].x = spts[8].x = spts[13].x = spts[18].x = spts[19].x = rec->left+20;
+ spts[0].y = spts[13].y = spts[18].y = rec->bottom-14;
+ spts[1].x = spts[2].x = spts[4].x = spts[5].x = spts[7].x = spts[21].x = rec->left+10;
+ spts[1].y = spts[2].y = spts[4].y = rec->bottom-10;
+ spts[3].x = spts[15].x = spts[16].x = spts[17].x = spts[20].x = spts[22].x = rec->right-20;
+ spts[3].y = spts[15].y = spts[16].y = spts[2].y + 3;
+ spts[5].y = spts[7].y = spts[21].y = rec->top+12;
+ spts[6].y = spts[8].y = spts[19].y = rec->top+8;
+ spts[9].x = spts[10].x = spts[11].x = spts[12].x = spts[14].x = spts[23].x = rec->right-10;
+ spts[9].y = spts[10].y = spts[23].y = spts[8].y+3;
+ spts[11].y = spts[12].y = spts[14].y = spts[0].y+3;
+ spts[17].y = spts[20].y = spts[22].y = spts[7].y+3;
+ switch(id) {
+ case 201: edge = 4; break;
+ case 202: edge = 16; break;
+ case 203: edge = 10; break;
+ case 204: edge = 18; break;
+ case 205: edge = 2; break;
+ case 206: edge = 14; break;
+ case 207: edge = 12; break;
+ case 208: edge = 0; break;
+ case 209: edge = 20; break;
+ case 210: edge = 22; break;
+ case 211: edge = 8; break;
+ case 212: edge = 6; break;
+ default: edge = -1; break;
+ }
+ Line.color = col1; o->SetLine(&Line);
+ if(true)for(i = 0; i < 24; i+= 2) {
+ if(i == edge){
+ Line.color = col2; o->SetLine(&Line);
+ o->oSolidLine(spts+i);
+ Line.color = col1; o->SetLine(&Line);
+ }
+ else o->oSolidLine(spts+i);
+ }
+ o->UpdateRect(rec, false);
+ break;
+ }
+}
diff --git a/Output.cpp b/Output.cpp
index 82e3083..2edb765 100755
--- a/Output.cpp
+++ b/Output.cpp
@@ -1,4 +1,4 @@
-//Output.cpp, Copyright (c) 2000-2006 R.Lackner
+//Output.cpp, Copyright (c) 2000-2007 R.Lackner
//
// This file is part of RLPlot.
//
@@ -56,7 +56,7 @@ anyOutput::anyOutput()
RLP.finc = 1.0f;
RLP.fp = 0.0f;
dPattern = 0xffffffffL; //impossible (invisible)line pattern to start with
- dBgCol = defs.Color(COL_BG);
+ dBgCol = defs.Color(COL_BG); OC_type = OC_UNKNOWN;
MrkMode = MRK_NONE; MrkRect = 0L;
VPorg.fx = VPorg.fy = 0.0; VPscale = 1.0;
MenuHeight = 0; cCursor = MC_ARROW;
@@ -96,6 +96,44 @@ anyOutput::SetRect(fRECT rec, int u, AxisDEF *x_ax, AxisDEF *y_ax)
}
void
+anyOutput::UseAxis(AxisDEF *ax, int type)
+{
+ AxisDEF *cax;
+
+ MrkMode = MRK_NONE;
+ if(!ax) return;
+ switch (type) {
+ case 1: //x-axis
+ memcpy(cax = &xAxis, ax, sizeof(AxisDEF));
+ Box1.Xmin = co2fix(ax->loc[0].fx);
+ Box1.Xmax = co2fix(ax->loc[1].fx);
+ ddx = GetAxisFac(&xAxis, Box1.Xmax - Box1.Xmin, 0);
+ break;
+ case 2: //y-axis
+ memcpy(cax = &yAxis, ax, sizeof(AxisDEF));
+ if(ax->flags & AXIS_3D) {
+ Box1.Ymax = co2fiy(ax->loc[0].fy);
+ Box1.Ymin = co2fiy(ax->loc[1].fy);
+ }
+ else {
+ Box1.Ymin = co2fiy(ax->loc[0].fy);
+ Box1.Ymax = co2fiy(ax->loc[1].fy);
+ }
+ ddy = GetAxisFac(&yAxis, Box1.Ymax - Box1.Ymin, 1);
+ break;
+ case 3: //z-axis
+ memcpy(cax = &zAxis, ax, sizeof(AxisDEF));
+ Box1z.fx = un2fiz(ax->loc[0].fz);
+ Box1z.fy = un2fiz(ax->loc[1].fz);
+ ddz = GetAxisFac(&zAxis, Box1z.fy - Box1z.fx, 2);
+ break;
+ default: //unnknown direction
+ return;
+ }
+ cax->owner = this;
+}
+
+void
anyOutput::SetSpace(fPOINT3D *cub1, fPOINT3D *cub2, int u, double *rot,
fPOINT3D *cent, AxisDEF *x_ax, AxisDEF *y_ax, AxisDEF *z_ax)
{
@@ -637,12 +675,21 @@ anyOutput::oGetTextExtent(char *text, int cb, int *width, int *height)
default: CharWidth = Helv_Char_Width; break;
}
if(!cb && text) cb = (int)strlen(text);
- for(i = w = 0; i < cb; i++) w += CharWidth[text[i]];
+ for(i = w = 0; i < cb; i++) w += ((unsigned)text[i] < 256 ? CharWidth[(unsigned)text[i]] : 35);
*width = iround(((double)w * (double)TxtSet.iSize)/52.0);
*height = TxtSet.iSize;
return true;
}
+bool
+anyOutput::oGetTextExtentW(w_char *text, int cb, int *width, int *height)
+{
+ if(cb < 1) for(cb = 0; text[cb]; cb++);
+ *width = (TxtSet.iSize * cb)>>1;
+ *height = TxtSet.iSize;
+ return true;
+}
+
bool
anyOutput::oSphere(int cx, int cy, int r, POINT *pts, int cp, char *nam)
{
@@ -1118,8 +1165,8 @@ HatchOut::IsInside(POINT p)
{
long tmp1, tmp2, tmp3, tmp4;
- if(p.x < DeskRect.left || p.x > DeskRect.right || p.y < DeskRect.top
- || p.y >DeskRect.bottom) return false;
+ if(out->OC_type != OC_HIMETRIC && (p.x < DeskRect.left || p.x > DeskRect.right || p.y < DeskRect.top
+ || p.y >DeskRect.bottom)) return false;
switch(ho){
case HO_RECT:
if(p.x > HatchDef.rec.rec.left && p.x < HatchDef.rec.rec.right &&
diff --git a/PlotObs.cpp b/PlotObs.cpp
index 8a7fe3a..6119931 100755
--- a/PlotObs.cpp
+++ b/PlotObs.cpp
@@ -1,4 +1,4 @@
-//PlotObs.cpp, Copyright (c) 2001-2006 R.Lackner
+//PlotObs.cpp, Copyright (c) 2001-2007 R.Lackner
//
// This file is part of RLPlot.
//
@@ -51,8 +51,9 @@ Plot::Plot(GraphObj *par, DataObj *d):GraphObj(par, d)
pos = rlp_strcpy(name, nsize, (char*)"Plot");
add_int_to_buff(&name, &pos, &nsize, ++cPlots, true, 0);
}
- use_xaxis = use_yaxis = 0; hidden = 0;
- x_info = y_info = z_info = 0L;
+ use_xaxis = use_yaxis = use_zaxis = 0; hidden = 0;
+ x_info = y_info = z_info = data_desc = 0L;
+ x_tv = y_tv = 0L;
}
double
@@ -95,20 +96,17 @@ Plot::CheckBounds(double x, double y)
bool
Plot::UseAxis(int idx)
{
- double dx, dy;
-
if(CurrAxes && CurrAxes[idx]) {
- dx = fabs(CurrAxes[idx]->GetSize(SIZE_XPOS+1) -
- CurrAxes[idx]->GetSize(SIZE_XPOS));
- dy = fabs(CurrAxes[idx]->GetSize(SIZE_YPOS+1) -
- CurrAxes[idx]->GetSize(SIZE_YPOS));
- if(dx > dy && idx != use_xaxis) {
+ switch(CurrAxes[idx]->type & 0xf) {
+ case 1: // x-axis
Undo.ValInt(parent, &use_xaxis, 0L);
use_xaxis = idx; return true;
- }
- else if(idx != use_yaxis) {
+ case 2: // y-axis
Undo.ValInt(parent, &use_yaxis, 0L);
use_yaxis = idx; return true;
+ case 3: // z-axis
+ Undo.ValInt(parent, &use_zaxis, 0L);
+ use_zaxis = idx; return true;
}
}
return false;
@@ -117,34 +115,20 @@ Plot::UseAxis(int idx)
void
Plot::ApplyAxes(anyOutput *o)
{
- AxisDEF x_axis, y_axis;
- double dsp;
- fRECT CurrRect;
-
if(!o || !CurrAxes || !parent) return;
- memcpy(&x_axis, &o->xAxis, sizeof(AxisDEF));
- memcpy(&y_axis, &o->yAxis, sizeof(AxisDEF));
- CurrRect.Xmin = (dsp = parent->GetSize(SIZE_GRECT_LEFT)) +
- parent->GetSize(SIZE_DRECT_LEFT);
- CurrRect.Xmax = dsp + parent->GetSize(SIZE_DRECT_RIGHT);
if(use_xaxis && CurrAxes[use_xaxis]) {
- memcpy(&x_axis, CurrAxes[use_xaxis]->axis, sizeof(AxisDEF));
- if(x_axis.flags & AXIS_DEFRECT) {
- x_axis.loc[0].fx += dsp; x_axis.loc[1].fx += dsp;
- }
+ o->UseAxis(CurrAxes[use_xaxis]->axis, CurrAxes[use_xaxis]->type & 0xf);
}
else use_xaxis = 0;
- CurrRect.Ymin = (dsp = parent->GetSize(SIZE_GRECT_TOP)) +
- parent->GetSize(SIZE_DRECT_BOTTOM);
- CurrRect.Ymax = dsp + parent->GetSize(SIZE_DRECT_TOP);
if(use_yaxis && CurrAxes[use_yaxis]) {
- memcpy(&y_axis, CurrAxes[use_yaxis]->axis, sizeof(AxisDEF));
- if(y_axis.flags & AXIS_DEFRECT) {
- y_axis.loc[0].fy += dsp; y_axis.loc[1].fy += dsp;
- }
+ o->UseAxis(CurrAxes[use_yaxis]->axis, CurrAxes[use_yaxis]->type & 0xf);
}
else use_yaxis = 0;
- o->SetRect(CurrRect, o->units, &x_axis, &y_axis);
+ if(use_zaxis && CurrAxes[use_zaxis]) {
+ o->UseAxis(CurrAxes[use_zaxis]->axis, CurrAxes[use_zaxis]->type & 0xf);
+ }
+ else use_zaxis = 0;
+ return;
}
void
@@ -175,10 +159,13 @@ DataObj *
Plot::CreaCumData(char *xr, char *yr, int mode, double base)
{
char **yranges;
- int i, j, nc, nr, ir, ic, n;
+ int i, j, nc, nr, ir, ic, n, c_num, c_txt, c_datetime;
double value, old_val;
DataObj *CumData = 0L;
- AccRange *ax = 0L, *ay = 0L;
+ anyResult ares;
+ AccRange *ax = 0L, **ayy = 0L;
+ TextValue *tv = 0L;
+ bool *validRows;
if(!xr || !yr || !mode || !data) return 0L;
if(!(CumData = new DataObj()))return 0L;
@@ -186,44 +173,92 @@ Plot::CreaCumData(char *xr, char *yr, int mode, double base)
if(!(ax = new AccRange(xr))) {
delete CumData; CumData = 0L; return 0L;
}
- for(nr = 0, ax->GetFirst(&ic, &ir); ax->GetNext(&ic, &ir); )
- if(data->GetValue(ir, ic, &value))nr++;
+ ax->DataTypes(data, &c_num, &c_txt, &c_datetime);
+ nr = ax->CountItems();
if(!(yranges = split(yr, '&', &nc))){
delete CumData; delete ax; return 0L;
}
- if(CumData->Init(mode == 1 || mode == 2 ? nr : nr * 2, nc+2)){
- // set x values as first column
- for(i = n = 0, ax->GetFirst(&ic, &ir); ax->GetNext(&ic, &ir); i++) {
- if(data->GetValue(ir, ic, &value)){
- CumData->SetValue(n, 0, value); CumData->SetValue(n++, 1, base);
+ if(x_tv) x_tv->Reset(); if(y_tv) y_tv->Reset();
+ j = mode == 1 || mode == 2 ? nr : nr * 2;
+ if(CumData->Init(j , nc+2) && (validRows = (bool*)calloc(j, sizeof(bool)))){
+ if(!c_num && (c_txt + c_datetime) > 0 ) {
+ if(x_tv) tv = x_tv;
+ else if(y_tv) tv = y_tv;
+ else tv = x_tv = new TextValue();
+ }
+ //setup all ranges
+ if(!(ayy = (AccRange**)calloc(nc, sizeof(AccRange*))))return 0L;
+ for(i = 0; i < nc; i++) {
+ if(yranges[i] && *yranges[i] && (ayy[i] = new AccRange(yranges[i]))) {
+ if(!ayy[i]->GetFirst(&ic, &ir)) return 0L;
}
}
- if(mode == 3 || mode == 4) for(i = 1; i <= nr; i++) { //complete polygon data
- if(CumData->GetValue(nr-i, 0, &value)) CumData->SetValue(i-1+nr, 0, value);
- }
- //process all y-ranges
- for (j = 2; j <= (nc+1); j++) if(ay = new AccRange(yranges[j-2])){
- for(i = n = 0; i < nr; i++) {
- if(CumData->GetValue(n, j-1, &value)) CumData->SetValue(n++, j, value);
- }
- for(i = n = 0, ay->GetFirst(&ic, &ir); ay->GetNext(&ic, &ir) && n < nr; i++) {
- if(data->GetValue(ir, ic, &value) && CumData->GetValue(n, j, &old_val)){
- switch (mode) {
- case 1: case 3: value += old_val; break;
- case 2: case 4: value = old_val -value; break;
+ // set x values as first column
+ for(i = n = 0, ax->GetFirst(&ic, &ir); ax->GetNext(&ic, &ir); i++, n++) {
+ if(data->GetResult(&ares, ir, ic, false)) {
+ if(tv) {
+ switch(ares.type) {
+ case ET_TEXT:
+ value = tv->GetValue(ares.text); break;
+ default:
+ TranslateResult(&ares);
+ value = tv->GetValue(ares.text); break;
}
- CumData->SetValue(n++, j, value);
+ CumData->SetValue(n, 0, value); CumData->SetValue(n, 1, base);
}
+ else if(ares.type == ET_VALUE && ares.value > -HUGE_VAL && ares.value < HUGE_VAL) {
+ CumData->SetValue(n, 0, value = ares.value); CumData->SetValue(n, 1, base);
+ }
+ else {
+ CumData->SetValue(n, 0, value = 0.0); CumData->SetValue(n, 1, base);
+ }
+ if(mode == 3 || mode == 4){ //complete polygon data
+ CumData->SetValue((nr<<1)-i-1, 0, value);
+ }
+ for(j = 0; j < nc; j++) {
+ if(CumData->GetValue(n, j+1, &value)) CumData->SetValue(n, j+2, value);
+ if(ayy[j]->GetNext(&ic, &ir) && data->GetResult(&ares, ir, ic, false)){
+ if(ares.type == ET_VALUE && ares.value > -HUGE_VAL && ares.value < HUGE_VAL){
+ value = ares.value; validRows[i] = true;
+ }
+ else value = 0.0; old_val = 0.0;
+ CumData->GetValue(n, j+2, &old_val);
+ switch (mode) {
+ case 1: case 3: value += old_val; break;
+ case 2: case 4: value = old_val -value; break;
+ }
+ CumData->SetValue(n, j+2, value);
+ }
+ if(mode == 3 || mode == 4) //complete polygon data
+ if(CumData->GetValue(n, j+1, &value)){
+ if(validRows[n]) validRows[(nr<<1)-i-1] = true;
+ CumData->SetValue((nr<<1)-i-1, j+2, value);
+ }
+ }
+ }
+ else {
+ for(j = 0; j < nc; j++) ayy[j]->GetNext(&ic, &ir);
}
- if(mode == 3 || mode == 4) for(i = 1; i <= nr; i++) { //complete polygon data
- if(CumData->GetValue(nr-i, j-1, &value)) CumData->SetValue(i-1+nr, j, value);
+ }
+ for(i = 0; i < nc; i++) delete ayy[i]; free(ayy);
+ for(i = 0; i < CumData->cRows; i++) {
+ if(!validRows[i]) {
+ CumData->cRows--;
+ for(j = 0; j < CumData->cCols; j++) {
+ if(CumData->etRows[i][j]) delete CumData->etRows[i][j];
+ }
+ free(CumData->etRows[i]);
+ for(j = i; j < CumData->cRows; j++) {
+ CumData->etRows[j] = CumData->etRows[j+1];
+ validRows[j] = validRows[j+1];
+ }
+ if(!validRows[i] && i < CumData->cRows) i--;
}
- delete ay; ay = 0L;
}
+ free(validRows);
}
for(i = 0; i < nc; i++) if(yranges[i]) free(yranges[i]);
- if(ax) delete ax; if(ay) delete ay;
- free(yranges);
+ if(ax) delete ax; free(yranges);
return CumData;
}
@@ -281,9 +316,12 @@ PlotScatt::PlotScatt(int src):Plot(0L, 0L)
PlotScatt::~PlotScatt()
{
ForEach(FE_FLUSH, 0L, 0L);
- if(name) free(name); name=0L;
- if(x_info) free(x_info); x_info = 0L;
- if(y_info) free(x_info); y_info = 0L;
+ if(name) free(name); name=0L;
+ if(x_info) free(x_info); x_info = 0L;
+ if(y_info) free(x_info); y_info = 0L;
+ if(data_desc) free(data_desc); data_desc = 0L;
+ if(x_tv) delete(x_tv); x_tv = 0L;
+ if(y_tv) delete(y_tv); y_tv = 0L;
Undo.InvalidGO(this);
}
@@ -470,6 +508,14 @@ PlotScatt::Command(int cmd, void *tmpl, anyOutput *o)
data = (DataObj *)tmpl;
}
ForEach(cmd, tmpl, o);
+ if(cmd == CMD_AUTOSCALE) {
+ if(x_tv) {
+ Bounds.Xmin = 0.5; Bounds.Xmax = ((double)x_tv->Count())+0.5;
+ }
+ if(y_tv) {
+ Bounds.Ymin = 0.5; Bounds.Xmax = ((double)y_tv->Count())+0.5;
+ }
+ }
if(cmd == CMD_AUTOSCALE && parent && parent->Id >= GO_PLOT && parent->Id < GO_GRAPH
&& Bounds.Xmax > Bounds.Xmin && Bounds.Ymax > Bounds.Ymin) {
((Plot*)parent)->CheckBounds(Bounds.Xmin, Bounds.Ymin);
@@ -684,6 +730,7 @@ xyStat::~xyStat()
if(name) free(name); name=0L;
if(x_info) free(x_info); x_info = 0L;
if(y_info) free(x_info); y_info = 0L;
+ if(x_tv) delete(x_tv); x_tv = 0;
Undo.InvalidGO(this);
}
@@ -720,10 +767,11 @@ xyStat::Command(int cmd, void *tmpl, anyOutput *o)
void
xyStat::CreateData()
{
- int i, j, k, l, m, n, *ny;
- double x, y, ss, d, lo, hi, **ay, *ax, *tay, *q1, *q2, *q3;
+ int i, j, k, l, m, n, *ny, c_num, c_txt, c_dattim;
+ double y, ss, d, lo, hi, **ay, *ax, *tay, *q1, *q2, *q3;
lfPOINT *xy;
AccRange *rX, *rY;
+ anyResult x_res, y_res;
if(!data || !xRange || !yRange || !xRange[0] || !yRange[0]) return;
if(!(rX = new AccRange(xRange)) || !(rY = new AccRange(yRange))) return;
@@ -733,6 +781,7 @@ xyStat::CreateData()
delete rX; delete rY;
return;
}
+ if(x_tv) delete x_tv; x_tv = 0L;
ny = (int*) calloc(m, sizeof(int));
ay = (double**) calloc(m, sizeof(double*));
ax = (double*) calloc(m, sizeof(double));
@@ -743,12 +792,27 @@ xyStat::CreateData()
delete rX; delete rY;
return;
}
- rX->GetFirst(&i, &j); rY->GetFirst(&k, &l);
+ rX->DataTypes(data, &c_num, &c_txt, &c_dattim);
+ if(c_num < 5 && (c_txt + c_dattim) > 5) {
+ x_tv = new TextValue();
+ }
+ rX->GetFirst(&i, &j); rY->GetFirst(&k, &l); dirty = true;
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++;
+ if(data->GetResult(&x_res, j, i, false) && data->GetResult(&y_res, l, k, false) && y_res.type == ET_VALUE) {
+ xy[n].fy = y_res.value;
+ if(x_tv){
+ switch(x_res.type) {
+ case ET_TEXT:
+ xy[n++].fx = x_tv->GetValue(x_res.text);
+ break;
+ case ET_VALUE: case ET_BOOL: case ET_DATE: case ET_TIME: case ET_DATETIME:
+ TranslateResult(&x_res);
+ xy[n++].fx = x_tv->GetValue(x_res.text);
+ break;
+ }
+ }
+ else if(x_res.type == ET_VALUE) xy[n++].fx = x_res.value;
}
}while(rX->GetNext(&i, &j) && rY->GetNext(&k, &l));
delete rX; delete rY;
@@ -871,6 +935,20 @@ FreqDist::FreqDist(GraphObj *par, DataObj *d):Plot(par, d)
Id = GO_FREQDIST;
}
+FreqDist::FreqDist(GraphObj *par, DataObj *d, char* range, bool bOnce):Plot(par, d)
+{
+ FileIO(INIT_VARS);
+ if(range && range[0]) {
+ ssRef = (char*)memdup(range, (int)strlen(range)+1, 0);
+ plots = (GraphObj**)calloc(nPlots=3, sizeof(GraphObj*));
+ ProcData(-1);
+ if(bOnce && ssRef) {
+ free(ssRef); ssRef = 0L;
+ }
+ }
+ Id = GO_FREQDIST;
+}
+
FreqDist::FreqDist(int src):Plot(0L, 0L)
{
FileIO(INIT_VARS);
@@ -892,6 +970,7 @@ FreqDist::~FreqDist()
if(name) free(name); name=0L;
if(x_info) free(x_info); x_info = 0L;
if(y_info) free(y_info); y_info = 0L;
+ if(x_tv) delete x_tv; x_tv = 0L;
}
void
@@ -977,8 +1056,11 @@ FreqDist::Command(int cmd, void *tmpl, anyOutput *o)
case CMD_AUTOSCALE:
if(hidden) return false;
if(dirty){
- Bounds.Xmin = Bounds.Ymin = HUGE_VAL;
+ Bounds.Xmin = HUGE_VAL; Bounds.Ymin = 0;
Bounds.Xmax = Bounds.Ymax = -HUGE_VAL;
+ if(dmax > dmin) {
+ Bounds.Xmin = dmin; Bounds.Xmax = dmax;
+ }
}
else{
if(parent && parent->Id >= GO_PLOT && parent->Id < GO_GRAPH &&
@@ -1020,48 +1102,85 @@ void
FreqDist::ProcData(int sel)
{
AccRange *ar;
- int nv, i, j, r, c, ncl, *f_data, cb_f, size_fo, pos_fo;
- double dmin = HUGE_VAL, dmax = -HUGE_VAL, min, max, sum, mean, sd, tmp, *s_data, *t_data, lstep;
+ int nv, i, j, r, c, ncl, *f_data, cb_f, size_fo, pos_fo, c_num, c_txt, c_dattim;
+ double min, max, sum, mean, sd, tmp, *s_data, *t_data, lstep;
double chi2, df, x, y;
anyResult *result;
+ bool bValid = false;
Bar **bars = 0L;
+ anyResult res;
TextDEF td;
char *fo, *fdesc = 0L, formula[500];
if(!parent || !data || !ssRef || !plots) return;
- if(curr_data) delete(curr_data);
+ if(curr_data) delete(curr_data); curr_data = 0L;
+ if(x_tv) delete x_tv; x_tv = 0L;
if((curr_data = new DataObj()) && (ar = new AccRange(ssRef))) {
+ if(!y_info && (y_info = (char*)malloc(25*sizeof(char)))) rlp_strcpy(y_info, 25, "No. of observations");
+ dmin = HUGE_VAL, dmax = -HUGE_VAL;
+ ar->DataTypes(data, &c_num, &c_txt, &c_dattim);
+ if(c_num < 5 && (c_txt + c_dattim) > 5) {
+ x_tv = new TextValue(); dmin = 0.0;
+ }
//copy spreadsheet data into array
nv = ar->CountItems(); ar->GetFirst(&c, &r);
if(!(s_data = (double*)malloc(nv * sizeof(double)))
|| !(t_data = (double*)malloc(nv * sizeof(double)))) {
delete(ar); return;
}
- for(sum = 0.0, nv = 0; ar->GetNext(&c, &r); ) if(data->GetValue(r, c, &tmp)) {
- if(tmp > dmax) dmax = tmp; if(tmp < dmin) dmin = tmp;
- s_data[nv] = tmp;
- switch (type & 0xff){
- case 2:
- if(tmp > 0.0) t_data[nv] = log(tmp);
- else nv--;
- break;
- default: t_data[nv] = tmp; break;
+ for(sum = 0.0, nv = 0; ar->GetNext(&c, &r); ) if(data->GetResult(&res, r, c, false)) {
+ if(x_tv){
+ switch(res.type) {
+ case ET_TEXT:
+ if((tmp = x_tv->GetValue(res.text))> 0.0)bValid = true;
+ else bValid = false; break;
+ case ET_VALUE: case ET_DATE: case ET_TIME: case ET_DATETIME: case ET_BOOL:
+ TranslateResult(&res);
+ if((tmp = x_tv->GetValue(res.text))> 0.0)bValid = true;
+ else bValid = false; break;
+ default:
+ bValid = false; break;
+ }
+ }
+ else {
+ if(res.type == ET_VALUE) {
+ tmp = res.value; bValid = true;
+ }
+ else bValid = false;
+ }
+ if(bValid) {
+ if(tmp > dmax) dmax = tmp; if(tmp < dmin) dmin = tmp;
+ s_data[nv] = tmp;
+ switch (type & 0xff){
+ case 2:
+ if(tmp > 0.0) t_data[nv] = log(tmp);
+ else nv--;
+ break;
+ default: t_data[nv] = tmp; break;
+ }
+ nv++;
}
- nv++;
+ }
+ delete(ar);
+ if(!nv || dmin >= dmax) {
+ free(s_data); s_data = 0L; free(t_data); t_data = 0L;
+ return;
}
min = dmin; max = dmax;
lstep = (max-min)/100.0;
- delete(ar);
d_variance(nv, t_data, &mean, &sd);
sd = sqrt(sd/((double)(nv-1)));
step = fabs(step);
- if(sel == -1) {
+ if(x_tv) {
+ start = 0.5; step = 1.0; max+= 0.5;
+ }
+ else if(sel == -1) {
start = min; step = (max - min)/(step != 0.0 ? step : 7.0);
}
else if(sel == -2) {
min = start;
}
- ncl = (int)(floor((max-start)/step));
+ ncl = (int)(floor((max-start)/step))+1;
if(plots[0] && (max > (Bounds.Xmax+step/2.0) || min < (Bounds.Xmin-step/2.0))) {
DeleteGO(plots[0]); plots[0] = 0L;
}
@@ -1091,6 +1210,7 @@ FreqDist::ProcData(int sel)
plots[0]->SetSize(SIZE_BAR_LINE, BarLine.width);
}
if(plots[0]){
+ Bounds.Xmin = dmin; Bounds.Xmax = dmax;
plots[0]->Command(CMD_SET_DATAOBJ, curr_data, 0L);
plots[0]->Command(CMD_AUTOSCALE, 0L, 0L);
}
@@ -1915,8 +2035,12 @@ BoxPlot::~BoxPlot()
if(curr_data) delete curr_data; curr_data = 0L;
if(xRange) free(xRange); xRange = 0L;
if(yRange) free(yRange); yRange = 0L;
+ if(x_info) free(x_info); x_info = 0L;
+ if(y_info) free(y_info); y_info = 0L;
if(case_prefix) free(case_prefix); case_prefix = 0L;
- if(name) free(name); name=0L;
+ if(name) free(name); name = 0L;
+ if(x_tv) delete(x_tv); x_tv = 0;
+ if(y_tv) delete(y_tv); y_tv = 0;
Undo.InvalidGO(this);
}
@@ -2069,6 +2193,9 @@ BoxPlot::Command(int cmd, void *tmpl, anyOutput *o)
}
dirty = false;
ForEach(cmd, tmpl, o);
+ if(x_tv) {
+ Bounds.Xmin = 0.5; Bounds.Xmax = ((double)x_tv->Count())+0.5;
+ }
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);
@@ -2076,10 +2203,12 @@ BoxPlot::Command(int cmd, void *tmpl, anyOutput *o)
}
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(parent) {
+ 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);
@@ -2189,10 +2318,11 @@ BoxPlot::ForEach(int cmd, void *tmpl, anyOutput *o)
void
BoxPlot::CreateData()
{
- int i, j, k, l, m, n, *ny;
- double x, y, ss, d, lo, hi, **ay, *ax, *tay, *q1, *q2, *q3;
+ int i, j, k, l, m, n, *ny, c_num, c_txt, c_dattim;
+ double y, ss, d, lo, hi, **ay, *ax, *tay, *q1, *q2, *q3;
lfPOINT *xy;
AccRange *rX, *rY;
+ anyResult x_res, y_res;
if(curr_data) delete curr_data; curr_data = 0L;
if(!data || !xRange || !yRange || !xRange[0] || !yRange[0]) return;
@@ -2202,6 +2332,7 @@ BoxPlot::CreateData()
delete rX; delete rY;
return;
}
+ if(x_tv) delete x_tv; x_tv = 0L;
ny = (int*) calloc(m, sizeof(int));
ay = (double**) calloc(m, sizeof(double*));
ax = (double*) calloc(m, sizeof(double));
@@ -2212,12 +2343,27 @@ BoxPlot::CreateData()
delete rX; delete rY;
return;
}
+ rX->DataTypes(data, &c_num, &c_txt, &c_dattim);
+ if(c_num < 5 && (c_txt + c_dattim) > 5) {
+ x_tv = new TextValue();
+ }
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++;
+ if(data->GetResult(&x_res, j, i, false) && data->GetResult(&y_res, l, k, false) && y_res.type == ET_VALUE) {
+ xy[n].fy = y_res.value;
+ if(x_tv){
+ switch(x_res.type) {
+ case ET_TEXT:
+ xy[n++].fx = x_tv->GetValue(x_res.text);
+ break;
+ case ET_VALUE: case ET_BOOL: case ET_DATE: case ET_TIME: case ET_DATETIME:
+ TranslateResult(&x_res);
+ xy[n++].fx = x_tv->GetValue(x_res.text);
+ break;
+ }
+ }
+ else if(x_res.type == ET_VALUE) xy[n++].fx = x_res.value;
}
}while(rX->GetNext(&i, &j) && rY->GetNext(&k, &l));
delete rX; delete rY;
@@ -2629,6 +2775,8 @@ StackBar::~StackBar()
if(ssXrange) free(ssXrange); if(ssYrange) free(ssYrange);
if(CumData) delete CumData; CumData = 0L;
if(name) free(name); name=0L;
+ if(x_tv) delete x_tv; x_tv = 0L;
+ if(y_tv) delete y_tv; y_tv = 0L;
Undo.InvalidGO(this);
}
@@ -2777,9 +2925,7 @@ StackBar::Command(int cmd, void *tmpl, anyOutput *o)
}
if(cum_data_mode){
if(CumData) delete CumData;
- CumData = CreaCumData(ssXrange, ssYrange, cum_data_mode, StartVal);
- if(cmd == CMD_SET_DATAOBJ) tmpl = CumData;
- if(cmd == CMD_UPDATE && CumData) {
+ if(CumData = CreaCumData(ssXrange, ssYrange, cum_data_mode, StartVal)) {
if(Polygons) for(i = 0; i < numPG; i++)
if(Polygons[i]) Polygons[i]->Command(CMD_SET_DATAOBJ, CumData, o);
if(Lines) for(i = 0; i < numPL; i++)
@@ -2790,6 +2936,7 @@ StackBar::Command(int cmd, void *tmpl, anyOutput *o)
if(Boxes[i]) Boxes[i]->Command(CMD_SET_DATAOBJ, CumData, o);
}
}
+ if(cmd == CMD_SET_DATAOBJ) tmpl = (void*) CumData;
if(Polygons) for(i = 0; i < numPG; i++)
if(Polygons[i]) Polygons[i]->Command(cmd, tmpl, o);
if(Lines) for(i = 0; i < numPL; i++)
@@ -3186,27 +3333,28 @@ Scatt3D::~Scatt3D()
Undo.InvalidGO(this);
if(Balls) {
for(i = 0; i < nBalls; i++) if(Balls[i]) DeleteGO(Balls[i]);
- free(Balls); Balls = 0L;
+ free(Balls); Balls = 0L;
}
if(Columns) {
for(i = 0; i < nColumns; i++) if(Columns[i]) DeleteGO(Columns[i]);
- free(Columns); Columns = 0L;
+ free(Columns); Columns = 0L;
}
if(DropLines) {
for(i = 0; i < nDropLines; i++) if(DropLines[i]) DeleteGO(DropLines[i]);
- free(DropLines); DropLines = 0L;
+ free(DropLines); DropLines = 0L;
}
if(Arrows) {
for(i = 0; i < nArrows; i++) if(Arrows[i]) DeleteGO(Arrows[i]);
- free(Arrows); Arrows = 0L;
+ free(Arrows); Arrows = 0L;
}
if(Line) {
- DeleteGO(Line); Line = 0L;
+ DeleteGO(Line); Line = 0L;
}
if(rib) {
- DeleteGO(rib); rib = 0L;
+ DeleteGO(rib); rib = 0L;
}
- if(name) free(name); name=0L;
+ if(name) free(name); name=0L;
+ if(data_desc) free(data_desc); data_desc = 0L;
}
double
@@ -3269,8 +3417,10 @@ Scatt3D::DoPlot(anyOutput *o)
long i;
RECT rc;
- if(!o) return;
+ if(!o || !parent) return;
+ if(use_xaxis || use_yaxis || use_zaxis) ApplyAxes(o);
o->GetSize(&rc);
+ parent->Command(CMD_REG_AXISPLOT, (void*)this, o);
rDims.left = rc.right; rDims.right = rc.left;
rDims.top = rc.bottom; rDims.bottom = rc.top;
if(Balls) {
@@ -3319,6 +3469,7 @@ Scatt3D::DoPlot(anyOutput *o)
UpdateMinMaxRect(&rDims, rib->rDims.right, rib->rDims.top);
UpdateMinMaxRect(&rDims, rib->rDims.left, rib->rDims.bottom);
}
+ if(use_xaxis || use_yaxis || use_zaxis)parent->Command(CMD_AXIS, 0L, o);
dirty = false;
}
@@ -3377,6 +3528,8 @@ Scatt3D::Command(int cmd, void *tmpl, anyOutput *o)
if(Arrows) for(i = 0; i < nArrows; i++)
if(Arrows[i]) Arrows[i]->Command(cmd, tmpl, o);
return true;
+ case CMD_USEAXIS:
+ return UseAxis(*((int*)tmpl));
case CMD_LEGEND:
if(!tmpl) return false;
if(Balls) {
@@ -3541,8 +3694,9 @@ Ribbon::~Ribbon()
for(i = 0; i < nPlanes; i++) if(planes[i]) DeleteGO(planes[i]);
free(planes); planes = 0L;
}
- if(values) free(values); values = 0L; nVal = 0;
- if(name) free(name); name=0L;
+ if(values) free(values); values = 0L; nVal = 0;
+ if(name) free(name); name=0L;
+ if(data_desc) free(data_desc); data_desc = 0L;
}
double
@@ -3698,6 +3852,7 @@ Ribbon::CreateObs()
if(!ssRefX || !ssRefY) return;
if(z_width == 0.0) z_width = 1.0; if(relwidth == 0.0) relwidth = 0.6;
if((rX = new AccRange(ssRefX)) && (rY = new AccRange(ssRefY))) {
+ if(!data_desc) data_desc = rY->RangeDesc(data, 1);
tmp = relwidth*z_width/2.0;
if(!(values = (fPOINT3D*)calloc(i = rX->CountItems(), sizeof(fPOINT3D)))){
delete rX; delete rY; return;
@@ -3705,17 +3860,18 @@ Ribbon::CreateObs()
if(!(planes = (Plane3D**)calloc(i-1, sizeof(Plane3D*)))){
free(values); values = 0L; delete rX; delete rY; return;
}
- for(i = 0, rX->GetFirst(&cx, &rx), rY->GetFirst(&cy, &ry);
+ for(i = j = 0, rX->GetFirst(&cx, &rx), rY->GetFirst(&cy, &ry);
rX->GetNext(&cx, &rx) && rY->GetNext(&cy, &ry); i++) {
if(data->GetValue(rx, cx, &fx) && data->GetValue(ry, cy, &fy)) {
values[i].fx = fx; values[i].fy = fy; values[i].fz = z_value;
pg[3].fx = pg[2].fx = fx; pg[3].fy = pg[2].fy = fy;
pg[2].fz = z_value - tmp; pg[3].fz = z_value +tmp;
- if(i) {
+ if(j) {
pg[4].fx = pg[0].fx; pg[4].fy = pg[0].fy; pg[4].fz = pg[0].fz;
planes[i-1] = new Plane3D(this, data, pg, 5);
if(planes[i-1]) planes[i-1]->Command(CMD_PG_FILL, &Fill, 0L);
}
+ j++;
pg[0].fx = pg[3].fx; pg[0].fy = pg[3].fy; pg[0].fz = pg[3].fz;
pg[1].fx = pg[2].fx; pg[1].fy = pg[2].fy; pg[1].fz = pg[2].fz;
}
@@ -3732,6 +3888,7 @@ Ribbon::CreateObs()
if(!(planes = (Plane3D**)calloc(i-1, sizeof(Plane3D*)))){
free(values); values = 0L; delete rX; delete rY; delete rZ; return;
}
+ if(!data_desc) data_desc = rY->RangeDesc(data, 1);
for(i = 0, rX->GetFirst(&cx, &rx), rY->GetFirst(&cy, &ry), rZ->GetFirst(&cz, &rz);
rX->GetNext(&cx, &rx) && rY->GetNext(&cy, &ry) && rZ->GetNext(&cz, &rz); i++) {
if(data->GetValue(rx, cx, &fx) && data->GetValue(ry, cy, &fy) &&
@@ -4258,13 +4415,20 @@ Function::Update(anyOutput *o, DWORD flags)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Calculate and display a user defined function
+static char *lastFunc2D = 0L, *lastParam2D=0L;
FitFunc::FitFunc(GraphObj *par, DataObj *d):Plot(par, d)
{
FileIO(INIT_VARS);
- x1 = 0.0; x2 = 100.0; xstep = 0.5; dl = 0L;
- cmdxy = (char*)malloc(20*sizeof(char)); parxy = (char*)malloc(20*sizeof(char));
- if(cmdxy) rlp_strcpy(cmdxy, 20, "a+b*x^c");
- if(parxy) rlp_strcpy(parxy, 20, "a=1; b=1; c=0.1;");
+ x1 = 0.0; x2 = 100.0; xstep = 0.5; dl = 0L;
+ if(lastFunc2D && lastFunc2D[0] && lastParam2D && lastParam2D[0]) {
+ cmdxy = (char*)memdup(lastFunc2D, (int)strlen(lastFunc2D)+1, 0);
+ parxy = (char*)memdup(lastParam2D, (int)strlen(lastParam2D)+1, 0);
+ }
+ if(!cmdxy || !parxy) {
+ cmdxy = (char*)malloc(20*sizeof(char)); parxy = (char*)malloc(20*sizeof(char));
+ if(cmdxy) rlp_strcpy(cmdxy, 20, "a+b*x^c");
+ if(parxy) rlp_strcpy(parxy, 20, "a=1; b=1; c=0.1;");
+ }
Id = GO_FITFUNC;
}
@@ -4277,7 +4441,6 @@ FitFunc::FitFunc(int src):Plot(0L, 0L)
}
}
-
FitFunc::~FitFunc()
{
int i;
@@ -4366,6 +4529,17 @@ FitFunc::Command(int cmd, void *tmpl, anyOutput *o)
return true;
}
return false;
+ case CMD_ENDDIALOG:
+ if(!cmdxy || !parxy) return false;
+ if(i = (int)strlen(cmdxy)) {
+ if(lastFunc2D = (char*)realloc(lastFunc2D, i+2))
+ rlp_strcpy(lastFunc2D, i+1, cmdxy);
+ }
+ if(i = (int)strlen(parxy)) {
+ if(lastParam2D = (char*)realloc(lastParam2D, i+2))
+ rlp_strcpy(lastParam2D, i+1, parxy);
+ }
+ return true;
case CMD_SCALE:
if(dl) return dl->Command(cmd, tmpl, o);
if(Symbols) for(i = 0; i < nPoints; i++) if(Symbols[i]) Symbols[i]->Command(cmd, tmpl, o);
@@ -4453,6 +4627,131 @@ FitFunc::Command(int cmd, void *tmpl, anyOutput *o)
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// normal quantile plot and derivates
+NormQuant::NormQuant(GraphObj *par, DataObj *d, char* range)
+ :Plot(par, d)
+{
+ FileIO(INIT_VARS);
+ if(range && range[0]) ssRef = (char*)memdup(range, (int)strlen(range)+1, 0);
+ else ssRef = 0L;
+ Id = GO_NORMQUANT;
+}
+
+NormQuant::NormQuant(GraphObj *par, DataObj *d, double *val, int nval)
+ :Plot(par, d)
+{
+ FileIO(INIT_VARS); ssRef = 0L;
+ if(val && nval) {
+ src_data = (double*)memdup(val, nval*sizeof(double), 0);
+ SortArray(nData = nval, src_data); ProcessData();
+ }
+ Id = GO_NORMQUANT;
+}
+
+NormQuant::NormQuant(int src):Plot(0L, 0L)
+{
+ FileIO(INIT_VARS);
+ if(src == FILE_READ) {
+ FileIO(FILE_READ);
+ if(nData)SortArray(nData, src_data); ProcessData();
+ }
+}
+
+NormQuant::~NormQuant()
+{
+ if(ssRef) free(ssRef); ssRef = 0L;
+ if(x_info) free(x_info); x_info = 0L;
+ if(y_info) free(y_info); y_info = 0L;
+ if(x_vals) free(x_vals); x_vals = 0L;
+ if(y_vals) free(y_vals); y_vals = 0L;
+ if(src_data)free(src_data); src_data = 0L;
+ if(sy)delete(sy);
+}
+
+void
+NormQuant::DoPlot(anyOutput *o)
+{
+ int i;
+
+ //draw symbols
+ if(sy && y_vals && src_data && y_vals && nValidData) {
+ sy->SetSize(SIZE_SYMBOL, defs.GetSize(SIZE_SYMBOL)/10.0);
+ for(i = 0; i < nValidData; i++) {
+ sy->SetSize(SIZE_XPOS, x_vals[i]);
+ sy->SetSize(SIZE_YPOS, y_vals[i]);
+ sy->DoPlot(o);
+ }
+ }
+}
+
+bool
+NormQuant::Command(int cmd, void *tmpl, anyOutput *o)
+{
+ switch(cmd) {
+ case CMD_LEGEND:
+ if(sy) ((Legend*)tmpl)->HasSym(0L, sy, x_info ? x_info : (char*)"Data");
+ return true;
+ case CMD_SCALE:
+ return true;
+ case CMD_UPDATE:
+ return true;
+ case CMD_REDRAW:
+ if(parent) return parent->Command(cmd, tmpl, o);
+ break;
+ case CMD_SET_DATAOBJ:
+ Id = GO_NORMQUANT;
+ if(sy) sy->Command(cmd, tmpl, o);
+ data = (DataObj *)tmpl;
+ return true;
+ }
+ return false;
+}
+
+bool
+NormQuant::ProcessData()
+{
+ int i, r, c, n;
+ AccRange *rD;
+ double y, dtmp, sum;
+
+ if(data && ssRef && ssRef[0] && (rD = new AccRange(ssRef))) {
+ if((n = rD->CountItems()) && (src_data = (double*)realloc(src_data, n * sizeof(double)))){
+ for(nData = 0, rD->GetFirst(&c, &r); rD->GetNext(&c, &r); ) {
+ if(data->GetValue(r, c, &dtmp)) src_data[nData++] = dtmp;
+ }
+ if(nData)SortArray(nData, src_data);
+ }
+ if(y_info = (char*)malloc(20)){
+ rlp_strcpy(y_info, 20, "Normal quantiles");
+ }
+ x_info = rD->RangeDesc(data, 2);
+ delete rD;
+ }
+ if(src_data && nData) {
+ Bounds.Ymin = HUGE_VAL; Bounds.Ymax = -HUGE_VAL;
+ x_vals = (double*)realloc(x_vals, nData * sizeof(double));
+ y_vals = (double*)realloc(y_vals, nData * sizeof(double));
+ for(n = i = 0, sum = dtmp = 1.0/((double)nData); i < (nData-1); i++ ) {
+ y = distinv(norm_dist, 0.0, 1.0, sum, 0.5);
+ if(y > -HUGE_VAL && y < HUGE_VAL) {
+ y_vals[n] = y; x_vals[n] = src_data[i];
+ if(y < Bounds.Ymin) Bounds.Ymin = y;
+ if(y > Bounds.Ymax) Bounds.Ymax = y;
+ n++;
+ }
+ sum += dtmp;
+ }
+ Bounds.Xmax = src_data[nData-1]; Bounds.Xmin = src_data[0];
+ if(Bounds.Ymax <= Bounds.Ymin) {
+ Bounds.Ymin = -5.0; Bounds.Ymax = 5.0;
+ }
+ nValidData = n;
+ return (n > 3);
+ }
+ return false;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// three dimensional graph
Plot3D::Plot3D(GraphObj *par, DataObj *d, DWORD flags):Plot(par, d)
{
@@ -4493,6 +4792,8 @@ Plot3D::~Plot3D()
free(Axes);
}
plots = 0L; nPlots = nAxes = 0;
+ if(nscp > 0 && nscp <= nPlots && Sc_Plots) free(Sc_Plots);
+ nscp = 0; Sc_Plots = 0L;
if(drag) DeleteGO(drag); drag = 0L;
if(dispObs) free(dispObs); dispObs = 0L;
free(RotDef);
@@ -4572,17 +4873,28 @@ Plot3D::DoPlot(anyOutput *o)
nObs = 0;
if(!parent || !o) return;
- o->MouseCursor(MC_WAIT, true);
+ if(nscp > 0 && nscp <= nPlots && Sc_Plots) free(Sc_Plots);
+ nscp = 0; Sc_Plots = 0L; o->MouseCursor(MC_WAIT, true);
if(dirty) DoAutoscale();
if(Axes && nAxes >2) { //if no axes then parent is another Plot3D ...
- o->LightSource(32.0, 16.0);
+ o->LightSource(32.0, 16.0); CurrAxes = Axes;
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());
+ if(nAxes >3) { //DEBUG
+ nAxes = nAxes;
+ }
for(i = 0; i< nAxes; i++) if(Axes[i]) Axes[i]->DoPlot(o);
}
+ else if(IsPlot3D(parent)) {
+ if (use_xaxis || use_yaxis || use_zaxis)ApplyAxes(o);
+ parent->Command(CMD_REG_AXISPLOT, (void*)this, o);
+ }
+ else {
+ CurrAxes = 0L;
+ }
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);
@@ -4620,6 +4932,7 @@ Plot3D::DoPlot(anyOutput *o)
}
for (i = 1; i <= nObs; i++) dispObs[i]->go->Command(CMD_REDRAW, 0L, o);
}
+ if(IsPlot3D(parent) && (use_xaxis || use_yaxis || use_zaxis))parent->Command(CMD_AXIS, 0L, o);
dirty = false;
o->MouseCursor(MC_ARROW, true);
}
@@ -4667,6 +4980,35 @@ Plot3D::Command(int cmd, void *tmpl, anyOutput *o)
return true;
}
break;
+ case CMD_USEAXIS:
+ if(IsPlot3D(parent)) return UseAxis(*((int*)tmpl));
+ break;
+ case CMD_REG_AXISPLOT: //notification: plot can handle its own axes
+ if(nscp > 0 && nscp <= nPlots && Sc_Plots) {
+ for(i = 0; i < nscp; i++)
+ if(Sc_Plots[i] == (GraphObj*)tmpl) return true;
+ if(tmpPlots = (GraphObj**)realloc(Sc_Plots, (nscp+1)*sizeof(GraphObj*))){
+ tmpPlots[nscp++] = (GraphObj *)tmpl;
+ Sc_Plots = tmpPlots;
+ }
+ else { //memory allocation error
+ nscp = 0;
+ Sc_Plots = 0L;
+ }
+ }
+ else {
+ if(Sc_Plots = (GraphObj **)calloc(1, sizeof(GraphObj*))){
+ Sc_Plots[0] = (GraphObj *)tmpl;
+ nscp = 1;
+ }
+ else nscp = 0;
+ }
+ return true;
+ case CMD_AXIS: //one of the plots has changed scaling: reset
+ CurrAxes = Axes;
+ if(o) o->SetSpace(&cu1, &cu2, defs.cUnits, RotDef, &rc, Axes[0]->GetAxis(),
+ Axes[1]->GetAxis(), Axes[2]->GetAxis());
+ return true;
case CMD_HIDE_MARK:
if(!tmpl) return false;
//do all axes
@@ -4707,10 +5049,12 @@ Plot3D::Command(int cmd, void *tmpl, anyOutput *o)
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!");
+ if(AddAxis()){
+ if(parent) return parent->Command(CMD_REDRAW, tmpl, o);
+ }
return false;
case CMD_SET_GO3D:
- if(IsPlot3D(parent)) return parent->Command(cmd, tmpl, o);
+ if(IsPlot3D(parent)) return parent->Command(CMD_REDRAW, 0L, o);
return AcceptObj((GraphObj *)tmpl);
case CMD_SETSCROLL: case CMD_REDRAW:
if(parent) return parent->Command(cmd, tmpl, o);
@@ -5324,13 +5668,20 @@ Func3D::Update()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// fit 3D function to data
+static char *lastFunc3D = 0L, *lastParam3D=0L;
FitFunc3D::FitFunc3D(GraphObj *par, DataObj *d)
:Plot3D(par, d, 0x0L)
{
FileIO(INIT_VARS);
- cmdxy = (char*)malloc(20*sizeof(char)); param = (char*)malloc(20*sizeof(char));
- if(cmdxy) rlp_strcpy(cmdxy, 20, (char*)"a+b*x^c");
- if(param) rlp_strcpy(param, 20, (char*)"a=1; b=1; c=0.1;");
+ if(lastFunc3D && lastFunc3D[0] && lastParam3D && lastParam3D[0]) {
+ cmdxy = (char*)memdup(lastFunc3D, (int)strlen(lastFunc3D)+1, 0);
+ param = (char*)memdup(lastParam3D, (int)strlen(lastParam3D)+1, 0);
+ }
+ if(!cmdxy || !param) {
+ cmdxy = (char*)malloc(20*sizeof(char)); param = (char*)malloc(20*sizeof(char));
+ if(cmdxy) rlp_strcpy(cmdxy, 20, (char*)"a+b*x^c");
+ if(param) rlp_strcpy(param, 20, (char*)"a=1; b=1; c=0.1;");
+ }
Id = GO_FITFUNC3D;
}
@@ -5360,7 +5711,20 @@ FitFunc3D::~FitFunc3D()
bool
FitFunc3D::Command(int cmd, void *tmpl, anyOutput *o)
{
+ int i;
+
switch(cmd) {
+ case CMD_ENDDIALOG:
+ if(!cmdxy || !param) return false;
+ if(i = (int)strlen(cmdxy)) {
+ if(lastFunc3D = (char*)realloc(lastFunc3D, i+2))
+ rlp_strcpy(lastFunc3D, i+1, cmdxy);
+ }
+ if(i = (int)strlen(param)) {
+ if(lastParam3D = (char*)realloc(lastParam3D, i+2))
+ rlp_strcpy(lastParam3D, i+1, param);
+ }
+ return true;
case CMD_SET_DATAOBJ:
Plot3D::Command(cmd, tmpl, o);
if(gob && gda) gob->Command(cmd, gda, o);
diff --git a/PropertyDlg.cpp b/PropertyDlg.cpp
index 68ceff3..65c8e0e 100755
--- a/PropertyDlg.cpp
+++ b/PropertyDlg.cpp
@@ -1,4 +1,4 @@
-//PropertyDlg.cpp, Copyright (c) 2001-2006 R.Lackner
+//PropertyDlg.cpp, Copyright (c) 2001-2007 R.Lackner
//Property dialogs for graphic objects
//
// This file is part of RLPlot.
@@ -658,7 +658,8 @@ static char *LineDlg_DlgTmpl =
"208,209,,EXRADIO,ODBUTTON,10,87,70,25,25\n"
"209,210,,EXRADIO,ODBUTTON,10,112,70,25,25\n"
"210,211,,EXRADIO,ODBUTTON,10,37,95,25,25\n"
- "211,,,EXRADIO,ODBUTTON,10,62,95,25,25\n"
+ "211,212,,EXRADIO,ODBUTTON,10,62,95,25,25\n"
+ "212,,,EXRADIO,ODBUTTON,10,87,95,25,25\n"
"300,301,,,LTEXT,5,15,30,80,9\n"
"301,302,,,EDTEXT,7,15,40,119,10\n"
"302,303,,,LTEXT,6,15,55,80,9\n"
@@ -698,8 +699,8 @@ DataLine::PropertyDlg()
LoopDlgWnd();
res = Dlg->GetResult();
switch (res) {
- case 201: case 202: case 203: case 204: case 205:
- case 206: case 207: case 208: case 209: case 210: case 211:
+ case 201: case 202: case 203: case 204: case 205: case 206:
+ case 207: case 208: case 209: case 210: case 211: case 212:
if((tmpType & 0x0f) == (res-201)) res = 1;
else {
tmpType &= ~0x0f; tmpType |= (res-201);
@@ -711,16 +712,13 @@ DataLine::PropertyDlg()
if(res == 1){ //OK pressed
Undo.SetDisp(cdisp);
if(ssXref && ssYref) {
- if(Dlg->GetText(301, TmpTxt, TMP_TXT_SIZE) && strcmp(ssXref, TmpTxt)) {
- cb = Undo.String(this, &ssXref, undo_flags); undo_flags |= UNDO_CONTINUE;
- if(ssXref = (char*)realloc(ssXref, (cb+=2))) rlp_strcpy(ssXref, cb, TmpTxt);
- }
- if(Dlg->GetText(303, TmpTxt, TMP_TXT_SIZE) && strcmp(ssYref, TmpTxt)) {
- cb = Undo.String(this, &ssYref, undo_flags); undo_flags |= UNDO_CONTINUE;
- if(ssYref = (char*)realloc(ssYref, (cb+=2))) rlp_strcpy(ssYref, cb, TmpTxt);
+ TmpTxt[0] = 0; Dlg->GetText(301, TmpTxt, TMP_TXT_SIZE);
+ undo_flags = CheckNewString(&ssXref, ssXref, TmpTxt, this, undo_flags);
+ TmpTxt[0] = 0; Dlg->GetText(303, TmpTxt, TMP_TXT_SIZE);
+ undo_flags = CheckNewString(&ssYref, ssYref, TmpTxt, this, undo_flags);
+ if(undo_flags & UNDO_CONTINUE) {
+ Command(CMD_UPDATE, 0L, cdisp); parent->Command(CMD_MRK_DIRTY, 0L, cdisp);
}
- 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)) {
@@ -1120,6 +1118,7 @@ ErrorBar::PropertyDlg()
Dlg->Activate(307, true); res = -1; break;
case 1: //accept for this object
case 2: // or all objects of plot
+ desc[0] = 0;
Undo.SetDisp(cdisp); Dlg->GetText(307, desc, 80);
Dlg->GetValue(101, &n_sb); Dlg->GetValue(104, &n_lw);
Dlg->GetColor(107, &n_col); Dlg->GetValue(305, &n_err);
@@ -1132,20 +1131,7 @@ ErrorBar::PropertyDlg()
undo_flags = CheckNewFloat(&ferr, o_err, n_err, parent, undo_flags);
undo_flags = CheckNewLFPoint(&fPos, &o_pos, &n_pos, parent, undo_flags);
if(undo_flags & UNDO_CONTINUE) parent->Command(CMD_MRK_DIRTY, 0L, 0L);
- if(desc[0] && name && name[0] && strcmp(desc, name)) {
- cb = Undo.String(this, &name, undo_flags);
- name = (char*)realloc(name, (cb+=2));
- rlp_strcpy(name, cb, desc); undo_flags |= UNDO_CONTINUE;
- }
- else if(desc[0] && !name) {
- cb = Undo.String(this, &name, undo_flags);
- name = (char*)realloc(name, (cb+=2));
- rlp_strcpy(name, cb, desc); undo_flags |= UNDO_CONTINUE;
- }
- else if(!desc[0] && name && name[0]) {
- Undo.String(this, &name, undo_flags);
- name[0] = 0; undo_flags |= UNDO_CONTINUE;
- }
+ undo_flags = CheckNewString(&name, name, desc, this, undo_flags);
undo_flags = CheckNewFloat(&SizeBar, o_sb, n_sb, parent, undo_flags);
undo_flags = CheckNewFloat(&ErrLine.width, o_lw, n_lw, parent, undo_flags);
undo_flags = CheckNewDword(&ErrLine.color, ErrLine.color, n_col, parent, undo_flags);
@@ -1538,26 +1524,13 @@ Whisker::PropertyDlg()
case 2: // or all objects of plot
Undo.SetDisp(cdisp); Dlg->GetValue(101, &n_size);
Dlg->GetValue(104, &n_lw); Dlg->GetColor(107, &n_col);
- Dlg->GetText(309, desc, 80);
+ desc[0] = 0; Dlg->GetText(309, desc, 80);
break;
}
}while (res <0);
switch (res) {
case 1: //new setting for current whisker
- if(desc[0] && name && name[0] && strcmp(desc, name)) {
- cb = Undo.String(this, &name, undo_flags);
- name = (char*)realloc(name, (cb+=2));
- rlp_strcpy(name, cb, desc); undo_flags |= UNDO_CONTINUE;
- }
- else if(desc[0]) {
- cb = Undo.String(this, &name, undo_flags);
- name = (char*)realloc(name, (cb+=2));
- rlp_strcpy(name, cb, desc); undo_flags |= UNDO_CONTINUE;
- }
- else if(name && name[0]) {
- Undo.String(this, &name, undo_flags);
- name[0] = 0; undo_flags |= UNDO_CONTINUE;
- }
+ undo_flags = CheckNewString(&name, name, desc, this, undo_flags);
if(Dlg->GetValue(301, &tmpVal)) n_pos.fx = tmpVal;
else n_pos.fx = pos1.fx;
if(Dlg->GetValue(303, &tmpVal)) n_pos.fy = tmpVal;
@@ -2361,7 +2334,7 @@ Label::PropertyDlg()
{603, 0, 0, LASTOBJ | TOUCHEXIT, ODBUTTON, (void*)OD_DrawOrder, 185, 90, 15, 15}};
DlgRoot *Dlg;
void *hDlg;
- int cb, res, i, c_style, c_font;
+ int res, i, c_style, c_font;
bool RetVal = false, check;
double tmp;
DWORD undo_flags = 0x0;
@@ -2532,12 +2505,7 @@ Label::PropertyDlg()
pa->Command(CMD_SAVE_TICKS, 0L, 0L); undo_flags |= UNDO_CONTINUE;
}
TmpTxt[0] = 0; Dlg->GetText(106, TmpTxt, TMP_TXT_SIZE);
- if(res == 1 && TextDef.text && TextDef.text[0] && strcmp(TextDef.text, TmpTxt)) {
- Undo.String(this, &TextDef.text, undo_flags);
- undo_flags |= UNDO_CONTINUE; cb = (int)strlen(TmpTxt);
- TextDef.text = (char*)realloc(TextDef.text, (cb+=2));
- rlp_strcpy(TextDef.text, cb, TmpTxt);
- }
+ if(res == 1) undo_flags = CheckNewString(&TextDef.text, TextDef.text, TmpTxt, this, undo_flags);
if(cmpTextDEF(&OldTxtDef, &NewTxtDef)){
if(NewTxtDef.ColTxt != TextDef.ColTxt) bBGvalid = false;
if (pa) pa->Command(CMD_TLB_TXTDEF, &NewTxtDef, 0L);
@@ -3348,6 +3316,7 @@ PlotScatt::PropertyDlg()
if(Dlg->GetText(101, TmpTxt, TMP_TXT_SIZE)) xRange = (char*)memdup(TmpTxt, ((int)strlen(TmpTxt))+2, 0);
if(Dlg->GetText(103, TmpTxt, TMP_TXT_SIZE)) yRange = (char*)memdup(TmpTxt, ((int)strlen(TmpTxt))+2, 0);
Bounds.Xmin = Bounds.Ymin = HUGE_VAL; Bounds.Xmax = Bounds.Ymax = -HUGE_VAL;
+ data_desc = rY->RangeDesc(data, 1);
//Create graphic objects
rX->GetFirst(&i, &j); rY->GetFirst(&k, &l);
rX->GetNext(&i, &j); rY->GetNext(&k, &l);
@@ -3523,14 +3492,9 @@ xyStat::PropertyDlg()
sprintf(text1, "a1:a%d", height); sprintf(text2, "b1:b%d", height);
#endif
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)) &&
(TheLine->name = (char*)malloc(cb_mdesc+2))) rlp_strcpy(TheLine->name, cb_mdesc+2, mdesc);
-
}
if((type & 0x0002) && (Symbols = (Symbol**)calloc(nPoints, sizeof(Symbol*)))) {
for(i = 0; i < height; i++) {
@@ -3609,6 +3573,7 @@ xyStat::PropertyDlg()
}
}
}
+ Command(CMD_AUTOSCALE, 0L, 0L);
bRet = true;
}
}
@@ -4344,6 +4309,7 @@ PolarPlot::PropertyDlg()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Box plot properties dialog
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static int boxplot_mode_sel = 52;
bool
BoxPlot::PropertyDlg()
{
@@ -4353,9 +4319,9 @@ BoxPlot::PropertyDlg()
{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},
+ {52, 53, 0, 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},
+ {60, 61, 100, 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, TmpTxt+100, 10, 49, 165, 10},
@@ -4428,6 +4394,13 @@ BoxPlot::PropertyDlg()
ci_box = ci_err = 95.0;
if(!(Dlg = new DlgRoot(PlotDlg, data)))return false;
TmpTxt[0] = TmpTxt[100] = 0;
+ //restore previous style
+ if(boxplot_mode_sel == 53) {
+ Dlg->ShowItem(61, false); Dlg->SetCheck(53, 0L, true);
+ }
+ else {
+ Dlg->SetCheck(52, 0L, true); Dlg->ShowItem(60, false);
+ }
hDlg = CreateDlgWnd("Box and Whisker Plot", 50, 50, 370, 550, Dlg, 0x0L);
do {
LoopDlgWnd();
@@ -4437,6 +4410,7 @@ BoxPlot::PropertyDlg()
if(Dlg->GetCheck(10)) res=-1;
break;
case 52: case 53:
+ boxplot_mode_sel = res;
if(res == 53) {
Dlg->ShowItem(60, true); Dlg->ShowItem(61, false);
}
@@ -4513,6 +4487,10 @@ BoxPlot::PropertyDlg()
else if(Dlg->GetText(102, TmpTxt+100, 50) && TmpTxt[100] && Dlg->GetText(104, TmpTxt+200, 50) && TmpTxt[200]){
xRange = (char*)memdup(TmpTxt+100, ((int)strlen(TmpTxt+100))+2, 0);
yRange = (char*)memdup(TmpTxt+200, ((int)strlen(TmpTxt+200))+2, 0);
+ if((rX = new AccRange(xRange)) && (rY1 = new AccRange(yRange))) {
+ x_info = rX->RangeDesc(data, 2); y_info = rY1->RangeDesc(data, 2);
+ delete rX; delete rY1; rX = rY1 = 0L;
+ }
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;
@@ -4744,80 +4722,6 @@ DensDisp::PropertyDlg()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// create stacked bar or stacked polygon
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-int com_StackDlg(int res, DlgRoot *Dlg, AccRange **rX, int *nx, char ***rd, int *currYR,
- AccRange **rY, bool *bContinue, int *ny, int *maxYR, bool *updateYR)
-{
- char **tmprd;
-
- switch (res) {
- case 1:
- if(rX && nx && Dlg->GetText(101, TmpTxt, TMP_TXT_SIZE) && TmpTxt[0] &&
- (*rX = new AccRange(TmpTxt))) *nx = rX[0]->CountItems();
- else if(nx) *nx = 0;
- if(Dlg->GetText(154, TmpTxt, TMP_TXT_SIZE) && TmpTxt[0]) {
- if(rd[0][*currYR]) free(rd[0][*currYR]);
- rd[0][*currYR] = (char*)memdup(TmpTxt, ((int)strlen(TmpTxt))+2, 0);
- }
- break;
- case 155:
- res = -1;
- *ny = 0;
- if(rX) {
- if(!(*currYR) && Dlg->GetText(101, TmpTxt, TMP_TXT_SIZE) && TmpTxt[0]) {
- if(*rX = new AccRange(TmpTxt)){
- *nx = rX[0]->CountItems();
- delete *rX; *rX = 0L;
- }
- }
- if(!(*nx)) {
- ErrorBox("X-range is empty\nor not valid!\n\nEnter a valid range\n"
- "for common x-values.");
- *bContinue = true;
- break;
- }
- }
- if(Dlg->GetText(154, TmpTxt, TMP_TXT_SIZE) && TmpTxt[0]) {
- if(*rY = new AccRange(TmpTxt)){
- *ny = rY[0]->CountItems();
- delete *rY;
- *rY = 0L;
- }
- }
- if(!(*ny)) {
- ErrorBox("Y-range is empty\nor not valid!\n\nEnter a valid range\n"
- "for y-values with the same\nsize as the x-range.");
- *bContinue = true;
- break;
- }
- if((*currYR)+1 > *maxYR) {
- tmprd = (char**)realloc(*rd, sizeof(char*)*((*currYR)+2));
- if(tmprd) *rd = tmprd;
- else break;
- *maxYR = (*currYR)+1;
- rd[0][*currYR] = 0L;
- rd[0][(*currYR)+1] = 0L;
- }
- if(rd[0][*currYR]) free(rd[0][*currYR]);
- rd[0][*currYR] = (char*)memdup(TmpTxt, ((int)strlen(TmpTxt))+2, 0); //store y-ranges
- *updateYR = true;
- (*currYR)++;
- Dlg->SetText(154, rd[0][*currYR]);
- Dlg->Activate(154, true);
- break;
- case 156:
- if(Dlg->GetText(154, TmpTxt, TMP_TXT_SIZE)){
- if(rd[0][*currYR]) free(rd[0][*currYR]);
- rd[0][*currYR] = (char*)memdup(TmpTxt, ((int)strlen(TmpTxt))+2, 0);;
- }
- else if(*currYR == *maxYR) (*maxYR)--;
- (*currYR)--;
- Dlg->SetText(154, rd[0][*currYR]);
- *updateYR = true;
- res = -1;
- break;
- }
- return res;
-}
static char *StackBar_DlgTmpl =
"1,2,,DEFAULT,PUSHBUTTON,-1,158,10,45,12\n"
@@ -4854,10 +4758,11 @@ StackBar::PropertyDlg()
DlgInfo *StackBarDlg;
DlgRoot *Dlg;
void *hDlg;
- int i, sc, j, res, currYR = 0, maxYR = 0, nx = 0, ny;
+ int i, sc, j, res, currYR = 0, maxYR = 0, nx = 0, ny, c_num, c_txt, c_datetime;
bool updateYR = true, bContinue = false, bSub, bRet = false, bHor;
char **rd = 0L, *rname;
AccRange *rX = 0L, *rY = 0L;
+ TextValue *tv = 0L;
if(!parent || !data) return false;
if(!UseRangeMark(data, 2, TmpTxt, TmpTxt+100, TmpTxt+200, TmpTxt+300, TmpTxt+400,
@@ -4915,8 +4820,14 @@ StackBar::PropertyDlg()
if(i) TmpTxt[j++] = '&';
j+= rlp_strcpy(TmpTxt+j, TMP_TXT_SIZE-j, rd[i]);
}
- if(Dlg->GetCheck(204)) y_info = rX->RangeDesc(data, 0);
- else x_info = rX->RangeDesc(data, 0);
+ rX->DataTypes(data, &c_num, &c_txt, &c_datetime);
+ if(!c_num && (c_txt + c_datetime) > 0 ) tv = new TextValue();
+ if(Dlg->GetCheck(204)) {
+ y_info = rX->RangeDesc(data, 3); y_tv = tv;
+ }
+ else {
+ x_info = rX->RangeDesc(data, 3); x_tv = tv;
+ }
ssYrange = (char*)memdup(TmpTxt, ((int)strlen(TmpTxt))+1, 0);
if(Dlg->GetText(101, TmpTxt, TMP_TXT_SIZE)) ssXrange = (char*)memdup(TmpTxt, ((int)strlen(TmpTxt))+1, 0);;
cum_data_mode = Dlg->GetCheck(200) ? 1 : 2;
@@ -4929,9 +4840,10 @@ StackBar::PropertyDlg()
numPlots = maxYR;
if(Boxes = (BoxPlot**)calloc(numPlots, sizeof(BoxPlot*)))
for(i = sc = 0; i < (maxYR) && rd[i] && *rd[i]; i++) {
- rY = new AccRange(rd[i]); rname = rY->RangeDesc(data, 1);
- if(Boxes[i]= new BoxPlot(this, CumData, Dlg->GetCheck(204)? 2:1, 0, i+1, i+2, rname)){
- Boxes[i]->Command(CMD_UPDATE, 0L, 0L); Boxes[i]->Command(CMD_AUTOSCALE, 0L, 0L);
+ rY = new AccRange(rd[i]); rname = rY->RangeDesc(data, 3);
+ if(Boxes[i]= new BoxPlot(0L, CumData, Dlg->GetCheck(204)? 2:1, 0, i+1, i+2, rname)){
+ Boxes[i]->Command(CMD_UPDATE, 0L, 0L); Boxes[i]->parent = this;
+ Boxes[i]->Command(CMD_AUTOSCALE, 0L, 0L);
Boxes[i]->Command(CMD_BOX_FILL, GetSchemeFill(&sc), 0L);
Boxes[i]->SetSize(SIZE_BOX, 60.0);
if(rname) free(rname); delete rY; rY = 0L;
@@ -4953,7 +4865,7 @@ StackBar::PropertyDlg()
#else
sprintf(TmpTxt+20, "%c1:%c%d", 'c'+i, 'c'+i, nx*2);
#endif
- rY = new AccRange(rd[i]); rname = rY->RangeDesc(data, 1);
+ rY = new AccRange(rd[i]); rname = rY->RangeDesc(data, 3);
if(Dlg->GetCheck(204)) Polygons[i]=new DataPolygon(this,CumData,TmpTxt+20,TmpTxt, rname);
else Polygons[i] = new DataPolygon(this, CumData, TmpTxt, TmpTxt+20, rname);
if(Polygons[i]) {
@@ -5271,7 +5183,8 @@ static char *MultiLineDlg_Tmpl =
"2,3,,,PUSHBUTTON,-2,158,25,45,12\n"
"3,,10,ISPARENT | CHECKED,GROUP,0,0,0,0,0\n"
"10,11,100,ISPARENT | CHECKED,SHEET,1,5,10,140,100\n"
- "11,20,300,ISPARENT,SHEET,2,5,10,140,100\n"
+ "11,12,300,ISPARENT,SHEET,2,5,10,140,100\n"
+ "12,20,200,ISPARENT,SHEET,15,5,10,140,100\n"
"20,,,CHECKED,CHECKPIN,0,5,0,12,8\n"
"100,101,,ISPARENT | CHECKED,GROUPBOX,3,12,30,128,75\n"
"101,102,,,LTEXT,0,25,39,60,8\n"
@@ -5282,7 +5195,17 @@ static char *MultiLineDlg_Tmpl =
"106,107,,,PUSHBUTTON,-9,60,87,35,12\n"
"107,108,,OWNDIALOG,COLBUTT,4,25,87,20,12\n"
"108,,,,LTEXT,12,47,90,30,9\n"
- "300,301,,TOUCHEXIT, RADIO1,13,20,35,80,9\n"
+ "200,201,,CHECKED,CHECKBOX,16,25,35,80,9\n"
+ "201,202,,,SYMBUTT,17,25,70,10,10\n"
+ "202,203,,,SYMBUTT,18,37,70,10,10\n"
+ "203,204,,,SYMBUTT,19,49,70,10,10\n"
+ "204,205,,,SYMBUTT,20,61,70,10,10\n"
+ "205,206,,,SYMBUTT,21,73,70,10,10\n"
+ "206,207,,,SYMBUTT,22,85,70,10,10\n"
+ "207,208,,,SYMBUTT,23,97,70,10,10\n"
+ "208,209,,,SYMBUTT,24,109,70,10,10\n"
+ "209,,,CHECKED,CHECKBOX,25,25,50,80,9\n"
+ "300,301,,TOUCHEXIT,RADIO1,13,20,35,80,9\n"
"301,302,,ODEXIT,COLBUTT,4,105,35,20,10\n"
"302,303,,CHECKED | TOUCHEXIT, RADIO1,14,20,55,80,9\n"
"303,304,,ODEXIT,COLBUTT,4,25,70,10,10\n"
@@ -5299,8 +5222,10 @@ MultiLines::PropertyDlg()
{
TabSHEET tab1 = {0, 25, 10, "Data"};
TabSHEET tab2 = {25, 60, 10, "Scheme"};
+ TabSHEET tab3 = {60, 97, 10, "Symbols"};
static DWORD colarr[] = {0x00000000L, 0x00ff0000L, 0x0000ff00L, 0x000000ffL,
0x00ff00ff, 0x00ffff00L, 0x0000ffff, 0x00c0c0c0};
+ Symbol *syms[8], **lsyms;
static DWORD defcol = 0x0L;
char x_txt[100], y_txt[100];
DlgInfo *StackBarDlg;
@@ -5308,17 +5233,24 @@ MultiLines::PropertyDlg()
(void*)&colarr[0], (void*)&colarr[1], (void*)&colarr[2], (void*)&colarr[3],
(void*)&colarr[4], (void*)&colarr[5], (void*)&colarr[6], (void*)&colarr[7],
(void*)"line color", (void*)" common color for lines:", (void*)" increment color scheme:",
- (void*)0x000000ff};
+ (void*) &tab3, (void*)" draw symbols", (void*)&syms[0], (void*)&syms[1], (void*)&syms[2],
+ (void*)&syms[3], (void*)&syms[4], (void*)&syms[5], (void*)&syms[6], (void*)&syms[7],
+ (void*) " use line color for symbols"};
DlgRoot *Dlg;
void *hDlg;
char **rdx=0L, **rdy=0L;
DWORD *rdc = 0L, curr_col;
- int i, j, res, currYR=0, maxYR=0, s1, s2;
+ int i, j, nd, res, currYR=0, maxYR=0, s1, s2, rx, ry, cx, cy;
+ double symsize, x, y;
bool updateYR = true, bContinue = false, bError, bRet = false;
AccRange *rX = 0L, *rY = 0L;
DataLine *dl;
if(!parent || !data) return false;
+ symsize = NiceValue(defs.GetSize(SIZE_SYMBOL)*.8);
+ for(i = 0; i < 8; i++) if(syms[i] = new Symbol(0L, data, 0.0, 0.0, i)) {
+ if(i != 2 && i != 3)syms[i]->SetSize(SIZE_SYMBOL, symsize);
+ }
if(!(StackBarDlg = CompileDialog(MultiLineDlg_Tmpl, dyndata)))return false;
if(!UseRangeMark(data, 2, TmpTxt, TmpTxt+100, TmpTxt+200, TmpTxt+300, TmpTxt+400,
TmpTxt+500, TmpTxt+600, TmpTxt+700, TmpTxt+800, TmpTxt+900, TmpTxt+1000)) return false;
@@ -5466,14 +5398,37 @@ MultiLines::PropertyDlg()
}while (res < 0);
if(res == 1 && rdx && rdy && maxYR) {
- maxYR++;
+ maxYR++; rX = rY = 0L;
if(xyPlots=(PlotScatt**)calloc(maxYR, sizeof(PlotScatt*))) for(i = numXY = 0; i < maxYR; i++){
if(rdx[i] && rdy[i] && rdx[i][0] && rdy[i][0]) {
+ if(Dlg->GetCheck(200) && (rX = new AccRange(rdx[i])) && (rY = new AccRange(rdy[i]))) {
+ lsyms = (Symbol**)calloc(rX->CountItems()+1, sizeof(Symbol*));
+ symsize = syms[i &0x07]->GetSize(SIZE_SYMBOL);
+ for(nd = 0, rX->GetFirst(&cx, &rx), rY->GetFirst(&cy, &ry); rX->GetNext(&cx, &rx), rY->GetNext(&cy, &ry); ) {
+ if(data->GetValue(rx, cx, &x) && data->GetValue(ry, cy, &y)) {
+ lsyms[nd] = new Symbol(0L, data, x, y, syms[i &0x07]->type, cx, rx, cy, ry);
+ if(Dlg->GetCheck(209)) lsyms[nd]->SetColor(COL_SYM_LINE, Dlg->GetCheck(300) ? defcol : rdc[i & 0x07]);
+ else {
+ lsyms[nd]->SetColor(COL_SYM_LINE, syms[i &0x07]->GetColor(COL_SYM_LINE));
+ lsyms[nd]->SetColor(COL_SYM_FILL, syms[i &0x07]->GetColor(COL_SYM_FILL));
+ }
+ lsyms[nd]->SetSize(SIZE_SYMBOL, symsize);
+ nd++;
+ }
+ }
+ }
+ else {
+ nd = 0; lsyms = 0L;
+ }
if(dl = new DataLine(this, data, rdx[i], rdy[i])) {
- dl->SetColor(COL_DATA_LINE, Dlg->GetCheck(300) ? defcol : rdc[i]);
- if(xyPlots[numXY] = new PlotScatt(this, data, 0, 0L, dl)) numXY++;
+ dl->SetColor(COL_DATA_LINE, Dlg->GetCheck(300) ? defcol : rdc[i & 0xf]);
+ if(xyPlots[numXY] = new PlotScatt(this, data, nd, lsyms, dl)) {
+ if(rY) xyPlots[numXY]->data_desc = rY->RangeDesc(data, 1);
+ numXY++;
+ }
else delete dl;
}
+ if(rX)delete rX; if(rY)delete rY; rX = rY = 0L;
}
}
if(numXY) bRet = true;
@@ -5488,7 +5443,12 @@ MultiLines::PropertyDlg()
for (i = 0; i < maxYR; i++) if(rdy[i]) free(rdy[i]);
free(rdy);
}
+ for(i = 0; i < 8; i++) if(syms[i]) delete syms[i];
free(StackBarDlg); if(rdc) free(rdc);
+ if(bRet) {
+ Bounds.Xmax = Bounds.Ymax = -HUGE_VAL; Bounds.Xmin = Bounds.Ymin = HUGE_VAL;
+ Command(CMD_AUTOSCALE, 0L, 0L);
+ }
return bRet;
}
@@ -6016,7 +5976,7 @@ Scatt3D::PropertyDlg()
if(Dlg->GetText(105, text3, 100) && (rZ = new AccRange(text3))) n3 = rZ->CountItems();
if(n1 && n2 && n3){
if(c_flags == 0x2000 || c_flags == 0x4000) {
- //no more but a ribbon ore surface
+ //no more but a ribbon or surface
}
else if(n1 == n2 && n2 == n3) {
//o.k., three ranges of equal size have been defined
@@ -6107,7 +6067,7 @@ Function::PropertyDlg()
{3, 10, 4, ISPARENT | CHECKED, GROUP, 0L, 138, 40, 55, 12},
{4, 5, 100, ISPARENT, SHEET, &tab1, 5, 10, 149, 110},
{5, 0, 500, ISPARENT | CHECKED, SHEET, &tab2, 5, 10, 149, 110},
- {10, 0, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
+ {10, 600, 0, 0x0L, CHECKPIN, 0L, 5, 0, 12, 8},
{100, 101, 0, 0x0L, LTEXT, (void*)"plot user defined function", 10, 24, 100, 8},
{101, 102, 0, 0x0L, RTEXT, (void*)"where x=", 10, 40, 28, 8},
{102, 103, 0, 0x0L, EDVAL1, &x1, 38, 40, 25, 10},
@@ -6117,7 +6077,11 @@ Function::PropertyDlg()
{106, 107, 0, 0x0L, EDVAL1, &xstep, 119, 40, 25, 10},
{107, 200, 0, 0x0L, RTEXT, (void*)"y=", 10, 56, 10, 8},
{200, 0, 0, 0x0L, TEXTBOX, (void*)cmdxy, 22, 54, 122, 40},
- {500, 0, 0, LASTOBJ | NOSELECT, ODBUTTON, (void*)OD_linedef, 15, 25, 130, 100}};
+ {500, 0, 0, NOSELECT, ODBUTTON, (void*)OD_linedef, 15, 25, 130, 100},
+ {600, 601, 0, TOUCHEXIT, ODBUTTON, (void*)OD_DrawOrder, 170, 45, 15, 15},
+ {601, 602, 0, TOUCHEXIT, ODBUTTON, (void*)OD_DrawOrder, 170, 60, 15, 15},
+ {602, 603, 0, TOUCHEXIT, ODBUTTON, (void*)OD_DrawOrder, 170, 75, 15, 15},
+ {603, 0, 0, LASTOBJ | TOUCHEXIT, ODBUTTON, (void*)OD_DrawOrder, 170, 90, 15, 15}};
DlgRoot *Dlg;
void *hDlg;
int res, undo_level = *Undo.pcb;
@@ -6144,11 +6108,14 @@ Function::PropertyDlg()
case 0:
if(Dlg->GetCheck(10)) res = -1;
break;
+ case 600: case 601: case 602: case 603:
+ Undo.SetDisp(cdisp);
+ res = ExecDrawOrderButt(parent, this, res);
}
}while (res < 0);
Undo.SetDisp(cdisp);
- while(*Undo.pcb > undo_level) Undo.Pop(cdisp);
- if(res == 1){ //OK pressed
+ if(res == 2) while(*Undo.pcb > undo_level) Undo.Restore(true, cdisp);
+ else 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);
@@ -6162,15 +6129,10 @@ Function::PropertyDlg()
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, TMP_TXT_SIZE);
- if(cmdxy && strcmp(cmdxy, TmpTxt)) {
- Undo.String(this, &cmdxy, undo_flags);
- free(cmdxy); undo_flags |= UNDO_CONTINUE;
- cmdxy = (char*)memdup(TmpTxt, (int)strlen(TmpTxt)+1, 0);
- }
+ if(Dlg->GetText(200, TmpTxt, TMP_TXT_SIZE))
+ undo_flags = CheckNewString(&cmdxy, cmdxy, TmpTxt, this, undo_flags);
if(undo_flags & UNDO_CONTINUE){
- Update(0L, UNDO_CONTINUE);
- Command(CMD_MRK_DIRTY, 0L, 0L);
+ Update(0L, UNDO_CONTINUE); Command(CMD_MRK_DIRTY, 0L, 0L);
}
OD_linedef(OD_GETLINE, 0L, 0L, 0L, (void *)&newLine, 0);
if(cmpLineDEF(&Line, &newLine)) {
@@ -6180,8 +6142,7 @@ Function::PropertyDlg()
bRet = (undo_flags & UNDO_CONTINUE) != 0;
}
}
- CloseDlgWnd(hDlg);
- delete Dlg;
+ CloseDlgWnd(hDlg); delete Dlg;
return bRet;
}
@@ -6309,6 +6270,7 @@ FitFunc::PropertyDlg()
}
Dlg->GetValue(153, &conv); Dlg->GetValue(155, &iter);
ReshapeFormula(&parxy); ReshapeFormula(&cmdxy);
+ do_formula(data, 0L); //clear any error condition
ares = do_formula(data, parxy);
if(ares->type != ET_VALUE) {
ErrorBox("Syntax Error in parameters.");
@@ -6383,14 +6345,12 @@ FitFunc::PropertyDlg()
}
xstep = (x2 - x1)/100.0;
OD_linedef(OD_GETLINE, 0L, 0L, 0L, (void *)&Line, 0);
- 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->Command(CMD_AUTOSCALE, 0L, 0L);
- CheckBounds(dl->Bounds.Xmin, dl->Bounds.Ymin);
+ 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->Command(CMD_AUTOSCALE, 0L, 0L); CheckBounds(dl->Bounds.Xmin, dl->Bounds.Ymin);
CheckBounds(dl->Bounds.Xmax, dl->Bounds.Ymax);
- bRet = true;
+ Command(CMD_ENDDIALOG, 0L, 0L); bRet = true;
}
else { //edit existing function
Dlg->GetValue(502, &n_x1); Dlg->GetValue(504, &n_x2);
@@ -6404,18 +6364,8 @@ FitFunc::PropertyDlg()
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);
- free(parxy); parxy = tmp_char; undo_flags |= UNDO_CONTINUE;
- o_parxy = 0L;
- }
- if(o_cmdxy && cmdxy && strcmp(o_cmdxy, cmdxy)) {
- tmp_char = cmdxy; cmdxy = o_cmdxy;
- Undo.String(this, &cmdxy, undo_flags);
- free(cmdxy); cmdxy = tmp_char; undo_flags |= UNDO_CONTINUE;
- o_cmdxy = 0L;
- }
+ undo_flags = CheckNewString(&parxy, o_parxy, parxy, this, undo_flags);
+ undo_flags = CheckNewString(&cmdxy, o_cmdxy, cmdxy, this, undo_flags);
if(undo_flags & UNDO_CONTINUE) {
Undo.ValInt(parent, (int*)&dirty, undo_flags);
Command(CMD_MRK_DIRTY, 0L, 0L);
@@ -6426,6 +6376,7 @@ FitFunc::PropertyDlg()
memcpy(&Line, &newLine, sizeof(LineDEF));
}
bRet = (undo_flags & UNDO_CONTINUE) != 0;
+ Command(CMD_ENDDIALOG, 0L, 0L);
}
}
CloseDlgWnd(hDlg);
@@ -6435,8 +6386,373 @@ FitFunc::PropertyDlg()
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Create a new normal qualntile plot
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static char *NormQuantDlg_Tmpl =
+ "1,2,,DEFAULT,PUSHBUTTON,-1,148,10,45,12\n"
+ "2,3,,,PUSHBUTTON,-2,148,25,45,12\n"
+ "3,,4,ISPARENT | CHECKED,GROUP,0,0,0,0,0\n"
+ "4,10,100,ISPARENT | CHECKED,SHEET,1,5,10,130,80\n"
+ "10,,,CHECKED,CHECKPIN,0,5,0,12,8\n"
+ "100,101,,,LTEXT,2,10,30,60,8\n"
+ "101,,,LASTOBJ,RANGEINPUT,-15,20,40,100,10";
+
+bool
+NormQuant::PropertyDlg()
+{
+ TabSHEET tab1 = {0, 25, 10, "Data"};
+ DlgInfo *QuantDlg;
+ void *dyndata[] = {(void*)&tab1, (void*)"range for variables"};
+ DlgRoot *Dlg;
+ void *hDlg;
+ int res;
+ char *mrk;
+ bool bContinue = false, bRet = false;
+
+ if(!parent || !data) return false;
+ if(!(QuantDlg = CompileDialog(NormQuantDlg_Tmpl, dyndata))) return false;
+ if(data->Command(CMD_GETMARK, &mrk, 0L))rlp_strcpy(TmpTxt, TMP_TXT_SIZE, mrk);
+ else UseRangeMark(data, 1, TmpTxt);
+ if(!(Dlg = new DlgRoot(QuantDlg, data)))return false;
+ hDlg = CreateDlgWnd("Normal Quantiles Plot", 50, 50, 420, 220, Dlg, 0x0L);
+ do {
+ LoopDlgWnd();
+ res = Dlg->GetResult();
+ switch (res) {
+ case 0:
+ if(bContinue) res = -1;
+ else if(Dlg->GetCheck(10)) res = -1;
+ break;
+ case -1:
+ bContinue = false;
+ break;
+ }
+ }while (res < 0);
+ if(res == 1 && Dlg->GetText(101, TmpTxt, TMP_TXT_SIZE)){
+ ssRef = (char*)memdup(TmpTxt, (int)strlen(TmpTxt)+1, 0);
+ bRet = ProcessData();
+ }
+ CloseDlgWnd(hDlg); delete Dlg; free(QuantDlg);
+ return bRet;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create a three dimensional graph
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static char *AddAxis3D_Tmpl =
+ "1,2,,DEFAULT, PUSHBUTTON,-1,148,10,45,12\n"
+ "2,3,,,PUSHBUTTON,-2,148,25,45,12\n"
+ "3,,4,ISPARENT | CHECKED,GROUP,0,0,0,0,0\n"
+ "4,5,50,TOUCHEXIT | ISPARENT,SHEET,1,5,10,130,148\n"
+ "5,6,200,ISPARENT | CHECKED,SHEET,2,5,10,130,148\n"
+ "6,20,300,ISPARENT,SHEET,3,5,10,130,148\n"
+ "20,,,NOSELECT,ODBUTTON,22,142,65,45,45\n"
+ "50,51,100,ISPARENT | CHECKED,GROUPBOX,4,10,30,120,36\n"
+ "51,120,,,CHECKBOX,5,17,37,80,8\n"
+ "100,101,,,RTEXT,6,10,51,35,8\n"
+ "101,102,,,EDVAL1,7,48,51,32,10\n"
+ "102,103,,,CTEXT,8,81,51,11,8\n"
+ "103,,,,EDVAL1,9,93,51,32,10\n"
+ "120,,121,ISPARENT | CHECKED,GROUPBOX,10,10,72,120,20\n"
+ "121,122,,,RTEXT,11,10,77,25,8\n"
+ "122,123,,,EDVAL1,12,37,77,25,10\n"
+ "123,124,,,LTEXT,-3,63,77,10,8\n"
+ "124,125,,,RTEXT,-11,73,77,25,8\n"
+ "125,130,,OWNDIALOG,COLBUTT,14,100,77,25,10\n"
+ "130,131,,ISPARENT | CHECKED,GROUPBOX,15,10,98,120,20\n"
+ "131,,,,EDTEXT,0,15,103,110,10\n"
+ "200,201,,,LTEXT,16,10,23,70,9\n"
+ "201,202,,CHECKED | EXRADIO,ODBUTTON,17,20,35,25,25\n"
+ "202,203,,EXRADIO,ODBUTTON,17,45,35,25,25\n"
+ "203,204,,EXRADIO,ODBUTTON,17,70,35,25,25\n"
+ "204,205,,EXRADIO,ODBUTTON,17,95,35,25,25\n"
+ "205,206,,EXRADIO,ODBUTTON,17,20,60,25,25\n"
+ "206,207,,EXRADIO,ODBUTTON,17,45,60,25,25\n"
+ "207,208,,EXRADIO,ODBUTTON,17,70,60,25,25\n"
+ "208,209,,EXRADIO,ODBUTTON,17,95,60,25,25\n"
+ "209,210,,EXRADIO,ODBUTTON,17,20,85,25,25\n"
+ "210,211,,EXRADIO,ODBUTTON,17,45,85,25,25\n"
+ "211,212,,EXRADIO,ODBUTTON,17,70,85,25,25\n"
+ "212,213,,EXRADIO,ODBUTTON,17,95,85,25,25\n"
+ "213,214,,,LTEXT,-12,20,120,70,9\n"
+ "214,215,,,LTEXT,-13,20,132,70,9\n"
+ "215,216,,,LTEXT,-14,20,144,70,9\n"
+ "216,217,250,ISPARENT | CHECKED,GROUP,0,0,0,0,0\n"
+ "217,218,260,HIDDEN | ISPARENT | CHECKED,GROUP,0,0,0,0,0\n"
+ "218,,270,HIDDEN |ISPARENT | CHECKED,GROUP,0,0,0,0,0\n"
+ "250,251,,,LTEXT,19,10,110,70,9\n"
+ "251,252,,,EDVAL1,0,58,120,32,10\n"
+ "252,253,,,LTEXT,-3,92,120,20,9\n"
+ "253,254,,,EDVAL1,0,43,132,32,10\n"
+ "254,255,,,CTEXT,-7,75,132,7,9\n"
+ "255,256,,,EDVAL1,0,82,132,32,10\n"
+ "256,257,,,LTEXT,-3,116,132,20,9\n"
+ "257,268,,,EDVAL1,0,58,144,32,10\n"
+ "260,261,,,LTEXT,20,10,110,70,9\n"
+ "261,262,,,EDVAL1,0,43,120,32,10\n"
+ "262,263,,,CTEXT,-7,75,120,7,9\n"
+ "263,264,,,EDVAL1,0,82,120,32,10\n"
+ "264,265,,,LTEXT,-3,116,120,20,9\n"
+ "265,266,,,EDVAL1,0,58,132,32,10\n"
+ "266,267,,,LTEXT,-3,92,132,20,9\n"
+ "267,268,,,EDVAL1,0,58,144,32,10\n"
+ "268,,,,LTEXT,-3,92,144,20,9\n"
+ "270,271,,,LTEXT,21,10,110,70,9\n"
+ "271,272,,,EDVAL1,0,58,120,32,10\n"
+ "272,273,,,LTEXT,-3,92,120,20,9\n"
+ "273,274,,,EDVAL1,0,58,132,32,10\n"
+ "274,275,,,LTEXT,-3,92,132,20,9\n"
+ "275,276,,,EDVAL1,0,43,144,32,10\n"
+ "276,277,,,CTEXT,-7,75,144,7,9\n"
+ "277,278,,,EDVAL1,0,82,144,32,10\n"
+ "278,,,,LTEXT,-3,116,144,20,9\n"
+ "300,,,LASTOBJ | NOSELECT,ODBUTTON,18,15,30,110,140";
+bool
+Plot3D::AddAxis()
+{
+ TabSHEET tab1 = {0, 25, 10, "Axis"};
+ TabSHEET tab2 = {25, 52, 10, "Style"};
+ TabSHEET tab3 = {52, 78, 10, "Plots"};
+ AxisDEF axis, ax_def[12], *caxdef;
+ double sizAxLine = DefSize(SIZE_AXIS_LINE);
+ DWORD colAxis = 0x0;
+ void *dyndata[] = {(void*)&tab1, (void*)&tab2, (void*)&tab3, (void*)" scaling ", (void*)" automatic scaling",
+ (void*)"axis from", (void*)&axis.min, (void*)"to", (void*)&axis.max, (void*)" line ", (void*)"width",
+ (void*)&sizAxLine, (void*)0L, (void *)&colAxis, (void*)" axis label ", (void*)"select a template:",
+ (void*)(OD_NewAxisTempl3D), (void*)OD_axisplot, (void*)"y-axis at:", (void*)"x-axis at:", (void*)"z-axis at:",
+ (void*)(OD_AxisDesc3D)};
+ DlgInfo *NewAxisDlg;
+ DlgRoot *Dlg;
+ void *hDlg;
+ int i, j, res, currTempl = 201, ax_type = 2, tick_type = 2;
+ double tlb_dx, tlb_dy, lb_x, lb_y;
+ TextDEF label_def, tlbdef;
+ anyOutput *cdisp = Undo.cdisp;
+ Axis *the_new, **tmpAxes;
+ bool bAxis = false, bRet = false;
+ char **names;
+ GraphObj **somePlots;
+ Label *label;
+
+ if(!Axes || nAxes < 3 || !(NewAxisDlg = CompileDialog(AddAxis3D_Tmpl, dyndata))) return false;
+ lb_y = 0.0; lb_x = DefSize(SIZE_AXIS_TICKS)*4.0;
+ tlb_dy = 0.0; tlb_dx = -DefSize(SIZE_AXIS_TICKS)*2.0;
+ tlbdef.ColTxt = colAxis; tlbdef.ColBg = 0x00ffffffL;
+ tlbdef.RotBL = tlbdef.RotCHAR = 0.0f; tlbdef.fSize = DefSize(SIZE_TICK_LABELS);
+ tlbdef.Align = TXA_VCENTER | TXA_HRIGHT;
+ tlbdef.Style = TXS_NORMAL; tlbdef.Mode = TXM_TRANSPARENT;
+ tlbdef.Font = FONT_HELVETICA; tlbdef.text = 0L;
+ if(!(names = (char**)calloc(nscp+2, sizeof(char*))))return false;
+ if(!(somePlots = (GraphObj**)calloc(nscp+2, sizeof(GraphObj*))))return false;
+ for(i = 0; i < 12; i++) {
+ ax_def[i].flags = AXIS_3D | AXIS_DEFRECT | AXIS_AUTOTICK;
+ ax_def[i].owner = 0L; ax_def[i].breaks = 0L;
+ ax_def[i].Center.fx = ax_def[i].Center.fy = ax_def[i].Radius = 0.0;
+ ax_def[i].nBreaks = 0L;
+ }
+ //y-axes
+ ax_def[0].min = ax_def[1].min = ax_def[2].min = ax_def[3].min = (caxdef = Axes[1]->GetAxis())->min;
+ ax_def[0].max = ax_def[1].max = ax_def[2].max = ax_def[3].max = caxdef->max;
+ ax_def[0].Start = ax_def[1].Start = ax_def[2].Start = ax_def[3].Start = caxdef->Start;
+ ax_def[0].Step = ax_def[1].Step = ax_def[2].Step = ax_def[3].Step = caxdef->Step;
+ ax_def[0].loc[0].fy = ax_def[1].loc[0].fy = ax_def[2].loc[0].fy = ax_def[3].loc[0].fy = caxdef->loc[0].fy;
+ ax_def[0].loc[1].fy = ax_def[1].loc[1].fy = ax_def[2].loc[1].fy = ax_def[3].loc[1].fy = caxdef->loc[1].fy;
+ ax_def[0].loc[0].fx = ax_def[0].loc[1].fx = ax_def[3].loc[0].fx = ax_def[3].loc[1].fx = cu1.fx;
+ ax_def[1].loc[0].fx = ax_def[1].loc[1].fx = ax_def[2].loc[0].fx = ax_def[2].loc[1].fx = cu2.fx;
+ ax_def[0].loc[0].fz = ax_def[0].loc[1].fz = ax_def[1].loc[0].fz = ax_def[1].loc[1].fz = cu2.fz;
+ ax_def[2].loc[0].fz = ax_def[2].loc[1].fz = ax_def[3].loc[0].fz = ax_def[3].loc[1].fz = cu1.fz;
+ ax_def[1].flags = ax_def[2].flags = AXIS_3D | AXIS_DEFRECT | AXIS_AUTOTICK | AXIS_POSTICKS;
+ ax_def[0].flags = ax_def[3].flags = AXIS_3D | AXIS_DEFRECT | AXIS_AUTOTICK | AXIS_NEGTICKS;
+ //x-axes
+ ax_def[4].min = ax_def[6].min = ax_def[8].min = ax_def[10].min = (caxdef = Axes[0]->GetAxis())->min;
+ ax_def[4].max = ax_def[6].max = ax_def[8].max = ax_def[10].max = caxdef->max;
+ ax_def[4].Start = ax_def[6].Start = ax_def[8].Start = ax_def[10].Start = caxdef->Start;
+ ax_def[4].Step = ax_def[6].Step = ax_def[8].Step = ax_def[10].Step = caxdef->Step;
+ ax_def[4].loc[0].fx = ax_def[6].loc[0].fx = ax_def[8].loc[0].fx = ax_def[10].loc[0].fx = caxdef->loc[0].fx;
+ ax_def[4].loc[1].fx = ax_def[6].loc[1].fx = ax_def[8].loc[1].fx = ax_def[10].loc[1].fx = caxdef->loc[1].fx;
+ ax_def[4].loc[0].fy = ax_def[4].loc[1].fy = ax_def[6].loc[0].fy = ax_def[6].loc[1].fy = cu1.fy;
+ ax_def[8].loc[0].fy = ax_def[8].loc[1].fy = ax_def[10].loc[0].fy = ax_def[10].loc[1].fy = cu2.fy;
+ ax_def[4].loc[0].fz = ax_def[4].loc[1].fz = ax_def[8].loc[0].fz = ax_def[8].loc[1].fz = cu2.fz;
+ ax_def[6].loc[0].fz = ax_def[6].loc[1].fz = ax_def[10].loc[0].fz = ax_def[10].loc[1].fz = cu1.fz;
+ ax_def[4].flags = ax_def[6].flags = AXIS_3D | AXIS_DEFRECT | AXIS_AUTOTICK | AXIS_NEGTICKS;
+ ax_def[8].flags = ax_def[10].flags = AXIS_3D | AXIS_DEFRECT | AXIS_AUTOTICK | AXIS_POSTICKS;
+ //z-axes
+ ax_def[5].min = ax_def[7].min = ax_def[9].min = ax_def[11].min = (caxdef = Axes[2]->GetAxis())->min;
+ ax_def[5].max = ax_def[7].max = ax_def[9].max = ax_def[11].max = caxdef->max;
+ ax_def[5].Start = ax_def[7].Start = ax_def[9].Start = ax_def[11].Start = caxdef->Start;
+ ax_def[5].Step = ax_def[7].Step = ax_def[9].Step = ax_def[11].Step = caxdef->Step;
+ ax_def[5].loc[0].fz = ax_def[7].loc[0].fz = ax_def[9].loc[0].fz = ax_def[11].loc[0].fz = caxdef->loc[0].fz;
+ ax_def[5].loc[1].fz = ax_def[7].loc[1].fz = ax_def[9].loc[1].fz = ax_def[11].loc[1].fz = caxdef->loc[1].fz;
+ ax_def[5].loc[0].fx = ax_def[5].loc[1].fx = ax_def[9].loc[0].fx = ax_def[9].loc[1].fx = cu2.fx;
+ ax_def[7].loc[0].fx = ax_def[7].loc[1].fx = ax_def[11].loc[0].fx = ax_def[11].loc[1].fx = cu1.fx;
+ ax_def[5].loc[0].fy = ax_def[5].loc[1].fy = ax_def[7].loc[0].fy = ax_def[7].loc[1].fy = cu1.fy;
+ ax_def[9].loc[0].fy = ax_def[9].loc[1].fy = ax_def[11].loc[0].fy = ax_def[11].loc[1].fy = cu2.fy;
+ ax_def[5].flags = ax_def[9].flags = AXIS_3D | AXIS_DEFRECT | AXIS_AUTOTICK | AXIS_POSTICKS;
+ ax_def[7].flags = ax_def[11].flags = AXIS_3D | AXIS_DEFRECT | AXIS_AUTOTICK | AXIS_NEGTICKS;
+ //the default axis is the first
+ memcpy(&axis, &ax_def[0], sizeof(AxisDEF));
+ if(names[0] = (char*)malloc(10)) rlp_strcpy(names[0], 10, "[none]");
+ for(i = 0, j = 1; i < nscp; i++) {
+ if(Sc_Plots[i] && Sc_Plots[i]->name){
+ names[j] = (char*)memdup(Sc_Plots[i]->name, (int)strlen(Sc_Plots[i]->name)+1, 0);
+ somePlots[j++] = Sc_Plots[i];
+ }
+ }
+ OD_axisplot(OD_ACCEPT, 0L, 0L, 0L, names, 0);
+ if(!(Dlg = new DlgRoot(NewAxisDlg, data)))return false;
+ Dlg->SetValue(251, ax_def[0].loc[0].fx); Dlg->SetValue(253, ax_def[0].loc[0].fy);
+ Dlg->SetValue(255, ax_def[0].loc[1].fy); Dlg->SetValue(257, ax_def[0].loc[0].fz);
+ if(!nscp){ //must be root plot3d to link to plot
+ Dlg->ShowItem(6, false);
+ }
+ hDlg = CreateDlgWnd("Add Axis to 3D Plot", 50, 50, 400, 360, Dlg, 0x0L);
+ do{
+ LoopDlgWnd();
+ res = Dlg->GetResult();
+ switch (res){
+ case 4: //the axis sheet
+ res = -1;
+ bAxis = true;
+ break;
+ //axis templates
+ case 201: case 202: case 203: case 204: case 205: case 206:
+ case 207: case 208: case 209: case 210: case 211: case 212:
+ i = currTempl-201;
+ switch(currTempl){
+ case 201: case 202: case 203: case 204: //prevoius is y-template
+ Dlg->GetValue(251, &axis.loc[0].fx); Dlg->GetValue(253, &axis.loc[0].fy);
+ Dlg->GetValue(255, &axis.loc[1].fy); Dlg->GetValue(257, &axis.loc[0].fz);
+ axis.loc[1].fx = axis.loc[0].fx; axis.loc[1].fz = axis.loc[0].fz;
+ memcpy(&ax_def[i], &axis, sizeof(AxisDEF));
+ break;
+ case 205: case 207: case 209: case 211: //prevoius is x-template
+ Dlg->GetValue(261, &axis.loc[0].fx); Dlg->GetValue(263, &axis.loc[1].fx);
+ Dlg->GetValue(265, &axis.loc[0].fy); Dlg->GetValue(267, &axis.loc[0].fz);
+ axis.loc[1].fy = axis.loc[0].fy; axis.loc[1].fz = axis.loc[0].fz;
+ memcpy(&ax_def[i], &axis, sizeof(AxisDEF));
+ break;
+ case 206: case 208: case 210: case 212: //previous is z-template
+ Dlg->GetValue(271, &axis.loc[0].fx); Dlg->GetValue(273, &axis.loc[0].fy);
+ Dlg->GetValue(275, &axis.loc[0].fz); Dlg->GetValue(277, &axis.loc[1].fz);
+ axis.loc[1].fx = axis.loc[0].fx; axis.loc[1].fy = axis.loc[0].fy;
+ memcpy(&ax_def[i], &axis, sizeof(AxisDEF));
+ break;
+ }
+ i = res-201;
+ switch (res) {
+ case 201: case 202: case 203: case 204: //y-template
+ Dlg->ShowItem(216, true); Dlg->ShowItem(217, false);
+ Dlg->ShowItem(218, false);
+ Dlg->SetValue(251, ax_def[i].loc[0].fx); Dlg->SetValue(253, ax_def[i].loc[0].fy);
+ Dlg->SetValue(255, ax_def[i].loc[1].fy); Dlg->SetValue(257, ax_def[i].loc[0].fz);
+ ax_type = tick_type = 2; tlb_dy = 0.0;
+ if(res == 202 || res == 203){
+ tlb_dx = DefSize(SIZE_AXIS_TICKS)*2.0;
+ tlbdef.Align = TXA_VCENTER | TXA_HLEFT;
+ }
+ else {
+ tlb_dx = -DefSize(SIZE_AXIS_TICKS)*2.0;
+ tlbdef.Align = TXA_VCENTER | TXA_HRIGHT;
+ }
+ break;
+ case 205: case 207: case 209: case 211: //x-template
+ Dlg->ShowItem(216, false); Dlg->ShowItem(217, true);
+ Dlg->ShowItem(218, false);
+ Dlg->SetValue(261, ax_def[i].loc[0].fx); Dlg->SetValue(263, ax_def[i].loc[1].fx);
+ Dlg->SetValue(265, ax_def[i].loc[0].fy); Dlg->SetValue(267, ax_def[i].loc[0].fz);
+ ax_type = 1; tick_type = 3; tlb_dx = 0;
+ if(res == 205 || res == 207){
+ tlb_dy = DefSize(SIZE_AXIS_TICKS)*2.0;
+ tlbdef.Align = TXA_VTOP | TXA_HCENTER;
+ }
+ else {
+ tlb_dy = -DefSize(SIZE_AXIS_TICKS)*2.0;
+ tlbdef.Align = TXA_VBOTTOM | TXA_HCENTER;
+ }
+ break;
+ case 206: case 208: case 210: case 212: //z-template
+ Dlg->ShowItem(216, false); Dlg->ShowItem(217, false);
+ Dlg->ShowItem(218, true);
+ Dlg->SetValue(271, ax_def[i].loc[0].fx); Dlg->SetValue(273, ax_def[i].loc[0].fy);
+ Dlg->SetValue(275, ax_def[i].loc[0].fz); Dlg->SetValue(277, ax_def[i].loc[1].fz);
+ ax_type = 3; tick_type = 2; tlb_dy = 0;
+ if(res == 206 || res == 210){
+ tlb_dx = DefSize(SIZE_AXIS_TICKS)*2.0;
+ tlbdef.Align = TXA_VCENTER | TXA_HLEFT;
+ }
+ else {
+ tlb_dx = -DefSize(SIZE_AXIS_TICKS)*2.0;
+ tlbdef.Align = TXA_VCENTER | TXA_HRIGHT;
+ }
+ break;
+ }
+ memcpy(&axis, &ax_def[res-201], sizeof(AxisDEF));
+ currTempl = res;
+ Dlg->DoPlot(0L);
+ res = -1;
+ break;
+ }
+ }while (res < 0);
+ if(res == 1) {
+ Undo.SetDisp(cdisp);
+ Dlg->GetValue(122, &sizAxLine); Dlg->GetColor(125, &colAxis);
+ Dlg->GetValue(101, &axis.min); Dlg->GetValue(103, &axis.max);
+ axis.Start = axis.min; axis.Center.fx = axis.Center.fy = 0.0;
+ axis.nBreaks = 0; axis.breaks = 0L; axis.Radius = 0.0;
+ tlbdef.ColTxt = colAxis;
+ label_def.ColTxt = colAxis; label_def.ColBg = 0x00ffffffL;
+ label_def.fSize = DefSize(SIZE_TICK_LABELS)*1.2f; label_def.RotBL = 0.0f;
+ label_def.RotCHAR = 0.0f; label_def.iSize = 0;
+ label_def.Align = TXA_VTOP | TXA_HCENTER; label_def.Mode = TXM_TRANSPARENT;
+ label_def.Style = TXS_NORMAL; label_def.Font = FONT_HELVETICA;
+ if(Dlg->GetCheck(51)) axis.flags |= AXIS_AUTOSCALE;
+ if(the_new = new Axis(this, data, &axis, axis.flags)){
+ the_new->SetSize(SIZE_TLB_YDIST, tlb_dy); the_new->SetSize(SIZE_TLB_XDIST, tlb_dx);
+ the_new->SetSize(SIZE_AXIS_LINE, sizAxLine);
+ the_new->SetColor(COL_AXIS, colAxis);
+ the_new->Command(CMD_TLB_TXTDEF, (void*)&tlbdef, 0L);
+ the_new->SetSize(SIZE_LB_XDIST, lb_x); the_new->SetSize(SIZE_LB_YDIST, lb_y);
+ the_new->type = ax_type;
+ the_new->Command(CMD_TICK_TYPE, &tick_type, 0L);
+ if(Dlg->GetText(131, TmpTxt, TMP_TXT_SIZE)) label_def.text = TmpTxt;
+ else label_def.text = 0L;
+ if(label = new Label(Axes[0], data, (axis.loc[0].fx + axis.loc[1].fx)/2.0,
+ (axis.loc[0].fy + axis.loc[1].fy)/2.0, &label_def,
+ label_def.RotBL < 45.0 ? LB_Y_PARENT : LB_X_PARENT)){
+ label->SetSize(SIZE_LB_XDIST, lb_x); label->SetSize(SIZE_LB_YDIST, lb_y);
+ if(the_new->Command(CMD_DROP_LABEL, (void*)label, 0L)) label = 0L;
+ else DeleteGO(label);
+ }
+ for(i = 0; i < nAxes && Axes[i]; i++);
+ if(i < nAxes) {
+ Undo.SetGO(this, (GraphObj**)(&Axes[i]), the_new, 0L);
+ bRet = true;
+ }
+ else {
+ if(tmpAxes = (Axis**)calloc(nAxes+1, sizeof(Axis*))){
+ memcpy(tmpAxes, Axes, nAxes * sizeof(Axis*));
+ Undo.ListGOmoved((GraphObj**)Axes, (GraphObj**)tmpAxes, nAxes);
+ Undo.SetGO(this, (GraphObj**)(&tmpAxes[nAxes]), the_new, 0L);
+ free(Axes); Axes = tmpAxes;
+ i = nAxes++; bRet = true;
+ }
+ }
+ CurrAxes = Axes;
+ if(bRet) {
+ OD_axisplot(OD_ACCEPT, 0L, 0L, (anyOutput*) &res, 0L, 0);
+ if(res && i) somePlots[res]->Command(CMD_USEAXIS, &i, 0L);
+ }
+ }
+ }
+ CloseDlgWnd(hDlg); delete Dlg; free(NewAxisDlg);
+ if(names) {
+ for(j = 0; names[j]; j++) if(names[j]) free(names[j]);
+ free(names);
+ }
+ if(somePlots) free(somePlots);
+ return bRet;
+}
+
static char *AddPlot3Dtmpl =
"1,2,,DEFAULT,PUSHBUTTON,-1,150,10,45,12\n"
"2,3,,,PUSHBUTTON,-2,150,25,45,12\n"
@@ -6536,17 +6852,17 @@ static char *Base25D_DlgTmpl =
"202,203,,,EDVAL1,9,65,45,25,10\n"
"203,204,,,RTEXT,10,48,57,13,8\n"
"204,,,,EDVAL1,11,65,57,25,10\n"
- "300,301,,CHECKED, RADIO1,12,15,35,80,9\n"
- "301,302,,OWNDIALOG | TOUCHEXIT,COLBUTT,13,110,35,20,10\n"
- "302,303,,,RADIO1,14,15,55,80,9\n"
- "303,304,,OWNDIALOG | TOUCHEXIT,COLBUTT,15,25,70,10,10\n"
- "304,305,,OWNDIALOG | TOUCHEXIT,COLBUTT,16,37,70,10,10\n"
- "305,306,,OWNDIALOG | TOUCHEXIT,COLBUTT,17,49,70,10,10\n"
- "306,307,,OWNDIALOG | TOUCHEXIT,COLBUTT,18,61,70,10,10\n"
- "307,308,,OWNDIALOG | TOUCHEXIT,COLBUTT,19,73,70,10,10\n"
- "308,309,,OWNDIALOG | TOUCHEXIT,COLBUTT,20,85,70,10,10\n"
- "309,310,,OWNDIALOG | TOUCHEXIT,COLBUTT,21,97,70,10,10\n"
- "310,,,LASTOBJ | OWNDIALOG | TOUCHEXIT,COLBUTT,22,109,70,10,10";
+ "300,301,,,RADIO1,12,15,35,80,9\n"
+ "301,302,,ODEXIT,COLBUTT,13,110,35,20,10\n"
+ "302,303,,CHECKED,RADIO1,14,15,55,80,9\n"
+ "303,304,,ODEXIT,COLBUTT,15,25,70,10,10\n"
+ "304,305,,ODEXIT,COLBUTT,16,37,70,10,10\n"
+ "305,306,,ODEXIT,COLBUTT,17,49,70,10,10\n"
+ "306,307,,ODEXIT,COLBUTT,18,61,70,10,10\n"
+ "307,308,,ODEXIT,COLBUTT,19,73,70,10,10\n"
+ "308,309,,ODEXIT,COLBUTT,20,85,70,10,10\n"
+ "309,310,,ODEXIT,COLBUTT,21,97,70,10,10\n"
+ "310,,,LASTOBJ | ODEXIT,COLBUTT,22,109,70,10,10";
bool
Chart25D::PropertyDlg()
{
@@ -6672,12 +6988,15 @@ Chart25D::PropertyDlg()
}while(rX->GetNext(&cx, &rx) && rY->GetNext(&cy, &ry));
if(ic) bRet = true;
}
- delete(rY); rY = 0L;
if(plot = new Scatt3D(this, data, cols, ic)){
if(bUseSch) plot->SetColor(COL_BAR_FILL, colarr[(i & 0x07)]);
else plot->SetColor(COL_BAR_FILL, defcol);
plots[nPlots++] = plot;
}
+ if(rY) {
+ plot->data_desc = rY->RangeDesc(data, 1);
+ delete(rY); rY = 0L;
+ }
}
}
}
@@ -7046,12 +7365,8 @@ Func3D::PropertyDlg()
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, TMP_TXT_SIZE);
- if(cmdxy && strcmp(cmdxy, TmpTxt)) {
- Undo.String(this, &cmdxy, undo_flags);
- if(cmdxy) free(cmdxy); cmdxy = (char*)memdup(TmpTxt, (int)strlen(TmpTxt)+1, 0);
- undo_flags |= UNDO_CONTINUE;
- }
+ TmpTxt[0] = 0; Dlg->GetText(200, TmpTxt, TMP_TXT_SIZE);
+ undo_flags = CheckNewString(&cmdxy, cmdxy, TmpTxt, this, undo_flags);
// if(undo_flags & UNDO_CONTINUE) Update(0L, UNDO_CONTINUE);
OD_linedef(OD_GETLINE, 0L, 0L, 0L, (void *)&newLine, 0);
if(cmpLineDEF(&Line, &newLine)) {
@@ -7221,6 +7536,7 @@ FitFunc3D::PropertyDlg()
}
Dlg->GetValue(153, &conv); Dlg->GetValue(155, &iter);
ReshapeFormula(¶m); ReshapeFormula(&cmdxy);
+ do_formula(data, 0L); //clear any error condition
ares = do_formula(data, param);
if(ares->type != ET_VALUE) {
ErrorBox("Syntax Error in parameters.");
@@ -7312,6 +7628,7 @@ FitFunc3D::PropertyDlg()
}
else free(Balls);
}
+ if(bRet)Command(CMD_ENDDIALOG, 0L, 0L);
}
else { //edit existing function
Dlg->GetValue(102, &x1); Dlg->GetValue(104, &x2);
@@ -7577,11 +7894,8 @@ Tick::PropertyDlg()
if(label && label->Id == GO_LABEL) {
td = ((Label*)label)->GetTextDef();
if(!Dlg->GetText(203, TmpTxt, TMP_TXT_SIZE)) TmpTxt[0] = 0;
- if(td->text && strcmp(td->text, TmpTxt)) {
- Undo.String(this, &td->text, undo_flags);
- undo_flags |= UNDO_CONTINUE;
+ if(undo_flags = CheckNewString(&td->text, td->text, TmpTxt, this, undo_flags))
label->Command(CMD_SETTEXT, TmpTxt, 0L);
- }
}
if (undo_flags & UNDO_CONTINUE) bRet = true;
}
@@ -7818,6 +8132,20 @@ Axis::PropertyDlg()
}
}
}
+ else if(IsPlot3D(parent) && (res=((Plot3D*)parent)->nscp)){
+ scp = ((Plot3D*)parent)->Sc_Plots;
+ CurrAxes = ((Plot3D*)parent)->Axes;
+ if(!scp || !(names = (char**)calloc(res+2, sizeof(char*))) ||
+ !(somePlots = (GraphObj**)calloc(res+2, sizeof(GraphObj*))))
+ return false;
+ if(names[0] = (char*)malloc(15 * sizeof(char))) rlp_strcpy(names[0], 15, "[unchanged]");
+ for(i = 0, j = 1; i < res; i++) {
+ if(scp[i] && scp[i]->name){
+ names[j] = (char*)memdup(scp[i]->name, (int)strlen(scp[i]->name)+1, 0);
+ somePlots[j++] = scp[i];
+ }
+ }
+ }
else {
names = (char**)calloc(2, sizeof(char*)); names[0] = (char*)malloc(10*sizeof(char));
rlp_strcpy(names[0], 10, "n.a.");
@@ -7928,7 +8256,7 @@ Axis::PropertyDlg()
memcpy(&new_a, &old_a, sizeof(AxisDEF));
i = rlp_strcpy(TmpTxt, TMP_TXT_SIZE, type_txt);
rlp_strcpy(TmpTxt+i, TMP_TXT_SIZE-i, "xis properties");
- hDlg = CreateDlgWnd(TmpTxt, 50, 50, 436, 384, Dlg, 0x0L);
+ hDlg = CreateDlgWnd(TmpTxt, 50, 50, 436, 390, Dlg, 0x0L);
switch(axis->flags & 0x70) {
case AXIS_LEFT:
case AXIS_RIGHT:
@@ -8134,11 +8462,22 @@ Axis::PropertyDlg()
else if(Dlg->GetCheck(106)) new_a.flags |= AXIS_RIGHT;
else if(Dlg->GetCheck(107)) new_a.flags |= AXIS_TOP;
else if(Dlg->GetCheck(108)) new_a.flags |= AXIS_BOTTOM;
+ if((new_a.flags & AXIS_LOG)== AXIS_LOG && new_a.min < defs.min4log) {
+ switch(type & 0x0f) {
+ case 1:
+ new_a.min = parent->GetSize(SIZE_BOUNDS_XMIN); break;
+ case 2:
+ new_a.min = parent->GetSize(SIZE_BOUNDS_YMIN); break;
+ case 3:
+ new_a.min = parent->GetSize(SIZE_BOUNDS_ZMIN); break;
+ }
+ }
if(cmpAxisDEF(&old_a, &new_a)) {
bChanged = true;
if(axis->flags != new_a.flags) parent->Command(CMD_MRK_DIRTY, 0L, 0L);
Undo.AxisDef(this, axis, undo_flags);
memcpy(axis, &new_a, sizeof(AxisDEF)); undo_flags |= UNDO_CONTINUE;
+ axis->Start = axis->min;
}
else if(new_a.breaks) free(new_a.breaks);
if(axis->nBreaks && Dlg->GetValue(406, &tmp))
@@ -8175,10 +8514,7 @@ Axis::PropertyDlg()
if(Dlg->GetText(131, TmpTxt, TMP_TXT_SIZE) && TmpTxt[0]) {
if(old_Label && strcmp(old_Label,TmpTxt) && axisLabel->Id == GO_LABEL){
lb_def = ((Label*)axisLabel)->GetTextDef();
- Undo.String(axisLabel, &lb_def->text, undo_flags);
- if(lb_def->text) free(lb_def->text);
- lb_def->text = (char*)memdup(TmpTxt, (int)strlen(TmpTxt)+1, 0);
- undo_flags |= UNDO_CONTINUE;
+ undo_flags = CheckNewString(&lb_def->text, old_Label, TmpTxt, this, undo_flags);
}
else if(!axisLabel) {
label_def.ColTxt = colAxis; label_def.ColBg = 0x00ffffffL;
@@ -8335,7 +8671,7 @@ static char *GraphDlgTmpl =
"6,7,300,ISPARENT,SHEET,3,5,10,157,122\n"
"100,101,,,LTEXT,4,10,25,60,8\n"
"101,102,500,TOUCHEXIT | ISPARENT,SHEET,5,10,37,147,90\n"
- "102,103,520,TOUCHEXIT | ISPARENT | CHECKED,SHEET,6,10,37,147,90\n"
+ "102,103,520,TOUCHEXIT | ISPARENT,SHEET,6,10,37,147,90\n"
"103,104,540,TOUCHEXIT | ISPARENT,SHEET,7,10,37,147,90\n"
"104,,560,TOUCHEXIT | ISPARENT,SHEET,8,10,37,147,90\n"
"200,201,,,LTEXT,9,10,35,60,8\n"
@@ -8362,7 +8698,7 @@ static char *GraphDlgTmpl =
"221,,,,LTEXT,-3,140,108,20,8\n"
"300,301,,,LTEXT,23,20,30,60,8\n"
"301,400,310,CHECKED | ISPARENT,GROUP,0,0,0,0,0\n"
- "310,311,,TOUCHEXIT | CHECKED | ISRADIO,ODBUTTON,24,20,42,25,25\n"
+ "310,311,,EXRADIO,ODBUTTON,24,20,42,25,25\n"
"311,312,,EXRADIO,ODBUTTON,24,45,42,25,25\n"
"312,313,,EXRADIO,ODBUTTON,24,70,42,25,25\n"
"313,314,,EXRADIO,ODBUTTON,24,95,42,25,25\n"
@@ -8376,13 +8712,14 @@ static char *GraphDlgTmpl =
"410,411,,EXRADIO,ODBUTTON,30,20,42,25,25\n"
"411,412,,EXRADIO,ODBUTTON,30,45,42,25,25\n"
"412,,,EXRADIO, ODBUTTON,30,70,42,25,25\n"
- "500,501,,EXRADIO | CHECKED,ODBUTTON,31,25,60,25,25\n"
+ "500,501,,EXRADIO,ODBUTTON,31,25,60,25,25\n"
"501,502,,EXRADIO,ODBUTTON,31,50,60,25,25\n"
"502,503,,EXRADIO,ODBUTTON,31,75,60,25,25\n"
"503,504,,EXRADIO,ODBUTTON,31,25,85,25,25\n"
"504,505,,EXRADIO,ODBUTTON,31,50,85,25,25\n"
- "505,,,EXRADIO, ODBUTTON,31,75,85,25,25\n"
- "520,521,,EXRADIO | CHECKED,ODBUTTON, 31, 20,50,25,25\n"
+ "505,506,,EXRADIO, ODBUTTON,31,75,85,25,25\n"
+ "506,,,EXRADIO, ODBUTTON,31,100,85,25,25\n"
+ "520,521,,EXRADIO,ODBUTTON, 31, 20,50,25,25\n"
"521,522,,EXRADIO,ODBUTTON,31,45,50,25,25\n"
"522,523,,EXRADIO,ODBUTTON,31,70,50,25,25\n"
"523,524,,EXRADIO,ODBUTTON,31,95,50,25,25\n"
@@ -8395,12 +8732,12 @@ static char *GraphDlgTmpl =
"530,531,,EXRADIO,ODBUTTON,31,20,100,25,25\n"
"531,532,,EXRADIO,ODBUTTON,31,45,100,25,25\n"
"532,,,EXRADIO,ODBUTTON,31,70,100,25,25\n"
- "540,541,,EXRADIO | CHECKED,ODBUTTON,31,20,60,25,25\n"
+ "540,541,,EXRADIO,ODBUTTON,31,20,60,25,25\n"
"541,542,,EXRADIO,ODBUTTON,31,45,60,25,25\n"
"542,543,,EXRADIO,ODBUTTON,31,70,60,25,25\n"
"543,544,,EXRADIO,ODBUTTON,31,95,60,25,25\n"
"544,,,TOUCHEXIT | ISRADIO,ODBUTTON, 31, 120,60,25,25\n"
- "560,561,,EXRADIO | CHECKED,ODBUTTON, 31,20,60,25,25\n"
+ "560,561,,EXRADIO,ODBUTTON, 31,20,60,25,25\n"
"561,562,,EXRADIO,ODBUTTON,31,45,60,25,25\n"
"562,563,,EXRADIO,ODBUTTON,31,70,60,25,25\n"
"563,564,,EXRADIO,ODBUTTON,31,95,60,25,25\n"
@@ -8409,6 +8746,7 @@ static char *GraphDlgTmpl =
"566,567,,EXRADIO,ODBUTTON,31,45,85,25,25\n"
"567,,,LASTOBJ | EXRADIO, ODBUTTON, 31, 70,85,25,25";
+static int selSheet = 102, selPlt = 520, selAxis = 310;
bool
Graph::PropertyDlg()
{
@@ -8431,7 +8769,7 @@ Graph::PropertyDlg()
DlgRoot *Dlg;
GraphObj *p;
void *hDlg;
- int i, res, selPlt = 520, selAxis = 310;
+ int i, res;
bool bRet, bContinue;
fRECT rc1, rc2;
@@ -8443,6 +8781,36 @@ Graph::PropertyDlg()
if(parent->Id != GO_PAGE) {
Dlg->Activate(202, false); Dlg->Activate(204, false);
}
+ //restore previous settitings
+ switch(selSheet) {
+ case 101:
+ if(selPlt >= 500 && selPlt <=506) Dlg->SetCheck(selPlt, 0L, true);
+ else Dlg->SetCheck(500, 0L, true);
+ Dlg->SetCheck(520, 0L, true); Dlg->SetCheck(540, 0L, true);
+ Dlg->SetCheck(560, 0L, true); break;
+ default:
+ if(selPlt >= 520 && selPlt <=532) Dlg->SetCheck(selPlt, 0L, true);
+ else Dlg->SetCheck(520, 0L, true); selSheet = 102;
+ Dlg->SetCheck(500, 0L, true); Dlg->SetCheck(540, 0L, true);
+ Dlg->SetCheck(560, 0L, true); break;
+ case 103:
+ if(selPlt >= 540 && selPlt <=544) Dlg->SetCheck(selPlt, 0L, true);
+ else Dlg->SetCheck(540, 0L, true);
+ Dlg->SetCheck(520, 0L, true); Dlg->SetCheck(500, 0L, true);
+ Dlg->SetCheck(560, 0L, true); break;
+ case 104:
+ if(selPlt >= 560 && selPlt <=567) Dlg->SetCheck(selPlt, 0L, true);
+ else Dlg->SetCheck(560, 0L, true);
+ Dlg->ShowItem(301, false); Dlg->ShowItem(400, true);
+ Dlg->SetCheck(520, 0L, true); Dlg->SetCheck(540, 0L, true);
+ Dlg->SetCheck(500, 0L, true); break;
+ }
+ Dlg->SetCheck(selSheet, 0L, true);
+ if(selAxis >= 310 && selAxis <= 314) Dlg->SetCheck(selAxis, 0L, true);
+ else Dlg->SetCheck(310, 0L, true);
+ if(selAxis >= 410 && selAxis <= 412) Dlg->SetCheck(selAxis, 0L, true);
+ else Dlg->SetCheck(410, 0L, true);
+ //display the dialog
hDlg = CreateDlgWnd("Create graph", 50, 50, 450, 300, Dlg, 0x0L);
bContinue = false;
do{
@@ -8457,24 +8825,24 @@ Graph::PropertyDlg()
bContinue = false;
break;
case 101: //only y data
- for(i = 500; i <= 505; i++) if(Dlg->GetCheck(i))selPlt = i;
+ for(i = 500; i <= 506; i++) if(Dlg->GetCheck(i))selPlt = i;
Dlg->ShowItem(301, true); Dlg->ShowItem(400, false);
- res = -1;
+ selSheet = res; res = -1;
break;
case 102: //xy data
for(i = 520; i <= 532; i++) if(Dlg->GetCheck(i))selPlt = i;
Dlg->ShowItem(301, true); Dlg->ShowItem(400, false);
- res = -1;
+ selSheet = res; res = -1;
break;
case 103: //x many y data
for(i = 540; i <= 544; i++) if(Dlg->GetCheck(i))selPlt = i;
Dlg->ShowItem(301, true); Dlg->ShowItem(400, false);
- res = -1;
+ selSheet = res; res = -1;
break;
case 104: //xyz data
for(i = 560; i <= 567; i++) if(Dlg->GetCheck(i))selPlt = i;
Dlg->ShowItem(301, false); Dlg->ShowItem(400, true);
- res = -1;
+ selSheet = res; res = -1;
break;
case 310: case 311: case 312: case 313: case 314:
AxisTempl = res-310;
@@ -8497,7 +8865,7 @@ Graph::PropertyDlg()
res = -1;
break;
case 500: case 501: case 502: case 503:
- case 504: case 505:
+ case 504: case 505: case 506:
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 532:
@@ -8554,6 +8922,7 @@ Graph::PropertyDlg()
else if(Dlg->GetCheck(503))p = new BarChart(this, data);
else if(Dlg->GetCheck(504))p = new GroupBars(this, data);
else if(Dlg->GetCheck(505))p = new FreqDist(this, data);
+ else if(Dlg->GetCheck(506))p = new NormQuant(this, data, 0L);
}
else if(Dlg->GetCheck(102)){
if(Dlg->GetCheck(524)) p = new BubblePlot(this, data);
@@ -8777,47 +9146,47 @@ Graph::Configure()
}
static char *AddAxisTmpl =
- "1,2,,DEFAULT, PUSHBUTTON,-1,148,10,45,12\n"
- "2,3,,,PUSHBUTTON,-2,148,25,45,12\n"
- "3,,4,ISPARENT | CHECKED,GROUP,0,0,0,0,0\n"
- "4,5,50,TOUCHEXIT | ISPARENT,SHEET,1,5,10,130,130\n"
- "5,6,200,ISPARENT | CHECKED,SHEET,2,5,10,130,130\n"
- "6,,300,ISPARENT,SHEET,3,5,10,130,130\n"
- "50,51,100,ISPARENT | CHECKED,GROUPBOX,4,10,30,120,36\n"
- "51,120,,,CHECKBOX,5,17,37,80,8\n"
- "100,101,,,RTEXT,6,10,51,35,8\n"
- "101,102,,,EDVAL1,7,48,51,32,10\n"
- "102,103,,,CTEXT,8,81,51,11,8\n"
- "103,,,,EDVAL1,9,93,51,32,10\n"
- "120,,121,ISPARENT | CHECKED,GROUPBOX,10,10,72,120,20\n"
- "121,122,,,RTEXT,11,10,77,25,8\n"
- "122,123,,,EDVAL1,12,37,77,25,10\n"
- "123,124,,,LTEXT,-3,63,77,10,8\n"
- "124,125,,,RTEXT,13,73,77,25,8\n"
- "125,130,,OWNDIALOG,COLBUTT,14,100,77,25,10\n"
- "130,131,,ISPARENT | CHECKED,GROUPBOX,15,10,98,120,20\n"
- "131,,,,EDTEXT,0,15,103,110,10\n"
- "200,201,,,LTEXT,16,10,30,70,9\n"
- "201,202,,CHECKED | EXRADIO,ODBUTTON,17,20,42,25,25\n"
- "202,203,,EXRADIO,ODBUTTON,17,45,42,25,25\n"
- "203,204,,EXRADIO,ODBUTTON,17,70,42,25,25\n"
- "204,205,,EXRADIO,ODBUTTON,17,95,42,25,25\n"
- "205,206,,EXRADIO,ODBUTTON,17,20,67,25,25\n"
- "206,207,,EXRADIO,ODBUTTON,17,45,67,25,25\n"
- "207,208,,EXRADIO,ODBUTTON,17,70,67,25,25\n"
- "208,210,,EXRADIO,ODBUTTON,17,95,67,25,25\n"
- "210,,220,ISPARENT | CHECKED, GROUPBOX,18,10,97,120,35\n"
- "220,221,,,RTEXT,-4,10,105,15,8\n"
- "221,222,,,EDVAL1,19,27,105,35,10\n"
- "222,223,,,LTEXT,-7,65,105,5,8\n"
- "223,224,,,EDVAL1,20,71,105,35,10\n"
- "224,225,,,LTEXT,-3,109,105,15,8\n"
- "225,226,,,RTEXT,-5,10,117,15,8\n"
- "226,227,,,EDVAL1,21,27,117,35,10\n"
- "227,228,,,LTEXT,-7,65,117,5,8\n"
- "228,229,,,EDVAL1,22,71,117,35,10\n"
- "229,,,,LTEXT,-3,109,117,15,8\n"
- "300,,,LASTOBJ | NOSELECT,ODBUTTON,23,15,30,110,140\n";
+ "1,2,,DEFAULT, PUSHBUTTON,-1,148,10,45,12\n"
+ "2,3,,,PUSHBUTTON,-2,148,25,45,12\n"
+ "3,,4,ISPARENT | CHECKED,GROUP,0,0,0,0,0\n"
+ "4,5,50,TOUCHEXIT | ISPARENT,SHEET,1,5,10,130,130\n"
+ "5,6,200,ISPARENT | CHECKED,SHEET,2,5,10,130,130\n"
+ "6,,300,ISPARENT,SHEET,3,5,10,130,130\n"
+ "50,51,100,ISPARENT | CHECKED,GROUPBOX,4,10,30,120,36\n"
+ "51,120,,,CHECKBOX,5,17,37,80,8\n"
+ "100,101,,,RTEXT,6,10,51,35,8\n"
+ "101,102,,,EDVAL1,7,48,51,32,10\n"
+ "102,103,,,CTEXT,8,81,51,11,8\n"
+ "103,,,,EDVAL1,9,93,51,32,10\n"
+ "120,,121,ISPARENT | CHECKED,GROUPBOX,10,10,72,120,20\n"
+ "121,122,,,RTEXT,11,10,77,25,8\n"
+ "122,123,,,EDVAL1,12,37,77,25,10\n"
+ "123,124,,,LTEXT,-3,63,77,10,8\n"
+ "124,125,,,RTEXT,-11,73,77,25,8\n"
+ "125,130,,OWNDIALOG,COLBUTT,14,100,77,25,10\n"
+ "130,131,,ISPARENT | CHECKED,GROUPBOX,15,10,98,120,20\n"
+ "131,,,,EDTEXT,0,15,103,110,10\n"
+ "200,201,,,LTEXT,16,10,30,70,9\n"
+ "201,202,,CHECKED | EXRADIO,ODBUTTON,17,20,42,25,25\n"
+ "202,203,,EXRADIO,ODBUTTON,17,45,42,25,25\n"
+ "203,204,,EXRADIO,ODBUTTON,17,70,42,25,25\n"
+ "204,205,,EXRADIO,ODBUTTON,17,95,42,25,25\n"
+ "205,206,,EXRADIO,ODBUTTON,17,20,67,25,25\n"
+ "206,207,,EXRADIO,ODBUTTON,17,45,67,25,25\n"
+ "207,208,,EXRADIO,ODBUTTON,17,70,67,25,25\n"
+ "208,210,,EXRADIO,ODBUTTON,17,95,67,25,25\n"
+ "210,,220,ISPARENT | CHECKED, GROUPBOX,18,10,97,120,35\n"
+ "220,221,,,RTEXT,-4,10,105,15,8\n"
+ "221,222,,,EDVAL1,19,27,105,35,10\n"
+ "222,223,,,LTEXT,-7,65,105,5,8\n"
+ "223,224,,,EDVAL1,20,71,105,35,10\n"
+ "224,225,,,LTEXT,-3,109,105,15,8\n"
+ "225,226,,,RTEXT,-5,10,117,15,8\n"
+ "226,227,,,EDVAL1,21,27,117,35,10\n"
+ "227,228,,,LTEXT,-7,65,117,5,8\n"
+ "228,229,,,EDVAL1,22,71,117,35,10\n"
+ "229,,,,LTEXT,-3,109,117,15,8\n"
+ "300,,,LASTOBJ | NOSELECT,ODBUTTON,23,15,30,110,140";
bool
Graph::AddAxis()
@@ -8830,10 +9199,10 @@ Graph::AddAxis()
DWORD colAxis = ColAX;
void *dyndata[] = {(void*)&tab1, (void*)&tab2, (void*)&tab3, (void*)" scaling ", (void*)" automatic scaling",
(void*)"axis from", (void*)&y_axis.min, (void*)"to", (void*)&y_axis.max, (void*)" line ", (void*)"width",
- (void*)&sizAxLine, (void*)"color", (void *)&colAxis, (void*)" axis label ", (void*)"select a template:",
+ (void*)&sizAxLine, (void*)0L, (void *)&colAxis, (void*)" axis label ", (void*)"select a template:",
(void*)(OD_NewAxisTempl), (void*)" placement ", (void*)&axis.loc[0].fx, (void*)&axis.loc[1].fx,
(void*)&axis.loc[0].fy, (void*)&axis.loc[1].fy, (void*)OD_axisplot};
- DlgInfo *NewAxisDlg = CompileDialog(AddAxisTmpl, dyndata);
+ DlgInfo *NewAxisDlg;
DlgRoot *Dlg;
void *hDlg;
int i, j, res, currTempl = 201;
@@ -8848,6 +9217,7 @@ Graph::AddAxis()
GraphObj **somePlots;
Label *label;
+ if(!(NewAxisDlg = CompileDialog(AddAxisTmpl, dyndata)))return false;
if(!(names = (char**)calloc(nscp+2, sizeof(char*))))return false;
if(!(somePlots = (GraphObj**)calloc(nscp+2, sizeof(GraphObj*))))return false;
if(!Axes) Axes = (Axis**)calloc(2, sizeof(Axis*));
diff --git a/QT_Spec.cpp b/QT_Spec.cpp
index 8623c1c..dbee7a8 100755
--- a/QT_Spec.cpp
+++ b/QT_Spec.cpp
@@ -1,4 +1,4 @@
-//QT_Spec.cpp, Copyright (c) 2001-2006 R.Lackner
+//QT_Spec.cpp, Copyright (c) 2001-2007 R.Lackner
//
// This file is part of RLPlot.
//
@@ -46,7 +46,7 @@ extern Default defs;
extern UndoObj Undo;
QApplication *QAppl;
-QWidget *MainWidget =0L;
+QWidget *MainWidget =0L, *CurrWidget = 0L;
POINT CurrWidgetPos = {0,0};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -83,12 +83,24 @@ char *SaveDataAsName(char *oldname)
// Get a new file name to store graph
char *SaveGraphAsName(char *oldname)
{
- QString fileName = QFileDialog::getSaveFileName(oldname?oldname:defs.currPath,
- "RLPlot files (*.rlp)", QAppl->focusWidget());
- if(!fileName.isEmpty()){
- strcpy(UserFileName, fileName);
- defs.FileHistory(UserFileName);
- return UserFileName;
+ QFileDialog qf(0,0,true);
+ QString filters("RLPlot files (*.rlp)");
+ int i, cb;
+ char *ext;
+
+ qf.setFilters(filters); qf.setDir(defs.currPath);
+ qf.setSelection(oldname); qf.setMode(QFileDialog::AnyFile);
+ if(qf.exec() == QDialog::Accepted) {
+ if(!qf.selectedFile().isEmpty()) {
+ cb = rlp_strcpy(UserFileName, 600, (char*)qf.selectedFile().ascii());
+ if(cb < 4 || UserFileName[cb-4] != '.'){
+ ext = (char*)qf.selectedFilter().ascii();
+ for(i = 0; ext[i] && ext[i] != '*'; i++);
+ rlp_strcpy(UserFileName+cb, 5, ext+i+1);
+ }
+ defs.FileHistory(UserFileName);
+ return UserFileName;
+ }
}
return 0L;
}
@@ -209,7 +221,7 @@ void Qt_Box()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
anyOutput *oTxtCur = 0L;
RECT rTxtCur, rCopyMark;
-bool bTxtCur = false;
+bool bTxtCur = false, bSuspend = false;
DWORD coTxtCur = 0x0L;
TxtCurBlink *cTxtCur = 0L;
POINT ptTxtCurLine[2];
@@ -230,9 +242,8 @@ void HideTextCursorObj(anyOutput *out)
void ShowTextCursor(anyOutput *out, RECT *disp, DWORD color)
{
- coTxtCur = color;
- HideTextCursor();
- oTxtCur = out;
+ coTxtCur = color; HideTextCursor();
+ oTxtCur = out; bSuspend = false;
memcpy(&rTxtCur, disp, sizeof(RECT));
ptTxtCurLine[0].x = rTxtCur.left; ptTxtCurLine[0].y = rTxtCur.top;
ptTxtCurLine[1].x = rTxtCur.right; ptTxtCurLine[1].y = rTxtCur.bottom;
@@ -264,21 +275,45 @@ void ShowCopyMark(anyOutput *out, RECT *mrk, int nRec)
int i;
if(!out || !mrk || !nRec || !cTxtCur) return;
- cTxtCur->oCopyMark = out;
+ cTxtCur->oCopyMark = out; bSuspend = false;
rCopyMark.left = mrk[0].left; rCopyMark.right = mrk[0].right;
rCopyMark.top = mrk[0].top; rCopyMark.bottom = mrk[0].bottom;
for(i = 1; i < nRec; i++) {
UpdateMinMaxRect(&rCopyMark, mrk[i].left, mrk[i].top);
UpdateMinMaxRect(&rCopyMark, mrk[i].right, mrk[i].bottom);
}
+ if(cTxtCur->bmCopyMark) delete(cTxtCur->bmCopyMark);
cTxtCur->bmCopyMark = new BitMapQT(rCopyMark.right - rCopyMark.left+1,
rCopyMark.bottom - rCopyMark.top+1, out->hres, out->vres);
}
+void InvalidateOutput(anyOutput *o)
+{
+ if(!o || !cTxtCur) return;
+ if(o == cTxtCur->oCopyMark) {
+ cTxtCur->oCopyMark = 0L;
+ if(cTxtCur->bmCopyMark) delete cTxtCur->bmCopyMark;
+ cTxtCur->bmCopyMark = 0L;
+ }
+ if(o == oTxtCur) {
+ oTxtCur = 0L; bTxtCur = false;
+ }
+}
+
+void SuspendAnimation(anyOutput *o, bool bSusp)
+{
+ if(!o || !cTxtCur) return;
+ if(!bSusp) bSuspend = false;
+ else {
+ if(o == cTxtCur->oCopyMark) bSuspend = bSusp;
+ if(o == oTxtCur) bSuspend = bSusp;
+ }
+}
+
LineDEF liCopyMark1 = {0.0f, 1.0f, 0x00ffffffL, 0L};
LineDEF liCopyMark2 = {0.0f, 6.0f, 0x0L, 0xf0f0f0f0L};
-TxtCurBlink::TxtCurBlink():QObject(MainWidget, 0)
+TxtCurBlink::TxtCurBlink():QObject(CurrWidget, 0)
{
isVis = false;
oCopyMark = 0L; bmCopyMark = 0L;
@@ -322,7 +357,7 @@ TxtCurBlink::showCopyMark()
void
TxtCurBlink::timerEvent(QTimerEvent *ev)
{
- showCopyMark();
+ if(bSuspend) return; showCopyMark();
if(!oTxtCur || (ptTxtCurLine[0].x == ptTxtCurLine[1].x &&
ptTxtCurLine[0].y == ptTxtCurLine[1].y)) return;
count++;
@@ -666,6 +701,9 @@ void GetDesktopSize(int *width, int *height)
QWidget *d = QApplication::desktop();
*width = d->width();
*height = d->height();
+ if(*width < 800 || *height < 600){
+ *width = 800; *height = 600;
+ }
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -683,26 +721,50 @@ DWORD SwapRB(DWORD col)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Common code for all QT output classes
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-bool com_TextOut(int x, int y, char *ctxt, TextDEF *TxtSet, QPainter *qP, anyOutput *o)
+bool com_QStringExt(QString txt, int *width, int *height, int cb, TextDEF *TxtSet, QPainter *qP)
+{
+ QRect rc;
+
+ if(cb >0)txt.truncate(cb);
+ rc = qP->boundingRect(0, 0, 10000, 1000, Qt::AlignLeft | Qt::AlignTop, txt);
+ *width = rc.rRight() - rc.rLeft();
+ *height = TxtSet->iSize +2;
+ return true;
+}
+
+bool
+com_GetTextExtent(char *txt, int *width, int *height, int cb, TextDEF *TxtSet, QPainter *qP)
+{
+ if(!txt || !txt[0]) return com_QStringExt(QString("a"), width, height, 1, TxtSet, qP);
+ else return com_QStringExt(QString(txt), width, height, cb > 0 ? cb : (int)strlen(txt), TxtSet, qP);
+}
+
+bool
+com_GetTextExtentW(w_char *txt, int *width, int *height, int cb, TextDEF *TxtSet, QPainter *qP)
+{
+ int i;
+ QString wtxt(0);
+
+ if(!txt || !txt[0]) return com_QStringExt(QString("a"), width, height, 1, TxtSet, qP);
+ for(i = 0; txt[i] && i < cb; i++) wtxt.append(QChar(txt[i]));
+ com_QStringExt(wtxt, width, height, cb, TxtSet, qP);
+}
+
+bool com_QStringOut(int x, int y, QString txt, TextDEF *TxtSet, QPainter *qP, anyOutput *o)
{
int i, w, h, ix, iy;
QBrush oldBrush;
QPen oldPen, currPen;
QWMatrix xf, dxf;
- QString txt(ctxt);
- if(!ctxt || !ctxt[0] || !TxtSet || !qP || !o) return false;
- if(TxtSet->Font==FONT_GREEK) {
- txt.truncate(0);
- for(i = 0; ctxt[i]; i++) {
- if((ctxt[i] >= 'A' && ctxt[i] <= 'Z')) txt.append(QChar(ctxt[i] - 'A' + 0x391));
- else if((ctxt[i] >= 'a' && ctxt[i] <= 'z')) txt.append(QChar(ctxt[i] - 'a' + 0x3B1));
- else txt.append(QChar(ctxt[i]));
- }
- }
+ if(!TxtSet->iSize && TxtSet->fSize > 0.0) TxtSet->iSize = o->un2ix(TxtSet->fSize);
+ if(!TxtSet->iSize) return false;
+ if(TxtSet->Align & TXA_VCENTER) y += iround(TxtSet->iSize * 0.4);
+ else if(TxtSet->Align & TXA_VBOTTOM) y -= iround(TxtSet->iSize * 0.1);
+ else y += iround(TxtSet->iSize);
oldBrush = qP->brush(); dxf = qP->worldMatrix();
- oldPen = currPen = qP->pen();
- o->oGetTextExtent(ctxt, -1, &w, &h); iy = y;
+ oldPen = currPen = qP->pen(); iy = y;
+ com_QStringExt(txt, &w, &h, -1, TxtSet, qP);
if(TxtSet->Align & TXA_HCENTER) ix = x - (w >> 1);
else if(TxtSet->Align & TXA_HRIGHT) ix = x - w;
else ix = x;
@@ -745,6 +807,33 @@ bool com_TextOut(int x, int y, char *ctxt, TextDEF *TxtSet, QPainter *qP, anyOut
return true;
}
+bool com_TextOut(int x, int y, char *ctxt, TextDEF *TxtSet, QPainter *qP, anyOutput *o)
+{
+ int i, w, h, ix, iy;
+ QString txt(ctxt);
+
+ if(!ctxt || !ctxt[0] || !TxtSet || !qP || !o) return false;
+ if(TxtSet->Font==FONT_GREEK) {
+ txt.truncate(0);
+ for(i = 0; ctxt[i]; i++) {
+ if((ctxt[i] >= 'A' && ctxt[i] <= 'Z')) txt.append(QChar(ctxt[i] - 'A' + 0x391));
+ else if((ctxt[i] >= 'a' && ctxt[i] <= 'z')) txt.append(QChar(ctxt[i] - 'a' + 0x3B1));
+ else txt.append(QChar(ctxt[i]));
+ }
+ }
+ return com_QStringOut(x, y, txt, TxtSet, qP, o);
+}
+
+bool com_TextOutW(int x, int y, w_char *wtxt, TextDEF *TxtSet, QPainter *qP, anyOutput *o)
+{
+ int i;
+ QString txt(0);
+
+ if(!wtxt || !wtxt[0] || !TxtSet || !qP || !o) return false;
+ for(i = 0; wtxt[i]; i++) txt.append(QChar(wtxt[i]));
+ return com_QStringOut(x, y, txt, TxtSet, qP, o);
+}
+
bool com_SetTextSpec(TextDEF *set, TextDEF *TxtSet, anyOutput *o, QFont qF, QPainter *qP)
{
bool RetVal;
@@ -757,7 +846,7 @@ bool com_SetTextSpec(TextDEF *set, TextDEF *TxtSet, anyOutput *o, QFont qF, QPai
qF.setItalic((TxtSet->Style & TXS_ITALIC) ? true : false);
qF.setUnderline((TxtSet->Style &TXS_UNDERLINE) ? true : false);
if((TxtSet->Style & TXS_SUPER) || (TxtSet->Style & TXS_SUB))
- qF.setPointSize((int)(TxtSet->iSize*0.71));
+ qF.setPointSize((TxtSet->iSize > 1) ? (int)(TxtSet->iSize*0.71) : 1);
else qF.setPointSize((TxtSet->iSize > 2) ? TxtSet->iSize : 2);
switch(TxtSet->Font){
case FONT_HELVETICA:
@@ -1272,17 +1361,13 @@ BitMapQT::CopyBitmap(int x, int y, anyOutput* sr, int sx, int sy,
bool
BitMapQT::oGetTextExtent(char *text, int cb, int *width, int *height)
{
- if(!text || !text[0]){
- QRect rc = qPainter.boundingRect(0, 0, 10000, 1000, Qt::AlignLeft | Qt::AlignTop, "A", 1);
- *width = rc.rLeft();
- }
- else {
- QRect rc = qPainter.boundingRect(0, 0, 10000, 1000, Qt::AlignLeft | Qt::AlignTop,
- text, cb > 0 ? cb : strlen(text));
- *width = rc.rRight() - rc.rLeft();
- }
- *height = TxtSet.iSize +2;
- return true;
+ return com_GetTextExtent(text, width, height, cb, &TxtSet, &qPainter);
+}
+
+bool
+BitMapQT::oGetTextExtentW(w_char *text, int cb, int *width, int *height)
+{
+ return com_GetTextExtentW(text, width, height, cb, &TxtSet, &qPainter);
}
bool
@@ -1374,13 +1459,17 @@ bool
BitMapQT::oTextOut(int x, int y, char *txt, int cb)
{
if(!txt || !txt[0]) return false;
- if(TxtSet.Align & TXA_VCENTER) y += iround(TxtSet.iSize * 0.4);
- else if(TxtSet.Align & TXA_VBOTTOM) y -= iround(TxtSet.iSize * 0.1);
- else y += iround(TxtSet.iSize * 1.0);
return com_TextOut(x, y, txt, &TxtSet, &qPainter, this);
}
bool
+BitMapQT::oTextOutW(int x, int y, w_char *txt, int cb)
+{
+ if(!txt || !txt[0]) return false;
+ return com_TextOutW(x, y, txt, &TxtSet, &qPainter, this);
+}
+
+bool
BitMapQT::oPolygon(POINT *pts, int cp, char *nam)
{
int i;
@@ -1397,47 +1486,63 @@ BitMapQT::oPolygon(POINT *pts, int cp, char *nam)
if(hgo) hgo->oPolygon(pts, cp);
}
-bool
-BitMapQT::oArc(int x1, int y1, int x2, int y2, int quads)
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The menu class
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+RLPmenu::RLPmenu(QWidget *par, anyOutput *o, GraphObj *g)
+:QMenuBar(par, 0L)
{
- int i, j;
+ parent = par; OutputClass = o; BaseObj = g;
+ connect(this, SIGNAL(activated(int)), this, SLOT(doMenuItem(int)));
+}
- if(x1 > x2) Swap(x1, x2); if(y1 > y2) Swap(y1, y2);
- switch(quads) {
- case 1: i = 270*16; j = 90*16; break;
- case 2: i = 180*16; j = 180*16; break;
- case 3: i = 90*16; j = 270*16; break;
- case 4: i = 0; j = 360*16; break;
- default: return false;
+void
+RLPmenu::doMenuItem(int id)
+{
+ if(OutputClass) Undo.SetDisp(OutputClass);
+ if(parent && (parent->y() || parent->x())) {
+ CurrWidgetPos.x = parent->x(); CurrWidgetPos.y = parent->y(); CurrWidget = parent;
}
- qPainter.drawArc(x1, y1, x2-x1, y2-y1, i, j);
- return true;
+ if(BaseObj) switch(id) {
+ case CM_REPANOV:
+ rep_anova(BaseObj, BaseObj->data); return;
+ case CM_REPKRUSKAL:
+ rep_kruskal(BaseObj, BaseObj->data); return;
+ case CM_CORRELM:
+ rep_correl(BaseObj, BaseObj->data, 0); return;
+ case CM_CORRELT:
+ rep_correl(BaseObj, BaseObj->data, 1); return;
+ }
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// The display output class
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-OutputQT::OutputQT(GraphObj *g):BitMapQT(g, 0L)
+OutputQT::OutputQT(GraphObj *g):BitMapQT(g, QAppl->desktop())
{
int w, h;
- RLPwidget *rw;
HScroll = VScroll = 0L;
+ GetDesktopSize(&w, &h);
CreateNewWindow(BaseObj = g);
- if(rw = (RLPwidget*)widget) {
- rw->move(CurrWidgetPos.x+50, CurrWidgetPos.y+50);
- rw->show();
- rw->mempic = mempic;
- rw->setBackgroundMode(QWidget::NoBackground);
+ if(widget) {
+ widget->setBackgroundMode(QWidget::NoBackground);
+ if(CurrWidgetPos.x >= ((w>>1)-100))CurrWidgetPos.x = CurrWidgetPos.y = 50;
+ widget->show();
+ widget->move(CurrWidgetPos.x+=50, CurrWidgetPos.y+=50);
+ if(widget->x() || widget->y()) {
+ CurrWidgetPos.x = widget->x(); CurrWidgetPos.y = widget->y();
+ }
}
}
OutputQT::OutputQT(DlgWidget *wi):BitMapQT(0L, wi)
{
//assume fixed size (dialog) widget
- widget = wi;
- HScroll = VScroll = 0L;
- BaseObj = 0L;
+ if(widget = wi) {
+ wi->move(CurrWidgetPos.x+50, CurrWidgetPos.y+50);
+ }
+ HScroll = VScroll = 0L; BaseObj = 0L;
wi->OutputClass = this;
wi->mempic = mempic;
wi->setBackgroundMode(QWidget::NoBackground);
@@ -1462,7 +1567,7 @@ OutputQT::ActualSize(RECT *rc)
rc->left = rc->top = 0;
rc->bottom = widget->height() - MenuHeight-6;
rc->right = widget->width();
- return true;
+ return (rc->right > 40 && rc->bottom > 40);
}
return false;
}
@@ -1587,24 +1692,29 @@ OutputQT::MouseCursor(int cid, bool force)
QBitmap *bits, *mask;
bits = mask = 0L;
+ CurrWidget = widget;
switch(cid) {
#ifdef Q_CHECK_PTR //Qt version 3
case MC_ARROW: widget->setCursor(QCursor(Qt::ArrowCursor)); break;
+ case MC_TXTFRM:
case MC_CROSS: widget->setCursor(QCursor(Qt::CrossCursor)); break;
case MC_WAIT: widget->setCursor(QCursor(Qt::WaitCursor)); break;
case MC_TEXT: widget->setCursor(QCursor(Qt::IbeamCursor)); break;
case MC_NORTH: widget->setCursor(QCursor(Qt::SizeVerCursor)); break;
case MC_NE: widget->setCursor(QCursor(Qt::SizeBDiagCursor));break;
+ case MC_COLWIDTH:
case MC_EAST: widget->setCursor(QCursor(Qt::SizeHorCursor)); break;
case MC_SE: widget->setCursor(QCursor(Qt::SizeFDiagCursor));break;
case MC_SALL: widget->setCursor(QCursor(Qt::SizeAllCursor)); break;
#else //Qt version 2
case MC_ARROW: widget->setCursor(QCursor(ArrowCursor)); break;
+ case MC_TXTFRM:
case MC_CROSS: widget->setCursor(QCursor(CrossCursor)); break;
case MC_WAIT: widget->setCursor(QCursor(WaitCursor)); break;
case MC_TEXT: widget->setCursor(QCursor(IbeamCursor)); break;
case MC_NORTH: widget->setCursor(QCursor(SizeVerCursor)); break;
case MC_NE: widget->setCursor(QCursor(SizeBDiagCursor));break;
+ case MC_COLWIDTH:
case MC_EAST: widget->setCursor(QCursor(SizeHorCursor)); break;
case MC_SE: widget->setCursor(QCursor(SizeFDiagCursor));break;
case MC_SALL: widget->setCursor(QCursor(SizeAllCursor)); break;
@@ -1655,6 +1765,9 @@ OutputQT::SetScroll(bool isVert, int iMin, int iMax, int iPSize, int iPos)
{
QScrollBar *sb;
+ if((CurrWidget = widget) && (widget->x() || widget->y())) {
+ CurrWidgetPos.x = widget->x(); CurrWidgetPos.y = widget->y();
+ }
if(isVert) {
if(!(sb = VScroll))return false;
}
@@ -1795,16 +1908,26 @@ OutputQT::SetMenu(int type)
graph->insertSeparator();
graph->insertItem("&Settings", widget, SLOT(cmDefaults()));
+ QPopupMenu *anov = new QPopupMenu(widget);
+ anov->insertItem("&One Way Anova", CM_REPANOV);
+ anov->insertItem("&Kruskal Wallis", CM_REPKRUSKAL);
+
+ QPopupMenu *corr = new QPopupMenu(widget);
+ corr->insertItem("Correlation &Matrix", CM_CORRELM);
+ corr->insertItem("Tiled &Plots", CM_CORRELT);
+
QPopupMenu *stats = new QPopupMenu(widget);
+ stats->insertItem("&Sample Stats", widget, SLOT(cmSmplStat()));
stats->insertItem("&Comp. Means", widget, SLOT(cmRepCmeans()));
- stats->insertItem("&Anova", widget, SLOT(cmRepanov()));
+ stats->insertItem("&Anova", anov);
stats->insertItem("&Regression", widget, SLOT(cmRepregr()));
+ stats->insertItem("C&orrelations", corr);
stats->insertItem("&2x2 Table", widget, SLOT(cmReptwoway()));
QPopupMenu *about = new QPopupMenu(widget);
about->insertItem("&About ...", widget, SLOT(cmAbout()));
- menu = new QMenuBar(widget);
+ menu = new RLPmenu(widget, this, BaseObj);
menu->insertItem("&File", file); menu->insertItem("&Edit", edit);
menu->insertItem("&Statistics", stats); menu->insertItem("&Graph", graph);
menu->insertItem("&?", about);
@@ -1876,7 +1999,7 @@ OutputQT::SetMenu(int type)
QPopupMenu *about = new QPopupMenu(widget);
about->insertItem("&About ...", widget, SLOT(cmAbout()));
- menu = new QMenuBar(widget);
+ menu = new RLPmenu(widget, this, BaseObj);
menu->insertItem("&File", file);
menu->insertItem("&Edit", edit);
menu->insertItem("&Display", displ);
@@ -1946,7 +2069,7 @@ OutputQT::SetMenu(int type)
QPopupMenu *about = new QPopupMenu(widget);
about->insertItem("&About ...", widget, SLOT(cmAbout()));
- menu = new QMenuBar(widget);
+ menu = new RLPmenu(widget, this, BaseObj);
menu->insertItem("&File", file);
menu->insertItem("&Edit", edit);
menu->insertItem("&Display", displ);
@@ -2007,6 +2130,7 @@ OutputQT::CreateNewWindow(GraphObj *g)
if(widget = new RLPwidget(0, 0, this, g)) {
widget->setCaption("OutputQT::CreateNewWindow");
widget->setGeometry(0, 0, (int)(w*.7f), (int)(h*.7f));
+ ((RLPwidget*)widget)->mempic = mempic;
HScroll = ((RLPwidget*)widget)->HScroll;
VScroll = ((RLPwidget*)widget)->VScroll;
}
@@ -2038,6 +2162,7 @@ RLPwidget::RLPwidget(QWidget *par, const char *name, anyOutput *o, GraphObj *g)
if(!MainWidget) QAppl->setMainWidget(MainWidget = this);
setMouseTracking(true);
setFocusPolicy(StrongFocus);
+ setKeyCompression(true);
}
RLPwidget::~RLPwidget()
@@ -2406,15 +2531,15 @@ RLPwidget::cmtText()
}
void
-RLPwidget::cmRepCmeans()
+RLPwidget::cmSmplStat()
{
- if(BaseObj) rep_compmeans(BaseObj, BaseObj->data);
+ if(BaseObj) rep_samplestats(BaseObj, BaseObj->data);
}
void
-RLPwidget::cmRepanov()
+RLPwidget::cmRepCmeans()
{
- if(BaseObj) rep_anova(BaseObj, BaseObj->data);
+ if(BaseObj) rep_compmeans(BaseObj, BaseObj->data);
}
void
@@ -2443,6 +2568,7 @@ RLPwidget::paintEvent(QPaintEvent *range)
void
RLPwidget::resizeEvent(QResizeEvent *)
{
+ CurrWidget = this;
HScroll->resize(width() -16, 16);
HScroll->move(0, height()-16);
VScroll->resize(16, height()-OutputClass->MenuHeight-16);
@@ -2478,6 +2604,7 @@ RLPwidget::mousePressEvent(QMouseEvent *e)
MouseEvent mev = {1, e->button() == Qt::LeftButton ? MOUSE_LBDOWN : -1, e->x(), e->y()};
HideTextCursor(); i = e->state();
+ CurrWidget = this;
if(i & Qt::ShiftButton) mev.StateFlags |= 0x08;
if(i & Qt::ControlButton) mev.StateFlags |= 0x10;
if (BaseObj)BaseObj->Command(CMD_MOUSE_EVENT, (void *)&mev, OutputClass);
@@ -2513,6 +2640,8 @@ void
RLPwidget::keyPressEvent(QKeyEvent *e)
{
int i, c;
+ QChar qc;
+ w_char uc;
if(BaseObj) switch(c = e->key()) {
case Key_Prior:
@@ -2557,12 +2686,15 @@ RLPwidget::keyPressEvent(QKeyEvent *e)
BaseObj->Command(CMD_POS_LAST, 0L, OutputClass);
break;
default:
- c = e->ascii();
- if(c == 3) cmCopy();
- else if(c == 22) cmPaste();
- else if(c == 26) cmUndo();
- else if(c >1 && c < 256)
- BaseObj->Command(CMD_ADDCHAR, (void *)(& c), OutputClass);
+ QString kres = e->text();
+ for(i = 0; i < kres.length(); i++) {
+ qc = kres.at(i); uc = qc.unicode();
+ if(uc == 3) cmCopy();
+ else if(uc == 22) cmPaste();
+ else if(uc == 26) cmUndo();
+ else if(uc > 255) BaseObj->Command(CMD_ADDCHARW, (void *)(&uc), OutputClass);
+ else BaseObj->Command(CMD_ADDCHAR, (void *)(&uc), OutputClass);
+ }
break;
}
e->accept();
@@ -2571,7 +2703,10 @@ RLPwidget::keyPressEvent(QKeyEvent *e)
void
RLPwidget::focusInEvent(QFocusEvent *e)
{
- CurrWidgetPos.x = x(); CurrWidgetPos.y = y();
+ if(x() || y()) {
+ CurrWidgetPos.x = x(); CurrWidgetPos.y = y();
+ }
+ CurrWidget = this;
if(BaseObj) {
if(BaseObj->Id == GO_GRAPH) CurrGraph = (Graph*)BaseObj;
}
@@ -2598,7 +2733,6 @@ RLPwidget::openHistoryFile(int idx)
}
}
-
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Print and output EPS to file
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2765,6 +2899,9 @@ PrintQT::Eject()
bool
PrintQT::oGetTextExtent(char *text, int cb, int *width, int *height)
{
+ return com_GetTextExtent(text, width, height, cb, &TxtSet, &qPainter);
+
+
if(!text || !text[0]){
QRect rc = qPainter.boundingRect(0, 0, 10000, 1000, Qt::AlignLeft | Qt::AlignTop, "A", 1);
*width = rc.rLeft();
@@ -2779,6 +2916,12 @@ PrintQT::oGetTextExtent(char *text, int cb, int *width, int *height)
}
bool
+PrintQT::oGetTextExtentW(w_char *text, int cb, int *width, int *height)
+{
+ return com_GetTextExtentW(text, width, height, cb, &TxtSet, &qPainter);
+}
+
+bool
PrintQT::oCircle(int x1, int y1, int x2, int y2, char* nam)
{
qPainter.drawEllipse(x1, y1, x2-x1, y2-y1);
@@ -2821,15 +2964,17 @@ bool
PrintQT::oTextOut(int x, int y, char *txt, int cb)
{
if(!txt || !txt[0]) return false;
- if(TxtSet.fSize > 0.0) TxtSet.iSize = un2ix(TxtSet.fSize);
- if(!TxtSet.iSize) return false;
- if(TxtSet.Align & TXA_VCENTER) y += iround(TxtSet.iSize * 0.4);
- else if(TxtSet.Align & TXA_VBOTTOM) y -= iround(TxtSet.iSize * 0.1);
- else y += iround(TxtSet.iSize * 1.0);
return com_TextOut(x, y, txt, &TxtSet, &qPainter, this);
}
bool
+PrintQT::oTextOutW(int x, int y, w_char *txt, int cb)
+{
+ if(!txt || !txt[0]) return false;
+ return com_TextOutW(x, y, txt, &TxtSet, &qPainter, this);
+}
+
+bool
PrintQT::oPolygon(POINT *pts, int cp, char *nam)
{
int i;
@@ -2847,12 +2992,6 @@ PrintQT::oPolygon(POINT *pts, int cp, char *nam)
return true;
}
-bool
-PrintQT::oArc(int x1, int y1, int x2, int y2, int quads)
-{
- return false;
-}
-
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Find a suitable www browser
void FindBrowser()
@@ -2936,7 +3075,10 @@ DlgWidget::mousePressEvent(QMouseEvent *e)
{
MouseEvent mev = {1, e->button() == Qt::LeftButton ? MOUSE_LBDOWN : -1, e->x(), e->y()};
- HideTextCursor();
+ HideTextCursor(); CurrWidget = this;
+ if(x() || y()) {
+ CurrWidgetPos.x = x(); CurrWidgetPos.y = y();
+ }
if (dlg) dlg->Command(CMD_MOUSE_EVENT, (void *)&mev, OutputClass);
}
@@ -2961,6 +3103,10 @@ DlgWidget::keyPressEvent(QKeyEvent *e)
{
int c;
+ CurrWidget = this;
+ if(x() || y()) {
+ CurrWidgetPos.x = x(); CurrWidgetPos.y = y();
+ }
if(dlg) switch(c = e->key()) {
case Key_Left:
if(e->state() & ShiftButton) dlg->Command(CMD_SHIFTLEFT, 0L, OutputClass);
@@ -3008,7 +3154,10 @@ DlgWidget::keyPressEvent(QKeyEvent *e)
void
DlgWidget::focusInEvent(QFocusEvent *e)
{
- CurrWidgetPos.x = x(); CurrWidgetPos.y = y();
+ CurrWidget = this;
+ if(x() || y()) {
+ CurrWidgetPos.x = x(); CurrWidgetPos.y = y();
+ }
}
void
@@ -3047,6 +3196,8 @@ void *CreateDlgWnd(char *title, int x, int y, int width, int height, tag_DlgObj
w->setCaption(title);
if(flags & 0x2) w->setFixedSize(width, height);
else w->setFixedSize(width-6, height-16);
+ o = new OutputQT(w); o->units = defs.cUnits;
+ o->Erase(0x00e0e0e0L); if(flags & 0x04) w->startTimer(100);
if(flags & 0x1) {
GetDesktopSize(&dw, &dh);
w->move((dw>>1) - ((w->width())>>1), (dh>>1) - ((w->height())>>1));
@@ -3060,8 +3211,6 @@ void *CreateDlgWnd(char *title, int x, int y, int width, int height, tag_DlgObj
}
w->move(x, y);
}
- o = new OutputQT(w); o->units = defs.cUnits;
- o->Erase(0x00e0e0e0L); if(flags & 0x04) w->startTimer(100);
d->DoPlot(o); w->show();
return w;
}
@@ -3076,6 +3225,9 @@ void CloseDlgWnd(void *hDlg)
HideCopyMark();
if(hDlg) {
delete((DlgWidget*) hDlg);
+ if(CurrWidgetPos.x > 50 && CurrWidgetPos.y > 50) {
+ CurrWidgetPos.x -= 50; CurrWidgetPos.y -= 50;
+ }
}
}
diff --git a/QT_Spec.h b/QT_Spec.h
index ccb1f4c..ac260ae 100755
--- a/QT_Spec.h
+++ b/QT_Spec.h
@@ -1,4 +1,4 @@
-//QT_Spec.h, Copyright (c) 2001, 2002, 2003, 2004 R.Lackner
+//QT_Spec.h, Copyright (c) 2001-2007 R.Lackner
//
// This file is part of RLPlot.
//
@@ -110,6 +110,22 @@ private:
#endif //RLP_PORT
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class RLPmenu:public QMenuBar {
+ Q_OBJECT
+public:
+ RLPmenu(QWidget *par, anyOutput *o, GraphObj *g);
+
+public slots:
+ void doMenuItem(int id);
+
+private:
+ anyOutput *OutputClass;
+ QWidget *parent;
+ GraphObj *BaseObj;
+
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// The Qt widget class implementet for RLPlot
class RLPwidget:public QWidget {
Q_OBJECT
@@ -172,8 +188,8 @@ public slots:
void cmtEllipse();
void cmtArrow();
void cmtText();
+ void cmSmplStat();
void cmRepCmeans();
- void cmRepanov();
void cmRepregr();
void cmReptwoway();
void cmFile1() {openHistoryFile(0);};
@@ -251,6 +267,7 @@ public:
bool CopyBitmap(int x, int y, anyOutput* src, int sx, int sy,
int sw, int sh, bool invert);
bool oGetTextExtent(char *text, int cb, int *width, int *height);
+ bool oGetTextExtentW(w_char *text, int cb, int *width, int *height);
bool oGetPix(int x, int y, DWORD *col);
bool oDrawIcon(int type, int x, int y);
bool oCircle(int x1, int y1, int x2, int y2, char* nam = 0L);
@@ -258,8 +275,8 @@ public:
bool oRectangle(int x1, int y1, int x2, int y2, char *nam = 0L);
bool oSolidLine(POINT *p);
bool oTextOut(int x, int y, char *txt, int cb);
+ bool oTextOutW(int x, int y, w_char *txt, int cb);
bool oPolygon(POINT *pts, int cp, char *nam = 0L);
- bool oArc(int x1, int y1, int x2, int y2, int quads);
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -287,7 +304,7 @@ public:
private:
GraphObj *BaseObj;
- QMenuBar *menu;
+ RLPmenu *menu;
};
class PrintQT:public anyOutput{
@@ -305,13 +322,14 @@ public:
bool EndPage();
bool Eject();
bool oGetTextExtent(char *text, int cb, int *width, int *height);
+ bool oGetTextExtentW(w_char *text, int cb, int *width, int *height);
bool oCircle(int x1, int y1, int x2, int y2, char* nam = 0L);
bool oPolyline(POINT * pts, int cp, char *nam = 0L);
bool oRectangle(int x1, int y1, int x2, int y2, char *nam = 0L);
bool oSolidLine(POINT *p);
bool oTextOut(int x, int y, char *txt, int cb);
+ bool oTextOutW(int x, int y, w_char *txt, int cb);
bool oPolygon(POINT *pts, int cp, char *nam = 0L);
- bool oArc(int x1, int y1, int x2, int y2, int quads);
private:
QPen qPen;
diff --git a/RLPLOT.RC b/RLPLOT.RC
index 76f54fd..4fd0459 100755
--- a/RLPLOT.RC
+++ b/RLPLOT.RC
@@ -135,10 +135,20 @@ BEGIN
END
POPUP "&Statistics"
BEGIN
+ MENUITEM "&Sample Stats" CM_SMPLSTAT
MENUITEM "&Comp. Means" CM_REPCMEANS
- MENUITEM "&Anova" CM_REPANOV
+ POPUP "&Anova"
+ BEGIN
+ MENUITEM "&One Way Anova" CM_REPANOV
+ MENUITEM "&Kruskal Wallis" CM_REPKRUSKAL
+ END
MENUITEM "&Regression" CM_REPREGR
- MENUITEM "&2x2 Table" CM_REPTWOWAY
+ POPUP "C&orrelations"
+ BEGIN
+ MENUITEM "Correlation &Matrix" CM_CORRELM
+ MENUITEM "Tiled &Plots" CM_CORRELT
+ END
+ MENUITEM "&2x2 Table" CM_REPTWOWAY
END
POPUP "&Graph"
BEGIN
diff --git a/TheDialog.cpp b/TheDialog.cpp
index e3aeeba..341e24c 100755
--- a/TheDialog.cpp
+++ b/TheDialog.cpp
@@ -1,4 +1,4 @@
-//TheDialog.cpp, Copyright (c) 2001-2006 R.Lackner
+//TheDialog.cpp, Copyright (c) 2001-2007 R.Lackner
//Operating system independent code for dialog boxes
//
// This file is part of RLPlot.
@@ -65,7 +65,7 @@ DlgRoot::DlgRoot(DlgInfo *tmpl, DataObj *d)
DlgText.iSize = dlgtxtheight; DlgText.ColBg = DlgBGcolor;
DlgText.fSize = defs.GetSize(SIZE_TEXT);
type = NONE; Id = -2; cContinue = 0;
- bActive = false; Result = -1; c_go = CurrGO;
+ bActive = bRedraw = false; Result = -1; c_go = CurrGO;
CurrDisp = 0L; oldFocus = DialogFocus; DialogFocus = 0L;
oldDefault = DialogDefault; oldTabStop = DialogTabStop;
data = d; ParentOut = Undo.cdisp;
@@ -196,6 +196,7 @@ DlgRoot::~DlgRoot()
int i;
if(data) data->Command(CMD_ETRACC, 0L, 0L);
+ HideTextCursor();
if(dlg){
for (i = 0; dlg[i] && i < cDlgs; i++) {
//we need to delete each object using a cast on its proper type
@@ -413,7 +414,7 @@ DlgRoot::DoPlot(anyOutput *o)
{
int i;
- HideCopyMark(); mrk_item = 0L;
+ HideCopyMark(); mrk_item = 0L; bRedraw = false;
if(tabstops) for(i = 0; i < cDlgs; tabstops[i++] = 0);
if(o)CurrDisp = o; DialogDefault = 0L;
if(CurrDisp) {
@@ -545,7 +546,7 @@ DlgRoot::SetText(int id, char *txt)
int i;
i = FindIndex(id);
- if(i && dlg[i] && dlg[i]->dialog->Command(CMD_SETTEXT, txt, CurrDisp)) DoPlot(CurrDisp);
+ if(i && dlg[i] && dlg[i]->dialog->Command(CMD_SETTEXT, txt, CurrDisp))bRedraw = true;
else return false;
return true;
}
@@ -558,7 +559,7 @@ DlgRoot::SetValue(int id, double val)
i = FindIndex(id);
WriteNatFloatToBuff(tmp_txt, val);
- if(i && dlg[i] && dlg[i]->dialog->Command(CMD_SETTEXT, tmp_txt+1, CurrDisp)) DoPlot(CurrDisp);
+ if(i && dlg[i] && dlg[i]->dialog->Command(CMD_SETTEXT, tmp_txt+1, CurrDisp))bRedraw = true;
else return false;
return true;
}
@@ -593,9 +594,7 @@ DlgRoot::TextSize(int id, int size)
i = FindIndex(id);
if(size <= 0.001f) return false;
- if(i && dlg[i]) {
- dlg[i]->dialog->TextDef.iSize = size;
- }
+ if(i && dlg[i]) dlg[i]->dialog->TextDef.iSize = size;
else return false;
return true;
}
@@ -617,10 +616,10 @@ DlgRoot::GetResult()
{
int ret;
- if(Result >= 0 && ParentOut) Undo.SetDisp(ParentOut);
+ ret = Result; Result = -1;
+ if(bRedraw)DoPlot(0L);
//return each result only once !
- ret = Result;
- Result = -1;
+ if(ret >= 0 && ParentOut) Undo.SetDisp(ParentOut);
return ret;
}
@@ -642,7 +641,7 @@ DlgRoot::ForEach(int cmd, int start, anyOutput *o)
if(dlg && CurrDisp) {
next = start;
do {
- if(dlg[next]->first) {
+ if(dlg[next] && dlg[next]->first) {
if(dlg[next]->flags && ISPARENT) {
if(dlg[next]->dialog) {
dlg[next]->dialog->Command(CMD_FLUSH, 0L, 0L);
@@ -668,7 +667,7 @@ DlgRoot::ForEach(int cmd, int start, anyOutput *o)
ForEach(cmd, FindIndex(dlg[next]->first), 0L);
}
//parent objects (groups) will channel command to children
- if(dlg[next]->dialog && dlg[next]->dialog->parent == this &&
+ if(dlg[next] && dlg[next]->dialog && dlg[next]->dialog->parent == this &&
!(dlg[next]->dialog->flags & HIDDEN)) switch(cmd) {
case CMD_DOPLOT:
dlg[next]->dialog->DoPlot(CurrDisp);
@@ -683,7 +682,7 @@ DlgRoot::ForEach(int cmd, int start, anyOutput *o)
dlg[next]->dialog->Select(mev->x, mev->y, CurrDisp);
break;
}
- next = FindIndex(dlg[next]->next);
+ next = FindIndex(dlg[next] ? dlg[next]->next : 0);
}while(next && next < cDlgs);
}
}
@@ -809,6 +808,9 @@ bool
PushButton::Command(int cmd, void *tmpl, anyOutput *o)
{
switch(cmd) {
+ case CMD_ENDDIALOG:
+ parent->Command(CMD_ENDDIALOG, (void *)this, o);
+ return true;
case CMD_ADDCHAR:
HideCopyMark();
if(parent && *((int*)tmpl) == 0x0d) //return pressed
@@ -1819,12 +1821,12 @@ InputText::Command(int cmd, void *tmpl, anyOutput *o)
case CMD_ADDCHAR:
if(Text && bActive && !(flags & NOEDIT)){
if(o) Undo.SetDisp(o);
- if(flags & TOUCHEXIT) parent->Command(CMD_ENDDIALOG, (void *)this, o);
o->SetTextSpec(&TextDef);
switch(*((int*)tmpl)) {
case 8: return Text->Command(CMD_BACKSP, o, NULL); //Backspace
default: return Text->AddChar(*((int*)tmpl), o, 0L);
}
+ if(flags & TOUCHEXIT) parent->Command(CMD_ENDDIALOG, (void *)this, o);
}
return false;
case CMD_SETTEXT:
@@ -2009,8 +2011,11 @@ RangeInput::Activate(int id, bool activate)
InputValue::InputValue(tag_DlgObj *par, DlgInfo * desc, RECT rec, double *value)
:InputText(par, desc, rec, 0L)
{
- WriteNatFloatToBuff(TmpTxt, *value);
- if(Text) Text->text = (char*)memdup(TmpTxt+1, (int)strlen(TmpTxt+1)+1, 0);
+ if(value) {
+ WriteNatFloatToBuff(TmpTxt, *value);
+ if(Text) Text->text = (char*)memdup(TmpTxt+1, (int)strlen(TmpTxt+1)+1, 0);
+ }
+ else if(Text) Text->SetText("");
}
InputValue::~InputValue()
@@ -2109,7 +2114,8 @@ TxtHSP::TxtHSP(tag_DlgObj *par, DlgInfo *desc, RECT rec, int *align)
}
d1[8].next = 0; d1[8].flags |= LASTOBJ;
txt.ColTxt = 0x00808080L; txt.ColBg = 0x00ffffff;
- txt.fSize = 8.0; txt.RotBL = txt.RotCHAR = 0.0;
+ txt.fSize = defs.GetSize(SIZE_TEXT)*2.0;
+ txt.RotBL = txt.RotCHAR = 0.0;
txt.iSize = 0; txt.Align = TXA_HCENTER | TXA_VCENTER;
txt.Style = TXS_NORMAL; txt.Font = FONT_HELVETICA;
txt.Mode = TXM_TRANSPARENT;
@@ -2727,11 +2733,9 @@ TabSheet::DoPlot(anyOutput *o)
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;
+ Line.color = 0x0L; Line.width = 0.0;
Fill.color = bChecked ? DlgBGhigh : DlgBGcolor;
- o->SetLine(&Line);
- o->SetFill(&Fill);
+ o->SetLine(&Line); o->SetFill(&Fill);
o->oPolygon(pts, 6);
if(bChecked) {
o->oRectangle(cr.left, rctab.bottom, cr.right, cr.bottom);
@@ -2745,6 +2749,10 @@ TabSheet::DoPlot(anyOutput *o)
o->oTextOut(rctab.right - 6, rctab.top + 3, Text, 0);
#else
o->oTextOut(rctab.right - 6, rctab.top + 5, Text, 0);
+ if(bChecked) {
+ Line.color = 0x0L; o->SetLine(&Line);
+ pts[0].y++; o->oSolidLine(pts);
+ }
#endif
Group::DoPlot(o);
o->UpdateRect(&cr, false);
@@ -3187,6 +3195,84 @@ LinePat::MBtrack(MouseEvent *mev, anyOutput *o)
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Common code for multiple range dialogs
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+int com_StackDlg(int res, DlgRoot *Dlg, AccRange **rX, int *nx, char ***rd, int *currYR,
+ AccRange **rY, bool *bContinue, int *ny, int *maxYR, bool *updateYR)
+{
+ char **tmprd;
+
+ switch (res) {
+ case 1:
+ if(rX && nx && Dlg->GetText(101, TmpTxt, TMP_TXT_SIZE) && TmpTxt[0] &&
+ (*rX = new AccRange(TmpTxt))) *nx = rX[0]->CountItems();
+ else if(nx) *nx = 0;
+ if(Dlg->GetText(154, TmpTxt, TMP_TXT_SIZE) && TmpTxt[0]) {
+ if(rd[0][*currYR]) free(rd[0][*currYR]);
+ rd[0][*currYR] = (char*)memdup(TmpTxt, ((int)strlen(TmpTxt))+2, 0);
+ }
+ break;
+ case 155:
+ res = -1;
+ *ny = 0;
+ if(rX) {
+ if(!(*currYR) && Dlg->GetText(101, TmpTxt, TMP_TXT_SIZE) && TmpTxt[0]) {
+ if(*rX = new AccRange(TmpTxt)){
+ *nx = rX[0]->CountItems();
+ delete *rX; *rX = 0L;
+ }
+ }
+ if(!(*nx)) {
+ ErrorBox("X-range is empty\nor not valid!\n\nEnter a valid range\n"
+ "for common x-values.");
+ *bContinue = true;
+ break;
+ }
+ }
+ if(Dlg->GetText(154, TmpTxt, TMP_TXT_SIZE) && TmpTxt[0]) {
+ if(*rY = new AccRange(TmpTxt)){
+ *ny = rY[0]->CountItems();
+ delete *rY;
+ *rY = 0L;
+ }
+ }
+ if(!(*ny)) {
+ ErrorBox("Y-range is empty\nor not valid!\n\nEnter a valid range\n"
+ "for y-values with the same\nsize as the x-range.");
+ *bContinue = true;
+ break;
+ }
+ if((*currYR)+1 > *maxYR) {
+ tmprd = (char**)realloc(*rd, sizeof(char*)*((*currYR)+2));
+ if(tmprd) *rd = tmprd;
+ else break;
+ *maxYR = (*currYR)+1;
+ rd[0][*currYR] = 0L;
+ rd[0][(*currYR)+1] = 0L;
+ }
+ if(rd[0][*currYR]) free(rd[0][*currYR]);
+ rd[0][*currYR] = (char*)memdup(TmpTxt, ((int)strlen(TmpTxt))+2, 0); //store y-ranges
+ *updateYR = true;
+ (*currYR)++;
+ Dlg->SetText(154, rd[0][*currYR]);
+ Dlg->Activate(154, true);
+ break;
+ case 156:
+ if(Dlg->GetText(154, TmpTxt, TMP_TXT_SIZE)){
+ if(rd[0][*currYR]) free(rd[0][*currYR]);
+ rd[0][*currYR] = (char*)memdup(TmpTxt, ((int)strlen(TmpTxt))+2, 0);;
+ }
+ else if(*currYR == *maxYR) (*maxYR)--;
+ (*currYR)--;
+ Dlg->SetText(154, rd[0][*currYR]);
+ *updateYR = true;
+ res = -1;
+ break;
+ }
+ return res;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Dialog meta compiler
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static char *std_text[] = {"OK", "Cancel", "", "x", "y", "z", "-", "Next >>", "<< Prev.",
@@ -3321,9 +3407,9 @@ bool UseRangeMark(DataObj *d, int type, char *r0, char *r1, char *r2, char *r3,
{
char *dst[] = {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10};
char *mrk, **ra =0L;;
- int i, j, k, ranges=0;
- bool success = false;
- RECT vrc;
+ int i, j, ranges=0;
+ bool success = false, bErr=false;
+ RECT vrc, rrc;
AccRange *ar;
bool bRet = true;
@@ -3338,47 +3424,19 @@ bool UseRangeMark(DataObj *d, int type, char *r0, char *r1, char *r2, char *r3,
case 1:
if(ranges > 1) {
for(i = 0; i < 11; i++) if(dst[i]) {
-#ifdef USE_WIN_SECURE
- if(i < ranges) sprintf_s(dst[i], 100, "%s", ra[i]);
- else {
- j = sprintf_s(dst[i], 100, "%s%d:", Int2ColLabel(vrc.left, false), vrc.top+1);
- sprintf_s(dst[i]+j, 100-j, "%s%d", Int2ColLabel(vrc.left, false), vrc.bottom+1);
- }
-#else
- if(i < ranges) sprintf(dst[i], "%s", ra[i]);
- else {
- j = sprintf(dst[i], "%s%d:", Int2ColLabel(vrc.left, false), vrc.top+1);
- sprintf(dst[i]+j, "%s%d", Int2ColLabel(vrc.left, false), vrc.bottom+1);
- }
-#endif
+ rlp_strcpy(dst[i], 100, i < ranges ? ra[i] : mkRangeRef(vrc.top, vrc.left, vrc.bottom, vrc.left));
}
success = true;
}
else if(vrc.top == vrc.bottom && (vrc.right - vrc.left) >2) {
- for(i = 0; i < 11; i++) {
- if(dst[i]){
-#ifdef USE_WIN_SECURE
- j = sprintf_s(dst[i], 100, "%s%d:", Int2ColLabel(vrc.left, false), vrc.top+1+i);
- sprintf_s(dst[i]+j, 100-j, "%s%d", Int2ColLabel(vrc.right, false), vrc.top+1+i);
-#else
- j = sprintf(dst[i], "%s%d:", Int2ColLabel(vrc.left, false), vrc.top+1+i);
- sprintf(dst[i]+j, "%s%d", Int2ColLabel(vrc.right, false), vrc.top+1+i);
-#endif
- }
+ for(i = 0; i < 11; i++) if(dst[i]){
+ rlp_strcpy(dst[i], 100, mkRangeRef(vrc.top+i, vrc.left, vrc.top+i, vrc.right));
}
success = true;
}
else if(vrc.right == vrc.left && (vrc.bottom - vrc.top) >2) {
- for(i = 0; i < 11; i++) {
- if(dst[i]){
-#ifdef USE_WIN_SECURE
- j = sprintf_s(dst[i], 100, "%s%d:", Int2ColLabel(vrc.left+i, false), vrc.top+1);
- sprintf_s(dst[i]+j, 100-j, "%s%d", Int2ColLabel(vrc.left+i, false), vrc.bottom+1);
-#else
- j = sprintf(dst[i], "%s%d:", Int2ColLabel(vrc.left+i, false), vrc.top+1);
- sprintf(dst[i]+j, "%s%d", Int2ColLabel(vrc.left+i, false), vrc.bottom+1);
-#endif
- }
+ for(i = 0; i < 11; i++) if(dst[i]){
+ rlp_strcpy(dst[i], 100, mkRangeRef(vrc.top, vrc.left+i, vrc.bottom, vrc.left+i));
}
success = true;
}
@@ -3387,46 +3445,44 @@ bool UseRangeMark(DataObj *d, int type, char *r0, char *r1, char *r2, char *r3,
for(i = 0; i < 11; i++) if(dst[i]) *(dst[i]) = 0;
if(ranges == 1) {
for(i = 0, j = vrc.left; i < 11 && j <= vrc.right; i++, j++) if(dst[i]){
-#ifdef USE_WIN_SECURE
- k = sprintf_s(dst[i], 100, "%s%d:", Int2ColLabel(vrc.left+i, false), vrc.top+1);
- sprintf_s(dst[i]+k, 100-k, "%s%d", Int2ColLabel(vrc.left+i, false), vrc.bottom+1);
-#else
- k = sprintf(dst[i], "%s%d:", Int2ColLabel(vrc.left+i, false), vrc.top+1);
- sprintf(dst[i]+k, "%s%d", Int2ColLabel(vrc.left+i, false), vrc.bottom+1);
-#endif
+ rlp_strcpy(dst[i], 100, mkRangeRef(vrc.top, vrc.left+i, vrc.bottom, vrc.left+i));
}
}
else if(ranges > 1) {
- ar = new AccRange(ra[0]); j = ar->CountItems(); delete ar;
- for(i = 1; i < 11 && i < ranges; i++){
+ ar = new AccRange(ra[0]); j = ar->CountItems();
+ ar->BoundRec(&rrc); delete ar;
+ if(rrc.left == rrc.right)for(i = 1; i < 11 && i < ranges && !bErr; i++){
+ ar = new AccRange(ra[i]); ar->BoundRec(&rrc);
+ if(rrc.left != rrc.right) bErr = true;
+ delete ar;
+ }
+ else if(rrc.top == rrc.bottom)for(i = 1; i < 11 && i < ranges && !bErr; i++){
+ ar = new AccRange(ra[i]); ar->BoundRec(&rrc);
+ if(rrc.top != rrc.bottom) bErr = true;
+ delete ar;
+ }
+ else for(i = 1; i < 11 && i < ranges && !bErr; i++){
ar = new AccRange(ra[i]);
- if(j != ar->CountItems()) {
- InfoBox("Cannot resolve multiple ranges\nwith different sizes.\n\n"
- "Please select ranges with equal size!");
- i = 12; bRet = false;
- }
+ if(j != ar->CountItems()) bErr = true;
delete ar;
}
- if(i < 12) for(i = 0; i < 11 && i < ranges; i++){
+ if(i < 12 && !bErr) for(i = 0; i < 11 && i < ranges; i++){
if(dst[i]) rlp_strcpy(dst[i], 100, ra[i]);
}
}
+ if(bErr) {
+ InfoBox("Cannot resolve multiple ranges\nwith different sizes.\n\n"
+ "Please select ranges with equal size!");
+ i = 12; bRet = false;
+ }
success = true;
}
}
else {
vrc.left = vrc.top = 0; vrc.right = vrc.bottom = 9;
}
- if(!success) for(i = 0; i < 11; i++) {
- if(dst[i]){
-#ifdef USE_WIN_SECURE
- j = sprintf_s(dst[i], 100, "%s%d:", Int2ColLabel(vrc.left+i, false), vrc.top+1);
- sprintf_s(dst[i]+j, 100-j, "%s%d", Int2ColLabel(vrc.left+i, false), vrc.bottom+1);
-#else
- j = sprintf(dst[i], "%s%d:", Int2ColLabel(vrc.left+i, false), vrc.top+1);
- sprintf(dst[i]+j, "%s%d", Int2ColLabel(vrc.left+i, false), vrc.bottom+1);
-#endif
- }
+ if(!success) for(i = 0; i < 11; i++) if(dst[i]){
+ rlp_strcpy(dst[i], 100, mkRangeRef(vrc.top, vrc.left+i, vrc.bottom, vrc.left+i));
}
if(ra) {
for(i = 0; i < ranges; i++) if(ra[i]) free(ra[i]);
@@ -3439,16 +3495,17 @@ bool UseRangeMark(DataObj *d, int type, char *r0, char *r1, char *r2, char *r3,
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Select color out of predefined palette
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static char *NewColorTmpl =
+ "1,2,,DEFAULT,PUSHBUTTON,-1,200,10,45,12\n"
+ "2,3,,,PUSHBUTTON,-2,200,25,45,12\n"
+ "3,7,4,CHECKED | ISPARENT,GROUPBOX,1,200,55,45,40\n"
+ "4,5,,,LTEXT,0,210,60,45,8\n"
+ "5,6,,,LTEXT,0,210,70,45,8\n"
+ "6,,,,LTEXT,0,210,80,45,8\n"
+ "7,,8,CHECKED | ISPARENT,GROUP,0,0,0,0,0";
+
DWORD GetNewColor(DWORD oldColor)
{
- char *NewColorTmpl =
- "1, 2, 0, DEFAULT, PUSHBUTTON, -1, 200, 10, 45, 12\n"
- "2, 3, 0, 0x0L, PUSHBUTTON, -2, 200, 25, 45, 12\n"
- "3, 7, 4, CHECKED | ISPARENT, GROUPBOX, 1, 200, 55, 45, 40\n"
- "4, 5, 0, 0x0L, LTEXT, 0, 210, 60, 45, 8\n"
- "5, 6, 0, 0x0L, LTEXT, 0, 210, 70, 45, 8\n"
- "6, 0, 0, 0x0L, LTEXT, 0, 210, 80, 45, 8\n"
- "7, 0, 8, CHECKED | ISPARENT, GROUP, 0, 0, 0, 0, 0";
void *ptypes[] = {(void*)" RGB "};
DlgInfo *ColDlg = CompileDialog(NewColorTmpl, ptypes);
DWORD currcol, newcol, palette[230];
@@ -3729,26 +3786,30 @@ void GetNewFill(FillDEF *oldfill)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// execute layers dialog
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static char* LayerDlg_Tmpl =
+ "1,3,0,DEFAULT,PUSHBUTTON,-1,165,10,45,12\n"
+ "3,20,100,ISPARENT | CHECKED,GROUP,0,0,0,0,0\n"
+ "20,550,,,CHECKPIN,0,10,0,12,8\n"
+ "100,101,,TOUCHEXIT,TREEVIEW,1,10,15,100,70\n"
+ "101,102,,,EDTEXT,2, 120, 25, 90, 10\n"
+ "102,200,150,ISPARENT | CHECKED | HIDDEN,GROUP,0L,0,0,0,0\n"
+ "150,151,,TOUCHEXIT,RADIO1,3,120,35,40,9\n"
+ "151,,,TOUCHEXIT,RADIO1,4,160,35,40,9\n"
+ "200,500,,,LTEXT,5,10,5,110,9\n"
+ "500,501,600,ISPARENT | CHECKED | HIDDEN,GROUP,0,0,0,0,0\n"
+ "501,,,HIDDEN | TOUCHEXIT,TRASH,0,125,72,15,15\n"
+ "550,,,HIDDEN | TOUCHEXIT,CONFIG,0,140,72,15,15\n"
+ "600,601,,TOUCHEXIT, ODBUTTON,6,125,50,15,15\n"
+ "601,602,,TOUCHEXIT, ODBUTTON,6,145,50,15,15\n"
+ "602,603,,TOUCHEXIT, ODBUTTON,6,165,50,15,15\n"
+ "603,,,LASTOBJ | TOUCHEXIT, ODBUTTON,6,185,50,15,15";
+
bool ShowLayers(GraphObj *root)
{
char curr_name[50];
- DlgInfo PageDlg[] = {
- {1, 3, 0, DEFAULT, PUSHBUTTON, (void*)"OK", 165, 10, 45, 12},
- {3, 20, 100, ISPARENT | CHECKED, GROUP, 0L, 0, 0, 0, 0},
- {20, 550, 0, 0x0L, CHECKPIN, 0L, 10, 0, 12, 8},
- {100, 101, 0, TOUCHEXIT, TREEVIEW, (void*)root, 10, 15, 100, 70},
- {101, 102, 0, 0x0L, EDTEXT, (void*)curr_name, 120, 25, 90, 10},
- {102, 200, 150, ISPARENT | CHECKED | HIDDEN, GROUP, 0L, 0, 0, 0, 0},
- {150, 151, 0, TOUCHEXIT, RADIO1, (void*)"hidden", 120, 35, 40, 9},
- {151, 0, 0, TOUCHEXIT, RADIO1, (void*)"visible", 160, 35, 40, 9},
- {200, 500, 0, 0x0L, LTEXT, (void*)"Layers:", 10, 5, 110, 9},
- {500, 501, 600, ISPARENT | CHECKED | HIDDEN, GROUP, 0L, 0, 0, 0, 0},
- {501, 0, 0, HIDDEN | TOUCHEXIT, TRASH, 0L, 125, 72, 15, 15},
- {550, 0, 0, HIDDEN | TOUCHEXIT, CONFIG, 0L, 140, 72, 15, 15},
- {600, 601, 0, TOUCHEXIT, ODBUTTON, (void*)OD_DrawOrder, 125, 50, 15, 15},
- {601, 602, 0, TOUCHEXIT, ODBUTTON, (void*)OD_DrawOrder, 145, 50, 15, 15},
- {602, 603, 0, TOUCHEXIT, ODBUTTON, (void*)OD_DrawOrder, 165, 50, 15, 15},
- {603, 0, 0, LASTOBJ | TOUCHEXIT, ODBUTTON, (void*)OD_DrawOrder, 185, 50, 15, 15}};
+ void *dyndata[] = {(void*)root, (void*)curr_name, (void*)"hidden", (void*)"visible",
+ (void*)"Layers:", (void*)OD_DrawOrder};
+ DlgInfo *LayerDlg;
DlgRoot *Dlg;
void *hDlg;
int res, cl;
@@ -3756,9 +3817,9 @@ bool ShowLayers(GraphObj *root)
ObjTree *ot = 0L;
GraphObj *cgo = 0L;
- if(!root) return false;
+ if(!root || !(LayerDlg = CompileDialog(LayerDlg_Tmpl, dyndata))) return false;
rlp_strcpy(curr_name, 50, "(root)");
- if(!(Dlg = new DlgRoot(PageDlg, 0L)))return false;
+ if(!(Dlg = new DlgRoot(LayerDlg, 0L)))return false;
Dlg->ItemCmd(100, CMD_OBJTREE, &ot);
if(!ot) {
delete Dlg; return false;
@@ -3834,8 +3895,7 @@ bool ShowLayers(GraphObj *root)
res = -1;
}
}while(res <0);
- CloseDlgWnd(hDlg);
- delete Dlg;
+ CloseDlgWnd(hDlg); delete Dlg; free(LayerDlg);
return false;
}
@@ -3904,7 +3964,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-2006 R. Lackner", 5, 54, 110, 8},
+ {7, 8, 0, 0x0L, CTEXT, (void*)"Copyright (C) 2002-2007 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},
@@ -3918,7 +3978,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-2006 R. Lackner", 5, 54, 110, 8},
+ {7, 8, 0, 0x0L, CTEXT, (void*)"Copyright (C) 2002-2007 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},
@@ -4156,7 +4216,7 @@ bool FillSsRange(DataObj *d, char **range, GraphObj *msg_go)
r1 = row; c1 = col;
for( ; rF->GetNext(&col, &row); startval += stepval) {
if(formula[0] == '=') {
- MoveFormula(d, formula, TmpTxt, col-c1, row-r1, -1, -1);
+ MoveFormula(d, formula, TmpTxt, TMP_TXT_SIZE, col-c1, row-r1, -1, -1);
d->SetText(row, col, TmpTxt);
}
else d->SetText(row, col, formula);
@@ -4869,7 +4929,7 @@ void OD_axisplot(int cmd, void *par, RECT *rec, anyOutput *o,
break;
case OD_ACCEPT:
if(data) names = (char**)data;
- else Dlg->GetInt(110, &axisplot_sel);
+ else if(Dlg) Dlg->GetInt(110, &axisplot_sel);
if(o) *((int*)o) = axisplot_sel;
}
}
diff --git a/TheDialog.h b/TheDialog.h
index ad8ac0e..aeed423 100755
--- a/TheDialog.h
+++ b/TheDialog.h
@@ -1,4 +1,4 @@
-//TheDialog.h, Copyright (c) 2001-2006 R.Lackner
+//TheDialog.h, Copyright (c) 2001-2007 R.Lackner
//Definitions for TheDialog.cpp
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
@@ -141,7 +141,7 @@ private:
int cDlgs, Result, cContinue;
DataObj *data;
Dialog *oldFocus, *oldDefault, *oldTabStop;
- bool bActive;
+ bool bActive, bRedraw;
GraphObj *c_go;
Dialog **tabstops, *mrk_item;
DlgTmpl **dlg;
@@ -536,6 +536,7 @@ private:
//prototypes TheDialog.cpp
bool UseRangeMark(DataObj *d, int type, char* =0L, char* =0L, char* =0L, char* =0L,
char* =0L, char* =0L, char* =0L, char* =0L, char* =0L, char* =0L, char* =0L);
+int com_StackDlg(int,DlgRoot*,AccRange**,int*,char***,int*,AccRange**,bool*,int*,int*,bool*);
DlgInfo *CompileDialog(char* tmpl, void **ptypes);
//prototypes ODbutton.cpp
@@ -552,3 +553,4 @@ void OD_PlotTempl(int cmd, void *par, RECT *rec, anyOutput *o, void *data, int i
void OD_AxisTempl(int cmd, void *par, RECT *rec, anyOutput *o, void *data, int id);
void OD_AxisTempl3D(int cmd, void *par, RECT *rec, anyOutput *o, void *data, int id);
void OD_NewAxisTempl(int cmd, void *par, RECT *rec, anyOutput *o, void *data, int id);
+void OD_NewAxisTempl3D(int cmd, void *par, RECT *rec, anyOutput *o, void *data, int id);
diff --git a/UtilObj.cpp b/UtilObj.cpp
index 2b39e4f..1512ddb 100755
--- a/UtilObj.cpp
+++ b/UtilObj.cpp
@@ -1,4 +1,4 @@
-//UtilObj.cpp, (c) 2000-2006 by R. Lackner
+//UtilObj.cpp, (c) 2000-2007 by R. Lackner
//
// This file is part of RLPlot.
//
@@ -232,13 +232,23 @@ EditText::Redraw(anyOutput *Out, bool display)
rc.left = loc.x; rc.right = crb.x;
rc.top = loc.y+1; rc.bottom = crb.y-2;
Out->oRectangle(loc.x, loc.y, crb.x-1, crb.y-1);
- if((!text || !text[0]) && (type & 0xff) == ET_VALUE){
+ if(!text || !text[0]){
+ if((type & 0xff) == ET_VALUE){
#ifdef USE_WIN_SECURE
- sprintf_s(tmptxt, 500, "%g", Value);
+ sprintf_s(tmptxt, 500, "%g", Value);
#else
- sprintf(tmptxt, "%g", Value);
+ sprintf(tmptxt, "%g", Value);
#endif
- if(text = (char*)realloc(text, strlen(tmptxt)+2)) rlp_strcpy(text, 500, tmptxt);
+ }
+ else if((type & 0xff) == ET_BOOL) {
+#ifdef USE_WIN_SECURE
+ sprintf_s(tmptxt, 500, Value != 0.0 ? "true" : "false");
+#else
+ sprintf(tmptxt, Value != 0.0 ? "true" : "false");
+#endif
+ }
+ else tmptxt[0] = 0;
+ if(tmptxt[0] && (text = (char*)realloc(text, strlen(tmptxt)+2))) rlp_strcpy(text, 500, tmptxt);
CursorPos = 0;
}
if(ftext) free(ftext); ftext = 0L;
@@ -1017,6 +1027,8 @@ typedef struct _tag_info {
int font, op;
}tag_info;
+#define UC_TAG 100
+
static tag_info tags[] = {
{"<i>", ~TXS_NORMAL, TXS_ITALIC, -1, 0},
{"</i>", ~TXS_ITALIC, TXS_NORMAL, -1, 0},
@@ -1075,7 +1087,7 @@ fmtText::StyleAt(int idx, TextDEF *txt_def, int *style, int *font)
if(!src || !split_text || (idx > (int)strlen(src))) return false;
memcpy(&td, txt_def, sizeof(TextDEF));
for(i = j = 0; i < n_split; i++) {
- if((n=split_text[i].tag) >= 0 && SetTextDef(&td, n)) j += (int)strlen(tags[n].tag);
+ if((n=split_text[i].tag) >= 0 && n < UC_TAG && SetTextDef(&td, n)) j += (int)strlen(tags[n].tag);
if(j > idx) break;
if(split_text[i].txt && split_text[i].txt[0]) j += (int)strlen(split_text[i].txt);
if(j >= idx) break;
@@ -1111,26 +1123,70 @@ fmtText::leftTag(char *txt, int cb)
return -1;
}
+int
+fmtText::ucTag(char *txt, int cb, int *tl, int *ucc)
+{
+ int i, uc=0;
+
+ if(txt[cb] != '&' || txt[cb+1] != '#') return -1;
+ for(i = cb+2; txt[i] && txt[i] != ';'; i++) {
+ if(!isdigit(txt[i])) return -1;
+ }
+ if(txt[i] != ';') return -1;
+ i -= cb;
+#ifdef USE_WIN_SECURE
+ sscanf_s(txt+cb+2, "%d", &uc);
+#else
+ sscanf(txt+cb+2, "%d", &uc);
+#endif
+ if(tl) *tl = i+1; if(ucc) *ucc = uc;
+ return UC_TAG;
+}
+
+int
+fmtText::ucLeft(char *txt, int cb, int *tl, int *ucc)
+{
+ int i, uc = 0;
+
+ for(i = 1; i < 6 && i < cb && txt[cb-i] != '#'; i++) {
+ if(!isdigit(txt[cb-i])) return -1;
+ }
+ if(txt[cb-i] != '#' || txt[cb-i-1] != '&') return -1;
+#ifdef USE_WIN_SECURE
+ sscanf_s(txt+cb-i+1, "%d", &uc);
+#else
+ sscanf(txt+cb-i+1, "%d", &uc);
+#endif
+ if(tl) *tl = i+1; if(ucc) *ucc = uc;
+ return UC_TAG;
+}
+
void
fmtText::cur_right(int *pos)
{
- int n;
+ int n, tl;
if(!src || !pos || !src[*pos]) return;
if(src[*pos] == '<' && (n=rightTag(src, *pos)) >= 0) {
*pos += (int)strlen(tags[n].tag);
cur_right(pos);
}
+ else if(src[*pos] == '&' && (ucTag(src, *pos, &tl, 0L)== UC_TAG)){
+ *pos += tl;
+ }
else (*pos)++;
}
void
fmtText::cur_left(int *pos)
{
- int n;
+ int n, tl;
if(!src || !pos || !(*pos)) return;
(*pos)--;
+ if(src[*pos] == ';' && (n=ucLeft(src, *pos, &tl, 0L)) == UC_TAG) {
+ *pos -= tl; return;
+ }
while (src[*pos] == '>' && (n=leftTag(src, *pos)) >= 0) {
*pos -= (int)strlen(tags[n].tag);
}
@@ -1148,9 +1204,19 @@ fmtText::oGetTextExtent(anyOutput *o, int *width, int *height, int cb)
if(!split_text) return o->oGetTextExtent(src, cb, width, height);
memcpy(&td1, &o->TxtSet, sizeof(TextDEF)); memcpy(&td2, &o->TxtSet, sizeof(TextDEF));
for(i = w = h = l = l1 = 0; i < n_split; i++){
- if((n=split_text[i].tag) >= 0 && SetTextDef(&td2, n)) {
- o->SetTextSpec(&td2);
- l += (int)strlen(tags[n].tag);
+ if(split_text[i].tag == UC_TAG) {
+ o->oGetTextExtentW((w_char*)(&split_text[i].uc), 1, &w1, &h1);
+ w += w1; h = h1 > h ? h1 : h;
+ l += split_text[i].uc_len;
+ }
+ else {
+ if((n=split_text[i].tag) >= 0 && SetTextDef(&td2, n)) {
+ o->SetTextSpec(&td2);
+ l += (int)strlen(tags[n].tag);
+ }
+ if(tags[n].font == -1 && tags[n].op > 0 && tags[n].op < 100) {
+ w += o->un2ix(td2.fSize/2.0);
+ }
}
if(split_text[i].txt && split_text[i].txt[0]){
l1 = l; l += (int)strlen(split_text[i].txt);
@@ -1159,9 +1225,6 @@ fmtText::oGetTextExtent(anyOutput *o, int *width, int *height, int cb)
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;
@@ -1215,17 +1278,21 @@ fmtText::SetTextDef(TextDEF *td, int idx)
bool
fmtText::Parse()
{
- int i, li, j, n;
+ int i, li, j, n, tl, uc;
char *tmp;
if((flags & 0x01) || !src || !(tmp = (char*)memdup(src, (int)strlen(src)+1, 0))) return false;
for(i = li = 0; src[i]; i++) {
+ if(i-li == 1 && split_text) {
+ if(src[li] == '<' && (n=rightTag(src, li))>=0) i--;
+ else if(src[li] == '&' && (n=ucTag(src, li, &tl, &uc))>0) i--;
+ }
if(src[i] == '<' && (n=rightTag(src, i))>=0) {
if(split_text) { //more tags in text
if(!(split_text = (fmt_txt_info *)realloc(split_text, (n_split+1)*sizeof(fmt_txt_info)))){
free(tmp); return false;
}
- for(j = li; j < i; j++) tmp[j-li]= src[j]; tmp[j-li]=0;
+ for(j = li; j < i; j++) tmp[j-li] = src[j]; tmp[j-li]=0;
split_text[n_split-1].txt = (char*)memdup(tmp, (int)strlen((char*)tmp)+1, 0);
i += (int)strlen(tags[n].tag); split_text[n_split].tag = n;
split_text[n_split++].txt = 0L;
@@ -1242,6 +1309,30 @@ fmtText::Parse()
}
li = i; i--;
}
+ else if(src[i] == '&' && (n=ucTag(src, i, &tl, &uc))>0) {
+ if(split_text) { //more tags in text
+ if(!(split_text = (fmt_txt_info *)realloc(split_text, (n_split+1)*sizeof(fmt_txt_info)))){
+ free(tmp); return false;
+ }
+ for(j = li; j < i; j++) tmp[j-li] = src[j]; tmp[j-li]=0;
+ split_text[n_split-1].txt = (char*)memdup(tmp, (int)strlen((char*)tmp)+1, 0);
+ i += tl; split_text[n_split].tag = n;
+ split_text[n_split].uc = uc; split_text[n_split].uc_len = tl;
+ split_text[n_split++].txt = 0L;
+ }
+ else { //first tag of text
+ if(!(split_text = (fmt_txt_info *)calloc(2, sizeof(fmt_txt_info)))){
+ free(tmp); return false;
+ }
+ for(j = 0; j < i; j++) tmp[j]= src[j]; tmp[j]=0;
+ split_text[0].tag = -1;
+ split_text[0].txt = (char*)memdup(tmp, (int)strlen((char*)tmp)+1, 0);
+ i += tl; split_text[1].tag = n;
+ split_text[1].uc = uc; n_split = 2;
+ split_text[1].uc_len = tl;
+ }
+ li = i;
+ }
}
if(split_text && n_split && li < i && src[li])
split_text[n_split-1].txt = (char*)memdup(src+li, (int)strlen((char*)src+li)+1,0);
@@ -1316,6 +1407,7 @@ fmtText::DrawFormatted(anyOutput *o)
int i, n, x, y, x1, y1, w, h;
TextDEF td1, td2;
double si, csi, fx, fy;
+ w_char one_uc[2];
if(!o || !split_text) return;
memcpy(&td1, &o->TxtSet, sizeof(TextDEF)); memcpy(&td2, &o->TxtSet, sizeof(TextDEF));
@@ -1330,8 +1422,14 @@ fmtText::DrawFormatted(anyOutput *o)
}
x = iround(fx); y = iround(fy);
td2.Align &= ~(TXA_HRIGHT | TXA_HCENTER); o->SetTextSpec(&td2);
- for(i = 0; i < n_split; i++) if(split_text[i].txt) {
- if((n=split_text[i].tag) >= 0 && SetTextDef(&td2, n)) o->SetTextSpec(&td2);
+ for(i = 0; i < n_split; i++) if(split_text[i].txt || split_text[i].tag == UC_TAG) {
+ if(split_text[i].tag == UC_TAG) {
+ one_uc[0] = split_text[i].uc; one_uc[1] = 0;
+ o->oGetTextExtentW(one_uc, 1, &w, &h);
+ if(!(o->oTextOutW(x, y, one_uc, 1))) o->oTextOut(x, y, "?", 1);
+ x = iround(fx += (w*csi)); y = iround(fy -= (w*si));
+ }
+ else if((n=split_text[i].tag) >= 0 && SetTextDef(&td2, n)) o->SetTextSpec(&td2);
else if(n >= 0 && tags[n].op) {
x1 = x + iround(o->un2fix(td2.fSize*0.25)*csi);
y1 = y - iround(o->un2fiy(td2.fSize*0.25)*si);
@@ -1366,7 +1464,7 @@ fmtText::DrawFormatted(anyOutput *o)
}
o->SetTextSpec(&td2);
}
- if(split_text[i].txt){
+ if(split_text[i].txt && split_text[i].txt[0]){
o->oTextOut(x, y, split_text[i].txt, 0);
o->oGetTextExtent(split_text[i].txt, 0, &w, &h);
x = iround(fx += (w*csi)); y = iround(fy -= (w*si));
@@ -1380,6 +1478,98 @@ fmtText::EditMode(bool bEdit)
if(bEdit) flags |= 0x01;
else flags &= ~(0x01);
}
+#undef UC_TAG
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// assign a value to a string
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+TextValue::TextValue()
+{
+ items = 0L; nitems = 0; next = inc = 1.0;
+}
+
+TextValue::TextValue(TextValItem **tvi, int ntvi)
+{
+ int i;
+
+ items = 0L; nitems = 0; next = inc = 1.0;
+ if(ntvi && (items = (TextValItem **)malloc(ntvi*sizeof(TextValItem*)))){
+ for(i = 0, nitems = ntvi; i < ntvi; i++) {
+ if(items[i] = (TextValItem*)memdup(tvi[i], sizeof(TextValItem), 0)){
+ if(tvi[i]->text) items[i]->text = (char*)memdup(tvi[i]->text, (int)strlen(tvi[i]->text)+1, 0);
+ }
+ }
+ nitems = ntvi; if(items[nitems-1]) next = items[nitems-1]->val + inc;
+ }
+}
+
+TextValue::~TextValue()
+{
+ Reset();
+}
+
+double
+TextValue::GetValue(char *txt)
+{
+ unsigned int hv1, hv2;
+ int i;
+
+ if(!txt || !txt[0]) return 0.0;
+ hv1 = HashValue((unsigned char*)txt);
+ hv2 = Hash2((unsigned char*)txt);
+ if(items && nitems) for(i = 0; i < nitems; i++) {
+ if(items[i] && items[i]->hv1 == hv1 && items[i]->hv2 == hv2) return items[i]->val;
+ }
+ else if(!items &&(items = (TextValItem **)malloc(sizeof(TextValItem*)))) {
+ if(items[0] = (TextValItem*)calloc(1, sizeof(TextValItem))) {
+ items[0]->hv1 = hv1; items[0]->hv2 = hv2;
+ items[0]->text = (char*)memdup(txt, (int)strlen(txt)+1, 0);
+ items[0]->val = next; next += inc;
+ nitems = 1; return (next-inc);
+ }
+ return 0.0;
+ }
+ else return 0.0;
+ if(items = (TextValItem **)realloc(items, (nitems+1)*sizeof(TextValItem*))){
+ if(items[nitems] = (TextValItem*)calloc(1, sizeof(TextValItem))) {
+ items[nitems]->hv1 = hv1; items[nitems]->hv2 = hv2;
+ items[nitems]->text = (char*)memdup(txt, (int)strlen(txt)+1, 0);
+ items[nitems]->val = next; next += inc; nitems++;
+ return (next-inc);
+ }
+ }
+ return 0.0;
+}
+
+bool
+TextValue::GetItem(int idx, char **text, double *value)
+{
+ if(items && idx >=0 && idx < nitems) {
+ if(text) *text = items[idx]->text;
+ if(value) *value = items[idx]->val;
+ return true;
+ }
+ return false;
+}
+
+void
+TextValue::Reset()
+{
+ int i;
+
+ if(items) for(i = 0; i < nitems; i++){
+ if(items[i]->text) free(items[i]->text);
+ free(items[i]);
+ }
+ if(items && nitems) free(items);
+ next = inc = 1.0; items = 0L; nitems = 0;
+}
+
+TextValue *
+TextValue::Copy()
+{
+ return new TextValue(items, nitems);
+}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// manage formats and style of a spreadsheet range
@@ -1475,7 +1665,7 @@ DataObj::DataObj()
{
cRows = cCols = 0;
etRows = 0L;
- ri = new RangeInfo(0, 1, 1, 1, 0L);
+ ri = new RangeInfo(0, 76, 19, 32, 0L);
}
DataObj::~DataObj()
@@ -1792,7 +1982,7 @@ notary::PushGO(unsigned int id, GraphObj *go)
if(!go) return true;
go->Id = id;
if(!goStack) {
- goStack = (GraphObj ***)calloc(8192, sizeof(GraphObj **));
+ if(!(goStack = (GraphObj ***)calloc(8192, sizeof(GraphObj **))))return false;
goStack[0] = (GraphObj **)calloc(8192, sizeof(GraphObj *));
if(goStack && goStack[0]) {
goStack[0][0] = go;
@@ -1921,12 +2111,15 @@ AccRange::~AccRange()
int
AccRange::CountItems()
{
- int RetVal;
+ int RetVal, l;
RetVal = 0;
- if(txt && Reset()) do {
- RetVal += ((x2-x1+1)*(y2-y1+1));
- } while((curridx < (int)strlen(txt)) && Parse(curridx));
+ if(txt && txt[0] && Reset()){
+ l = (int)strlen(txt);
+ do {
+ RetVal += ((x2-x1+1)*(y2-y1+1));
+ } while((curridx < l) && Parse(curridx));
+ }
return RetVal;
}
@@ -1961,7 +2154,7 @@ bool
AccRange::NextRow(int *y)
{
if(cy <= y2) {
- *y = cy; cy++; return true;
+ *y = cy; cy++; cx = x1; return true;
}
else if(txt[curridx] && Parse(curridx)) return NextRow(y);
return false;
@@ -2014,7 +2207,7 @@ AccRange::Parse(int start)
i = start;
if(!txt) return false;
- if(txt[i] == ';' || txt[i] == ',') i++;
+ while(txt[i] == ';' || txt[i] == ',') i++;
if(!txt[i]) return false;
step = x1 = y1 = x2 = y2 = 0;
v = &x1;
@@ -2077,20 +2270,36 @@ AccRange::Parse(int start)
char *
AccRange::RangeDesc(void *d, int style)
{
- anyResult res;
+ anyResult res, res1;
int cb;
char *desc;
if(!d || !txt || !Reset())return 0L;
- ((DataObj*)d)->GetResult(&res, y1, x1, false);
- if(res.type == ET_TEXT) {
+ if(!((DataObj*)d)->GetResult(&res, y1, x1, false))return 0L;
+ if(style == 3) {
+ if(x1 == x2 && y1 > 0 && res.type == ET_TEXT) {
+ if(((DataObj*)d)->GetResult(&res1, 0, x1, false) && res1.type == ET_TEXT)
+ return (char*)memdup(res1.text, (int)strlen(res1.text)+1, 0);
+ }
+ if(y1 == y2 && x1 > 0 && res.type == ET_TEXT) {
+ if(((DataObj*)d)->GetResult(&res1, y1, 0, false) && res1.type == ET_TEXT)
+ return (char*)memdup(res1.text, (int)strlen(res1.text)+1, 0);
+ }
+ }
+ switch(res.type) {
+ case ET_TEXT:
+ if(res.text && res.text[0])
+ return (char*)memdup(res.text, (int)strlen(res.text)+1, 0);
+ else return 0L;
+ case ET_DATE: case ET_DATETIME: case ET_TIME:
+ TranslateResult(&res);
if(res.text && res.text[0])
return (char*)memdup(res.text, (int)strlen(res.text)+1, 0);
else return 0L;
}
if(!(desc = (char*)malloc(40*sizeof(char))))return 0L;
if(x1 == x2) {
- if(style == 1) cb = rlp_strcpy(desc, 40, "Col. ");
+ if(style == 1 || style == 3) cb = rlp_strcpy(desc, 40, "Col. ");
else if(style == 2) cb = rlp_strcpy(desc, 40, "Column ");
else goto rdesc_err;
rlp_strcpy(desc+cb, 40-cb, Int2ColLabel(x1, true));
@@ -2109,6 +2318,29 @@ rdesc_err:
return 0L;
}
+int
+AccRange::DataTypes(void *d, int *numerical, int *strings, int *datetime)
+{
+ anyResult res;
+ int n, r, c, c_num, c_txt, c_dattim;
+
+ if(!d || !Reset()) return 0;
+ for(n = c_num = c_txt = c_dattim = 0, GetFirst(&c, &r); GetNext(&c, &r); n++) {
+ if(((DataObj*)d)->GetResult(&res, r, c, false)) {
+ switch(res.type) {
+ case ET_VALUE: c_num++; break;
+ case ET_TEXT: c_txt++; break;
+ case ET_DATE: case ET_TIME: case ET_DATETIME:
+ c_dattim++; break;
+ }
+ }
+ }
+ if(numerical) *numerical = c_num;
+ if(strings) *strings = c_txt;
+ if(datetime) *datetime = c_dattim;
+ return n;
+}
+
//---------------------------------------------------------------------------
// Use the Delauney triangulation to create a 3D mesh of dispersed data
//---------------------------------------------------------------------------
@@ -2254,7 +2486,7 @@ Default::Default()
Fill_0.scale = Fill_1.scale = Fill_2.scale = 1.0; //size = 100%
Fill_0.hatch = &FillLine_0; Fill_1.hatch = &FillLine_1; Fill_2.hatch = &FillLine_2;
Fill_0.color2 = Fill_1.color2 = Fill_2.color2 = 0x00ffffffL; //white background
- OutLine_0.width = .2; OutLine_1.width = .1; OutLine_2.width = 0.008;
+ OutLine_0.width = .2; OutLine_1.width = .02; OutLine_2.width = 0.008;
OutLine_0.patlength = 6.0; OutLine_1.patlength = 0.6; OutLine_2.patlength = 0.24;
OutLine_0.color = OutLine_1.color = OutLine_2.color = 0x00000000L;
OutLine_0.pattern = OutLine_1.pattern = OutLine_2.pattern = 0L;
@@ -2348,6 +2580,7 @@ Default::GetSize(int select)
case SIZE_CELLTEXT: RetVal = 4.5*ss_txt; break;
case SIZE_RRECT_RAD:
return rrect_rad ? *rrect_rad : GetSize(SIZE_SYMBOL);
+ case SIZE_SCALE: return 1.0;
default: return 0.0;
}
switch(cUnits) {
@@ -2875,6 +3108,7 @@ UndoObj::KillDisp(anyOutput *o)
{
int i, j, c_buf;
+ InvalidateOutput(o); //kill text cursor and animated rectangle
if(o && buffers) {
for(i = 0, c_buf = -1; i < ndisp; i++) {
if(buffers[i] && buffers[i]->disp == o) {
@@ -2961,9 +3195,8 @@ UndoObj::Restore(bool redraw, anyOutput*o)
if(!buff[idx]) return;
if(buff[idx]->zd.org.fx != cdisp->VPorg.fx ||
buff[idx]->zd.org.fy != cdisp->VPorg.fy || buff[idx]->zd.scale != cdisp->VPscale){
- cdisp->VPorg.fx = buff[idx]->zd.org.fx;
- cdisp->VPorg.fy = buff[idx]->zd.org.fy;
- cdisp->VPscale = buff[idx]->zd.scale;
+ cdisp->VPorg.fx = buff[idx]->zd.org.fx; cdisp->VPorg.fy = buff[idx]->zd.org.fy;
+ cdisp->VPscale = buff[idx]->zd.scale; HideCopyMark();
if(cdisp->VPscale > 100.0) cdisp->VPscale = 100.0;
if(cdisp->VPscale < 0.05) cdisp->VPscale = 0.05;
if(buff[idx]->owner)
@@ -3073,8 +3306,9 @@ 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) && buff[idx]->data)
- strcpy ((char*)(*buff[idx]->loc), (char*)(buff[idx]->data));
+ if(*(buff[idx]->loc) && buff[idx]->data)
+ rlp_strcpy ((char*)(*buff[idx]->loc), 100, (char*)(buff[idx]->data));
+ else if(*(buff[idx]->loc))((char*)*(buff[idx]->loc))[0] = 0;
if(buff[idx]->data) free(buff[idx]->data);
CurrGO = buff[idx]->owner; break;
case UNDO_ROTDEF:
@@ -3337,7 +3571,8 @@ UndoObj::String(GraphObj *go, char **s, DWORD flags)
int iret;
if(s && *s && *(*s)){
- ptr = strdup(*(s)); iret = (int)strlen(*(s));
+ iret = (int)strlen(*(s));
+ ptr = (char*)memdup(*(s), iret+1, 0);
}
else {
ptr = 0L; iret = 0;
@@ -3397,8 +3632,10 @@ UndoObj::TextDef(GraphObj *go, TextDEF *td, DWORD flags)
TextDEF *ptr;
if(!(ptr = (TextDEF*) memdup(td, sizeof(TextDEF), 0))) return;
- if(td->text) ptr->text = strdup(td->text);
- if(0 > NewItem(UNDO_TEXTDEF, flags, go, ptr, (void**)td)) free(ptr);
+ if(td->text && td->text[0]) ptr->text = (char*)memdup(td->text, (int)strlen(td->text)+1, 0);
+ if(0 > NewItem(UNDO_TEXTDEF, flags, go, ptr, (void**)td)){
+ if(ptr->text) free(ptr->text); free(ptr);
+ }
}
void
@@ -3459,7 +3696,7 @@ UndoObj::TextCell(EditText *et, anyOutput *o, char *text, int *cur, int *m1, int
if(o) {
o_save = cdisp; SetDisp(o);
if(ptr = (EtBuff*) calloc(1, sizeof(EtBuff))) {
- if(text && text[0]) ptr->txt = strdup(text);
+ if(text && text[0]) ptr->txt = (char*)memdup(text, (int)strlen(text)+1, 0);
ptr->cur = cur; ptr->m1 = m1; ptr->m2 = m2;
ptr->vcur = *cur; ptr->vm1 = *m1; ptr->vm2 = *m2;
ptr->row = et->row; ptr->col = et->col;
diff --git a/Utils.cpp b/Utils.cpp
index 0a538db..66bea56 100755
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -1,4 +1,4 @@
-//Utils.cpp, Copyright (c) 2000-2006 R.Lackner
+//Utils.cpp, Copyright (c) 2000-2007 R.Lackner
//Collection of utility functions and classes for RLPlot
//
// This file is part of RLPlot.
@@ -89,7 +89,11 @@ void NiceAxis(AxisDEF *axis, int nTick)
HiVal = LoVal = Step * floor(axis->min/Step);
axis->max *=1.05f;
while(HiVal < axis->max) HiVal += Step;
- axis->min = LoVal;
+ if((axis->flags & AXIS_LOG) == AXIS_LOG) {
+ if (LoVal > defs.min4log) axis->min = LoVal;
+ if ((LoVal + Step) > defs.min4log && (LoVal + Step) < axis->min) axis->min = LoVal+Step;
+ }
+ else axis->min = LoVal;
axis->max = HiVal;
axis->Start = axis->min;
axis->Step = Step;
@@ -126,8 +130,7 @@ double base4log(AxisDEF *axis, int direc)
case 2: cmd = SIZE_BOUNDS_ZMIN; break;
default: return 1.0;
}
- if(axis->min > defs.min4log) lv = axis->min;
- else lv = ((GraphObj*)axis->owner)->GetSize(cmd);
+ lv = axis->min > defs.min4log ? axis->min : defs.min4log;
if(lv <= defs.min4log) return defs.min4log;
lv = log10(lv);
lv -= (Magn = floor(lv));
@@ -303,7 +306,7 @@ char *strreplace(char *needle, char *replace, char *haystack)
static size_t reslen = 0;
size_t i, j, k, l;
- if(!needle || !needle[0] || !haystack || !haystack[0]) haystack;
+ if(!needle || !needle[0] || !haystack || !haystack[0]) return result;
if(!result) result = (char*)malloc(reslen = 100);
result[0] = 0; l = strlen(needle);
for(i = j = k = 0; haystack[i]; i++, j=0) {
@@ -542,9 +545,31 @@ char *Int2ColLabel(int nr1, bool uc)
return RetTxt+i+1;
}
+char *mkCellRef(int row, int col)
+{
+ static char RetTxt[20];
+
+#ifdef USE_WIN_SECURE
+ sprintf_s(RetTxt, 20, "%s%d", Int2ColLabel(col, false), row+1);
+#else
+ sprintf(RetTxt, "%s%d", Int2ColLabel(col, false), row+1);
+#endif
+ return RetTxt;
+}
+
+char *mkRangeRef(int r1, int c1, int r2, int c2)
+{
+ static char RetTxt[40];
+ int cb;
+
+ cb = rlp_strcpy(RetTxt, 20, mkCellRef(r1, c1));
+ RetTxt[cb++] = ':';
+ rlp_strcpy(RetTxt+cb, 40-cb, mkCellRef(r2, c2));
+ return RetTxt;
+}
//convert strings to XML specifications
//this offers a limited support for special characters
-char *str2xml(char *str)
+char *str2xml(char *str, bool bGreek)
{
int i, j;
wchar_t wc;
@@ -565,7 +590,14 @@ char *str2xml(char *str)
j += rlp_strcpy(TmpTxt+j, TMP_TXT_SIZE-j, ">");
break;
default:
- if((unsigned char)str[i] <= 127) TmpTxt[j++]=str[i];
+#ifdef USE_WIN_SECURE
+ if(bGreek && str[i] >= 'A' && str[i] <= 'Z') j += sprintf_s(TmpTxt+j, 20, "&#%d;", str[i] - 'A' + 0x391);
+ else if(bGreek && str[i] >= 'a' && str[i] <= 'z') j += sprintf_s(TmpTxt+j, 20, "&#%d;", str[i] - 'a' + 0x3B1);
+#else
+ if(bGreek && str[i] >= 'A' && str[i] <= 'Z') j += sprintf(TmpTxt+j, "&#%d;", str[i] - 'A' + 0x391);
+ else if(bGreek && str[i] >= 'a' && str[i] <= 'z') j += sprintf(TmpTxt+j, "&#%d;", str[i] - 'a' + 0x3B1);
+#endif
+ else if((unsigned char)str[i] <= 127) TmpTxt[j++]=str[i];
else {
if(mbtowc(&wc, str+i, 1) >0)
#ifdef USE_WIN_SECURE
@@ -610,7 +642,7 @@ char **split(char *str, char sep, int *nl)
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];
+ char mant[30], expo[30], fmt[20];
double num;
o->oGetTextExtent(num_str, slen = (int)strlen(num_str), &w, &h);
@@ -636,8 +668,8 @@ char *fit_num_rect(anyOutput *o, int max_width, char *num_str)
#endif
if(k >0) do {
#ifdef USE_WIN_SECURE
- sprintf_s(fmt, 10, "%%.%dlf%s", k, expo);
- slen = sprintf_s(num_str, 40, fmt, num); //num_str is much longer than 40
+ sprintf_s(fmt, 20, "%%.%dlf%s", k, expo);
+ slen = sprintf_s(num_str, 60, fmt, num); //num_str is much longer than 60
#else
sprintf(fmt, "%%.%dlf%s", k, expo);
slen = sprintf(num_str, fmt, num);
@@ -939,6 +971,90 @@ void DrawBezier(long *cp, POINT *pts, POINT p0, POINT p1, POINT p2, POINT p3, in
}
//----------------------------------------------------------------------------
+// create a Bezier spline through data points
+static void ipol_curve(lfPOINT *p1, lfPOINT *p2, lfPOINT *p3, lfPOINT *cp1, lfPOINT *cp2)
+{
+ double dx, dy, l;
+ lfPOINT tHat;
+
+ tHat.fx = p3->fx - p1->fx; tHat.fy = p3->fy - p1->fy;
+ l = sqrt(tHat.fx * tHat.fx + tHat.fy * tHat.fy);
+ tHat.fx /= l; tHat.fy /= l;
+ cp1->fx = cp2->fx = p2->fx; cp1->fy = cp2->fy = p2->fy;
+ dx = p3->fx - p2->fx; dy = p3->fy - p2->fy; l = sqrt(dx*dx + dy*dy)/3.0;
+ cp2->fx += (tHat.fx * l); cp2->fy += (tHat.fy *l);
+ dx = p2->fx - p1->fx; dy = p2->fy - p1->fy; l = sqrt(dx*dx + dy*dy)/3.0;
+ cp1->fx -= (tHat.fx * l); cp1->fy -= (tHat.fy *l);
+}
+
+static void mirr_vecvec(lfPOINT *a0, lfPOINT *a1, lfPOINT *v1)
+{
+ double dx, dy, as, ac, vs, vc, s, c, l;
+ lfPOINT sol1, sol2;
+
+ //mirror vector a0 -> v1 by rotation around vector a0 -> a1
+ dx = a1->fx - a0->fx; dy = a1->fy - a0->fy;
+ l = sqrt(dx*dx + dy*dy); as = dy/l; ac = dx/l;
+ dx = v1->fx - a0->fx; dy = v1->fy - a0->fy;
+ l = sqrt(dx*dx + dy*dy); vs = dy/l; vc = dx/l;
+ //calculate cw and ccw solution
+ s = sin((asin(as)-asin(vs))*2.0); c = cos((acos(ac)-acos(vc))*2.0);
+ sol1.fx = dx * c + dy * s + a0->fx; sol1.fy = dy * c - dx * s + a0->fy;
+ s = sin((asin(as)-asin(-vs))*2.0); c = cos((acos(ac)-acos(-vc))*2.0);
+ sol2.fx = dx * c + dy * s + a0->fx; sol2.fy = dy * c - dx * s + a0->fy;
+ //get better solution
+ dx = sol1.fx - a1->fx; dy = sol1.fy - a1->fy;
+ l = sqrt(dx*dx + dy*dy);
+ dx = sol2.fx - a1->fx; dy = sol2.fy - a1->fy;
+ if( l < sqrt(dx*dx + dy*dy)) {
+ v1->fx = sol1.fx; v1->fy = sol1.fy;
+ }
+ else {
+ v1->fx = sol2.fx; v1->fy = sol2.fy;
+ }
+}
+
+int mkCurve(lfPOINT *src, int n1, lfPOINT **dst, bool bClosed)
+{
+ int i, j, iret;
+
+ if(!src || n1 < 3) return 0;
+ if(!(*dst = (lfPOINT*)malloc((n1*3+2) * sizeof(lfPOINT))))return 0;
+ for(i = j = iret = 0; i < n1; i++, j += 3) {
+ (*dst)[j].fx = src[i].fx; (*dst)[j].fy = src[i].fy;
+ if(i && i < (n1-1)){
+ ipol_curve(&src[i-1], &src[i], &src[i+1], *dst+j-1, *dst+j+1);
+ }
+ else if(i) {
+ iret = j+1; break;
+ }
+ }
+ if(bClosed && iret >2) {
+ if((*dst)[j].fx != (*dst)[0].fx || (*dst)[j].fy != (*dst)[0].fy) {
+ j += 3; iret += 3;
+ (*dst)[j].fx = (*dst)[0].fx; (*dst)[j].fy = (*dst)[0].fy;
+ }
+ if(j < 6) {
+ free(*dst); *dst = 0L; return 0;
+ }
+ ipol_curve(*dst+j-3, *dst+j, *dst+3, *dst+j-1, *dst+1);
+ ipol_curve(*dst+j-6, *dst+j-3, *dst+j, *dst+j-4, *dst+j-2);
+ }
+ else if(!bClosed && iret>3) {
+ (*dst)[1].fx = (*dst)[0].fx + (*dst)[3].fx - (*dst)[2].fx;
+ (*dst)[1].fy = (*dst)[0].fy + (*dst)[3].fy - (*dst)[2].fy;
+ mirr_vecvec(*dst, *dst+3, *dst+1);
+ (*dst)[j-1].fx = (*dst)[j].fx + (*dst)[j-3].fx - (*dst)[j-2].fx;
+ (*dst)[j-1].fy = (*dst)[j].fy + (*dst)[j-3].fy - (*dst)[j-2].fy;
+ mirr_vecvec(*dst+j, *dst+j-3, *dst+j-1);
+ }
+ else {
+ free(*dst); *dst = 0L; return 0;
+ }
+ return iret;
+}
+
+//----------------------------------------------------------------------------
// create a circular polygon
//use circular Bresenham's algorithm to draw arcs
//Ref: C. Montani, R. Scopigno (1990) "Speres-To-Voxel Conversion", in:
@@ -1253,6 +1369,7 @@ void DeleteGO(GraphObj *go)
case GO_FITFUNC3D: delete((FitFunc3D*)go); break;
case GO_BEZIER: delete((Bezier*)go); break;
case GO_TEXTFRAME: delete((TextFrame*)go); break;
+ case GO_NORMQUANT: delete((NormQuant*)go); break;
default:
#ifdef USE_WIN_SECURE
sprintf_s(TmpTxt, TMP_TXT_SIZE, "Cannot delete Object\nwith Id %ld", go->Id);
@@ -1395,7 +1512,7 @@ bool FileExist(char *FileName)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool IsPlot3D(GraphObj *g)
{
- if(g && (g->Id == GO_PLOT3D || g->Id == GO_FUNC3D)) return true;
+ if(g && (g->Id == GO_PLOT3D || g->Id == GO_FUNC3D || g->Id == GO_FITFUNC3D)) return true;
return false;
}
@@ -1561,6 +1678,31 @@ DWORD CheckNewLFPoint(lfPOINT *loc, lfPOINT *old_v, lfPOINT *new_v, GraphObj *pa
return flags;
}
+DWORD CheckNewString(char **loc, char *s_old, char *s_new, GraphObj *par, DWORD flags)
+{
+ int ocb, ncb, cb;
+
+ if(s_old && s_new) {
+ if(!strcmp(s_old, s_new)) return flags;
+ ocb = (int)strlen(s_old); ncb = (int)strlen(s_new);
+ cb = ncb > ocb ? ncb : ocb;
+ if(cb > ocb) {
+ *loc = (char*)realloc(*loc, cb * sizeof(char)+1);
+ }
+ Undo.String(par, loc, flags); flags |= UNDO_CONTINUE;
+ if(*loc) rlp_strcpy(*loc, cb+1, s_new);
+ }
+ else if(!s_old && s_new && s_new[0]) {
+ Undo.String(par, loc, flags); flags |= UNDO_CONTINUE;
+ *loc = (char *)memdup(s_new, (int)strlen(s_new) +1, 0);
+ }
+ else if(s_old && s_old[0] && !s_new) {
+ Undo.String(par, loc, flags); flags |= UNDO_CONTINUE;
+ if(*loc) *loc[0] = 0;
+ }
+ return flags;
+}
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//execute clipping of 3D objects
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Version.h b/Version.h
index 95a98b5..2e349aa 100755
--- a/Version.h
+++ b/Version.h
@@ -1,4 +1,4 @@
-//RLPlot.h, Copyright (c) 2000-2006 R.Lackner
+//RLPlot.h, Copyright (c) 2000-2007 R.Lackner
//
// This file is part of RLPlot.
//
@@ -16,4 +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 "1.2"
+#define SZ_VERSION "1.3"
diff --git a/WinSpec.cpp b/WinSpec.cpp
index e59c53b..a51b74b 100755
--- a/WinSpec.cpp
+++ b/WinSpec.cpp
@@ -1,4 +1,4 @@
-//WinSpec.cpp, Copyright (c) 2000-2006 R.Lackner
+//WinSpec.cpp, Copyright (c) 2000-2007 R.Lackner
//the entire code of this module is highly specific to Windows!
//
// This file is part of RLPlot.
@@ -19,6 +19,9 @@
//
#include <stdio.h>
#include <math.h>
+#include <fcntl.h> //file open flags
+#include <sys/stat.h> //I/O flags
+#include <io.h> //for read/write
#include "rlplot.h"
#include "WinSpec.h"
#include "rlplot.rc"
@@ -30,7 +33,6 @@ extern int dlgtxtheight;
HINSTANCE hInstance;
HWND MainWnd = 0L;
HACCEL accel;
-bool isWIN95 = false;
extern tag_Units Units[];
extern GraphObj *CurrGO; //Selected Graphic Objects
extern Graph *CurrGraph;
@@ -42,13 +44,11 @@ extern UndoObj Undo;
const char name[] = "RLPLOT1";
-static unsigned int cf_rlpgraph = RegisterClipboardFormat("rlp_graph");
static unsigned int cf_rlpobj = RegisterClipboardFormat("rlp_obj");
static unsigned int cf_rlpxml = RegisterClipboardFormat("rlp_xml");
long FAR PASCAL WndProc(HWND, UINT, UINT, LONG);
PrintWin *Printer = 0L;
-
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// I/O File name dialogs
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -98,8 +98,10 @@ char *SaveDataAsName(char *oldname)
char *SaveGraphAsName(char *oldname)
{
static char szFile[500], szFileTitle[256];
- static char szFilter[] = "RLPlot Graph (*.RLP)\0*.rlp\0";
+ static char szFilter[] = "RLPlot Graph (*.rlp)\0*.rlp\0";
OPENFILENAME ofn;
+ int i, j, cb;
+ char *ext;
szFile[0] = '\0';
if(oldname)rlp_strcpy(szFile, 500, oldname);
@@ -117,6 +119,16 @@ char *SaveGraphAsName(char *oldname)
ofn.lpstrTitle = "Save Graph As";
if(GetSaveFileName(&ofn)){
+ if(!(cb = (int)strlen(szFile)) || !szFile[0])return 0L;
+ if(cb < 4 || szFile[cb-4] != '.'){
+ for(i = j = 0; (j>>1) < (int)(ofn.nFilterIndex-1); i++) {
+ if(szFilter[i] == '\0') j++;
+ }
+ ext = szFilter+i;
+ for(i = 0; ext[i] && ext[i] != '*'; i++);
+ rlp_strcpy(szFile+cb, 5, ext+i+1);
+ }
+ defs.FileHistory(szFile);
defs.FileHistory(szFile);
return szFile;
}
@@ -128,7 +140,7 @@ char *SaveGraphAsName(char *oldname)
char *OpenGraphName(char *oldname)
{
static char szFile[500], szFileTitle[256];
- static char szFilter[] = "RLPlot Graph (*.RLP)\0*.rlp\0";
+ static char szFilter[] = "RLPlot Graph (*.rlp)\0*.rlp\0";
OPENFILENAME ofn;
szFile[0] = '\0';
@@ -193,8 +205,10 @@ void OpenExportName(GraphObj *g, char *oldname)
static char szFile[500], szFileTitle[256];
static char szFilter[] = "Scalable Vector Graphics (*.svg)\0*.svg\0"
"Encapsulated Post Script (*.eps)\0*.eps\0"
- "MSWindows MetaFile(*.wmf)\0*.wmf\0Tag Image File Format (*.tif)\0*.tif\0";
+ "Enhanced MetaFile(*.emf)\0*.emf\0Windows MetaFile(*.wmf)\0*.wmf\0"
+ "Tag Image File Format (*.tif)\0*.tif\0";
OPENFILENAME ofn;
+ WinCopyWMF *wmf;
int i;
szFile[0] = '\0';
@@ -219,8 +233,19 @@ void OpenExportName(GraphObj *g, char *oldname)
if(0==_stricmp(".svg", szFile+i-4)) {
DoExportSvg(g, szFile, 0L);
}
+ else if(0==_stricmp(".emf", szFile+i-4)) {
+ wmf = new WinCopyWMF(g, 0L, szFile);
+ if(wmf && wmf->StartPage()) {
+ g->DoPlot(wmf); wmf->EndPage(); delete wmf;
+ }
+ else if(wmf) delete wmf; g->Command(CMD_REDRAW, 0L, 0L);
+ }
else if(0==_stricmp(".wmf", szFile+i-4)) {
- DoExportWmf(g, szFile, 600.0f, 0L);
+ wmf = new WinCopyWMF(g, szFile, 0L);
+ if(wmf && wmf->StartPage()) {
+ g->DoPlot(wmf); wmf->EndPage(); delete wmf;
+ }
+ else if(wmf) delete wmf; g->Command(CMD_REDRAW, 0L, 0L);
}
else if(0==_stricmp(".eps", szFile+i-4)) {
DoExportEps(g, szFile, 0L);
@@ -277,7 +302,7 @@ void Qt_Box()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
anyOutput *oTxtCur = 0L, *oCopyMark = 0L;
RECT rTxtCur, rCopyMark;
-bool bTxtCur = false, bTxtCurIsVis = false;
+bool bTxtCur = false, bTxtCurIsVis = false, bSuspend = false;
DWORD cTxtCur = 0x0L;
HWND hwndTxtCur = 0L;
int iTxtCurCount = 0;
@@ -302,9 +327,8 @@ void ShowTextCursor(anyOutput *out, RECT *disp, DWORD color)
{
HWND wnd = GetFocus();
- cTxtCur = color;
- HideTextCursor();
- oTxtCur = out;
+ cTxtCur = color; HideTextCursor();
+ oTxtCur = out; bSuspend = false;
iTxtCurCount = -2;
memcpy(&rTxtCur, disp, sizeof(RECT));
ptTxtCurLine[0].x = rTxtCur.left; ptTxtCurLine[0].y = rTxtCur.top;
@@ -317,6 +341,7 @@ void ShowTextCursor(anyOutput *out, RECT *disp, DWORD color)
void HideCopyMark()
{
if(bmCopyMark && oCopyMark) {
+ bmCopyMark = 0L;
oCopyMark->UpdateRect(&rCopyMark, false);
delete bmCopyMark;
}
@@ -327,7 +352,7 @@ void ShowCopyMark(anyOutput *out, RECT *mrk, int nRec)
{
int i;
- HideCopyMark();
+ HideCopyMark(); bSuspend = false;
if(!out || !mrk || !nRec) return;
oCopyMark = out;
rCopyMark.left = mrk[0].left; rCopyMark.right = mrk[0].right;
@@ -340,6 +365,29 @@ void ShowCopyMark(anyOutput *out, RECT *mrk, int nRec)
rCopyMark.bottom - rCopyMark.top, out->hres, out->vres);
}
+void InvalidateOutput(anyOutput *o)
+{
+ if(!o) return;
+ if(o == oCopyMark) {
+ oCopyMark = 0L;
+ if(bmCopyMark) delete bmCopyMark;
+ bmCopyMark = 0L;
+ }
+ if(o == oTxtCur) {
+ oTxtCur = 0L; bTxtCur = false;
+ }
+}
+
+void SuspendAnimation(anyOutput *o, bool bSusp)
+{
+ if(!o) return;
+ if(!bSusp) bSuspend = false;
+ else {
+ if(o == oCopyMark) bSuspend = bSusp;
+ if(o == oTxtCur) bSuspend = bSusp;
+ }
+}
+
LineDEF liCopyMark1 = {0.0f, 1.0f, 0x00ffffffL, 0L};
LineDEF liCopyMark2 = {0.0f, 6.0f, 0x0L, 0xf0f0f0f0L};
@@ -350,6 +398,7 @@ LRESULT FAR PASCAL TimerWndProc(HWND hwnd, UINT message, UINT wParam, LONG lPara
switch(message) {
case WM_TIMER:
+ if(bSuspend) return 0;
if(bmCopyMark && oCopyMark) {
bmCopyMark->CopyBitmap(0, 0, oCopyMark, rCopyMark.left, rCopyMark.top,
rCopyMark.right - rCopyMark.left, rCopyMark.bottom - rCopyMark.top, false);
@@ -440,14 +489,10 @@ void TestClipboard(GraphObj *g)
(ptr = (unsigned char*) GlobalLock(hmem))) ProcMemData(g, ptr, true);
else if((hmem = GetClipboardData(cf_rlpobj)) &&
(ptr = (unsigned char*) GlobalLock(hmem))) OpenGraph(g, 0L, ptr, true);
- else if((hmem = GetClipboardData(cf_rlpgraph)) &&
- (ptr = (unsigned char*) GlobalLock(hmem))) OpenGraph(g, 0L, ptr, true);
}
else if(g->Id == GO_PAGE || g->Id == GO_GRAPH) {
if((hmem = GetClipboardData(cf_rlpobj)) &&
(ptr = (unsigned char*) GlobalLock(hmem))) OpenGraph(g, 0L, ptr, true);
- else if((hmem = GetClipboardData(cf_rlpgraph)) &&
- (ptr = (unsigned char*) GlobalLock(hmem))) OpenGraph(g, 0L, ptr, true);
}
else TestClipboard(g->parent);
if(hmem) GlobalUnlock(hmem);
@@ -503,8 +548,11 @@ void GetDesktopSize(int *width, int *height)
RECT rc;
GetClientRect(GetDesktopWindow(), &rc);
- *width = rc.right;
- *height = rc.bottom;
+ *width = rc.right - rc.left;
+ *height = rc.bottom - rc.top;
+ if(*width < 800 || *height < 600){
+ *width = 800; *height = 600;
+ }
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -548,80 +596,119 @@ void noreflptr(long ref)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Common code for any Windows output class
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-bool com_oTextOut(int x, int y, char *txt, int cb,
- HFONT *hFont, HDC *dc, TextDEF *td, bool win95mode, anyOutput *o)
+bool com_oTextOutW(int x, int y, w_char *txt, int cb, HFONT *hFont, HDC *dc,
+ TextDEF *td, anyOutput *o)
{
XFORM xf;
- WCHAR *uc;
- int i, ix, iy, align;
+ int ix, iy, w, h, dtflags;
+ RECT dtrc;
+
if(!*hFont || !txt || !txt[0]) return false;
- SelectObject(*dc, *hFont);
- SetTextColor(*dc, td->ColTxt);
- SetBkColor(*dc, td->ColBg);
- align = ((td->Align & TXA_HRIGHT) ? TA_RIGHT : (td->Align &
- TXA_HCENTER) ? TA_CENTER : TA_LEFT) | ((td->Align & TXA_VBOTTOM) ?
- TA_BOTTOM : TA_TOP);
- SetTextAlign(*dc, align);
- SetBkMode(*dc, td->Mode ? TRANSPARENT : OPAQUE);
- ix = iy = 0;
- if(td->Style & TXS_SUB) {
- if((td->Align & TXA_VCENTER) == TXA_VCENTER) iy += o->un2iy(td->fSize*0.4);
- else if((td->Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy += o->un2iy(td->fSize*0.2);
- else if((td->Align & TXA_VTOP) == TXA_VTOP) iy += o->un2iy(td->fSize*.6);
- }
- else if(td->Style & TXS_SUPER) {
- if((td->Align & TXA_VCENTER) == TXA_VCENTER) iy -= o->un2iy(td->fSize*0.4);
- else if((td->Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy -= o->un2iy(td->fSize*0.6);
- else if((td->Align & TXA_VTOP) == TXA_VTOP) iy += o->un2iy(td->fSize*.0);
- }
- if(!win95mode && (fabs(td->RotBL) >.01 || fabs(td->RotCHAR) >.01)) {
+ if(cb < 1) cb = (int)wcslen(txt);
+ SelectObject(*dc, *hFont); SetTextColor(*dc, td->ColTxt);
+ SetBkColor(*dc, td->ColBg); SetBkMode(*dc, td->Mode ? TRANSPARENT : OPAQUE);
+ ix = iy = 0; SetTextAlign(*dc, TA_LEFT | TA_TOP);
+ if(o->OC_type == OC_HIMETRIC) {
+ if(td->Style & TXS_SUB) {
+ if((td->Align & TXA_VCENTER) == TXA_VCENTER) iy -= o->un2iy(td->fSize*0.4);
+ else if((td->Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy -= o->un2iy(td->fSize*0.2);
+ else if((td->Align & TXA_VTOP) == TXA_VTOP) iy -= o->un2iy(td->fSize*.6);
+ }
+ else if(td->Style & TXS_SUPER) {
+ if((td->Align & TXA_VCENTER) == TXA_VCENTER) iy += o->un2iy(td->fSize*0.4);
+ else if((td->Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy += o->un2iy(td->fSize*0.6);
+ else if((td->Align & TXA_VTOP) == TXA_VTOP) iy -= o->un2iy(td->fSize*.0);
+ }
+ else {
+ if((td->Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy += td->iSize;
+ else if((td->Align & TXA_VCENTER) == TXA_VCENTER) iy += (td->iSize>>1);
+ }
+ }
+ else {
+ if(td->Style & TXS_SUB) {
+ if((td->Align & TXA_VCENTER) == TXA_VCENTER) iy += o->un2iy(td->fSize*0.4);
+ else if((td->Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy += o->un2iy(td->fSize*0.2);
+ else if((td->Align & TXA_VTOP) == TXA_VTOP) iy += o->un2iy(td->fSize*.6);
+ }
+ else if(td->Style & TXS_SUPER) {
+ if((td->Align & TXA_VCENTER) == TXA_VCENTER) iy -= o->un2iy(td->fSize*0.4);
+ else if((td->Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy -= o->un2iy(td->fSize*0.6);
+ else if((td->Align & TXA_VTOP) == TXA_VTOP) iy += o->un2iy(td->fSize*.0);
+ }
+ else {
+ if((td->Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy -= td->iSize;
+ else if((td->Align & TXA_VCENTER) == TXA_VCENTER) iy -= (td->iSize>>1);
+ }
+ }
+ dtflags = DT_NOCLIP | DT_NOPREFIX;
+ o->oGetTextExtentW(txt, cb, &w, &h);
+ if((td->Align & TXA_HCENTER) == TXA_HCENTER) {
+ dtrc.left = x+ix-(w>>1); dtflags |= DT_CENTER;
+ }
+ else if((td->Align & TXA_HRIGHT) == TXA_HRIGHT) {
+ dtrc.left = x+ix-w; dtflags |= DT_RIGHT;
+ }
+ else {
+ dtrc.left = x+ix; dtflags |= DT_LEFT;
+ }
+ dtrc.top = iy + y; dtrc.right = dtrc.left+w; dtrc.bottom = dtrc.top+h;
+ if(fabs(td->RotBL) >.01 || fabs(td->RotCHAR) >.01) {
SetGraphicsMode(*dc, GM_ADVANCED);
- xf.eM11 = xf.eM22 = (float)cos(td->RotBL *0.01745329252);
- xf.eM12 = (float)-sin(td->RotBL *0.01745329252);
- xf.eM21 = -xf.eM12;
- xf.eDx = (float)x;
- xf.eDy = (float)y;
- SetWorldTransform(*dc, &xf);
- if(td->Font==FONT_GREEK && (uc=(WCHAR *)calloc(strlen(txt)+1, sizeof(WCHAR)))) {
- for(i = 0; txt[i]; i++) {
- if((txt[i] >= 'A' && txt[i] <= 'Z')) uc[i] = txt[i] - 'A' + 0x391;
- else if((txt[i] >= 'a' && txt[i] <= 'z')) uc[i] = txt[i] - 'a' + 0x3B1;
- else uc[i] = txt[i];
- }
- TextOutW(*dc, ix, iy+((td->Align & TXA_VCENTER) ? - td->iSize/2 : 0), uc,
- (cb > 0) ? cb : (int)strlen(txt));
- free(uc);
+ if(o->OC_type == OC_HIMETRIC) {
+ if((td->Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy -= (td->iSize<<1);
+ else if((td->Align & TXA_VCENTER) == TXA_VCENTER) iy -= (td->iSize);
+ xf.eM11 = (float)cos(td->RotBL *0.01745329252);
+ xf.eM12 = (float)sin(td->RotBL *0.01745329252);
+ xf.eM22 = (float)-cos(td->RotBL *0.01745329252);
+ xf.eM21 = xf.eM12;
}
else {
- TextOut(*dc, ix, iy+((td->Align & TXA_VCENTER) ? - td->iSize/2 : 0), txt,
- (cb > 0) ? cb : (int)strlen(txt));
+ xf.eM11 = xf.eM22 = (float)cos(td->RotBL *0.01745329252);
+ xf.eM12 = (float)-sin(td->RotBL *0.01745329252);
+ xf.eM21 = -xf.eM12;
}
-// DrawText(*dc, txt, (cb> 0)? cb : strlen(txt), 0L /*LPRECT*/, uFormat);
+ xf.eDx = (float)x; xf.eDy = (float)y; SetWorldTransform(*dc, &xf);
+ dtrc.left -= x; dtrc.right -= x;
+ dtrc.top = iy; dtrc.bottom = dtrc.top + h;
+ DrawTextW(*dc, txt, cb, &dtrc, dtflags);
ModifyWorldTransform(*dc, &xf, MWT_IDENTITY);
SetGraphicsMode(*dc, GM_COMPATIBLE);
return true;
}
else {
- if(!win95mode && td->Font==FONT_GREEK && (uc=(WCHAR *)calloc(strlen(txt)+1, sizeof(WCHAR)))) {
- for(i = 0; txt[i]; i++) {
- if((txt[i] >= 'A' && txt[i] <= 'Z')) uc[i] = txt[i] - 'A' + 0x391;
- else if((txt[i] >= 'a' && txt[i] <= 'z')) uc[i] = txt[i] - 'a' + 0x3B1;
- else uc[i] = txt[i];
- }
- TextOutW(*dc, x+ix, iy + ((td->Align & TXA_VCENTER) ? y - td->iSize/2 : y), uc,
- (cb > 0) ? cb : (int)strlen(txt));
- free(uc);
- return true;
+ DrawTextW(*dc, txt, cb, &dtrc, DT_CENTER | DT_NOCLIP | DT_NOPREFIX);
+ return true;
+ }
+ return false;
+}
+
+bool com_oTextOut(int x, int y, char *atxt, int cb, HFONT *hFont, HDC *dc, TextDEF *td, anyOutput *o)
+{
+ unsigned char *utxt = (unsigned char*)atxt;
+ w_char *uc;
+ int i;
+
+ if(!*hFont || !atxt || !atxt[0]) return false;
+ if(cb < 1) cb = (int)strlen(atxt);
+ if(!(uc=(WCHAR *)calloc(cb+1, sizeof(WCHAR)))) return false;
+ if(td->Font==FONT_GREEK) {
+ for(i = 0; utxt[i]; i++) {
+ if((utxt[i] >= 'A' && utxt[i] <= 'Z')) uc[i] = utxt[i] - 'A' + 0x391;
+ else if((utxt[i] >= 'a' && utxt[i] <= 'z')) uc[i] = utxt[i] - 'a' + 0x3B1;
+ else uc[i] = utxt[i];
}
- else if(TextOut(*dc, x+ix, iy + ((td->Align & TXA_VCENTER) ? y - td->iSize/2 : y), txt,
- (cb > 0) ? cb : (int)strlen(txt))) return true;
}
+ else {
+ for(i = 0; utxt[i]; i++) uc[i] = utxt[i];
+ }
+ com_oTextOutW(x, y, uc, cb, hFont, dc, td, o);
+ free(uc);
return false;
}
bool com_SetTextSpec(TextDEF *set, anyOutput *o, HFONT *hFont, TextDEF *TxtSet,
- HDC *dc, bool win95mode)
+ HDC *dc)
{
bool IsModified, RetVal;
LOGFONT FontRec;
@@ -641,14 +728,8 @@ bool com_SetTextSpec(TextDEF *set, anyOutput *o, HFONT *hFont, TextDEF *TxtSet,
else FontRec.lfHeight = TxtSet->iSize;
if(FontRec.lfHeight <2) FontRec.lfHeight = 2;
FontRec.lfWidth = 0;
- if(win95mode) { //Win 95, 98
- FontRec.lfEscapement = iround(TxtSet->RotBL*10); //text angle
- FontRec.lfOrientation = iround(TxtSet->RotBL*10); //base line angle
- }
- else { //Win NT, 2000, XP
- FontRec.lfEscapement = 0; //text angle
- FontRec.lfOrientation = 0; //base line angle
- }
+ FontRec.lfEscapement = 0; //text angle
+ FontRec.lfOrientation = 0; //base line angle
FontRec.lfWeight = (TxtSet->Style & TXS_BOLD) ? FW_BOLD : FW_NORMAL;
FontRec.lfItalic = (TxtSet->Style & TXS_ITALIC) ? TRUE : FALSE;
FontRec.lfUnderline = (TxtSet->Style & TXS_UNDERLINE) ? TRUE : FALSE;
@@ -683,30 +764,37 @@ bool com_SetTextSpec(TextDEF *set, anyOutput *o, HFONT *hFont, TextDEF *TxtSet,
return RetVal;
}
-bool com_Arc(HDC dc, int x1, int y1, int x2, int y2, int quads)
+bool com_oGetTextExtentW(w_char *text, int cb, int *width, int *height, HDC dc, TextDEF *TxtSet)
{
- int bx, by, ex, ey;
+ SIZE TextExtent;
+ double si, csi, d;
- if(x1 > x2) Swap(x1, x2); if(y1 > y2) Swap(y1, y2);
- switch (quads) {
- case 1:
- bx = (x1+x2)>>1; by = y2;
- ex = x2; ey = (y1 +y2)>>1;
- break;
- case 2:
- bx = x1; ex = x2; by = ey = (y1 +y2)>>1;
- break;
- case 3:
- bx = (x1+x2)>>1; by = y1;
- ex = x2; ey = (y1 +y2)>>1;
- break;
- case 4:
- bx = ex = x2; by = ey = (y1 +y2)>>1;
- break;
- default: return false;
+ if(!text || !TxtSet) return false;
+ if(!GetTextExtentPoint32W(dc, text, cb ? cb : (int)wcslen(text), &TextExtent))return false;
+ if(fabs(TxtSet->RotBL) >0.01) {
+ si = fabs(sin(TxtSet->RotBL * 0.01745329252)); csi = fabs(cos(TxtSet->RotBL * 0.01745329252));
+ d = si > csi ? 1.0/si : 1.0/csi;
+ d = (TextExtent.cx * ((7.0 + d)/8.0));
+ TextExtent.cx = iround(d);
}
- if(Arc(dc, x1, y1, x2, y2, bx, by, ex, ey)) return true;
- return false;
+ *width = TextExtent.cx; *height = TextExtent.cy;
+ return true;
+}
+
+bool com_oGetTextExtent(char *text, int cb, int *width, int *height, HDC dc, TextDEF *TxtSet)
+{
+ int i;
+ unsigned char *utext;
+ w_char *uc;
+ bool bRet;
+
+ if(!text || !TxtSet) return false;
+ if(!cb) cb = (int)strlen(text);
+ if(!(uc = (w_char *) malloc((cb+1)*sizeof(w_char))))return false;
+ for(i = 0, utext = (unsigned char*)text ; i <= cb; i++) uc[i] = utext[i];
+ bRet = com_oGetTextExtentW(uc, cb, width, height, dc, TxtSet);
+ free(uc);
+ return bRet;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -864,7 +952,7 @@ BitMapWin::SetFill(FillDEF *fill)
bool
BitMapWin::SetTextSpec(TextDEF *set)
{
- return com_SetTextSpec(set, this, &hFont, &TxtSet, &memDC, isWIN95);
+ return com_SetTextSpec(set, this, &hFont, &TxtSet, &memDC);
}
bool
@@ -904,19 +992,13 @@ BitMapWin::CopyBitmap(int x, int y, anyOutput* sr, int sx, int sy,
bool
BitMapWin::oGetTextExtent(char *text, int cb, int *width, int *height)
{
- SIZE TextExtent;
- double si, csi, d;
+ return com_oGetTextExtent(text, cb, width, height, memDC, &TxtSet);
+}
- if(!text) return false;
- if(!GetTextExtentPoint32(memDC, text, cb ? cb : (int)strlen(text), &TextExtent))return false;
- if(fabs(TxtSet.RotBL) >0.01) {
- si = fabs(sin(TxtSet.RotBL * 0.01745329252)); csi = fabs(cos(TxtSet.RotBL * 0.01745329252));
- d = si > csi ? 1.0/si : 1.0/csi;
- d = (TextExtent.cx * ((7.0 + d)/8.0));
- TextExtent.cx = iround(d);
- }
- *width = TextExtent.cx; *height = TextExtent.cy;
- return true;
+bool
+BitMapWin::oGetTextExtentW(w_char *text, int cb, int *width, int *height)
+{
+ return com_oGetTextExtentW(text, cb, width, height, memDC, &TxtSet);
}
bool
@@ -1004,7 +1086,13 @@ BitMapWin::oSolidLine(POINT *p)
bool
BitMapWin::oTextOut(int x, int y, char *txt, int cb)
{
- return com_oTextOut(x, y, txt, cb, &hFont, &memDC, &TxtSet, isWIN95, this);
+ return com_oTextOut(x, y, txt, cb, &hFont, &memDC, &TxtSet, this);
+}
+
+bool
+BitMapWin::oTextOutW(int x, int y, w_char *txt, int cb)
+{
+ return com_oTextOutW(x, y, txt, cb, &hFont, &memDC, &TxtSet, this);
}
bool
@@ -1018,12 +1106,6 @@ BitMapWin::oPolygon(POINT *pts, int cp, char *nam)
return false;
}
-bool
-BitMapWin::oArc(int x1, int y1, int x2, int y2, int quads)
-{
- return com_Arc(memDC, x1, y1, x2, y2, quads);
-}
-
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Output to windows window
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1033,6 +1115,7 @@ OutputWin::OutputWin(GraphObj *g, HWND hw):BitMapWin(g, hw)
if(g) {
if(!hw) CreateNewWindow(g);
else hWnd = hw;
+ if(!MainWnd) MainWnd = hWnd;
}
else { //its a dialog window
hWnd = hw;
@@ -1050,7 +1133,7 @@ OutputWin::~OutputWin()
bool
OutputWin::ActualSize(RECT *rc)
{
- if(GetClientRect(hWnd, rc)) return true;
+ if(GetClientRect(hWnd, rc)&& (rc->right-rc->left) > 40 && (rc->bottom - rc->top) > 40) return true;
return false;
}
@@ -1176,12 +1259,14 @@ OutputWin::MouseCursor(int cid, bool force)
switch(cid) {
case MC_ARROW:
hoc = SetCursor(LoadCursor(NULL, IDC_ARROW)); break;
+ case MC_TXTFRM:
case MC_CROSS: hoc = SetCursor(LoadCursor(NULL, IDC_CROSS)); break;
case MC_WAIT:
hoc = SetCursor(LoadCursor(NULL, IDC_WAIT)); break;
case MC_TEXT: hoc = SetCursor(LoadCursor(NULL, IDC_IBEAM)); break;
case MC_NORTH: hoc = SetCursor(LoadCursor(NULL, IDC_SIZENS)); break;
case MC_NE: hoc = SetCursor(LoadCursor(NULL, IDC_SIZENESW));break;
+ case MC_COLWIDTH:
case MC_EAST: hoc = SetCursor(LoadCursor(NULL, IDC_SIZEWE)); break;
case MC_SE: hoc = SetCursor(LoadCursor(NULL, IDC_SIZENWSE));break;
case MC_SALL: hoc = SetCursor(LoadCursor(NULL, IDC_SIZEALL)); break;
@@ -1431,16 +1516,18 @@ OutputWin::CreateNewWindow(void *g)
// Copy to Clipboard
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create Windows Meta File for clipboard
-WinCopyWMF::WinCopyWMF(GraphObj *g)
+WinCopyWMF::WinCopyWMF(GraphObj *g, char *file_wmf, char *file_emf)
{
- DeskRect.left = DeskRect.top = 0;
- DeskRect.right = DeskRect.bottom = 0x4fffffffL;
- hPen = CreatePen(PS_SOLID, 1, dLineCol = 0x00ffffffL);
+ HDC dc;
+ HWND hwndDesk;
+
+ DeskRect.left = DeskRect.top = 0; DeskRect.right = DeskRect.bottom = 0x4fffffffL;
+ hPen = CreatePen(PS_SOLID, 1, dLineCol = 0x00ff0000L);
hBrush = CreateSolidBrush(dFillCol =dBgCol = 0x00ffffffL);
- dPattern = 0L;
- go = g;
- hgo = 0L;
- hres = vres = 1000.0;
+ dPattern = 0L; go = g; hgo = 0L; bott_y = 0;
+ dc = GetDC(hwndDesk = GetDesktopWindow());
+ hres = (double)GetDeviceCaps(dc, LOGPIXELSX); vres = (double)GetDeviceCaps(dc, LOGPIXELSY);
+ ReleaseDC(hwndDesk, dc); wmf_file = file_wmf; emf_file = file_emf;
}
WinCopyWMF::~WinCopyWMF()
@@ -1456,7 +1543,7 @@ WinCopyWMF::SetLine(LineDEF *lDef)
{
int iw;
HPEN newPen;
-
+
if(!hPen || lDef->width != LineWidth || lDef->width != LineWidth ||
lDef->pattern != dPattern || lDef->color != dLineCol) {
LineWidth = lDef->width;
@@ -1503,59 +1590,104 @@ WinCopyWMF::SetFill(FillDEF *fill)
bool
WinCopyWMF::SetTextSpec(TextDEF *set)
{
- return com_SetTextSpec(set, this, &hFont, &TxtSet, &hdc, true);
+ return com_SetTextSpec(set, this, &hFont, &TxtSet, &hdc);
+}
+
+bool
+WinCopyWMF::oGetTextExtent(char *text, int cb, int *width, int *height)
+{
+ return com_oGetTextExtent(text, cb, width, height, hdc, &TxtSet);
+}
+
+bool
+WinCopyWMF::oGetTextExtentW(w_char *text, int cb, int *width, int *height)
+{
+ return com_oGetTextExtentW(text, cb, width, height, hdc, &TxtSet);
}
bool
WinCopyWMF::StartPage()
{
int w, h;
-
+ RECT rect;
+ double res;
if(!go) return false;
- w = un2ix(go->GetSize(SIZE_GRECT_RIGHT) - go->GetSize(SIZE_GRECT_LEFT));
- h = un2iy(go->GetSize(SIZE_GRECT_BOTTOM) - go->GetSize(SIZE_GRECT_TOP));
- w++; h++;
- if(!(hdc = CreateMetaFile(NULL))) return false;
- if(hPen)SelectObject(hdc, hPen);
- if(hBrush) SelectObject(hdc, hBrush);
- VPorg.fy = -co2fiy(go->GetSize(SIZE_GRECT_TOP));
+ res = Units[defs.cUnits].convert;
+ w = iround(hres*res*(go->GetSize(SIZE_GRECT_RIGHT) - go->GetSize(SIZE_GRECT_LEFT)));
+ h = iround(vres*res*(go->GetSize(SIZE_GRECT_BOTTOM) - go->GetSize(SIZE_GRECT_TOP)));
+ rect.left = rect.top = 0;
+ rect.bottom = h+560; rect.right = w+720;
+ if(!(hdc = CreateEnhMetaFile(0L, emf_file, &rect, "RLPlot")))return false;
+ if(SetMapMode(hdc, MM_HIMETRIC)) {
+ hres = vres = 2540.0; OC_type = OC_HIMETRIC;
+ bott_y = un2iy(go->GetSize(SIZE_GRECT_TOP) - go->GetSize(SIZE_GRECT_BOTTOM));
+ VPorg.fy = bott_y;
+ }
+ else return false;
+ if(hPen)SelectObject(hdc, hPen); if(hBrush) SelectObject(hdc, hBrush);
VPorg.fx = -co2fix(go->GetSize(SIZE_GRECT_LEFT));
- SetMapMode(hdc, MM_HIENGLISH);
- SetWindowExtEx(hdc, w, h, 0L);
- SetWindowOrgEx(hdc, 0, 0, 0L);
return true;
}
bool
WinCopyWMF::EndPage()
{
- HMETAFILE hmf;
- HGLOBAL hGMem;
- LPMETAFILEPICT pMFP;
-
- hmf = CloseMetaFile(hdc);
- hGMem = GlobalAlloc(GHND, sizeof(METAFILEPICT));
- pMFP = (LPMETAFILEPICT)GlobalLock(hGMem);
- pMFP->mm = MM_ANISOTROPIC;
- pMFP->xExt = (long)(Box1.Xmax+Box1.Xmin);
- pMFP->yExt = (long)(Box1.Ymax+Box1.Ymin);
- pMFP->hMF = hmf;
- GlobalUnlock(hGMem);
- // We do not open the Clipboard because we are responding to WM_RENDERFORMAT
- SetClipboardData(CF_METAFILEPICT, hGMem);
+ int iFile;
+ HENHMETAFILE hmf;
+ unsigned int cb;
+ unsigned char *buff;
+ HDC dc;
+
+ hmf = CloseEnhMetaFile(hdc);
+ if(emf_file); // nothing more to do
+ else if(wmf_file) {
+ dc = GetDC(MainWnd);
+ cb = GetWinMetaFileBits(hmf, 0, 0L, MM_HIMETRIC, dc);
+ if(cb && (buff = (unsigned char*)malloc(cb+1))){
+#ifdef USE_WIN_SECURE
+ if(_sopen_s(&iFile, wmf_file, O_RDWR | O_BINARY | O_CREAT | O_TRUNC,
+ 0x40, S_IWRITE) || iFile < 0){
+ ErrorBox("Open failed for metafile");
+ free(buff); return false;
+ }
+#else
+ if(-1 ==(iFile = open(wmf_file, O_RDWR | O_BINARY | O_CREAT | O_TRUNC,
+ S_IWRITE | S_IREAD))){
+ ErrorBox("Open failed for metafile");
+ free(buff); return false;
+ }
+#endif
+ if(cb = GetWinMetaFileBits(hmf, cb, buff, MM_HIMETRIC, dc)){
+#ifdef USE_WIN_SECURE
+ _write(iFile, buff, cb);
+ _close(iFile);
+#else
+ write(iFile, buff, cb);
+ close(iFile);
+#endif
+ }
+ free(buff);
+ }
+ ReleaseDC(MainWnd, dc);
+ }
+ else SetClipboardData(CF_ENHMETAFILE, hmf);
+ DeleteEnhMetaFile(hmf);
return true;
}
bool
-WinCopyWMF::oCircle(int x1, int y1, int x2, int y2, char* nam)
+WinCopyWMF::oCircle(int ix1, int iy1, int ix2, int iy2, char* nam)
{
+ int x1=ix1, x2=ix2, y1, y2;
BOOL RetVal;
+ y1 = bott_y - iy1; y2 = bott_y - iy2;
+ if(x2 > x1) x2 = ix2 + 25; else x1 = ix1 + 25;
+ if(y1 > y2) y2 -= 25; else y1 -=25;
RetVal = Ellipse(hdc, x1, y1, x2, y2);
if(RetVal && hgo) return hgo->oCircle(x1, y1, x2, y2);
- else if(RetVal) return true;
- return false;
+ return RetVal != 0;
}
bool
@@ -1564,31 +1696,32 @@ WinCopyWMF::oPolyline(POINT * pts, int cp, char *nam)
int i;
if(cp < 1) return false;
+ for (i = 0; i < cp; i++) pts[i].y = bott_y - pts[i].y;
if (dPattern) {
for (i = 1; i < cp; i++) PatLine(pts[i-1], pts[i]);
return true;
}
- else {
- if(Polyline(hdc, pts, cp))return true;
- else return false;
- }
- return false;
+ return (0 != Polyline(hdc, pts, cp));
}
bool
-WinCopyWMF::oRectangle(int x1, int y1, int x2, int y2, char *name)
+WinCopyWMF::oRectangle(int ix1, int iy1, int ix2, int iy2, char *name)
{
+ int x1=ix1, x2=ix2, y1, y2;
BOOL RetVal;
+ y1 = bott_y - iy1; y2 = bott_y - iy2;
+ if(x2 > x1) x2 = ix2 + 25; else x1 = ix1 + 25;
+ if(y1 > y2) y2 -= 25; else y1 -=25;
RetVal = Rectangle(hdc, x1, y1, x2, y2);
- if(RetVal && hgo) return hgo->oRectangle(x1, y1, x2, y2, 0L);
- else if (RetVal) return true;
- return false;
+ if(RetVal && hgo) return hgo->oRectangle(ix1, iy1, ix2, iy2, 0L);
+ return RetVal != 0;
}
bool
WinCopyWMF::oSolidLine(POINT *p)
{
+ p[0].y = bott_y - p[0].y; p[1].y = bott_y - p[1].y;
if(Polyline(hdc, p, 2)) return true;
return false;
}
@@ -1596,24 +1729,30 @@ WinCopyWMF::oSolidLine(POINT *p)
bool
WinCopyWMF::oTextOut(int x, int y, char *txt, int cb)
{
- return com_oTextOut(x, y, txt, cb, &hFont, &hdc, &TxtSet, true, this);
+ y = bott_y - y;
+ return com_oTextOut(x, y, txt, cb, &hFont, &hdc, &TxtSet, this);
}
bool
-WinCopyWMF::oPolygon(POINT *pts, int cp, char *nam)
+WinCopyWMF::oTextOutW(int x, int y, w_char *txt, int cb)
{
- BOOL RetVal;
-
- RetVal = Polygon(hdc, pts, cp);
- if(RetVal && hgo) return hgo->oPolygon(pts, cp);
- else if (RetVal) return true;
- return false;
+ y = bott_y - y;
+ return com_oTextOutW(x, y, txt, cb, &hFont, &hdc, &TxtSet, this);
}
bool
-WinCopyWMF::oArc(int x1, int y1, int x2, int y2, int quads)
+WinCopyWMF::oPolygon(POINT *pts, int cp, char *nam)
{
- return com_Arc(hdc, x1, y1, x2, y2, quads);
+ int i;
+ BOOL RetVal;
+
+ for (i = 0; i < cp; i++) pts[i].y = bott_y - pts[i].y;
+ RetVal = Polygon(hdc, pts, cp);
+ if(RetVal && hgo) {
+ for (i = 0; i < cp; i++) pts[i].y = - pts[i].y + bott_y ;
+ return hgo->oPolygon(pts, cp);
+ }
+ return (RetVal != 0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1729,7 +1868,19 @@ PrintWin::SetFill(FillDEF *fill)
bool
PrintWin::SetTextSpec(TextDEF *set)
{
- return com_SetTextSpec(set, this, &hFont, &TxtSet, &hDC, isWIN95);
+ return com_SetTextSpec(set, this, &hFont, &TxtSet, &hDC);
+}
+
+bool
+PrintWin::oGetTextExtent(char *text, int cb, int *width, int *height)
+{
+ return com_oGetTextExtent(text, cb, width, height, hDC, &TxtSet);
+}
+
+bool
+PrintWin::oGetTextExtentW(w_char *text, int cb, int *width, int *height)
+{
+ return com_oGetTextExtentW(text, cb, width, height, hDC, &TxtSet);
}
bool
@@ -1827,7 +1978,13 @@ PrintWin::oSolidLine(POINT *p)
bool
PrintWin::oTextOut(int x, int y, char *txt, int cb)
{
- return com_oTextOut(x, y, txt, cb, &hFont, &hDC, &TxtSet, isWIN95, this);
+ return com_oTextOut(x, y, txt, cb, &hFont, &hDC, &TxtSet, this);
+}
+
+bool
+PrintWin::oTextOutW(int x, int y, w_char *txt, int cb)
+{
+ return com_oTextOutW(x, y, txt, cb, &hFont, &hDC, &TxtSet, this);
}
bool
@@ -1841,21 +1998,13 @@ PrintWin::oPolygon(POINT *pts, int cp, char *nam)
return false;
}
-bool
-PrintWin::oArc(int x1, int y1, int x2, int y2, int quads)
-{
- return com_Arc(hDC, x1, y1, x2, y2, quads);
-}
-
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Find a suitable www browser
void FindBrowser()
{
char text[600];
long size = 599;
- HDC dc;
HKEY hdl;
- HWND hwnd;
int i;
//find the default browser
@@ -1909,11 +2058,6 @@ void FindBrowser()
GetProfileString("intl", "sList", ".", text, 2);
if(text[0]) defs.ColSep[0] = text[0];
if(GetProfileInt("intl", "iMeasure", 0)) defs.dUnits = defs.cUnits = 2;
- //test if windows95
- dc = GetDC(hwnd = GetDesktopWindow());
- isWIN95 = (0 == SetGraphicsMode(dc, GM_ADVANCED));
- SetGraphicsMode(dc, GM_COMPATIBLE);
- ReleaseDC(hwnd, dc);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1925,6 +2069,8 @@ int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInstance,
WNDCLASS wndclass;
MSG msg;
DefsRW *drw;
+ HWND hwnd;
+ HDC dc;
//OS dependent initialization
dlgtxtheight = 16;
@@ -1952,9 +2098,14 @@ int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInstance,
wndclass.lpszClassName = name;
RegisterClass(&wndclass);
- ShowBanner(true);
- InitTextCursor(true);
- Printer = new PrintWin();
+ dc = GetDC(hwnd = GetDesktopWindow());
+ if(0 == SetGraphicsMode(dc, GM_ADVANCED)){
+ ErrorBox("RLPlot detected an\nold version of Windows which\nis no longer supported!\n");
+ return 1;
+ }
+ SetGraphicsMode(dc, GM_COMPATIBLE);
+ ReleaseDC(hwnd, dc); ShowBanner(true);
+ InitTextCursor(true); Printer = new PrintWin();
accel = LoadAccelerators(hInstance, MAKEINTRESOURCE(ACCELERATORS_1));
while(GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
@@ -2004,13 +2155,14 @@ void CopyData(GraphObj *g, unsigned int cf)
}
}
-void CopyGraph(GraphObj *g, unsigned int cf)
+void CopyGraph(GraphObj *g, unsigned int cf, anyOutput *o)
{
HGLOBAL hmem;
char *dt, *buf;
long cb;
if(!(dt = GraphToMem(g, &cb)))return;
+ if(o) ShowCopyMark(o, &g->rDims, 1);
if(hmem = GlobalAlloc(GMEM_MOVEABLE, cb+1)) {
if(buf = (char *)GlobalLock(hmem)) {
memcpy(buf, dt, cb);
@@ -2029,10 +2181,10 @@ void ScrollEvent(bool bVert, HWND hwnd, UINT type, GraphObj *g, OutputWin *w)
if(hwnd && g && w) {
cmd = bVert ? CMD_SETVPOS : CMD_SETHPOS;
- LineStep = g->Id == GO_GRAPH ? 8 : 1;
si.fMask = SIF_ALL;
si.cbSize = sizeof(SCROLLINFO);
if(!(GetScrollInfo(hwnd, bVert ? SB_VERT : SB_HORZ, &si)))return;
+ LineStep = (g->Id == GO_GRAPH || g->Id == GO_PAGE) ? 16 : 1;
switch(type){
case SB_LINEUP:
pos = si.nPos - LineStep;
@@ -2090,7 +2242,8 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
{
static WinCopyWMF *CopyWMF = NULL;
static BitMapWin *CopyBMP = NULL;
- static bool CtrlDown = false;
+ static bool CtrlDown = false, bAltKey = false;
+ static w_char uc_char;
PAINTSTRUCT ps;
OutputWin *w;
GraphObj *g;
@@ -2123,9 +2276,12 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
else if(message == WM_MOUSEMOVE)mev.Action = MOUSE_MOVE;
g->Command(CMD_MOUSE_EVENT, (void *)&mev, w);
break;
+ case 0x020A: //WM_MOUSEWHEEL
+ ScrollEvent(true, hwnd, (int)wParam > 0 ? SB_LINEUP : SB_LINEDOWN, g, w);
+ return 0;
case WM_KEYDOWN:
+ cc = (wParam & 0xff);
if(g && w && (GetKeyState(VK_LCONTROL) || GetKeyState(VK_RCONTROL))){
- cc = (wParam & 0xff);
if(cc == 0xbb || cc == 0x6b ) g->Command(CMD_ZOOM, &"+", w);
else if(cc == 0xbd || cc == 0x6d ) g->Command(CMD_ZOOM, &"-", w);
else break;
@@ -2134,8 +2290,36 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
break;
case WM_CHAR:
cc = (wParam & 0xff);
+ if(bAltKey && uc_char) {
+ if(uc_char >=255) {
+ g->Command(CMD_ADDCHARW, (void *)(& uc_char), w);
+ uc_char = 0; bAltKey = false;
+ return 0;
+ }
+ else cc = (int)uc_char;
+ uc_char = 0; bAltKey = false;
+ }
g->Command(CMD_ADDCHAR, (void *)(& cc), w);
return 0;
+ case WM_SYSKEYDOWN:
+ if(wParam == VK_MENU) {
+ bAltKey = true; uc_char = 0;
+ }
+ break;
+ case WM_SYSKEYUP:
+ if(wParam == VK_MENU) bAltKey = false;
+ if(bAltKey) {
+ cc = (wParam & 0xff);
+ if( cc >= 0x60 && cc <= 0x69) {
+ uc_char *= 10; uc_char += (cc-0x60);
+ return 0;
+ }
+ else {
+ uc_char = 0; bAltKey = false;
+ return 0;
+ }
+ }
+ break;
case WM_VSCROLL: case WM_HSCROLL:
ScrollEvent(message == WM_VSCROLL, hwnd, wParam & 0xffff, g, w);
return 0;
@@ -2143,8 +2327,6 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
switch(message) {
case WM_CREATE:
- //assume that the first window created is the main window
- if(!MainWnd) MainWnd = hwnd;
break;
case WM_SIZE:
if(g && w) g->Command(CMD_SETSCROLL, 0L, w);
@@ -2170,8 +2352,8 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
return 0;
case WM_RENDERFORMAT:
if(g && w) switch(wParam){
- case CF_METAFILEPICT:
- CopyWMF = new WinCopyWMF(copy_obj);
+ case CF_ENHMETAFILE:
+ CopyWMF = new WinCopyWMF(copy_obj, 0L, 0L);
if(CopyWMF && CopyWMF->StartPage()) {
copy_obj->DoPlot(CopyWMF);
CopyWMF->EndPage();
@@ -2192,7 +2374,7 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
if(g->Id == GO_SPREADDATA) CopyData(g, wParam);
break;
default:
- if(wParam == cf_rlpgraph) CopyGraph(copy_obj, wParam);
+// if(wParam == cf_rlpgraph) CopyGraph(copy_obj, wParam, w);
if(wParam == cf_rlpxml) CopyData(g, wParam);
break;
}
@@ -2218,7 +2400,7 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
}
g->Command(CMD_MOUSECURSOR, 0L, w);
return 0;
- case CM_COPY: case CM_CUT:
+ case CM_COPY: case CM_CUT: case CM_COPYGRAPH:
EmptyClip();
if(g->Id != GO_SPREADDATA && CurrGO && CurrGO->Id == GO_TEXTFRAME) {
if(CurrGO->Command(CMD_COPY, 0L, w))return 0;
@@ -2230,32 +2412,29 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
SetClipboardData(cf_rlpxml, NULL);
}
else if(g->Id == GO_PAGE) {
- SetClipboardData(CF_METAFILEPICT, NULL);
+ SetClipboardData(CF_ENHMETAFILE, NULL);
+ SetClipboardData(CF_BITMAP, NULL);
+ if(CurrGraph) {
+ CopyGraph(CurrGraph, cf_rlpobj, w); copy_obj = CurrGraph;
+ }
+ }
+ else if(CurrGraph && CurrGraph->Id == GO_GRAPH){
+ SetClipboardData(CF_ENHMETAFILE, NULL);
+ SetClipboardData(CF_BITMAP, NULL);
+ CopyGraph(CurrGraph, cf_rlpobj, w); copy_obj = CurrGraph;
+ }
+ else if(g->Id == GO_GRAPH){
+ SetClipboardData(CF_ENHMETAFILE, NULL);
SetClipboardData(CF_BITMAP, NULL);
- SetClipboardData(cf_rlpgraph, NULL);
- if(g->Id == GO_PAGE && CurrGraph) CopyGraph(CurrGraph, cf_rlpobj);
- copy_obj = g;
+ CopyGraph(g, cf_rlpobj, w); copy_obj = g;
}
CloseClipboard();
return 0;
case CM_UPDATE:
g->Command(CMD_UPDATE, 0L, w);
return 0;
- case CM_COPYGRAPH:
- EmptyClip();
- if(CurrGO && CurrGO->Id == GO_TEXTFRAME) {
- if(CurrGO->Command(CMD_COPY, 0L, w))return 0;
- }
- OpenClipboard(GetFocus());
- SetClipboardData(CF_METAFILEPICT, NULL);
- SetClipboardData(CF_BITMAP, NULL);
- SetClipboardData(cf_rlpgraph, NULL);
- if(g->Id == GO_PAGE && CurrGraph) CopyGraph(CurrGraph, cf_rlpobj);
- copy_obj = g;
- CloseClipboard();
- return 0;
case CM_OPEN:
- g->Command(CMD_OPEN, (void *)NULL, w);
+ g->Command(CMD_OPEN, 0L, w);
return 0;
case CM_FILE1: case CM_FILE2: case CM_FILE3:
case CM_FILE4: case CM_FILE5: case CM_FILE6:
@@ -2433,15 +2612,27 @@ long FAR PASCAL WndProc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
case CM_DELCOL:
g->Command(CMD_DELCOL, 0L, w);
return 0;
+ case CM_SMPLSTAT:
+ if(g->data) rep_samplestats(g, g->data);
+ return 0;
case CM_REPCMEANS:
if(g->data) rep_compmeans(g, g->data);
return 0;
case CM_REPANOV:
if(g->data) rep_anova(g, g->data);
return 0;
+ case CM_REPKRUSKAL:
+ if(g->data) rep_kruskal(g, g->data);
+ return 0;
case CM_REPREGR:
if(g->data) rep_regression(g, g->data);
return 0;
+ case CM_CORRELM:
+ if(g->data) rep_correl(g, g->data, 0);
+ return 0;
+ case CM_CORRELT:
+ if(g->data) rep_correl(g, g->data, 1);
+ return 0;
case CM_REPTWOWAY:
if(g->data) rep_twowaytable(g, g->data);
return 0;
diff --git a/WinSpec.h b/WinSpec.h
index 50a0c99..aaa60b8 100755
--- a/WinSpec.h
+++ b/WinSpec.h
@@ -38,6 +38,7 @@ public:
bool CopyBitmap(int x, int y, anyOutput* src, int sx, int sy,
int sw, int sh, bool invert);
bool oGetTextExtent(char *text, int cb, int *width, int *height);
+ bool oGetTextExtentW(w_char *text, int cb, int *width, int *height);
bool oGetPix(int x, int y, DWORD *col);
bool oDrawIcon(int type, int x, int y);
bool oCircle(int x1, int y1, int x2, int y2, char* nam = 0L);
@@ -45,8 +46,8 @@ public:
bool oRectangle(int x1, int y1, int x2, int y2, char* nam = 0L);
bool oSolidLine(POINT *p);
bool oTextOut(int x, int y, char *txt, int cb);
+ bool oTextOutW(int x, int y, w_char *txt, int cb);
bool oPolygon(POINT *pts, int cp, char *nam = 0L);
- bool oArc(int x1, int y1, int x2, int y2, int quads);
};
class OutputWin:public BitMapWin{
@@ -79,11 +80,13 @@ private:
class WinCopyWMF:public anyOutput {
public:
- WinCopyWMF(GraphObj *g);
+ WinCopyWMF(GraphObj *g, char* file_wmf, char *file_emf);
~WinCopyWMF();
bool SetLine(LineDEF *lDef);
bool SetFill(FillDEF *fill);
bool SetTextSpec(TextDEF *set);
+ bool oGetTextExtent(char *text, int cb, int *width, int *height);
+ bool oGetTextExtentW(w_char *text, int cb, int *width, int *height);
bool StartPage();
bool EndPage();
bool oCircle(int x1, int y1, int x2, int y2, char* nam = 0L);
@@ -91,16 +94,18 @@ public:
bool oRectangle(int x1, int y1, int x2, int y2, char *nam = 0L);
bool oSolidLine(POINT *p);
bool oTextOut(int x, int y, char *txt, int cb);
+ bool oTextOutW(int x, int y, w_char *txt, int cb);
bool oPolygon(POINT *pts, int cp, char *nam = 0L);
- bool oArc(int x1, int y1, int x2, int y2, int quads);
private:
+ int bott_y;
GraphObj *go;
HDC hdc;
HPEN hPen;
HBRUSH hBrush;
HFONT hFont;
HatchOut *hgo;
+ char *wmf_file, *emf_file;
};
class PrintWin:public anyOutput{
@@ -110,6 +115,8 @@ public:
bool SetLine(LineDEF *lDef);
bool SetFill(FillDEF *fill);
bool SetTextSpec(TextDEF *set);
+ bool oGetTextExtent(char *text, int cb, int *width, int *height);
+ bool oGetTextExtentW(w_char *text, int cb, int *width, int *height);
bool StartPage();
bool EndPage();
bool Eject();
@@ -118,8 +125,8 @@ public:
bool oRectangle(int x1, int y1, int x2, int y2, char *nam = 0L);
bool oSolidLine(POINT *p);
bool oTextOut(int x, int y, char *txt, int cb);
+ bool oTextOutW(int x, int y, w_char *txt, int cb);
bool oPolygon(POINT *pts, int cp, char *nam = 0L);
- bool oArc(int x1, int y1, int x2, int y2, int quads);
private:
HPEN hPen;
diff --git a/menu.h b/menu.h
index 8e02c7f..dd3e9e9 100755
--- a/menu.h
+++ b/menu.h
@@ -1,4 +1,4 @@
-//menu.h, (C) 2006 R.Lackner
+//menu.h, (C) 2006, 2007 R.Lackner
//
// This file is part of RLPlot.
//
@@ -92,8 +92,11 @@
#define CM_SHPGUP 615
#define CM_SHPGDOWN 616
-#define CM_REPCMEANS 650
-#define CM_REPANOV 651
-#define CM_REPREGR 652
-#define CM_REPTWOWAY 653
-
+#define CM_SMPLSTAT 650
+#define CM_REPCMEANS 651
+#define CM_REPANOV 652
+#define CM_REPKRUSKAL 653
+#define CM_REPREGR 654
+#define CM_CORRELM 655
+#define CM_CORRELT 656
+#define CM_REPTWOWAY 657
diff --git a/mfcalc.cpp b/mfcalc.cpp
index 9d20746..a7da92b 100644
--- a/mfcalc.cpp
+++ b/mfcalc.cpp
@@ -10,51 +10,60 @@
#define ARR 260
#define BLOCK 261
#define PBLOCK 262
-#define PI 263
-#define E 264
-#define CLVAL 265
-#define PSEP 266
-#define IF 267
-#define ELSE 268
-#define BTRUE 269
-#define BFALSE 270
-#define DATE1 271
-#define TIME1 272
-#define DATETIME1 273
-#define DIM 274
-#define WHILE 275
-#define VAR 276
-#define FNCT 277
-#define BFNCT 278
-#define AFNCT 279
-#define SFNCT 280
-#define FUNC1 281
-#define FUNC2 282
-#define FUNC3 283
-#define TXT 284
-#define SRFUNC 285
-#define YYFNC 286
-#define FUNC4 287
-#define YYFNC2 288
-#define YYFNC3 289
-#define CLAUSE 290
-#define SER 291
-#define COLR 292
-#define COLC 293
-#define AND 294
-#define OR 295
-#define EQ 296
-#define NE 297
-#define GT 298
-#define GE 299
-#define LT 300
-#define LE 301
-#define NEG 302
-#define INC 303
-#define DEC 304
-#define PINC 305
-#define PDEC 306
-#define PDIM 307
+#define IBLOCK 263
+#define PI 264
+#define E 265
+#define CLVAL 266
+#define PSEP 267
+#define IF 268
+#define ELSE 269
+#define BTRUE 270
+#define BFALSE 271
+#define DATE1 272
+#define TIME1 273
+#define DATETIME1 274
+#define DIM 275
+#define WHILE 276
+#define FOR 277
+#define INARR 278
+#define RANGEARR 279
+#define RETURN 280
+#define BREAK 281
+#define VAR 282
+#define FNCT 283
+#define BFNCT 284
+#define AFNCT 285
+#define SFNCT 286
+#define FUNC1 287
+#define FUNC2 288
+#define FUNC3 289
+#define TXT 290
+#define SRFUNC 291
+#define YYFNC 292
+#define FUNC4 293
+#define YYFNC2 294
+#define YYFNC3 295
+#define ADDEQ 296
+#define SUBEQ 297
+#define MULEQ 298
+#define DIVEQ 299
+#define CLAUSE 300
+#define SER 301
+#define COLC 302
+#define AND 303
+#define OR 304
+#define EQ 305
+#define NE 306
+#define GT 307
+#define GE 308
+#define LT 309
+#define LE 310
+#define NEG 311
+#define INC 312
+#define DEC 313
+#define PINC 314
+#define PDEC 315
+#define PDIM 316
/*
@@ -128,7 +137,8 @@ typedef struct{
}YYSTYPE;
-static int yy_maxiter = 1000;
+static int yy_maxiter = 100000; //maximum loop count
+static int block_res; //result of eval()
static symrec *putsym (unsigned int h_name, unsigned int h2_name, int sym_type);
static symrec *getsym (unsigned int h_name, unsigned int h2_name, char *sym_name = 0L);
@@ -139,7 +149,7 @@ static double *PushArray(double *arr);
static double *ReallocArray(double *arr, int size);
static char *add_strings(char *st1, char *st2);
static char *string_value(YYSTYPE *exp);
-static void eval(YYSTYPE *dst, YYSTYPE *sr);
+static int eval(YYSTYPE *dst, YYSTYPE *sr);
static int range_array(YYSTYPE * res, char *range);
static int range_array2(YYSTYPE *res1, YYSTYPE *res2);
static void exec_clause(YYSTYPE *res);
@@ -148,9 +158,10 @@ static void yyerror(char *s);
static void make_time(YYSTYPE *dst, double h, double m, double s);
static int yylex(void);
static double nop() {return 0.0;};
+static double for_loop(char *block1, char *block2);
static char res_txt[1000];
-static anyResult line_res = {ET_UNKNOWN, 0.0, res_txt};
+static anyResult line_res = {ET_UNKNOWN, 0.0, res_txt, 0L, 0};
static DataObj *curr_data;
static char *last_error = 0L; //error text
static char *last_err_desc = 0L; //short error description
@@ -170,23 +181,23 @@ static int parse_level = 0; //count reentrances into parser
-#define YYFINAL 269
+#define YYFINAL 260
#define YYFLAG -32768
-#define YYNTBASE 69
+#define YYNTBASE 78
-#define YYTRANSLATE(x) ((unsigned)(x) <= 307 ? yytranslate[x] : 76)
+#define YYTRANSLATE(x) ((unsigned)(x) <= 316 ? yytranslate[x] : 87)
static const char yytranslate[] = { 0,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 63,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 72,
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, 65,
- 66, 53, 52, 37, 51, 2, 54, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 68, 64, 2,
- 36, 2, 42, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 74,
+ 75, 62, 61, 47, 60, 2, 63, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 77, 73, 2,
+ 42, 2, 51, 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,
- 55, 2, 67, 56, 2, 2, 2, 2, 2, 2,
+ 64, 2, 76, 65, 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,
@@ -205,98 +216,98 @@ static const char yytranslate[] = { 0,
2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
- 27, 28, 29, 30, 31, 32, 33, 34, 35, 38,
- 39, 40, 41, 43, 44, 45, 46, 47, 48, 49,
- 50, 57, 58, 59, 60, 61, 62
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 43, 44, 45, 46, 48,
+ 49, 50, 52, 53, 54, 55, 56, 57, 58, 59,
+ 66, 67, 68, 69, 70, 71
};
#if YYDEBUG != 0
static const short yyprhs[] = { 0,
0, 1, 4, 6, 8, 10, 13, 16, 19, 22,
- 25, 28, 30, 34, 38, 42, 47, 54, 61, 68,
- 75, 77, 81, 83, 85, 89, 93, 95, 99, 101,
- 106, 108, 110, 114, 118, 122, 126, 130, 134, 138,
- 142, 144, 146, 148, 150, 152, 154, 156, 158, 162,
- 166, 171, 176, 183, 192, 197, 202, 209, 216, 223,
- 230, 237, 244, 251, 258, 265, 274, 281, 290, 301,
- 308, 312, 317, 324, 331, 338, 345, 354, 363, 372,
- 381, 390, 399, 408, 417, 423, 431, 435, 439, 443,
- 447, 451, 454, 457, 460, 463, 467, 470, 474, 480,
- 485, 492, 498, 504, 508, 512, 518, 524, 530
+ 25, 29, 35, 39, 43, 46, 48, 51, 53, 57,
+ 61, 65, 70, 77, 84, 91, 98, 100, 102, 104,
+ 108, 112, 114, 118, 120, 125, 127, 129, 133, 137,
+ 141, 145, 149, 153, 157, 161, 163, 165, 167, 169,
+ 171, 173, 175, 177, 179, 181, 183, 185, 187, 191,
+ 195, 199, 203, 207, 211, 216, 221, 228, 237, 242,
+ 247, 254, 261, 268, 275, 282, 289, 296, 303, 310,
+ 319, 326, 335, 346, 353, 360, 364, 369, 376, 381,
+ 390, 394, 398, 402, 406, 409, 412, 415, 418, 422,
+ 425, 429, 435, 440, 447, 454, 461, 468, 475, 481,
+ 485, 491, 497, 503
};
static const short yyrhs[] = { -1,
- 69, 70, 0, 63, 0, 64, 0, 37, 0, 75,
- 63, 0, 75, 64, 0, 75, 37, 0, 71, 63,
- 0, 71, 64, 0, 1, 63, 0, 5, 0, 71,
- 52, 75, 0, 75, 52, 71, 0, 71, 52, 71,
- 0, 31, 65, 75, 66, 0, 31, 65, 75, 12,
- 71, 66, 0, 31, 65, 75, 12, 75, 66, 0,
- 31, 65, 75, 37, 71, 66, 0, 31, 65, 75,
- 37, 75, 66, 0, 71, 0, 22, 40, 22, 0,
- 6, 0, 75, 0, 73, 37, 73, 0, 73, 38,
- 75, 0, 72, 0, 3, 39, 3, 0, 4, 0,
- 24, 65, 75, 66, 0, 15, 0, 16, 0, 75,
- 43, 75, 0, 75, 44, 75, 0, 75, 45, 75,
- 0, 75, 46, 75, 0, 75, 47, 75, 0, 75,
- 48, 75, 0, 75, 49, 75, 0, 75, 50, 75,
- 0, 3, 0, 74, 0, 30, 0, 11, 0, 9,
- 0, 10, 0, 22, 0, 7, 0, 22, 36, 75,
- 0, 22, 36, 71, 0, 23, 65, 75, 66, 0,
- 25, 65, 73, 66, 0, 25, 65, 75, 12, 73,
- 66, 0, 25, 65, 75, 12, 75, 12, 75, 66,
- 0, 26, 65, 71, 66, 0, 26, 65, 75, 66,
- 0, 26, 65, 71, 12, 71, 66, 0, 26, 65,
- 75, 12, 71, 66, 0, 26, 65, 75, 12, 75,
- 66, 0, 26, 65, 71, 12, 75, 66, 0, 26,
- 65, 71, 37, 71, 66, 0, 26, 65, 75, 37,
- 71, 66, 0, 26, 65, 71, 37, 75, 66, 0,
- 26, 65, 75, 37, 75, 66, 0, 28, 65, 72,
- 12, 72, 66, 0, 28, 65, 72, 12, 72, 12,
- 72, 66, 0, 29, 65, 73, 12, 73, 66, 0,
- 29, 65, 73, 12, 73, 12, 72, 66, 0, 33,
- 65, 75, 12, 75, 12, 73, 12, 72, 66, 0,
- 27, 65, 73, 12, 72, 66, 0, 32, 65, 66,
- 0, 32, 65, 73, 66, 0, 34, 65, 75, 12,
- 75, 66, 0, 34, 65, 71, 12, 75, 66, 0,
- 34, 65, 75, 12, 71, 66, 0, 34, 65, 71,
- 12, 71, 66, 0, 35, 65, 71, 12, 71, 12,
- 71, 66, 0, 35, 65, 75, 12, 71, 12, 71,
- 66, 0, 35, 65, 71, 12, 75, 12, 71, 66,
- 0, 35, 65, 71, 12, 71, 12, 75, 66, 0,
- 35, 65, 75, 12, 75, 12, 71, 66, 0, 35,
- 65, 75, 12, 71, 12, 75, 66, 0, 35, 65,
- 71, 12, 75, 12, 75, 66, 0, 35, 65, 75,
- 12, 75, 12, 75, 66, 0, 13, 65, 75, 66,
- 7, 0, 13, 65, 75, 66, 7, 14, 7, 0,
- 21, 8, 7, 0, 75, 52, 75, 0, 75, 51,
- 75, 0, 75, 53, 75, 0, 75, 54, 75, 0,
- 22, 58, 0, 22, 59, 0, 58, 22, 0, 59,
- 22, 0, 75, 56, 75, 0, 51, 75, 0, 65,
- 73, 66, 0, 20, 22, 55, 75, 67, 0, 75,
- 55, 75, 67, 0, 75, 55, 75, 67, 36, 75,
- 0, 3, 40, 3, 40, 3, 0, 3, 68, 3,
- 68, 3, 0, 3, 40, 3, 0, 3, 68, 3,
- 0, 75, 42, 75, 41, 75, 0, 75, 42, 5,
- 41, 5, 0, 75, 42, 5, 41, 75, 0, 75,
- 42, 75, 41, 5, 0
+ 78, 79, 0, 72, 0, 73, 0, 47, 0, 86,
+ 72, 0, 86, 73, 0, 86, 47, 0, 80, 72,
+ 0, 80, 73, 0, 14, 8, 84, 0, 14, 8,
+ 84, 15, 84, 0, 23, 8, 84, 0, 22, 8,
+ 84, 0, 26, 9, 0, 27, 0, 1, 72, 0,
+ 5, 0, 80, 61, 86, 0, 86, 61, 80, 0,
+ 80, 61, 80, 0, 37, 74, 86, 75, 0, 37,
+ 74, 86, 13, 80, 75, 0, 37, 74, 86, 13,
+ 86, 75, 0, 37, 74, 86, 47, 80, 75, 0,
+ 37, 74, 86, 47, 86, 75, 0, 80, 0, 6,
+ 0, 86, 0, 82, 47, 82, 0, 82, 48, 86,
+ 0, 81, 0, 3, 49, 3, 0, 4, 0, 30,
+ 74, 86, 75, 0, 16, 0, 17, 0, 86, 52,
+ 86, 0, 86, 53, 86, 0, 86, 54, 86, 0,
+ 86, 55, 86, 0, 86, 56, 86, 0, 86, 57,
+ 86, 0, 86, 58, 86, 0, 86, 59, 86, 0,
+ 7, 0, 9, 0, 86, 0, 80, 0, 3, 0,
+ 25, 0, 83, 0, 36, 0, 12, 0, 10, 0,
+ 11, 0, 28, 0, 84, 0, 28, 42, 86, 0,
+ 28, 42, 80, 0, 28, 43, 86, 0, 28, 44,
+ 86, 0, 28, 45, 86, 0, 28, 46, 86, 0,
+ 29, 74, 86, 75, 0, 31, 74, 82, 75, 0,
+ 31, 74, 86, 13, 82, 75, 0, 31, 74, 86,
+ 13, 86, 13, 86, 75, 0, 32, 74, 80, 75,
+ 0, 32, 74, 86, 75, 0, 32, 74, 80, 13,
+ 80, 75, 0, 32, 74, 86, 13, 80, 75, 0,
+ 32, 74, 86, 13, 86, 75, 0, 32, 74, 80,
+ 13, 86, 75, 0, 32, 74, 80, 47, 80, 75,
+ 0, 32, 74, 86, 47, 80, 75, 0, 32, 74,
+ 80, 47, 86, 75, 0, 32, 74, 86, 47, 86,
+ 75, 0, 34, 74, 85, 13, 85, 75, 0, 34,
+ 74, 85, 13, 85, 13, 85, 75, 0, 35, 74,
+ 82, 13, 82, 75, 0, 35, 74, 82, 13, 82,
+ 13, 81, 75, 0, 39, 74, 86, 13, 86, 13,
+ 82, 13, 81, 75, 0, 33, 74, 82, 13, 81,
+ 75, 0, 33, 74, 82, 13, 25, 75, 0, 38,
+ 74, 75, 0, 38, 74, 82, 75, 0, 40, 74,
+ 85, 13, 85, 75, 0, 40, 74, 85, 75, 0,
+ 41, 74, 85, 13, 85, 13, 85, 75, 0, 86,
+ 61, 86, 0, 86, 60, 86, 0, 86, 62, 86,
+ 0, 86, 63, 86, 0, 28, 67, 0, 28, 68,
+ 0, 67, 28, 0, 68, 28, 0, 86, 65, 86,
+ 0, 60, 86, 0, 74, 85, 75, 0, 21, 28,
+ 64, 86, 76, 0, 86, 64, 86, 76, 0, 86,
+ 64, 86, 76, 42, 86, 0, 86, 64, 86, 76,
+ 43, 86, 0, 86, 64, 86, 76, 44, 86, 0,
+ 86, 64, 86, 76, 45, 86, 0, 86, 64, 86,
+ 76, 46, 86, 0, 3, 77, 3, 77, 3, 0,
+ 3, 77, 3, 0, 86, 51, 86, 50, 86, 0,
+ 86, 51, 5, 50, 5, 0, 86, 51, 5, 50,
+ 86, 0, 86, 51, 86, 50, 5, 0
};
#endif
#if YYDEBUG != 0
static const short yyrline[] = { 0,
- 132, 133, 136, 136, 136, 137, 138, 139, 140, 141,
- 142, 145, 147, 148, 149, 150, 151, 152, 153, 154,
- 157, 159, 163, 164, 165, 166, 167, 168, 172, 173,
- 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
- 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
- 196, 197, 198, 200, 203, 204, 205, 206, 207, 208,
- 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
- 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
- 229, 230, 231, 232, 233, 234, 235, 239, 243, 247,
- 248, 250, 251, 252, 253, 254, 255, 256, 257, 259,
- 261, 263, 264, 265, 266, 267, 268, 269, 270
+ 135, 136, 139, 139, 139, 140, 141, 142, 143, 144,
+ 145, 147, 150, 151, 153, 154, 155, 158, 160, 161,
+ 162, 163, 164, 165, 166, 167, 170, 174, 175, 176,
+ 177, 178, 179, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 197, 197, 199, 199, 201,
+ 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+ 212, 213, 214, 215, 217, 218, 219, 221, 224, 225,
+ 226, 227, 228, 229, 230, 231, 232, 233, 234, 235,
+ 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
+ 246, 250, 254, 255, 257, 258, 259, 260, 261, 262,
+ 263, 264, 266, 268, 270, 273, 276, 279, 283, 284,
+ 285, 286, 287, 288
};
#endif
@@ -304,390 +315,359 @@ static const short yyrline[] = { 0,
#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
static const char * const yytname[] = { "$","error","$undefined.","NUM","BOOLVAL",
-"STR","ARR","BLOCK","PBLOCK","PI","E","CLVAL","PSEP","IF","ELSE","BTRUE","BFALSE",
-"DATE1","TIME1","DATETIME1","DIM","WHILE","VAR","FNCT","BFNCT","AFNCT","SFNCT",
-"FUNC1","FUNC2","FUNC3","TXT","SRFUNC","YYFNC","FUNC4","YYFNC2","YYFNC3","'='",
-"','","CLAUSE","SER","COLR","COLC","'?'","AND","OR","EQ","NE","GT","GE","LT",
+"STR","ARR","BLOCK","PBLOCK","IBLOCK","PI","E","CLVAL","PSEP","IF","ELSE","BTRUE",
+"BFALSE","DATE1","TIME1","DATETIME1","DIM","WHILE","FOR","INARR","RANGEARR",
+"RETURN","BREAK","VAR","FNCT","BFNCT","AFNCT","SFNCT","FUNC1","FUNC2","FUNC3",
+"TXT","SRFUNC","YYFNC","FUNC4","YYFNC2","YYFNC3","'='","ADDEQ","SUBEQ","MULEQ",
+"DIVEQ","','","CLAUSE","SER","COLC","'?'","AND","OR","EQ","NE","GT","GE","LT",
"LE","'-'","'+'","'*'","'/'","'['","'^'","NEG","INC","DEC","PINC","PDEC","PDIM",
"'\\n'","';'","'('","')'","']'","':'","input","line","str_exp","range","arr",
-"bool","exp", NULL
+"bool","block","anyarg","exp", NULL
};
#endif
static const short yyr1[] = { 0,
- 69, 69, 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 72, 72, 73, 73, 73, 73, 73, 73, 74, 74,
- 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
- 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
- 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
- 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
- 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
- 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
- 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
- 75, 75, 75, 75, 75, 75, 75, 75, 75
+ 78, 78, 79, 79, 79, 79, 79, 79, 79, 79,
+ 79, 79, 79, 79, 79, 79, 79, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 81, 82, 82, 82,
+ 82, 82, 82, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 84, 84, 85, 85, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86
};
static const short yyr2[] = { 0,
0, 2, 1, 1, 1, 2, 2, 2, 2, 2,
- 2, 1, 3, 3, 3, 4, 6, 6, 6, 6,
- 1, 3, 1, 1, 3, 3, 1, 3, 1, 4,
- 1, 1, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 5, 3, 3, 2, 1, 2, 1, 3, 3,
+ 3, 4, 6, 6, 6, 6, 1, 1, 1, 3,
+ 3, 1, 3, 1, 4, 1, 1, 3, 3, 3,
+ 3, 3, 3, 3, 3, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 3, 3,
- 4, 4, 6, 8, 4, 4, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 8, 6, 8, 10, 6,
- 3, 4, 6, 6, 6, 6, 8, 8, 8, 8,
- 8, 8, 8, 8, 5, 7, 3, 3, 3, 3,
- 3, 2, 2, 2, 2, 3, 2, 3, 5, 4,
- 6, 5, 5, 3, 3, 5, 5, 5, 5
+ 3, 3, 3, 3, 4, 4, 6, 8, 4, 4,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 8,
+ 6, 8, 10, 6, 6, 3, 4, 6, 4, 8,
+ 3, 3, 3, 3, 2, 2, 2, 2, 3, 2,
+ 3, 5, 4, 6, 6, 6, 6, 6, 5, 3,
+ 5, 5, 5, 5
};
static const short yydefact[] = { 1,
- 0, 0, 41, 29, 12, 48, 45, 46, 44, 0,
- 31, 32, 0, 0, 47, 0, 0, 0, 0, 0,
- 0, 0, 43, 0, 0, 0, 0, 0, 5, 0,
- 0, 0, 3, 4, 0, 2, 0, 42, 0, 11,
- 0, 0, 0, 0, 0, 0, 92, 93, 0, 0,
+ 0, 0, 50, 34, 18, 46, 47, 55, 56, 54,
+ 0, 36, 37, 0, 0, 0, 51, 0, 16, 57,
+ 0, 0, 0, 0, 0, 0, 0, 53, 0, 0,
+ 0, 0, 0, 5, 0, 0, 0, 3, 4, 0,
+ 2, 0, 52, 58, 0, 17, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 0, 0, 95, 96, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 97, 94, 95, 41, 23, 47, 21, 27, 0, 24,
- 0, 9, 10, 8, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,
- 7, 104, 105, 0, 0, 87, 50, 49, 0, 0,
- 0, 24, 0, 0, 0, 0, 0, 0, 0, 71,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 98, 15, 13, 0, 0, 33, 34, 35, 36,
- 37, 38, 39, 40, 89, 14, 88, 90, 91, 0,
- 96, 0, 0, 0, 0, 51, 30, 52, 0, 0,
- 0, 55, 0, 0, 56, 0, 0, 0, 0, 0,
- 16, 72, 0, 0, 0, 0, 0, 88, 28, 22,
- 25, 26, 0, 0, 100, 102, 103, 85, 99, 0,
- 24, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 107, 108, 109, 106, 0,
- 0, 53, 0, 57, 60, 61, 63, 58, 59, 62,
- 64, 70, 0, 65, 0, 67, 17, 18, 19, 20,
- 0, 76, 74, 75, 73, 0, 0, 0, 0, 101,
- 86, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 54, 66, 68, 0, 77, 80, 79,
- 83, 78, 82, 81, 84, 0, 69, 0, 0
+ 0, 100, 97, 98, 49, 0, 48, 0, 9, 10,
+ 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 6, 7, 110, 11,
+ 0, 14, 13, 60, 59, 61, 62, 63, 64, 0,
+ 0, 50, 28, 27, 32, 0, 29, 0, 0, 0,
+ 29, 0, 0, 0, 86, 0, 0, 0, 0, 0,
+ 101, 21, 19, 0, 0, 38, 39, 40, 41, 42,
+ 43, 44, 45, 92, 20, 91, 93, 94, 0, 99,
+ 0, 0, 0, 65, 35, 0, 0, 0, 66, 0,
+ 0, 0, 69, 0, 0, 70, 0, 0, 0, 0,
+ 0, 22, 87, 0, 0, 89, 0, 91, 0, 0,
+ 103, 109, 12, 102, 33, 30, 31, 0, 29, 0,
+ 0, 0, 0, 0, 0, 0, 0, 51, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 112,
+ 113, 114, 111, 0, 0, 0, 0, 0, 67, 0,
+ 71, 74, 75, 77, 72, 73, 76, 78, 85, 84,
+ 0, 79, 0, 81, 23, 24, 25, 26, 0, 88,
+ 0, 104, 105, 106, 107, 108, 0, 0, 0, 0,
+ 0, 68, 80, 82, 0, 90, 0, 83, 0, 0
};
static const short yydefgoto[] = { 1,
- 36, 67, 68, 69, 38, 70
+ 41, 114, 115, 116, 43, 44, 76, 77
};
static const short yypact[] = {-32768,
- 242, -55, -3,-32768,-32768,-32768,-32768,-32768,-32768, -52,
--32768,-32768, -7, 9, 70, -44, -42, -33, 4, 6,
- 7, 28,-32768, 31, 47, 52, 73, 95,-32768, 707,
- 41, 93,-32768,-32768, 369,-32768, 50,-32768, 822,-32768,
- 131, 158, 707, 112, 162, 426,-32768,-32768, 707, 707,
- 369, 426, 369, 483, 369, 707, 305, 707, 426, 426,
--32768,-32768,-32768, -30,-32768, 65, 118,-32768, -26, 363,
- 426,-32768,-32768,-32768, 540, 707, 707, 707, 707, 707,
- 707, 707, 707, 707, 426, 707, 707, 707, 707,-32768,
--32768, 159, 103, 871, 707,-32768, 118, 363, 896, 921,
- -19, 135, -6, 731, 54, 163, 363, 61, 757,-32768,
- -4, 420, -11, 477, -9, 534, 707, 195, 181, 369,
- 707,-32768,-32768, 86, 165, 1272, 699, 699, 141, 141,
- 141, 141, 141, 141, 86,-32768, 86, 12, 12, 299,
--32768, 204, 210, 207, 845,-32768,-32768,-32768, 369, 426,
- 426,-32768, 426, 426,-32768, 483, 483, 369, 426, 426,
--32768,-32768, 707, 426, 426, 426, 426, 86,-32768,-32768,
- 182, 1287, 597, 654, 183,-32768,-32768, 209,-32768, -2,
- 591, -36, 946, -27, 971, 38, 996, 43, 1021, 155,
- -5, -10, 67, 1046, 69, 1071, 648, 78, 1096, 79,
- 1121, -8, 783, 2, 802,-32768, 1287,-32768, 1287, 707,
- 218,-32768, 707,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
--32768,-32768, 483,-32768, 483,-32768,-32768,-32768,-32768,-32768,
- 369,-32768,-32768,-32768,-32768, 426, 426, 426, 426, 1287,
--32768, 1146, 160, 161, 88, 80, 1171, 85, 1196, 91,
- 1221, 102, 1246,-32768,-32768,-32768, 483,-32768,-32768,-32768,
--32768,-32768,-32768,-32768,-32768, 164,-32768, 228,-32768
+ 255, -52, -45,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+ 27,-32768,-32768, 42, 67, 72,-32768, 94,-32768, 80,
+ 43, 46, 47, 53, 62, 63, 65,-32768, 76, 77,
+ 78, 81, 88,-32768, 724, 86, 121,-32768,-32768, 454,
+-32768, 40,-32768,-32768, 845,-32768, 105, 95, 90, 95,
+ 95,-32768, 454, 724, 724, 724, 724,-32768,-32768, 724,
+ 724, 400, 454, 400, 454, 400, 724, 327, 724, 454,
+ 454,-32768,-32768,-32768, 104, 96, 391, 454,-32768,-32768,
+-32768, 562, 724, 724, 724, 724, 724, 724, 724, 724,
+ 724, 454, 724, 724, 724, 724,-32768,-32768, 97, 160,
+ 724,-32768,-32768, 104, 391, 445, 445, 445, 445, 894,
+ 919, -34,-32768, 104,-32768, -26, 716, -11, 145, -8,
+ 391, 163, 0, 748,-32768, -2, 773, -4, 164, 724,
+-32768,-32768, 79, 130, 1120, 496, 496, 70, 70, 70,
+ 70, 70, 70, 79,-32768, 79, 34, 34, 320,-32768,
+ 178, 95, 868,-32768,-32768, 180, 400, 724,-32768, 400,
+ 454, 454,-32768, 454, 454,-32768, 508, 454, 400, 454,
+ 454,-32768,-32768, 724, 454,-32768, 454, 79, 616, 670,
+ -17,-32768,-32768,-32768,-32768, 136, 445, 31, 801, -44,
+ 944, -42, 969, -37, 994, -31, 1019, 110, 111, 391,
+ -3, -6, -24, 1044, 36, 1069, 826, 112, 175,-32768,
+ 445,-32768, 445, 724, 724, 724, 724, 724,-32768, 724,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+ 454,-32768, 454,-32768,-32768,-32768,-32768,-32768, 400,-32768,
+ 454, 445, 445, 445, 445, 445, 1094, 115, 116, 10,
+ 118,-32768,-32768,-32768, 454,-32768, 119,-32768, 195,-32768
};
static const short yypgoto[] = {-32768,
--32768, 51, -49, -31,-32768, -1
+-32768, 75, -159, -50,-32768, -47, -59, -1
};
-#define YYLAST 1343
-
-
-static const short yytable[] = { 39,
- 164, 225, 166, 236, 106, 150, 223, 40, 118, 41,
- 120, 121, 43, 238, 44, 71, 45, 120, 121, 101,
- 49, 105, 50, 108, 71, 111, 120, 121, 61, 214,
- 151, 51, 120, 121, 120, 121, 41, 42, 216, 122,
- 71, 94, 71, 71, 98, 71, 148, 99, 100, 102,
- 104, 37, 107, 71, 109, 226, 112, 114, 116, 152,
- 224, 162, 62, 212, 42, 156, 88, 89, 52, 124,
- 53, 54, 158, 126, 127, 128, 129, 130, 131, 132,
- 133, 134, 135, 137, 138, 139, 140, 141, 171, 71,
- 120, 121, 55, 145, 71, 56, 97, 120, 121, 257,
- 46, 71, 103, 218, 119, 46, 190, 191, 220, 113,
- 115, 57, 72, 73, 63, 168, 58, 180, 71, 172,
- 71, 123, 47, 48, 120, 121, 192, 47, 48, 71,
- 71, 71, 227, 92, 229, 136, 71, 59, 86, 87,
- 88, 89, 71, 232, 234, 258, 149, 181, 183, 185,
- 260, 187, 189, 71, 107, 107, 262, 194, 196, 60,
- 93, 197, 199, 201, 203, 205, 95, 264, 96, 71,
- 143, 207, 209, 243, 157, 244, 75, 76, 77, 78,
- 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
- 89, 84, 117, 86, 87, 88, 89, 169, 142, 245,
- 182, 184, 170, 186, 188, 173, 176, 266, 240, 193,
- 195, 242, 177, 178, 198, 200, 202, 204, 210, 121,
- 222, 107, 211, 107, 241, 255, 256, 269, 0, 267,
- 0, 0, 0, 0, 247, 249, 251, 253, 0, 0,
- 0, 268, 2, 0, 3, 4, 5, 0, 6, 0,
- 7, 8, 9, 0, 10, 107, 11, 12, 0, 0,
- 0, 13, 14, 15, 16, 17, 18, 19, 20, 21,
- 22, 23, 24, 25, 26, 27, 28, 0, 29, 0,
- 0, 0, 0, 0, 0, 0, 246, 248, 250, 252,
- 0, 0, 30, 0, 0, 0, 0, 0, 0, 31,
- 32, 0, 0, 0, 33, 34, 35, 64, 4, 5,
- 65, 6, 0, 7, 8, 9, 0, 10, 0, 11,
- 12, 0, 0, 0, 13, 14, 66, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
- 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- 117, 86, 87, 88, 89, 30, 0, 0, 0, 0,
- 0, 0, 31, 32, 0, 175, 0, 0, 0, 35,
- 110, 64, 4, 5, 65, 6, 0, 7, 8, 9,
- 0, 10, 0, 11, 12, 0, 0, 0, 13, 14,
- 66, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 75, 76, 77, 78, 79, 80,
- 81, 82, 83, 84, 85, 86, 87, 88, 89, 30,
- 0, 0, 0, 0, 0, 0, 31, 32, 3, 4,
- 5, 163, 6, 35, 7, 8, 9, 0, 10, 0,
- 11, 12, 0, 0, 0, 13, 14, 15, 16, 17,
+#define YYLAST 1185
+
+
+static const short yytable[] = { 45,
+ 100, 161, 102, 103, 167, 122, 233, 199, 175, 231,
+ 128, 129, 169, 120, 156, 123, 78, 126, 78, 46,
+ 157, 158, 255, 78, 214, 215, 216, 217, 218, 78,
+ 221, 47, 223, 72, 48, 162, 78, 225, 157, 158,
+ 157, 158, 47, 227, 157, 158, 157, 158, 159, 78,
+ 235, 105, 106, 107, 108, 109, 157, 158, 110, 111,
+ 117, 119, 121, 163, 121, 124, 121, 127, 234, 49,
+ 176, 232, 173, 249, 50, 42, 133, 157, 158, 51,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+ 146, 147, 148, 149, 150, 257, 78, 95, 96, 153,
+ 78, 6, 52, 7, 183, 219, 186, 99, 201, 188,
+ 237, 79, 80, 73, 75, 208, 60, 209, 202, 61,
+ 62, 53, 54, 55, 56, 57, 63, 104, 178, 91,
+ 130, 93, 94, 95, 96, 64, 65, 118, 66, 75,
+ 93, 94, 95, 96, 75, 75, 58, 59, 74, 67,
+ 68, 69, 132, 101, 70, 121, 187, 164, 189, 191,
+ 193, 71, 195, 197, 78, 200, 145, 121, 204, 206,
+ 131, 248, 207, 151, 152, 168, 177, 211, 213, 179,
+ 182, 251, 185, 158, 229, 230, 240, 241, 250, 253,
+ 254, 165, 256, 258, 260, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 0, 0, 242, 243, 244, 245, 246, 0, 247, 166,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 200, 0, 0, 0, 190, 192, 121, 194, 196,
+ 0, 0, 75, 0, 203, 205, 0, 0, 0, 75,
+ 0, 75, 0, 200, 259, 2, 0, 3, 4, 5,
+ 0, 6, 0, 7, 8, 9, 10, 0, 11, 0,
+ 12, 13, 0, 0, 0, 14, 15, 16, 0, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
- 28, 75, 76, 77, 78, 79, 80, 81, 82, 83,
- 84, 117, 86, 87, 88, 89, 30, 0, 0, 0,
- 0, 0, 0, 31, 32, 3, 4, 5, 165, 6,
- 35, 7, 8, 9, 0, 10, 0, 11, 12, 0,
- 0, 0, 13, 14, 66, 16, 17, 18, 19, 20,
- 21, 22, 23, 24, 25, 26, 27, 28, 75, 76,
- 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
- 87, 88, 89, 30, 0, 0, 0, 0, 0, 0,
- 31, 32, 3, 4, 125, 167, 6, 35, 7, 8,
- 9, 0, 10, 0, 11, 12, 0, 0, 0, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 0, 25, 26, 27, 28, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
- 30, 0, 0, 0, 0, 0, 0, 31, 32, 3,
- 4, 206, 213, 6, 35, 7, 8, 9, 0, 10,
- 0, 11, 12, 0, 0, 0, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 0, 25, 26,
- 27, 28, 75, 76, 77, 78, 79, 80, 81, 82,
- 83, 84, 85, 86, 87, 88, 89, 30, 0, 0,
- 0, 0, 0, 0, 31, 32, 3, 4, 208, 231,
- 6, 35, 7, 8, 9, 0, 10, 0, 11, 12,
- 0, 0, 0, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 0, 25, 26, 27, 28, 75,
- 76, 77, 78, 79, 80, 81, 82, 83, 84, 117,
- 86, 87, 88, 89, 30, 0, 0, 0, 0, 3,
- 4, 31, 32, 6, 0, 7, 8, 9, 35, 10,
- 0, 11, 12, 0, 0, 0, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 0, 25, 26,
- 27, 28, 153, 78, 79, 80, 81, 82, 83, 84,
- 117, 86, 87, 88, 89, 0, 0, 30, 0, 0,
- 0, 0, 0, 0, 31, 32, 0, 154, 159, 0,
- 0, 35, 75, 76, 77, 78, 79, 80, 81, 82,
- 83, 84, 85, 86, 87, 88, 89, 0, 0, 0,
- 0, 0, 0, 160, 237, 0, 155, 0, 75, 76,
- 77, 78, 79, 80, 81, 82, 83, 84, 117, 86,
- 87, 88, 89, 239, 0, 0, 0, 0, 0, 0,
- 0, 0, 161, 0, 75, 76, 77, 78, 79, 80,
- 81, 82, 83, 84, 85, 86, 87, 88, 89, 0,
- 0, 0, 0, 75, 76, 77, 78, 79, 80, 81,
- 82, 83, 84, 85, 86, 87, 88, 89, 74, 0,
- 0, 0, 0, 75, 76, 77, 78, 79, 80, 81,
- 82, 83, 84, 85, 86, 87, 88, 89, 0, 0,
- 0, 0, 0, 0, 90, 91, 75, 76, 77, 78,
- 79, 80, 81, 82, 83, 84, 117, 86, 87, 88,
- 89, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 179, 75, 76, 77, 78, 79, 80, 81, 82,
- 83, 84, 117, 86, 87, 88, 89, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 144, 75, 76, 77,
- 78, 79, 80, 81, 82, 83, 84, 117, 86, 87,
- 88, 89, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 146, 75, 76, 77, 78, 79, 80, 81, 82,
- 83, 84, 117, 86, 87, 88, 89, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 147, 75, 76, 77,
- 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 215, 75, 76, 77, 78, 79, 80, 81, 82,
- 83, 84, 85, 86, 87, 88, 89, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 217, 75, 76, 77,
- 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 219, 75, 76, 77, 78, 79, 80, 81, 82,
- 83, 84, 85, 86, 87, 88, 89, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 221, 75, 76, 77,
- 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 228, 75, 76, 77, 78, 79, 80, 81, 82,
- 83, 84, 85, 86, 87, 88, 89, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 230, 75, 76, 77,
- 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 233, 75, 76, 77, 78, 79, 80, 81, 82,
- 83, 84, 85, 86, 87, 88, 89, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 235, 75, 76, 77,
- 78, 79, 80, 81, 82, 83, 84, 117, 86, 87,
- 88, 89, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 254, 75, 76, 77, 78, 79, 80, 81, 82,
- 83, 84, 85, 86, 87, 88, 89, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 259, 75, 76, 77,
- 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 261, 75, 76, 77, 78, 79, 80, 81, 82,
- 83, 84, 85, 86, 87, 88, 89, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 263, 75, 76, 77,
- 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 265, 174, 75, 76, 77, 78, 79, 80, 81,
- 82, 83, 84, 117, 86, 87, 88, 89, 75, 76,
- 77, 78, 79, 80, 81, 82, 83, 84, 117, 86,
- 87, 88, 89
+ 28, 29, 30, 31, 32, 33, 0, 0, 0, 0,
+ 0, 34, 0, 0, 0, 75, 0, 0, 0, 0,
+ 0, 0, 0, 0, 35, 75, 0, 0, 0, 0,
+ 0, 36, 37, 0, 0, 0, 38, 39, 40, 112,
+ 4, 5, 113, 6, 0, 7, 8, 9, 10, 0,
+ 0, 0, 12, 13, 0, 0, 0, 14, 0, 0,
+ 0, 17, 0, 0, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 0, 0,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 130, 93, 94, 95, 96, 0, 35, 0, 0, 0,
+ 0, 0, 0, 36, 37, 181, 0, 0, 0, 0,
+ 40, 125, 112, 4, 5, 113, 6, 0, 7, 8,
+ 9, 10, 0, 0, 0, 12, 13, 0, 0, 0,
+ 14, 0, 0, 0, 17, 0, 0, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 3, 4, 5, 35,
+ 6, 0, 7, 8, 9, 10, 36, 37, 0, 12,
+ 13, 0, 0, 40, 14, 0, 0, 0, 17, 0,
+ 0, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 130, 93, 94, 95, 96,
+ 3, 4, 5, 35, 6, 0, 7, 8, 9, 10,
+ 36, 37, 0, 12, 13, 0, 0, 40, 14, 0,
+ 0, 0, 198, 0, 0, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 85,
+ 86, 87, 88, 89, 90, 91, 130, 93, 94, 95,
+ 96, 0, 0, 0, 3, 4, 134, 35, 6, 0,
+ 7, 8, 9, 10, 36, 37, 0, 12, 13, 0,
+ 0, 40, 14, 0, 0, 0, 17, 0, 0, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 0, 30,
+ 31, 32, 33, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 3, 4,
+ 210, 35, 6, 0, 7, 8, 9, 10, 36, 37,
+ 0, 12, 13, 0, 0, 40, 14, 0, 0, 0,
+ 17, 0, 0, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 0, 30, 31, 32, 33, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 4, 212, 35, 6, 0, 7, 8,
+ 9, 10, 36, 37, 0, 12, 13, 0, 0, 40,
+ 14, 0, 0, 0, 17, 0, 0, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 0, 30, 31, 32,
+ 33, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 3, 4, 160, 35,
+ 6, 0, 7, 8, 9, 10, 36, 37, 0, 12,
+ 13, 0, 0, 40, 14, 0, 0, 0, 17, 0,
+ 0, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 170, 30, 31, 32, 33, 0, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 0, 0, 35, 0, 174, 0, 0, 0, 0,
+ 36, 37, 0, 0, 171, 0, 0, 40, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 130, 93,
+ 94, 95, 96, 220, 0, 0, 0, 0, 0, 0,
+ 0, 0, 172, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 130, 93, 94, 95, 96, 239, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 130, 93, 94, 95,
+ 96, 81, 0, 0, 0, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 0, 0, 0, 0, 0, 0, 97, 98, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 130, 93,
+ 94, 95, 96, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 184, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 130, 93, 94, 95, 96, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 154, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 130,
+ 93, 94, 95, 96, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 155, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 222, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 224, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 226, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 228, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 236, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 238, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 130, 93, 94, 95, 96, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 252, 180,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 130, 93, 94, 95, 96
};
static const short yycheck[] = { 1,
- 12, 12, 12, 12, 54, 12, 12, 63, 39, 40,
- 37, 38, 65, 12, 22, 52, 8, 37, 38, 51,
- 65, 53, 65, 55, 52, 57, 37, 38, 30, 66,
- 37, 65, 37, 38, 37, 38, 40, 68, 66, 66,
- 52, 43, 52, 52, 46, 52, 66, 49, 50, 51,
- 52, 1, 54, 52, 56, 66, 58, 59, 60, 66,
- 66, 66, 22, 66, 68, 12, 55, 56, 65, 71,
- 65, 65, 12, 75, 76, 77, 78, 79, 80, 81,
- 82, 83, 84, 85, 86, 87, 88, 89, 120, 52,
- 37, 38, 65, 95, 52, 65, 46, 37, 38, 12,
- 36, 52, 52, 66, 40, 36, 156, 157, 66, 59,
- 60, 65, 63, 64, 22, 117, 65, 149, 52, 121,
- 52, 71, 58, 59, 37, 38, 158, 58, 59, 52,
- 52, 52, 66, 3, 66, 85, 52, 65, 53, 54,
- 55, 56, 52, 66, 66, 66, 12, 149, 150, 151,
- 66, 153, 154, 52, 156, 157, 66, 159, 160, 65,
- 3, 163, 164, 165, 166, 167, 55, 66, 7, 52,
- 68, 173, 174, 223, 12, 225, 42, 43, 44, 45,
- 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 51, 52, 53, 54, 55, 56, 3, 40, 231,
- 150, 151, 22, 153, 154, 41, 3, 257, 210, 159,
- 160, 213, 3, 7, 164, 165, 166, 167, 36, 38,
- 66, 223, 14, 225, 7, 66, 66, 0, -1, 66,
- -1, -1, -1, -1, 236, 237, 238, 239, -1, -1,
- -1, 0, 1, -1, 3, 4, 5, -1, 7, -1,
- 9, 10, 11, -1, 13, 257, 15, 16, -1, -1,
- -1, 20, 21, 22, 23, 24, 25, 26, 27, 28,
- 29, 30, 31, 32, 33, 34, 35, -1, 37, -1,
- -1, -1, -1, -1, -1, -1, 236, 237, 238, 239,
- -1, -1, 51, -1, -1, -1, -1, -1, -1, 58,
- 59, -1, -1, -1, 63, 64, 65, 3, 4, 5,
- 6, 7, -1, 9, 10, 11, -1, 13, -1, 15,
- 16, -1, -1, -1, 20, 21, 22, 23, 24, 25,
+ 48, 13, 50, 51, 13, 65, 13, 167, 13, 13,
+ 70, 71, 13, 64, 49, 66, 61, 68, 61, 72,
+ 47, 48, 13, 61, 42, 43, 44, 45, 46, 61,
+ 75, 77, 75, 35, 8, 47, 61, 75, 47, 48,
+ 47, 48, 77, 75, 47, 48, 47, 48, 75, 61,
+ 75, 53, 54, 55, 56, 57, 47, 48, 60, 61,
+ 62, 63, 64, 75, 66, 67, 68, 69, 75, 28,
+ 75, 75, 75, 233, 8, 1, 78, 47, 48, 8,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 95, 96, 255, 61, 64, 65, 101,
+ 61, 7, 9, 9, 152, 75, 157, 3, 168, 160,
+ 75, 72, 73, 28, 40, 175, 74, 177, 169, 74,
+ 74, 42, 43, 44, 45, 46, 74, 53, 130, 60,
+ 61, 62, 63, 64, 65, 74, 74, 63, 74, 65,
+ 62, 63, 64, 65, 70, 71, 67, 68, 28, 74,
+ 74, 74, 78, 64, 74, 157, 158, 13, 160, 161,
+ 162, 74, 164, 165, 61, 167, 92, 169, 170, 171,
+ 75, 231, 174, 77, 15, 13, 13, 179, 180, 50,
+ 3, 241, 3, 48, 75, 75, 75, 13, 239, 75,
+ 75, 47, 75, 75, 0, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ -1, -1, 214, 215, 216, 217, 218, -1, 220, 75,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 233, -1, -1, -1, 161, 162, 239, 164, 165,
+ -1, -1, 168, -1, 170, 171, -1, -1, -1, 175,
+ -1, 177, -1, 255, 0, 1, -1, 3, 4, 5,
+ -1, 7, -1, 9, 10, 11, 12, -1, 14, -1,
+ 16, 17, -1, -1, -1, 21, 22, 23, -1, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
- 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- 52, 53, 54, 55, 56, 51, -1, -1, -1, -1,
- -1, -1, 58, 59, -1, 67, -1, -1, -1, 65,
- 66, 3, 4, 5, 6, 7, -1, 9, 10, 11,
- -1, 13, -1, 15, 16, -1, -1, -1, 20, 21,
- 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 51,
- -1, -1, -1, -1, -1, -1, 58, 59, 3, 4,
- 5, 12, 7, 65, 9, 10, 11, -1, 13, -1,
- 15, 16, -1, -1, -1, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 42, 43, 44, 45, 46, 47, 48, 49, 50,
- 51, 52, 53, 54, 55, 56, 51, -1, -1, -1,
- -1, -1, -1, 58, 59, 3, 4, 5, 12, 7,
- 65, 9, 10, 11, -1, 13, -1, 15, 16, -1,
- -1, -1, 20, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35, 42, 43,
- 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 51, -1, -1, -1, -1, -1, -1,
- 58, 59, 3, 4, 5, 12, 7, 65, 9, 10,
- 11, -1, 13, -1, 15, 16, -1, -1, -1, 20,
- 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
- -1, 32, 33, 34, 35, 42, 43, 44, 45, 46,
- 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- 51, -1, -1, -1, -1, -1, -1, 58, 59, 3,
- 4, 5, 12, 7, 65, 9, 10, 11, -1, 13,
- -1, 15, 16, -1, -1, -1, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, -1, 32, 33,
- 34, 35, 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, 51, -1, -1,
- -1, -1, -1, -1, 58, 59, 3, 4, 5, 12,
- 7, 65, 9, 10, 11, -1, 13, -1, 15, 16,
- -1, -1, -1, 20, 21, 22, 23, 24, 25, 26,
- 27, 28, 29, 30, -1, 32, 33, 34, 35, 42,
- 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- 53, 54, 55, 56, 51, -1, -1, -1, -1, 3,
- 4, 58, 59, 7, -1, 9, 10, 11, 65, 13,
- -1, 15, 16, -1, -1, -1, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, -1, 32, 33,
- 34, 35, 12, 45, 46, 47, 48, 49, 50, 51,
- 52, 53, 54, 55, 56, -1, -1, 51, -1, -1,
- -1, -1, -1, -1, 58, 59, -1, 37, 12, -1,
- -1, 65, 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, -1, -1, -1,
- -1, -1, -1, 37, 12, -1, 66, -1, 42, 43,
- 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 12, -1, -1, -1, -1, -1, -1,
- -1, -1, 66, -1, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, -1,
- -1, -1, -1, 42, 43, 44, 45, 46, 47, 48,
- 49, 50, 51, 52, 53, 54, 55, 56, 37, -1,
- -1, -1, -1, 42, 43, 44, 45, 46, 47, 48,
- 49, 50, 51, 52, 53, 54, 55, 56, -1, -1,
- -1, -1, -1, -1, 63, 64, 42, 43, 44, 45,
- 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- 56, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 67, 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 66, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- 55, 56, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 66, 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 66, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- 55, 56, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 66, 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 66, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- 55, 56, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 66, 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 66, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- 55, 56, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 66, 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 66, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- 55, 56, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 66, 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 66, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- 55, 56, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 66, 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 66, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- 55, 56, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 66, 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 66, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- 55, 56, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 66, 41, 42, 43, 44, 45, 46, 47, 48,
- 49, 50, 51, 52, 53, 54, 55, 56, 42, 43,
- 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56
+ 36, 37, 38, 39, 40, 41, -1, -1, -1, -1,
+ -1, 47, -1, -1, -1, 231, -1, -1, -1, -1,
+ -1, -1, -1, -1, 60, 241, -1, -1, -1, -1,
+ -1, 67, 68, -1, -1, -1, 72, 73, 74, 3,
+ 4, 5, 6, 7, -1, 9, 10, 11, 12, -1,
+ -1, -1, 16, 17, -1, -1, -1, 21, -1, -1,
+ -1, 25, -1, -1, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, -1, -1,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, -1, 60, -1, -1, -1,
+ -1, -1, -1, 67, 68, 76, -1, -1, -1, -1,
+ 74, 75, 3, 4, 5, 6, 7, -1, 9, 10,
+ 11, 12, -1, -1, -1, 16, 17, -1, -1, -1,
+ 21, -1, -1, -1, 25, -1, -1, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 3, 4, 5, 60,
+ 7, -1, 9, 10, 11, 12, 67, 68, -1, 16,
+ 17, -1, -1, 74, 21, -1, -1, -1, 25, -1,
+ -1, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 3, 4, 5, 60, 7, -1, 9, 10, 11, 12,
+ 67, 68, -1, 16, 17, -1, -1, 74, 21, -1,
+ -1, -1, 25, -1, -1, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, -1, -1, -1, 3, 4, 5, 60, 7, -1,
+ 9, 10, 11, 12, 67, 68, -1, 16, 17, -1,
+ -1, 74, 21, -1, -1, -1, 25, -1, -1, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, -1, 38,
+ 39, 40, 41, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 3, 4,
+ 5, 60, 7, -1, 9, 10, 11, 12, 67, 68,
+ -1, 16, 17, -1, -1, 74, 21, -1, -1, -1,
+ 25, -1, -1, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, -1, 38, 39, 40, 41, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3, 4, 5, 60, 7, -1, 9, 10,
+ 11, 12, 67, 68, -1, 16, 17, -1, -1, 74,
+ 21, -1, -1, -1, 25, -1, -1, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, -1, 38, 39, 40,
+ 41, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3, 4, 13, 60,
+ 7, -1, 9, 10, 11, 12, 67, 68, -1, 16,
+ 17, -1, -1, 74, 21, -1, -1, -1, 25, -1,
+ -1, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 13, 38, 39, 40, 41, -1, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, -1, -1, 60, -1, 13, -1, -1, -1, -1,
+ 67, 68, -1, -1, 47, -1, -1, 74, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 13, -1, -1, -1, -1, -1, -1,
+ -1, -1, 75, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 13, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 47, -1, -1, -1, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ -1, -1, -1, -1, -1, -1, 72, 73, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 76, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 75, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 75, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 75, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 75, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 75, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 75, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 75, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 75, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 75, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65
};
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
@@ -1018,7 +998,7 @@ yynewstate:
#endif
/* Get the current used size of the three stacks, in elements. */
- int size = (int)(yyssp - yyss) + 1;
+ int size = yyssp - yyss + 1;
#ifdef yyoverflow
/* Each stack pointer address is followed by the size of
@@ -1248,312 +1228,328 @@ case 10:
{store_res(&yyvsp[-1]); return 0;;
break;}
case 11:
-{yyerrok;;
+{if(block_res = eval(&yyval, &yyvsp[-1]))return block_res;
+ if(yyval.val != 0.0) if(block_res = eval(&yyval, &yyvsp[0]))return block_res;;
break;}
case 12:
-{;;
+{if(block_res = eval(&yyval, &yyvsp[-3])) return block_res;
+ if(yyval.val != 0.0) {if(block_res = eval(&yyval, &yyvsp[-2])) return block_res;}
+ else if(block_res = eval(&yyval, &yyvsp[0])) return block_res;;
break;}
case 13:
-{yyval.text=add_strings(yyvsp[-2].text, string_value(&yyvsp[0])); yyval.type = STR;;
+{for_loop(yyvsp[-1].text, yyvsp[0].text);;
break;}
case 14:
-{yyval.text=add_strings(string_value(&yyvsp[-2]), yyvsp[0].text); yyval.type = STR;;
+{for(int i=0; i< yy_maxiter; i++){ if(block_res = eval(&yyval, &yyvsp[-1]))return block_res;
+ if(yyval.val != 0.0){if(block_res = eval(&yyval, &yyvsp[0]))return block_res;} else break;};
break;}
case 15:
-{yyval.text=add_strings(yyvsp[-2].text, yyvsp[0].text); yyval.type = STR;;
+{if(block_res = eval(&yyval, &yyvsp[0]) == 1) return 1; else return 2;;
break;}
case 16:
-{((yyvsp[-3].tptr->fnctptr)(&yyval, &yyvsp[-1], 0L)); yyval.type = STR;;
+{return 3;;
break;}
case 17:
-{((yyvsp[-5].tptr->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;;
+{yyerrok;;
break;}
case 18:
-{((yyvsp[-5].tptr->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;;
+{;;
break;}
case 19:
-{((yyvsp[-5].tptr->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;;
+{yyval.text=add_strings(yyvsp[-2].text, string_value(&yyvsp[0])); yyval.type = STR;;
break;}
case 20:
-{((yyvsp[-5].tptr->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;;
+{yyval.text=add_strings(string_value(&yyvsp[-2]), yyvsp[0].text); yyval.type = STR;;
break;}
case 21:
-{;;
+{yyval.text=add_strings(yyvsp[-2].text, yyvsp[0].text); yyval.type = STR;;
break;}
case 22:
-{if(yyval.text = PushString(" "))
- sprintf(yyval.text, "%s:%s", yyvsp[-2].tptr->name, yyvsp[0].tptr->name); yyval.type = STR;;
+{if(yyvsp[-3].tptr->fnctptr)((yyvsp[-3].tptr->fnctptr)(&yyval, &yyvsp[-1], 0L)); yyval.type = STR;;
+ break;}
+case 23:
+{if(yyvsp[-5].tptr->fnctptr)((yyvsp[-5].tptr->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;;
break;}
case 24:
-{if(!yyval.a_data) {yyval.a_data = PushArray((double*)malloc(sizeof(double))); yyval.a_count = 1; yyval.a_data[0] = yyval.val;};
+{if(yyvsp[-5].tptr->fnctptr)((yyvsp[-5].tptr->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;;
break;}
case 25:
-{push(&yyval, &yyvsp[0]);yyval.type = ARR;;
+{if(yyvsp[-5].tptr->fnctptr)((yyvsp[-5].tptr->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;;
break;}
case 26:
-{exec_clause(&yyval);yyval.type = ARR;;
+{if(yyvsp[-5].tptr->fnctptr)((yyvsp[-5].tptr->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;;
break;}
case 27:
-{range_array(&yyval, yyvsp[0].text);yyval.type = ARR;;
+{;;
break;}
case 28:
-{if(yyvsp[-2].val < yyvsp[0].val && (yyval.a_data = PushArray((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 ); yyval.type = ARR;;
+{;;
+ break;}
+case 29:
+{if(!yyval.a_data) {yyval.a_data = PushArray((double*)malloc(sizeof(double))); yyval.a_count = 1; yyval.a_data[0] = yyval.val;};
break;}
case 30:
-{yyval.val = ((yyvsp[-3].tptr->fnctptr)(yyvsp[-1].val)); yyval.type = BOOLVAL;;
+{push(&yyval, &yyvsp[0]);yyval.type = ARR;;
break;}
case 31:
-{yyval.val = 1.0; yyval.type = BOOLVAL;;
+{exec_clause(&yyval);yyval.type = ARR;;
break;}
case 32:
-{yyval.val = 0.0; yyval.type = BOOLVAL;;
+{range_array(&yyval, yyvsp[0].text);yyval.type = ARR;;
break;}
case 33:
-{yyval.val = ((yyvsp[-2].val != 0) && (yyvsp[0].val != 0))? 1 : 0; yyval.type = BOOLVAL;;
- break;}
-case 34:
-{yyval.val = ((yyvsp[-2].val != 0) || (yyvsp[0].val != 0))? 1 : 0; yyval.type = BOOLVAL;;
+{if(yyvsp[-2].val < yyvsp[0].val && (yyval.a_data = PushArray((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 ); yyval.type = ARR;;
break;}
case 35:
-{yyval.val = (yyvsp[-2].val == yyvsp[0].val) ? 1 : 0; yyval.type = BOOLVAL;;
+{yyval.val = yyvsp[-3].tptr->fnctptr ? ((yyvsp[-3].tptr->fnctptr)(yyvsp[-1].val)): 0.0; yyval.type = BOOLVAL;;
break;}
case 36:
-{yyval.val = (yyvsp[-2].val != yyvsp[0].val) ? 1 : 0; yyval.type = BOOLVAL;;
+{yyval.val = 1.0; yyval.type = BOOLVAL;;
break;}
case 37:
-{yyval.val = (yyvsp[-2].val > yyvsp[0].val) ? 1 : 0; yyval.type = BOOLVAL;;
+{yyval.val = 0.0; yyval.type = BOOLVAL;;
break;}
case 38:
-{yyval.val = (yyvsp[-2].val >= yyvsp[0].val) ? 1 : 0; yyval.type = BOOLVAL;;
+{yyval.val = ((yyvsp[-2].val != 0) && (yyvsp[0].val != 0))? 1 : 0; yyval.type = BOOLVAL;;
break;}
case 39:
-{yyval.val = (yyvsp[-2].val < yyvsp[0].val) ? 1 : 0; yyval.type = BOOLVAL;;
+{yyval.val = ((yyvsp[-2].val != 0) || (yyvsp[0].val != 0))? 1 : 0; yyval.type = BOOLVAL;;
break;}
case 40:
-{yyval.val = (yyvsp[-2].val <= yyvsp[0].val) ? 1 : 0; yyval.type = BOOLVAL;;
+{yyval.val = (yyvsp[-2].val == yyvsp[0].val) ? 1 : 0; yyval.type = BOOLVAL;;
break;}
case 41:
-{yyval.val = yyvsp[0].val; yyval.type = NUM;;
+{yyval.val = (yyvsp[-2].val != yyvsp[0].val) ? 1 : 0; yyval.type = BOOLVAL;;
break;}
case 42:
-{yyval.val = yyvsp[0].val; yyval.type = BOOLVAL;;
+{yyval.val = (yyvsp[-2].val > yyvsp[0].val) ? 1 : 0; yyval.type = BOOLVAL;;
break;}
case 43:
-{yyval.val = 0.0;;
+{yyval.val = (yyvsp[-2].val >= yyvsp[0].val) ? 1 : 0; yyval.type = BOOLVAL;;
break;}
case 44:
-{yyval.val = syntax_level ? syntax_level->clval : 0.0; yyval.type = NUM;;
+{yyval.val = (yyvsp[-2].val < yyvsp[0].val) ? 1 : 0; yyval.type = BOOLVAL;;
break;}
case 45:
-{yyval.val = _PI; yyval.type = NUM;;
- break;}
-case 46:
-{yyval.val = 2.71828182845905; yyval.type = NUM;;
- break;}
-case 47:
-{yyvsp[0].tptr->GetValue(&yyval);;
- break;}
-case 48:
-{eval(&yyvsp[0], &yyval);;
- break;}
-case 49:
-{yyvsp[-2].tptr->SetValue(&yyval, &yyvsp[0]);;
+{yyval.val = (yyvsp[-2].val <= yyvsp[0].val) ? 1 : 0; yyval.type = BOOLVAL;;
break;}
case 50:
-{yyvsp[-2].tptr->SetValue(&yyval, &yyvsp[0]);;
+{yyval.val = yyvsp[0].val; yyval.type = NUM;;
break;}
case 51:
-{yyval.val = ((yyvsp[-3].tptr->fnctptr)(yyvsp[-1].val)); yyval.type = NUM;;
+{yyval.type = ARR;;
break;}
case 52:
-{yyval.val = ((yyvsp[-3].tptr->fnctptr)(proc_clause(&yyvsp[-1]))); yyval.type = NUM;;
+{yyval.val = yyvsp[0].val; yyval.type = BOOLVAL;;
break;}
case 53:
-{ if(!yyval.a_data){yyval.a_data=PushArray((double*)malloc(sizeof(double)));yyval.a_data[0]=yyvsp[-3].val;yyval.a_count=1;}
- push(&yyval, &yyvsp[-1]);yyval.val = ((yyvsp[-5].tptr->fnctptr)(&yyval)); yyval.type = NUM;;
+{yyval.val = 0.0;;
break;}
case 54:
-{ yyval.a_data = PushArray((double*)malloc(3*sizeof(double)));
- yyval.a_count = 3; yyval.a_data[0] = yyvsp[-5].val; yyval.a_data[1] = yyvsp[-3].val; yyval.a_data[2] = yyvsp[-1].val;
- yyval.val = ((yyvsp[-7].tptr->fnctptr)(&yyval)); yyval.type = NUM;;
+{yyval.val = syntax_level ? syntax_level->clval : 0.0; yyval.type = NUM;;
break;}
case 55:
-{yyval.type = NUM; yyval.val = ((yyvsp[-3].tptr->fnctptr)(&yyvsp[-1], &yyval, 0L));;
+{yyval.val = _PI; yyval.type = NUM;;
break;}
case 56:
-{yyval.type = NUM; yyvsp[-1].text = string_value(&yyvsp[-1]); yyval.val = ((yyvsp[-3].tptr->fnctptr)(&yyvsp[-1], &yyval, 0L));;
+{yyval.val = 2.71828182845905; yyval.type = NUM;;
break;}
case 57:
-{yyval.val = ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;;
+{if(yyvsp[0].tptr)yyvsp[0].tptr->GetValue(&yyval);;
break;}
case 58:
-{yyval.val = ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;;
+{if(block_res = eval(&yyval, &yyvsp[0]))return block_res;;
break;}
case 59:
-{yyval.val = ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;;
+{if(yyvsp[-2].tptr)yyvsp[-2].tptr->SetValue(&yyval, &yyvsp[0]);;
break;}
case 60:
-{yyval.val = ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;;
+{if(yyvsp[-2].tptr)yyvsp[-2].tptr->SetValue(&yyval, &yyvsp[0]);;
break;}
case 61:
-{yyval.val = ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;;
+{if(yyvsp[-2].tptr){yyvsp[-2].tptr->GetValue(&yyval); yyvsp[-2].tptr->SetValue(yyval.val + yyvsp[0].val);};
break;}
case 62:
-{yyval.val = ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;;
+{if(yyvsp[-2].tptr){yyvsp[-2].tptr->GetValue(&yyval); yyvsp[-2].tptr->SetValue(yyval.val - yyvsp[0].val);};
break;}
case 63:
-{yyval.val = ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;;
+{if(yyvsp[-2].tptr){yyvsp[-2].tptr->GetValue(&yyval); yyvsp[-2].tptr->SetValue(yyval.val * yyvsp[0].val);};
break;}
case 64:
-{yyval.val = ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;;
+{if(yyvsp[-2].tptr){yyvsp[-2].tptr->GetValue(&yyval); yyvsp[-2].tptr->SetValue(yyvsp[0].val != 0.0 ? yyval.val / yyvsp[0].val :
+ (getsym(HashValue((unsigned char*)"zdiv"), Hash2((unsigned char*)"zdiv")))->GetValue());};
break;}
case 65:
-{range_array2(&yyvsp[-3], &yyvsp[-1]);yyval.val = ((*yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyvsp[-1], 0L)); yyval.type = NUM;;
+{yyval.val = yyvsp[-3].tptr->fnctptr ? ((yyvsp[-3].tptr->fnctptr)(yyvsp[-1].val)): 0.0; yyval.type = NUM;;
break;}
case 66:
-{range_array2(&yyvsp[-5], &yyvsp[-3]); yyval.val = ((*yyvsp[-7].tptr->fnctptr)(&yyvsp[-5], &yyvsp[-3], yyvsp[-1].text)); yyval.type = NUM;;
+{yyval.val = yyvsp[-3].tptr->fnctptr ? ((yyvsp[-3].tptr->fnctptr)(proc_clause(&yyvsp[-1]))) : 0.0; yyval.type = NUM; yyval.a_data = 0L; yyval.a_count = 0; yyval.text = 0L;;
break;}
case 67:
-{yyval.val=((*yyvsp[-5].tptr->fnctptr)(proc_clause(&yyvsp[-3]), proc_clause(&yyvsp[-1]), 0L));;
+{ if(!yyval.a_data){yyval.a_data=PushArray((double*)malloc(sizeof(double)));yyval.a_data[0]=yyvsp[-3].val;yyval.a_count=1;}
+ push(&yyval, &yyvsp[-1]);yyval.val = yyvsp[-5].tptr->fnctptr ?((yyvsp[-5].tptr->fnctptr)(&yyval)):0.0; yyval.type = NUM;;
break;}
case 68:
-{yyval.val=((*yyvsp[-7].tptr->fnctptr)(proc_clause(&yyvsp[-5]), proc_clause(&yyvsp[-3]), yyvsp[-1].text));;
+{ yyval.a_data = PushArray((double*)malloc(3*sizeof(double)));
+ yyval.a_count = 3; yyval.a_data[0] = yyvsp[-5].val; yyval.a_data[1] = yyvsp[-3].val; yyval.a_data[2] = yyvsp[-1].val;
+ yyval.val = yyvsp[-7].tptr->fnctptr ? ((yyvsp[-7].tptr->fnctptr)(&yyval)) : 0.0; yyval.type = NUM;;
break;}
case 69:
-{proc_clause(&yyvsp[-3]); yyval.val=(*yyvsp[-9].tptr->fnctptr)(yyvsp[-7].val, yyvsp[-5].val, &yyvsp[-3], &yyvsp[-1]); yyval.type = NUM;;
+{yyval.type = NUM; yyval.val = yyvsp[-3].tptr->fnctptr ? ((yyvsp[-3].tptr->fnctptr)(&yyvsp[-1], &yyval, 0L)) : 0.0;;
break;}
case 70:
-{yyval.val = ((*yyvsp[-5].tptr->fnctptr)(proc_clause(&yyvsp[-3]), yyvsp[-1].text)); yyval.type = NUM;;
+{yyval.type = NUM; yyvsp[-1].text = string_value(&yyvsp[-1]); yyval.val = yyvsp[-3].tptr->fnctptr ? ((yyvsp[-3].tptr->fnctptr)(&yyvsp[-1], &yyval, 0L)) : 0.0;;
break;}
case 71:
-{(*yyvsp[-2].tptr->fnctptr)(&yyval, 0L);;
+{yyval.val = yyvsp[-5].tptr->fnctptr ? ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;;
break;}
case 72:
-{(*yyvsp[-3].tptr->fnctptr)(&yyval, &yyvsp[-1]);;
+{yyval.val = yyvsp[-5].tptr->fnctptr ?((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;;
break;}
case 73:
-{(*yyvsp[-5].tptr->fnctptr)(&yyval, &yyvsp[-3], &yyvsp[-1]);;
+{yyval.val = yyvsp[-5].tptr->fnctptr ? ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;;
break;}
case 74:
-{(*yyvsp[-5].tptr->fnctptr)(&yyval, &yyvsp[-3], &yyvsp[-1]);;
+{yyval.val = yyvsp[-5].tptr->fnctptr ? ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;;
break;}
case 75:
-{(*yyvsp[-5].tptr->fnctptr)(&yyval, &yyvsp[-3], &yyvsp[-1]);;
+{yyval.val = yyvsp[-5].tptr->fnctptr ? ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;;
break;}
case 76:
-{(*yyvsp[-5].tptr->fnctptr)(&yyval, &yyvsp[-3], &yyvsp[-1]);;
+{yyval.val = yyvsp[-5].tptr->fnctptr ? ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;;
break;}
case 77:
-{(*yyvsp[-7].tptr->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);;
+{yyval.val = yyvsp[-5].tptr->fnctptr ? ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;;
break;}
case 78:
-{(*yyvsp[-7].tptr->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);;
+{yyval.val = yyvsp[-5].tptr->fnctptr ? ((yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;;
break;}
case 79:
-{(*yyvsp[-7].tptr->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);;
+{range_array2(&yyvsp[-3], &yyvsp[-1]);yyval.val = yyvsp[-5].tptr->fnctptr ? ((*yyvsp[-5].tptr->fnctptr)(&yyvsp[-3], &yyvsp[-1], 0L)) : 0.0; yyval.type = NUM;;
break;}
case 80:
-{(*yyvsp[-7].tptr->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);;
+{range_array2(&yyvsp[-5], &yyvsp[-3]); yyval.val = yyvsp[-7].tptr->fnctptr ? ((*yyvsp[-7].tptr->fnctptr)(&yyvsp[-5], &yyvsp[-3], yyvsp[-1].text)) : 0.0; yyval.type = NUM;;
break;}
case 81:
-{(*yyvsp[-7].tptr->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);;
+{yyval.val= yyvsp[-5].tptr->fnctptr ? ((*yyvsp[-5].tptr->fnctptr)(proc_clause(&yyvsp[-3]), proc_clause(&yyvsp[-1]), 0L)) : 0.0;;
break;}
case 82:
-{(*yyvsp[-7].tptr->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);;
+{yyval.val=yyvsp[-7].tptr->fnctptr ? ((*yyvsp[-7].tptr->fnctptr)(proc_clause(&yyvsp[-5]), proc_clause(&yyvsp[-3]), yyvsp[-1].text)) : 0.0;;
break;}
case 83:
-{(*yyvsp[-7].tptr->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);;
+{proc_clause(&yyvsp[-3]); yyval.val=yyvsp[-9].tptr->fnctptr ? (*yyvsp[-9].tptr->fnctptr)(yyvsp[-7].val, yyvsp[-5].val, &yyvsp[-3], &yyvsp[-1]) : 0.0; yyval.type = NUM;;
break;}
case 84:
-{(*yyvsp[-7].tptr->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);;
+{yyval.val = yyvsp[-5].tptr->fnctptr ? ((*yyvsp[-5].tptr->fnctptr)(proc_clause(&yyvsp[-3]), yyvsp[-1].text)) : 0.0; yyval.type = NUM;;
break;}
case 85:
-{if(yyvsp[-2].val != 0.0)eval(&yyval, &yyvsp[0]);;
+{yyval.val = yyvsp[-5].tptr->fnctptr ? ((*yyvsp[-5].tptr->fnctptr)(proc_clause(&yyvsp[-3]), yyvsp[-1].text)) : 0.0; yyval.type = NUM;;
break;}
case 86:
-{yyvsp[-4].val != 0.0 ? eval(&yyval, &yyvsp[-2]) : eval(&yyval, &yyvsp[0]);;
+{if(yyvsp[-2].tptr->fnctptr)(*yyvsp[-2].tptr->fnctptr)(&yyval, 0L);;
break;}
case 87:
-{for(int i=0; i< yy_maxiter; i++){
- eval(&yyval, &yyvsp[-1]);
- if(yyval.val != 0.0)eval(&yyval, &yyvsp[0]);
- else break;};
+{if(yyvsp[-3].tptr->fnctptr)(*yyvsp[-3].tptr->fnctptr)(&yyval, &yyvsp[-1]);;
break;}
case 88:
+{if(yyvsp[-5].tptr->fnctptr)(*yyvsp[-5].tptr->fnctptr)(&yyval, &yyvsp[-3], &yyvsp[-1]);;
+ break;}
+case 89:
+{if(yyvsp[-3].tptr->fnctptr)(*yyvsp[-3].tptr->fnctptr)(&yyval, &yyvsp[-1], 0L);;
+ break;}
+case 90:
+{if(yyvsp[-7].tptr->fnctptr)(*yyvsp[-7].tptr->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);;
+ break;}
+case 91:
{yyval.val = yyvsp[-2].val + yyvsp[0].val; yyval.type = NUM;
if(yyvsp[0].type == DATE1 || yyvsp[-2].type == DATE1) yyval.type = DATE1;
else if(yyvsp[0].type == TIME1 || yyvsp[-2].type == TIME1) yyval.type = TIME1;
else if(yyvsp[0].type == DATETIME1 || yyvsp[-2].type == DATETIME1) yyval.type = DATETIME1;;
break;}
-case 89:
+case 92:
{yyval.val = yyvsp[-2].val - yyvsp[0].val; yyval.type = NUM;
if(yyvsp[0].type == DATE1 || yyvsp[-2].type == DATE1) yyval.type = DATE1;
else if(yyvsp[0].type == TIME1 || yyvsp[-2].type == TIME1) yyval.type = TIME1;
else if(yyvsp[0].type == DATETIME1 || yyvsp[-2].type == DATETIME1) yyval.type = DATETIME1;;
break;}
-case 90:
+case 93:
{yyval.val = yyvsp[-2].val * yyvsp[0].val; yyval.type = NUM;;
break;}
-case 91:
+case 94:
{yyval.type = NUM; if(yyvsp[0].val != 0.0) yyval.val = yyvsp[-2].val / yyvsp[0].val;
else yyval.val = (getsym(HashValue((unsigned char*)"zdiv"), Hash2((unsigned char*)"zdiv")))->GetValue(); ;
break;}
-case 92:
+case 95:
{yyval.val=yyvsp[-1].tptr->GetValue(); yyvsp[-1].tptr->SetValue(yyval.val+1.0); yyval.val -= 1.0; yyval.type = NUM;;
break;}
-case 93:
+case 96:
{yyval.val=yyvsp[-1].tptr->GetValue(); yyvsp[-1].tptr->SetValue(yyval.val-1.0); yyval.val += 1.0; yyval.type = NUM;;
break;}
-case 94:
+case 97:
{yyval.val=yyvsp[0].tptr->GetValue(); yyvsp[0].tptr->SetValue(yyval.val+1.0); yyval.type = NUM;;
break;}
-case 95:
+case 98:
{yyval.val=yyvsp[0].tptr->GetValue(); yyvsp[0].tptr->SetValue(yyval.val-1.0); yyval.type = NUM;;
break;}
-case 96:
+case 99:
{yyval.val = (yyvsp[0].val >0 && yyvsp[0].val/2.0 == floor(yyvsp[0].val/2.0)) ? fabs(pow(yyvsp[-2].val,yyvsp[0].val) ): pow(yyvsp[-2].val, yyvsp[0].val); yyval.type = NUM;;
break;}
-case 97:
+case 100:
{yyval.val = -yyvsp[0].val; yyval.type = NUM;;
break;}
-case 98:
+case 101:
{memcpy(&yyval, &yyvsp[-1], sizeof(YYSTYPE)); yyvsp[-1].a_data = 0L; yyvsp[-1].a_count = 0;;
break;}
-case 99:
+case 102:
{yyval.a_data = PushArray((double*)calloc((int)yyvsp[-1].val, sizeof(double))); yyval.a_count=(int)(yyvsp[-1].val);
yyval.type = ARR; yyvsp[-3].tptr->SetValue(&yyval,&yyval);;
break;}
-case 100:
+case 103:
{if(yyvsp[-3].a_data && yyvsp[-1].val >= 0.0 && yyvsp[-1].val < yyvsp[-3].a_count) yyval.val = yyvsp[-3].a_data[(int)yyvsp[-1].val];
else {yyval.val = 0.0; last_err_desc = "#INDEX";} yyval.type = NUM;;
break;}
-case 101:
+case 104:
{if(yyvsp[-5].a_data && yyvsp[-3].val >= 0.0 && yyvsp[-3].val < yyvsp[-5].a_count) yyval.val = yyvsp[-5].a_data[(int)yyvsp[-3].val] = yyvsp[0].val;
else {yyval.val = 0.0; last_err_desc = "#INDEX";} yyval.type = NUM;;
break;}
-case 102:
-{make_time(&yyval, yyvsp[-4].val, yyvsp[-2].val, yyvsp[0].val+1.0e-10);;
+case 105:
+{if(yyvsp[-5].a_data && yyvsp[-3].val >= 0.0 && yyvsp[-3].val < yyvsp[-5].a_count)
+ yyval.val = yyvsp[-5].a_data[(int)yyvsp[-3].val] += yyvsp[0].val;
+ else {yyval.val = 0.0; last_err_desc = "#INDEX";} yyval.type = NUM;;
break;}
-case 103:
-{make_time(&yyval, yyvsp[-4].val, yyvsp[-2].val, yyvsp[0].val+1.0e-10);;
+case 106:
+{if(yyvsp[-5].a_data && yyvsp[-3].val >= 0.0 && yyvsp[-3].val < yyvsp[-5].a_count)
+ yyval.val = yyvsp[-5].a_data[(int)yyvsp[-3].val] -= yyvsp[0].val;
+ else {yyval.val = 0.0; last_err_desc = "#INDEX";} yyval.type = NUM;;
break;}
-case 104:
-{make_time(&yyval, yyvsp[-2].val, yyvsp[0].val, 1.0e-10);;
+case 107:
+{if(yyvsp[-5].a_data && yyvsp[-3].val >= 0.0 && yyvsp[-3].val < yyvsp[-5].a_count)
+ yyval.val = yyvsp[-5].a_data[(int)yyvsp[-3].val] *= yyvsp[0].val;
+ else {yyval.val = 0.0; last_err_desc = "#INDEX";} yyval.type = NUM;;
break;}
-case 105:
+case 108:
+{if(yyvsp[-5].a_data && yyvsp[-3].val >= 0.0 && yyvsp[-3].val < yyvsp[-5].a_count){
+ if(yyvsp[0].val != 0.0) yyval.val = yyvsp[-5].a_data[(int)yyvsp[-3].val] /= yyvsp[0].val;
+ else {yyval.val = (getsym(HashValue((unsigned char*)"zdiv"), Hash2((unsigned char*)"zdiv")))->GetValue();}}
+ else {yyval.val = 0.0; last_err_desc = "#INDEX";} yyval.type = NUM;;
+ break;}
+case 109:
+{make_time(&yyval, yyvsp[-4].val, yyvsp[-2].val, yyvsp[0].val+1.0e-10);;
+ break;}
+case 110:
{make_time(&yyval, yyvsp[-2].val, yyvsp[0].val, 1.0e-10);;
break;}
-case 106:
+case 111:
{memcpy(&yyval, yyvsp[-4].val != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE));
break;}
-case 107:
+case 112:
{memcpy(&yyval, yyvsp[-4].val != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE));
break;}
-case 108:
+case 113:
{memcpy(&yyval, yyvsp[-4].val != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE));
break;}
-case 109:
+case 114:
{memcpy(&yyval, yyvsp[-4].val != 0.0 ? &yyvsp[-2] : &yyvsp[0], sizeof(YYSTYPE));
break;}
}
@@ -1845,7 +1841,7 @@ symrec::GetValue(void *re)
res->text = 0L; break;
case ET_TEXT:
res->type = STR; res->val = 0.0;
- if(ares.text) res->text = PushString(text = strdup(ares.text));
+ if(ares.text) res->text = PushString(text = (char*)memdup(ares.text, (int)strlen(ares.text)+1, 0));
else res->text = 0L; break;
default:
res->type = NUM; res->val = var;
@@ -1859,15 +1855,19 @@ symrec::GetValue(void *re)
}
if(!isValid) NoInit();
if(a_data && a_count) {
+ if(text && text[0]) res->text = PushString(text);
+ else res->text = 0L;
res->a_data = a_data; res->a_count = a_count;
res->val = 0.0; res->type = ARR;
}
else if(text && text[0]) {
res->text = PushString(text);
- res->val = var; res->type = STR;
+ res->a_data = 0L; res->a_count = 0;
+ res->val = 0.0; res->type = STR;
}
else {
res->type = NUM; res->val = var;
+ res->a_data = 0L; res->a_count = 0;
res->text = 0L;
}
}
@@ -1901,7 +1901,13 @@ symrec::SetValue(void* d, void* s)
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);
+ else {
+ if(curr_data->SetValue(row, col, src->val))
+ switch(src->type) {
+ case BOOLVAL:
+ curr_data->etRows[row][col]->type = ET_BOOL; break;
+ }
+ }
curr_data->Command(CMD_UPDATE, 0L, 0L);
}
isValid = true;
@@ -2003,7 +2009,7 @@ static void store_res(YYSTYPE *res)
if(last_err_desc) {
line_res.type = ET_TEXT;
line_res.value = 0.0;
- strcpy(res_txt, last_err_desc);
+ rlp_strcpy(res_txt, 1000, last_err_desc);
}
else if(res->type == NUM){
line_res.type = ET_VALUE;
@@ -2028,7 +2034,7 @@ static void store_res(YYSTYPE *res)
else if(res->type == STR) {
line_res.type = ET_TEXT;
line_res.value = 0.0;
- if(res->text) strcpy(res_txt, res->text);
+ if(res->text) rlp_strcpy(res_txt, 1000, res->text);
}
else if((res->type == ARR || (res->a_data)) && res->a_count == 1) {
line_res.type = ET_VALUE;
@@ -2041,12 +2047,14 @@ static void store_res(YYSTYPE *res)
else if(res->type == ARR || (res->a_data)) {
line_res.type = ET_TEXT;
line_res.value = 0.0;
- strcpy(res_txt, "#ARRAY");
+ line_res.a_data = res->a_data;
+ line_res.a_count = res->a_count;
+ rlp_strcpy(res_txt, 1000, "#ARRAY");
}
else if(res->tptr && res->tptr->type == TXT) {
line_res.type = ET_TEXT;
line_res.value = 0.0;
- if(res->tptr->text) strcpy(res_txt, res->tptr->text);
+ if(res->tptr->text) rlp_strcpy(res_txt, 1000, res->tptr->text);
}
else {
line_res.type = ET_VALUE;
@@ -2088,7 +2096,11 @@ static char *string_value(YYSTYPE *exp)
st1 = exp->tptr->text;
}
else {
+#ifdef USE_WIN_SECURE
+ sprintf_s(tmp, 50, "%g", exp->val);
+#else
sprintf(tmp,"%g", exp->val);
+#endif
st1 = tmp;
}
return PushString(st1);
@@ -2115,51 +2127,53 @@ static void pop_syntax()
}
}
-static void eval(YYSTYPE *dst, YYSTYPE *sr)
+static int eval(YYSTYPE *dst, YYSTYPE *sr)
{
char *s_buffer;
- int s_buff_pos, s_yychar, s_yynerrs, length;
+ int s_buff_pos, s_yychar, s_yynerrs, length, parse_res;
anyResult *ar;
- if(!sr || !sr->text) return;
- parse_level++;
+ if(!sr || !sr->text || !sr->text[0]) return 1;
s_buffer = buffer; s_buff_pos = buff_pos;
- s_yychar = yychar; s_yynerrs = yynerrs;
- if (sr->text && (length=(int)strlen(sr->text)) && (buffer = (char*)malloc(length+2))) {
- strcpy(buffer, sr->text); buffer[length++] = ';';
- buffer[length] = 0; buff_pos = 0;
- do {
- yyparse();
- }while(buff_pos < length);
- free(buffer); ar = &line_res;
+ s_yychar = yychar; s_yynerrs = yynerrs;
+ if(!(length = (int)strlen(sr->text)))return 1;
+ parse_level++;
+ if(sr->text[length-1] == ';') buffer = sr->text;
+ else {
+ buffer = (char*)malloc(length+2);
+ rlp_strcpy(buffer, length+1, sr->text);
+ buffer[length++] = ';'; buffer[length] = 0;
+ }
+ if(buffer && buffer[0]){
+ buff_pos = 0;
+ while(!(parse_res = yyparse()) && buff_pos < length);
+ if(buffer != sr->text) free(buffer);
+ ar = &line_res;
buffer = s_buffer; buff_pos = s_buff_pos;
- yychar = s_yychar; yynerrs = s_yynerrs;
+ yychar = s_yychar; yynerrs = s_yynerrs;
}
- else return;
- yylval.a_data = 0L; yylval.a_count = 0;
+ else return 1;
+ dst->a_data = ar->a_data; dst->a_count = ar->a_count;
+ if(parse_res == 2) return 2;
+ else if(parse_res == 3 && sr->type == IBLOCK) return 3;
+ else if(parse_res == 1) return 1;
switch(ar->type) {
case ET_BOOL:
- dst->type = BOOLVAL;
- dst->val = ar->value;
- dst->text = 0L;
- break;
+ dst->type = BOOLVAL; dst->val = ar->value;
+ dst->text = 0L; break;
case ET_VALUE:
- dst->type = NUM;
- dst->val = ar->value;
- dst->text = 0L;
- break;
+ dst->type = NUM; dst->val = ar->value;
+ dst->text = 0L; break;
case ET_TEXT:
- dst->type = STR;
- dst->val = 0.0;
+ 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;
+ dst->type = NUM; dst->val = 0.0;
+ dst->text = 0L; break;
}
parse_level--;
+ return 0;
}
// more functions
@@ -2532,7 +2546,7 @@ static double lognorminv(YYSTYPE *sr)
if(!sr) return 0.0;
sr->val = 0.0;
if(sr->a_data && sr->a_count == 3) {
- sr->val = distinv(lognorm_dist, sr->a_data[1], sr->a_data[2], sr->a_data[0], sr->a_data[1]);
+ sr->val = distinv(lognorm_dist, sr->a_data[1], sr->a_data[2], sr->a_data[0], exp(sr->a_data[1]));
}
else yyargserr("Wrong number of arguments\nin call to lognorminv(p, mean, SD).");
return sr->val;
@@ -2662,12 +2676,23 @@ static double finv(YYSTYPE *sr)
return sr->val;
}
+static double ksdist(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2){
+ sr->val = ks_dist((int)sr->a_data[0], sr->a_data[1]);
+ }
+ else yyargserr("Wrong number of arguments\nin call to ksdist(n, D).");
+ 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);
+ sr1->val = sr2->val = d_pearson(sr1->a_data, sr2->a_data, sr1->a_count, dest, curr_data, 0L);
}
else yyargserr("Bad arguments in call to function\npearson(range1; range2 [;\"dest\"]).");
return sr1->val;
@@ -2678,7 +2703,7 @@ 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);
+ sr1->val = sr2->val = d_spearman(sr1->a_data, sr2->a_data, sr1->a_count, dest, curr_data, 0L);
}
else yyargserr("Bad arguments in call to function\nspearman(range1; range2 [;\"dest\"]).");
return sr1->val;
@@ -2689,7 +2714,7 @@ static double kendall(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_kendall(sr1->a_data, sr2->a_data, sr1->a_count, dest, curr_data);
+ sr1->val = sr2->val = d_kendall(sr1->a_data, sr2->a_data, sr1->a_count, dest, curr_data, 0L);
}
else yyargserr("Bad arguments in call to function\nkendall(range1; range2 [;\"dest\"]).");
return sr1->val;
@@ -2762,6 +2787,34 @@ static double ftest(YYSTYPE *sr1, YYSTYPE *sr2, char *dest)
return sr1->val;
}
+static double p_tukey(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0;
+ if(sr->a_data && sr->a_count == 4){
+ sr->val = ptukey(sr->a_data[0], sr->a_data[3], sr->a_data[1], sr->a_data[2], 1, 0);
+ }
+ else if(sr->a_data && sr->a_count == 3){
+ sr->val = ptukey(sr->a_data[0], 1.0, sr->a_data[1], sr->a_data[2], 1, 0);
+ }
+ else yyargserr("Wrong number of arguments\nin call to ptukey(q, nm, df[, nr = 1]).");
+ return sr->val;
+}
+
+static double q_tukey(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0;
+ if(sr->a_data && sr->a_count == 4){
+ sr->val = qtukey(sr->a_data[0], sr->a_data[3], sr->a_data[1], sr->a_data[2], 1, 0);
+ }
+ else if(sr->a_data && sr->a_count == 3){
+ sr->val = qtukey(sr->a_data[0], 1.0, sr->a_data[1], sr->a_data[2], 1, 0);
+ }
+ else yyargserr("Wrong number of arguments\nin call to qtukey(p, nm, df[, nr = 1]).");
+ return sr->val;
+}
+
static double fill(YYSTYPE *sr, char *dest)
{
AccRange *ar;
@@ -2905,10 +2958,11 @@ static void ftime(YYSTYPE *dst, YYSTYPE *src)
dst->type = TIME1; dst->val = src->val;
}
-static void asort(YYSTYPE *dst, YYSTYPE *src)
+static void invert(YYSTYPE *dst, YYSTYPE *src)
{
+ int i;
+
if(!dst || !src) return;
- dst->type = ARR;
switch(src->a_count) {
case 0:
dst->a_data = PushArray((double*)malloc(sizeof(double)));
@@ -2921,46 +2975,70 @@ static void asort(YYSTYPE *dst, YYSTYPE *src)
default:
dst->a_data = PushArray((double*)memdup(src->a_data, src->a_count * sizeof(double), 0));
dst->a_count = src->a_count;
- SortArray(dst->a_count, dst->a_data);
+ for(i = 0; i < src->a_count; i++) dst->a_data[i] = src->a_data[src->a_count-1-i];
}
}
-static void _crank(YYSTYPE *dst, YYSTYPE *src)
+static void asort(YYSTYPE *dst, YYSTYPE *src)
{
- double tmp;
-
if(!dst || !src) return;
dst->type = ARR;
switch(src->a_count) {
- case 0: case 1:
+ case 0:
dst->a_data = PushArray((double*)malloc(sizeof(double)));
- dst->a_count = 1; dst->a_data[0] = dst->val = 1;
+ dst->a_count = 1; dst->a_data[0] = dst->val = src->val;
+ break;
+ case 1:
+ dst->a_data = PushArray((double*)malloc(sizeof(double)));
+ dst->a_count = 1; dst->a_data[0] = dst->val = src->a_data[0];
break;
default:
dst->a_data = PushArray((double*)memdup(src->a_data, src->a_count * sizeof(double), 0));
dst->a_count = src->a_count;
- crank(dst->a_count, dst->a_data, &tmp);
+ SortArray(dst->a_count, dst->a_data);
}
}
+static void asort2(YYSTYPE *res, YYSTYPE *sr1, YYSTYPE *sr2, char *fmt)
+{
+ int n;
+
+ res->val = 0.0; res->type = NUM;
+ if(!sr1 || !sr2 || !sr1->a_data || !sr2->a_data) return;
+ n = sr1->a_count > sr2->a_count ? sr2->a_count : sr1->a_count;
+ res->val = (double)n;
+ if(n >1) SortArray2(n, sr1->a_data, sr2->a_data);
+ return;
+}
+
+static double _crank(YYSTYPE *src)
+{
+ double tmp = -1.0;
+
+ if(!src) return tmp;
+ tmp = 0.0;
+ if(src->a_data && src->a_count > 1.0)crank(src->a_count, src->a_data, &tmp);
+ return tmp;
+}
+
static void ltrim(YYSTYPE *dst, YYSTYPE *src)
{
if(!src || !dst || !src->text) return;
- dst->text = PushString(str_ltrim(strdup(src->text)));
+ dst->text = PushString(str_ltrim(src->text));
dst->type = STR; dst->val = 0.0;
}
static void rtrim(YYSTYPE *dst, YYSTYPE *src)
{
if(!src || !dst || !src->text) return;
- dst->text = PushString(str_rtrim(strdup(src->text)));
+ dst->text = PushString(str_rtrim(src->text));
dst->type = STR; dst->val = 0.0;
}
static void trim(YYSTYPE *dst, YYSTYPE *src)
{
if(!src || !dst || !src->text) return;
- dst->text = PushString(str_trim(strdup(src->text)));
+ dst->text = PushString(str_trim(src->text));
dst->type = STR; dst->val = 0.0;
}
@@ -3063,6 +3141,59 @@ static void uc_word(YYSTYPE *dst, YYSTYPE *src)
else dst->text = 0L;
}
+static void exec(YYSTYPE *dst, YYSTYPE *src1, YYSTYPE *src2)
+{
+ char *cmd = 0L;
+ int cmd_pos = 0, cmd_size, r, c;
+ AccRange *ar = 0L;
+ anyResult res, *eres;
+
+ if(!src1 || !src1->text || !src1->text[0]) return;
+ if((cmd =(char*)malloc((cmd_size = 1000) * sizeof(char))) && (ar = new AccRange(src1->text))) {
+ if(src2 && src2->text[0] && src2->text[0]) {
+ add_to_buff(&cmd, &cmd_pos, &cmd_size, src2->text, 0);
+ while(cmd_pos && cmd[cmd_pos-1] < 33) cmd_pos--;
+ if(cmd_pos && cmd[cmd_pos-1] != ';') cmd[cmd_pos++] = ';';
+ }
+ cmd[cmd_pos] = 0;
+ ar->GetFirst(&c, &r); ar->GetNext(&c, &r);
+ do {
+ curr_data->GetResult(&res, r, c, false);
+ switch(res.type) {
+ case ET_VALUE: //numerical value
+ if(res.value == -HUGE_VAL)
+ add_to_buff(&cmd, &cmd_pos, &cmd_size, "-inf", 4);
+ else if(res.value == HUGE_VAL)
+ add_to_buff(&cmd, &cmd_pos, &cmd_size, "inf", 3);
+ else add_dbl_to_buff(&cmd, &cmd_pos, &cmd_size, res.value, false);
+ break;
+ case ET_TEXT: //text cell
+ if(res.text && res.text[0]) {
+ if(res.text[0] == res.text[1] && res.text[0] == '/') ar->NextRow(&r);
+ else add_to_buff(&cmd, &cmd_pos, &cmd_size, res.text, 0);
+ }
+ break;
+ }
+ }while(ar->GetNext(&c, &r));
+ eres = do_formula(curr_data, cmd);
+ switch(eres->type) {
+ case ET_BOOL:
+ dst->type = BOOLVAL; dst->val = eres->value;
+ dst->text = 0L; break;
+ case ET_VALUE:
+ dst->type = NUM; dst->val = eres->value;
+ dst->text = 0L; break;
+ case ET_TEXT:
+ dst->type = STR; dst->val = 0.0;
+ dst->text = PushString(eres->text); break;
+ default:
+ dst->type = NUM; dst->val = 0.0;
+ dst->text = 0L; break;
+ }
+ }
+ if(cmd) free(cmd); if(ar) delete ar;
+}
+
// Store strings in a list
static char **str_list = 0L;
static int n_str = 0;
@@ -3071,7 +3202,7 @@ static char *PushString(char *text)
{
if(text && text[0]) {
if(str_list = (char**)realloc(str_list, sizeof(char*)*(n_str+1)))
- str_list[n_str] = strdup(text);
+ str_list[n_str] = (char*)memdup(text, (int)strlen(text)+1, 0);
return str_list[n_str++];
}
return 0L;
@@ -3084,9 +3215,10 @@ static int n_arr = 0;
static double *PushArray(double *arr)
{
if(arr) {
- if(arr_list = (double**)realloc(arr_list, sizeof(double*)*(n_arr+1)))
+ if(arr_list = (double**)realloc(arr_list, sizeof(double*)*(n_arr+1))){
arr_list[n_arr] = arr;
- return arr_list[n_arr++];
+ return arr_list[n_arr++];
+ }
}
return 0L;
}
@@ -3153,6 +3285,7 @@ void InitArithFuncs(DataObj *d)
double (*fnct)(double);
};
fdef fncts[] = {
+ INIT_SYM(AFNCT, "ptukey", p_tukey), INIT_SYM(AFNCT, "qtukey", q_tukey),
INIT_SYM(YYFNC, "toupper", to_upper), INIT_SYM(YYFNC, "tolower", to_lower),
INIT_SYM(YYFNC, "ucfirst", uc_first), INIT_SYM(YYFNC, "ucword", uc_word),
INIT_SYM(SFNCT, "asc", asc), INIT_SYM(YYFNC, "chr", chr),
@@ -3160,7 +3293,7 @@ void InitArithFuncs(DataObj *d)
INIT_SYM(YYFNC2, "strpos",_strpos), INIT_SYM(FUNC4, "classes", classes),
INIT_SYM(AFNCT, "rank", rank), INIT_SYM(YYFNC, "ltrim", ltrim),
INIT_SYM(YYFNC, "rtrim", rtrim), INIT_SYM(YYFNC, "trim", trim),
- INIT_SYM(YYFNC, "asort", asort), INIT_SYM(YYFNC, "crank", _crank),
+ INIT_SYM(YYFNC, "asort", asort), INIT_SYM(AFNCT, "crank", _crank),
INIT_SYM(SRFUNC, "datestr", datestr), INIT_SYM(SFNCT, "dateval", dateval),
INIT_SYM(BFNCT, "leapyear", leapyear), INIT_SYM(YYFNC, "today", today),
INIT_SYM(YYFNC, "now", now), INIT_SYM(FNCT, "year", year),
@@ -3172,7 +3305,7 @@ void InitArithFuncs(DataObj *d)
INIT_SYM(FUNC1, "fill", fill), INIT_SYM(FUNC2, "pearson", pearson),
INIT_SYM(FUNC2, "spearman", spearman), INIT_SYM(FUNC2, "kendall", kendall),
INIT_SYM(FUNC2, "correl", pearson), INIT_SYM(FUNC2, "regression", regression),
- INIT_SYM(FUNC2, "covar", covar),
+ INIT_SYM(FUNC2, "covar", covar), INIT_SYM(YYFNC2, "exec", exec),
INIT_SYM(FUNC3, "utest", utest), INIT_SYM(FUNC2, "ttest2", ttest2),
INIT_SYM(FUNC3, "ttest", ttest), INIT_SYM(FUNC3, "ftest", ftest),
INIT_SYM(AFNCT, "variance", variance), INIT_SYM(AFNCT, "stdev", stdev),
@@ -3183,24 +3316,21 @@ void InitArithFuncs(DataObj *d)
INIT_SYM(AFNCT, "median", quartile2), INIT_SYM(AFNCT, "quartile1", quartile1),
INIT_SYM(AFNCT, "quartile2",quartile2), INIT_SYM(AFNCT, "quartile3", quartile3),
INIT_SYM(AFNCT, "gmean", gmean), INIT_SYM(AFNCT, "hmean", hmean),
- INIT_SYM(AFNCT, "tdist", tdist),
- INIT_SYM(AFNCT, "tfreq", tfreq),
- INIT_SYM(AFNCT, "tinv", tinv),
+ INIT_SYM(AFNCT, "tdist", tdist), INIT_SYM(AFNCT, "tfreq", tfreq),
+ INIT_SYM(AFNCT, "tinv", tinv), INIT_SYM(YYFNC, "invert", invert),
INIT_SYM(AFNCT, "poisdist", poisdist), INIT_SYM(AFNCT, "poisfreq", poisfreq),
INIT_SYM(AFNCT, "expdist", expdist), INIT_SYM(AFNCT, "expfreq", expfreq),
- INIT_SYM(AFNCT, "expinv", expinv),
- INIT_SYM(AFNCT, "fdist", fdist),
- INIT_SYM(AFNCT, "ffreq", ffreq),
+ INIT_SYM(AFNCT, "expinv", expinv), INIT_SYM(AFNCT, "fdist", fdist),
+ INIT_SYM(AFNCT, "ffreq", ffreq), INIT_SYM(AFNCT, "ksdist", ksdist),
INIT_SYM(AFNCT, "finv", finv), INIT_SYM(AFNCT, "gammp", _gammp),
INIT_SYM(AFNCT, "gammq", _gammq), INIT_SYM(AFNCT, "beta", beta),
INIT_SYM(AFNCT, "betai", _betai), INIT_SYM(AFNCT, "bincof", _bincof),
- INIT_SYM(AFNCT, "binomdist",binomdist),
- INIT_SYM(AFNCT, "binomfreq",binomfreq),
+ INIT_SYM(AFNCT, "binomdist",binomdist), INIT_SYM(AFNCT, "binomfreq",binomfreq),
INIT_SYM(AFNCT, "normdist", normdist),
INIT_SYM(AFNCT, "norminv", norminv), INIT_SYM(AFNCT, "normfreq", normfreq),
INIT_SYM(AFNCT, "lognormdist", lognormdist), INIT_SYM(AFNCT, "lognormfreq", lognormfreq),
INIT_SYM(AFNCT, "lognorminv",lognorminv), INIT_SYM(AFNCT, "chidist", chidist),
- INIT_SYM(AFNCT, "chifreq", chifreq),
+ INIT_SYM(AFNCT, "chifreq", chifreq), INIT_SYM(YYFNC2, "asort2", asort2),
INIT_SYM(AFNCT, "chiinv", chiinv), INIT_SYM(SFNCT, "strlen", _strlen),
INIT_SYM(YYFNC, "eval", eval), INIT_SYM(FNCT, "erf", errf),
INIT_SYM(FNCT, "erfc", errfc), INIT_SYM(FNCT, "sign", sign),
@@ -3403,7 +3533,7 @@ static YYSTYPE *proc_clause(YYSTYPE *res)
if(!syntax_level) break;
syntax_level->clval = res->a_data[i];
yyparse();
- if(line_res.type == ET_VALUE && line_res.value != 0.0) n_data[n++] = res->a_data[i];
+ if((line_res.type == ET_VALUE || line_res.type == ET_BOOL) && line_res.value != 0.0) n_data[n++] = res->a_data[i];
}
res->a_data = n_data; res->a_count = n;
res->text=0L;
@@ -3515,16 +3645,28 @@ static int is_ttoken(unsigned int h_nam, unsigned int h2_nam)
if(h2_nam == 5220) return CLVAL;
break;
case 362:
- if(h2_nam == 42878) return IF;
+ if(h2_nam == 42878) return (syntax_level->last_tok = IF);
break;
case 28421:
if(h2_nam == 82147317) return (syntax_level->last_tok = WHILE);
break;
+ case 1518:
+ if(h2_nam == 20654586) return (syntax_level->last_tok = FOR);
+ break;
+ case 370:
+ if(h2_nam == 46206) return INARR;
+ break;
case 1457:
if(h2_nam == 18357885) return DIM;
break;
+ case 108774:
+ if(h2_nam == 0x27d5d1fe) return (syntax_level->last_tok = RETURN);
+ break;
+ case 23583:
+ if(h2_nam == 0x954f67ff) return BREAK;
+ break;
case 6033:
- if((h2_nam & 0x7fffffff) == 0x6371377d) return ELSE;
+ if((h2_nam & 0x7fffffff) == 0x6371377d) return (syntax_level->last_tok = ELSE);
break;
case 7097:
if((h2_nam & 0x7fffffff) == 0x550a2d65) return BTRUE;
@@ -3547,6 +3689,8 @@ static char *copy_block()
first[0] = '{'; last[0] = '}'; break;
case '(':
first[0] = '('; last[0] = ')'; break;
+ default:
+ first[0] = '\0'; last[0] = ';'; break;
}
if(!(res = (char*)malloc(strlen(src)+2))) return 0L;
for(i = 1, level = mode = j = 0; src[i]; i++) {
@@ -3561,7 +3705,7 @@ static char *copy_block()
if(src[i] == last[level]) {
if(level) level--;
else {
- res[j-1] = 0; buff_pos += j;
+ res[j-1] = ';'; res[j] = 0; buff_pos += j;
return res;
}
}
@@ -3577,25 +3721,103 @@ static char *copy_block()
}
}
}
+ res[j] = ';'; res[j+1] = 0; buff_pos += j;
return res;
}
static symrec *curr_sym;
-static int yylex (void)
+static double for_loop(char *block1, char *block2)
+{
+ char *last_buffer, *bb1, *bb2, *bb3;
+ int i, a_count, last_buff_pos, cb1;
+ double *a_data;
+ YYSTYPE yyres, yysrc;
+ symrec *var;
+
+ if(!block1 || !block1[0]) return 0.0;
+ bb1 = bb2 = bb3 = 0L; parse_level++;
+ cb1 = (int)strlen(block1);
+ last_buffer = buffer; last_buff_pos = buff_pos;
+ buffer = block1; buff_pos = 0;
+ //test for syntax 1
+ bb1 = copy_block();
+ if(buff_pos < cb1) bb2 = copy_block();
+ if(buff_pos < cb1) bb3 = copy_block();
+ if(bb1 && bb2 && bb3) { //syntax 1 found !
+ yysrc.text = bb1; if(bb1[0]) eval(&yyres, &yysrc);
+ for(i = 0; i < yy_maxiter; i++) {
+ yysrc.text = bb2;
+ if(bb2[0]) {
+ eval(&yyres, &yysrc);
+ if(yyres.type != NUM && yyres.type != BOOLVAL) yyres.val = 0.0;
+ }
+ else yyres.val = 1.0;
+ if(yyres.val != 0.0) {
+ if(block2 && block2[0]) {
+ yysrc.text = block2;
+ eval(&yyres, &yysrc);
+ }
+ yysrc.text = bb3;
+ eval(&yyres, &yysrc);
+ }
+ else break;
+ }
+ if(i) last_error = 0L;
+ }
+ //test for syntax 2
+ else if(!bb2) {
+ buff_pos = 0;
+ if (VAR == yylex() && (var = curr_sym) && INARR == yylex() && buffer[buff_pos]){
+ yysrc.text = buffer + buff_pos;
+ eval(&yyres, &yysrc);
+ a_count = yyres.a_count;
+ a_data = yyres.a_data;
+ for(i = 0; i < a_count && i < yy_maxiter; i++) {
+ var->SetValue(a_data[i]);
+ if(block2 && block2[0]) {
+ yysrc.text = block2;
+ eval(&yyres, &yysrc);
+ }
+ }
+ last_error = 0;
+ }
+ else yyerror("parse error");
+ }
+ else yyerror("parse error");
+ if(bb1) free(bb1); if(bb2) free(bb2); if(bb3) free(bb3);
+ buffer = last_buffer; buff_pos = last_buff_pos;
+ parse_level--;
+ return 0.0;
+}
+
+static int yylex()
{
int i, c, tok;
unsigned int h_nam, h2_nam;
char tmp_txt[80], *block;
symrec *s;
+ memset(&yylval, 0, sizeof(YYSTYPE));
while((c = buffer[buff_pos++]) == ' ' || c == '\t'); //get first nonwhite char
if(!c) return 0;
+ //test for implicit block statement
+ if(syntax_level && (syntax_level->last_tok == PBLOCK
+ || syntax_level->last_tok == ELSE || syntax_level->last_tok == RETURN) && c != '{'){
+ buff_pos--;
+ if(block = copy_block()) {
+ yylval.text = PushString(block);
+ free(block);
+ }
+ syntax_level->last_tok = 0;
+ return yylval.type = IBLOCK;
+ }
//test for block statement
if(c == '{') {
if(block = copy_block()) {
yylval.text = PushString(block);
free(block);
}
+ syntax_level->last_tok = 0;
return yylval.type = BLOCK;
}
//test for '..' operator
@@ -3617,14 +3839,30 @@ static int yylex (void)
}
}
tmp_txt[i] = 0;
+#ifdef USE_WIN_SECURE
+ sscanf_s(tmp_txt, "%lf", &yylval.val);
+#else
sscanf(tmp_txt, "%lf", &yylval.val);
+#endif
return yylval.type = NUM;
}
//test for name or stringtoken
- if(c > 31 && (isalpha(c) || c=='$')) {
- for(buff_pos--, i = 0; i < 79 && ((c = buffer[buff_pos]) && c > 31 && (isalnum(c) || c == '$')); buff_pos++) {
+ if(c > 31 && (isalpha(c) || c=='$' || c =='_')) {
+ for(buff_pos--, i = 0; i < 79 && ((c = buffer[buff_pos]) && c > 31 && (isalnum(c) || c == '$' || c == '_')); buff_pos++) {
tmp_txt[i++] = (char)c;
}
+ while(buffer[buff_pos] == ' ' || buffer[buff_pos] == '\t') buff_pos++;
+ if(buffer[buff_pos] == ':' && !(syntax_level && syntax_level->last_tok == '?')){
+ tmp_txt[i++] = buffer[buff_pos++];
+ for(; i < 79 && ((c = buffer[buff_pos]) && c > 31 && (isalnum(c) || c == '$')); buff_pos++) {
+ tmp_txt[i++] = (char)c;
+ }
+ tmp_txt[i] = 0;
+ yylval.text = PushString(tmp_txt);
+ range_array(&yylval, yylval.text);
+ yylval.val = 0.0;
+ return yylval.type = RANGEARR;
+ }
tmp_txt[i] = 0;
h_nam = HashValue((unsigned char*)tmp_txt);
h2_nam = Hash2((unsigned char*)tmp_txt);
@@ -3636,8 +3874,7 @@ static int yylex (void)
if(!(s = getsym(h_nam, h2_nam, tmp_txt))){
s = putsym(h_nam, h2_nam, VAR);
s->SetName(tmp_txt);
- }
-
+ }
curr_sym = yylval.tptr = s; return s->type;
}
//test for string
@@ -3683,33 +3920,45 @@ static int yylex (void)
pop_syntax();
break;
case '(':
- if(syntax_level->last_tok == WHILE){
+ if(syntax_level->last_tok == WHILE || syntax_level->last_tok == FOR
+ || syntax_level->last_tok == IF){
if(block = copy_block()) {
yylval.text = PushString(block);
free(block);
}
- return yylval.type = PBLOCK;
+ return yylval.type = syntax_level->last_tok = PBLOCK;
}
push_syntax();
+ if(syntax_level) syntax_level->last_tok = c;
+ break;
case '?':
if(syntax_level) syntax_level->last_tok = c;
break;
case ':':
if(syntax_level) {
- if(syntax_level->last_tok == '(') return COLR;
- else if(syntax_level->last_tok == '?') return COLC;
+ if(syntax_level->last_tok == '?') return COLC;
}
break;
case ';':
+ if(buff_pos <2)return yylex();
if(syntax_level) {
if(syntax_level->last_tok == '(') return PSEP;
+ else syntax_level->last_tok = 0;
}
break;
+ case '*':
+ if(buffer[buff_pos] == '=') tok = MULEQ;
+ break;
+ case '/':
+ if(buffer[buff_pos] == '=') tok = DIVEQ;
+ break;
case '+':
if(buffer[buff_pos] == '+') tok = INC;
+ else if(buffer[buff_pos] == '=') tok = ADDEQ;
break;
case '-':
if(buffer[buff_pos] == '-') tok = DEC;
+ else if(buffer[buff_pos] == '=') tok = SUBEQ;
break;
}
if(tok) {
@@ -3733,7 +3982,7 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
symrec *sx, *sy;
lfPOINT *new_points;
long npoints = 0;
- int length, res_mode = 0;
+ int length, parse_res, res_mode = 0;
if(x1 < x2) step = fabs(step);
else step = -fabs(step);
@@ -3748,11 +3997,10 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
pop_parser();
return false;
}
- strcpy(buffer, param); buffer[length++] = ';';
+ rlp_strcpy(buffer, length+1, param);
+ buffer[length++] = ';';
buffer[length] = 0; buff_pos = 0;
- do {
- yyparse();
- }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
free(buffer); buffer = 0L;
}
length = (int)strlen(expr);
@@ -3760,9 +4008,7 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
for(x = x1; step > 0.0 ? x <= x2 : x >= x2; x += step) {
if(sx){
sx->SetValue(x); buff_pos = 0;
- do {
- yyparse();
- }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
switch (res_mode) {
case 1:
y = sy->GetValue(); break;
@@ -3784,9 +4030,9 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
*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);
+ if(d) {
+ d->Command(CMD_CLEAR_ERROR, 0L, 0L);
+ d->Command(CMD_REDRAW, 0L, 0L);
}
return true;
}
@@ -3794,7 +4040,7 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
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;
+ int length, parse_res, nr, nc, r, c, res_mode=0;
symrec *sx, *sz, *sy;
double x, y, z;
@@ -3807,11 +4053,10 @@ bool do_func3D(DataObj *d, double x1, double x2, double xstep, double z1, double
pop_parser();
return false;
}
- strcpy(buffer, param); buffer[length++] = ';';
+ rlp_strcpy(buffer, length+1, param);
+ buffer[length++] = ';';
buffer[length] = 0; buff_pos = 0;
- do {
- yyparse();
- }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
free(buffer); buffer = 0L;
}
length = (int)strlen(expr); buffer = expr;
@@ -3821,9 +4066,7 @@ bool do_func3D(DataObj *d, double x1, double x2, double xstep, double z1, double
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);
+ while(!(parse_res = yyparse()) && buff_pos < length);
switch (res_mode) {
case 1:
y = sy->GetValue(); break;
@@ -3848,13 +4091,15 @@ bool do_func3D(DataObj *d, double x1, double x2, double xstep, double z1, double
anyResult *do_formula(DataObj *d, char *expr)
{
- int length;
+ int length, parse_res;
static anyResult ret, *pret = 0L;
if(d) curr_data = d;
ret.type = ET_ERROR; ret.text = 0L;
+ ret.a_data = 0L; ret.a_count = 0;
if(!expr || !expr[0]) {
if(!sym_table) InitArithFuncs(0L);
+ last_error = 0L;
return &ret;
}
push_parser(); //make code reentrant
@@ -3863,14 +4108,13 @@ anyResult *do_formula(DataObj *d, char *expr)
pop_parser();
return &ret;
}
- strcpy(buffer, expr); if(buffer[length-1] != ';') buffer[length++] = ';';
+ rlp_strcpy(buffer, length+1, expr);
+ if(buffer[length-1] != ';') buffer[length++] = ';';
buffer[length] = 0; buff_pos = 0;
- do {
- yyparse();
- }while(buff_pos < length);
+ while(!(parse_res= yyparse()) && buff_pos < length);
ret.type = ET_ERROR; ret.text = 0L;
- if(curr_data && last_error) {
- if(!(strcmp(last_error, "parse error"))) curr_data->Command(CMD_ERROR, 0L, 0L);
+ if(parse_res == 1 && curr_data) {
+ if(last_error && (!(strcmp(last_error, "parse error")))) curr_data->Command(CMD_ERROR, 0L, 0L);
if(last_err_desc) pret = &line_res;
else pret = &ret;
}
@@ -3882,7 +4126,7 @@ anyResult *do_formula(DataObj *d, char *expr)
return pret;
}
-bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy, int r0, int c0)
+bool MoveFormula(DataObj *d, char *of, char *nf, int nfsize, int dx, int dy, int r0, int c0)
{
int length, length2, tok, pos, i;
char *res, desc1[2], desc2[2];
@@ -3895,7 +4139,7 @@ bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy, int r0, int c0)
pop_parser();
return false;
}
- strcpy(buffer, of); buffer[length++] = ';';
+ rlp_strcpy(buffer, length+1, of); buffer[length++] = ';';
buffer[length] = 0; buff_pos = pos = 0;
if(!(res = (char *)calloc(length2 = (length*2+10), sizeof(char))))return false;
length2--;
@@ -3918,7 +4162,7 @@ bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy, int r0, int c0)
case YYFNC2: case YYFNC3:
pos += rlp_strcpy(res+pos, length2-pos, curr_sym->name);
break;
- case COLR: case COLC:
+ case COLC:
res[pos++] = ':';
break;
case PSEP:
@@ -3950,7 +4194,9 @@ bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy, int r0, int c0)
else pos += rlp_strcpy(res+pos, length2-pos, curr_sym->name);
break;
case STR:
- pos += sprintf(res+pos, "\"%s\"", yylval.text && yylval.text[0] ? yylval.text : "");
+ pos += rlp_strcpy(res+pos, length2-pos, "\"");
+ pos += rlp_strcpy(res+pos, length2-pos, yylval.text);
+ pos += rlp_strcpy(res+pos, length2-pos, "\"");
break;
case SER:
res[pos++] = '.'; res[pos++] = '.';
@@ -4000,31 +4246,67 @@ bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy, int r0, int c0)
case IF:
res[pos++] = 'i'; res[pos++] = 'f';
break;
+ case ADDEQ:
+ res[pos++] = '+'; res[pos++] = '=';
+ break;
+ case SUBEQ:
+ res[pos++] = '-'; res[pos++] = '=';
+ break;
+ case MULEQ:
+ res[pos++] = '*'; res[pos++] = '=';
+ break;
+ case DIVEQ:
+ res[pos++] = '/'; res[pos++] = '=';
+ break;
case WHILE:
pos += rlp_strcpy(res+pos, length2-pos, "while");
break;
+ case FOR:
+ pos += rlp_strcpy(res+pos, length2-pos, "for");
+ break;
+ case INARR:
+ pos += rlp_strcpy(res+pos, length2-pos, "in");
+ break;
case ELSE:
pos += rlp_strcpy(res+pos, length2-pos, "else");
break;
+ case RETURN:
+ pos += rlp_strcpy(res+pos, length2-pos, " return");
+ break;
+ case BREAK:
+ pos += rlp_strcpy(res+pos, length2-pos, " break");
+ break;
+ case RANGEARR:
+ for(i = 0; yylval.text[i]; i++) if(yylval.text[i] == ':') {
+ yylval.text[i] = ';'; break;
+ }
+ MoveFormula(d, yylval.text, res+pos, nfsize-pos-2, dx, dy, r0, c0);
+ while(res[pos]) {
+ pos++; if(res[pos] == ';') res[pos] = ':';
+ }
+ break;
case BLOCK:
-#ifdef USE_WIN_SECURE
- pos += sprintf_s(res+pos, TMP_TXT_SIZE-pos, "{%s}", yylval.text && yylval.text[0] ? yylval.text : "");
-#else
- pos += sprintf(res+pos, "{%s}", yylval.text && yylval.text[0] ? yylval.text : "");
-#endif
+ res[pos++] = '{';
+ MoveFormula(d, yylval.text, res+pos, nfsize-pos-2, dx, dy, r0, c0);
+ pos += (int)strlen(res+pos);
+ res[pos++] = '}';
+ break;
+ case IBLOCK:
+ MoveFormula(d, yylval.text, res+pos, nfsize-pos-2, dx, dy, r0, c0);
+ pos += (int)strlen(res+pos);
+ res[pos++] = ';';
break;
case PBLOCK:
-#ifdef USE_WIN_SECURE
- pos += sprintf_s(res+pos, TMP_TXT_SIZE-pos, "(%s)", yylval.text && yylval.text[0] ? yylval.text : "");
-#else
- pos += sprintf(res+pos, "(%s)", yylval.text && yylval.text[0] ? yylval.text : "");
-#endif
+ res[pos++] = '(';
+ MoveFormula(d, yylval.text, res+pos, nfsize-pos-2, dx, dy, r0, c0);
+ pos += (int)strlen(res+pos);
+ res[pos++] = ')';
break;
}
res[pos] = 0;
}while(buff_pos < length);
while((res[pos-1] == ';' || res[pos-1] == ' ') && pos > 0) { res[pos-1] = 0; pos--;}
- strcpy(nf, res); free(res);
+ rlp_strcpy(nf, nfsize, res); free(res);
free(buffer); buffer = 0L;
clear_table();
pop_parser();
@@ -4035,7 +4317,7 @@ static char *txt_formula; //function to fit
static double **parval; //pointers to parameter values
static void fcurve(double x, double z, double **a, double *y, double dyda[], int ma)
{
- int i, length;
+ int i, length, parse_res;
double tmp, y1, y2;
symrec *symx, *symz, *sy=0L;
@@ -4049,7 +4331,7 @@ static void fcurve(double x, double z, double **a, double *y, double dyda[], int
symx->SetValue(x); symz->SetValue(z);
buffer = txt_formula;
buff_pos = 0; length = (int)strlen(txt_formula);
- do { yyparse(); }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
if(sy = getsym(hn_y, h2_y)) *y = sy->GetValue();
else *y = line_res.value;
if(*y == HUGE_VAL || *y == -HUGE_VAL) {
@@ -4062,11 +4344,11 @@ static void fcurve(double x, double z, double **a, double *y, double dyda[], int
tmp = *parval[i];
*parval[i] = tmp*.995;
buff_pos = 0;
- do { yyparse(); }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
y1 = sy ? sy->GetValue() : line_res.value;
*parval[i] = tmp*1.005;
buff_pos = 0;
- do { yyparse(); }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
y2 = sy ? sy->GetValue() : line_res.value;
*parval[i] = tmp;
dyda[i] = (y2-y1)*100.0/tmp;
@@ -4081,7 +4363,8 @@ static void fcurve(double x, double z, double **a, double *y, double dyda[], int
int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr, double conv, int maxiter, double *chi_2)
{
- int length, i, j, k, l, ndata, nparam, r1, r2, r3, c1, c2, c3, *lista, itst, itst1;
+ int length, i, j, k, l, ndata, nparam, r1, r2, r3, c1, c2, c3;
+ int *lista, itst, itst1, parse_res;
symrec *tab1, *tab2, *csr, **parsym;
AccRange *arx, *ary, *arz;
double *x, *y, *z, currx, curry, currz, alamda, chisq, ochisq;
@@ -4141,12 +4424,10 @@ int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr,
free(y); free(x); delete arx; delete ary;
return 0;
}
- strcpy(buffer, *par); buffer[length++] = ';';
+ rlp_strcpy(buffer, length, *par); buffer[length++] = ';';
buffer[length] = 0; buff_pos = 0;
tab1 = sym_table;
- do {
- yyparse();
- }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
tab2 = sym_table; free(buffer); buffer =0L;
for(nparam = 0, csr=tab2; csr != tab1; nparam++, csr = csr->next);
parsym = (symrec**)malloc((nparam+1)*sizeof(symrec*));
@@ -4176,10 +4457,18 @@ int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr,
if(k > 20) {
if(tmp_txt[j-1] == ' ') j--;
if(tmp_txt[j-1] == ';') j--;
+#ifdef USE_WIN_SECURE
+ l = sprintf_s(tmp_txt+j, 500-j, "\n");
+#else
l = sprintf(tmp_txt+j, "\n");
+#endif
j += l; k = 0;
}
+#ifdef USE_WIN_SECURE
+ l += sprintf_s(tmp_txt+j, 500-j, "%s%s=%g;", j && k ? " " : "", parsym[i]->name, parsym[i]->GetValue());
+#else
l += sprintf(tmp_txt+j, "%s%s=%g;", j && k ? " " : "", parsym[i]->name, parsym[i]->GetValue());
+#endif
j += l; k += l;
}
free(*par);
@@ -4187,9 +4476,7 @@ int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr,
if(chi_2) *chi_2 = chisq;
//write back spreadsheet data if necessary
buffer = *par; length = (int)strlen(buffer);
- do {
- yyparse();
- }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
buffer = 0L;
free_dmatrix(alpha, 1, nparam, 1, nparam);
free_dmatrix(covar, 1, nparam, 1, nparam);
@@ -4198,10 +4485,12 @@ int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr,
if(parval) free(parval); if(parsym) free(parsym);
clear_table();
pop_parser();
- if(curr_data){
- curr_data->Command(CMD_CLEAR_ERROR, 0L, 0L);
- curr_data->Command(CMD_REDRAW, 0L, 0L);
+ if(d){
+ d->Command(CMD_CLEAR_ERROR, 0L, 0L);
+ d->Command(CMD_REDRAW, 0L, 0L);
}
return itst < maxiter ? itst+1 : maxiter;
}
+
+
diff --git a/mfcalc.y b/mfcalc.y
index e033364..1676c43 100755
--- a/mfcalc.y
+++ b/mfcalc.y
@@ -70,7 +70,8 @@ typedef struct{
}YYSTYPE;
-static int yy_maxiter = 1000;
+static int yy_maxiter = 100000; //maximum loop count
+static int block_res; //result of eval()
static symrec *putsym (unsigned int h_name, unsigned int h2_name, int sym_type);
static symrec *getsym (unsigned int h_name, unsigned int h2_name, char *sym_name = 0L);
@@ -81,7 +82,7 @@ static double *PushArray(double *arr);
static double *ReallocArray(double *arr, int size);
static char *add_strings(char *st1, char *st2);
static char *string_value(YYSTYPE *exp);
-static void eval(YYSTYPE *dst, YYSTYPE *sr);
+static int eval(YYSTYPE *dst, YYSTYPE *sr);
static int range_array(YYSTYPE * res, char *range);
static int range_array2(YYSTYPE *res1, YYSTYPE *res2);
static void exec_clause(YYSTYPE *res);
@@ -90,9 +91,10 @@ static void yyerror(char *s);
static void make_time(YYSTYPE *dst, double h, double m, double s);
static int yylex(void);
static double nop() {return 0.0;};
+static double for_loop(char *block1, char *block2);
static char res_txt[1000];
-static anyResult line_res = {ET_UNKNOWN, 0.0, res_txt};
+static anyResult line_res = {ET_UNKNOWN, 0.0, res_txt, 0L, 0};
static DataObj *curr_data;
static char *last_error = 0L; //error text
static char *last_err_desc = 0L; //short error description
@@ -104,17 +106,18 @@ static int parse_level = 0; //count reentrances into parser
#define MAX_PARSE 20 //maximum number of reentances
%}
-%token <val> NUM BOOLVAL STR ARR BLOCK PBLOCK PI E CLVAL PSEP IF ELSE
-%token <val> BTRUE BFALSE DATE1 TIME1 DATETIME1 DIM WHILE
+%token <val> NUM BOOLVAL STR ARR BLOCK PBLOCK IBLOCK PI E CLVAL PSEP IF ELSE
+%token <val> BTRUE BFALSE DATE1 TIME1 DATETIME1 DIM WHILE FOR INARR RANGEARR
+%token <val> RETURN BREAK
%token <tptr> VAR FNCT BFNCT AFNCT SFNCT FUNC1 FUNC2 FUNC3 TXT SRFUNC YYFNC
%token <tptr> FUNC4 YYFNC2 YYFNC3
-%type <val> exp str_exp arr bool
+%type <val> exp str_exp arr bool block anyarg
-%right '='
+%right '=' ADDEQ SUBEQ MULEQ DIVEQ
%left ',' /* list separator */
%left CLAUSE /* clause (where) operator */
%left SER
-%right COLR COLC /* range sep., conditional sep. */
+%right COLC /* conditional sep. */
%right '?' /* conditional assignment */
%left AND OR
%left EQ NE GT GE LT LE
@@ -139,6 +142,16 @@ line: '\n' | ';' | ','
| exp ',' {store_res(&yyvsp[-1]); return 0;}
| str_exp '\n' {store_res(&yyvsp[-1]); return 0;}
| str_exp ';' {store_res(&yyvsp[-1]); return 0;}
+ | IF PBLOCK block {if(block_res = eval(&yyval, &yyvsp[-1]))return block_res;
+ if(yyval.val != 0.0) if(block_res = eval(&yyval, &yyvsp[0]))return block_res;}
+ | IF PBLOCK block ELSE block {if(block_res = eval(&yyval, &yyvsp[-3])) return block_res;
+ if(yyval.val != 0.0) {if(block_res = eval(&yyval, &yyvsp[-2])) return block_res;}
+ else if(block_res = eval(&yyval, &yyvsp[0])) return block_res;}
+ | FOR PBLOCK block {for_loop(yyvsp[-1].text, yyvsp[0].text);}
+ | WHILE PBLOCK block {for(int i=0; i< yy_maxiter; i++){ if(block_res = eval(&yyval, &yyvsp[-1]))return block_res;
+ if(yyval.val != 0.0){if(block_res = eval(&yyval, &yyvsp[0]))return block_res;} else break;}}
+ | RETURN IBLOCK {if(block_res = eval(&yyval, &yyvsp[0]) == 1) return 1; else return 2;}
+ | BREAK {return 3;}
| error '\n' {yyerrok;}
;
@@ -147,30 +160,28 @@ str_exp:
|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;}
- |SRFUNC '(' exp ')' {(($1->fnctptr)(&yyval, &yyvsp[-1], 0L)); yyval.type = STR;}
- |SRFUNC '(' exp PSEP str_exp ')' {(($1->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;}
- |SRFUNC '(' exp PSEP exp ')' {(($1->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;}
- |SRFUNC '(' exp ',' str_exp ')' {(($1->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;}
- |SRFUNC '(' exp ',' exp ')' {(($1->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;}
+ |SRFUNC '(' exp ')' {if($1->fnctptr)(($1->fnctptr)(&yyval, &yyvsp[-1], 0L)); yyval.type = STR;}
+ |SRFUNC '(' exp PSEP str_exp ')' {if($1->fnctptr)(($1->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;}
+ |SRFUNC '(' exp PSEP exp ')' {if($1->fnctptr)(($1->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;}
+ |SRFUNC '(' exp ',' str_exp ')' {if($1->fnctptr)(($1->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;}
+ |SRFUNC '(' exp ',' exp ')' {if($1->fnctptr)(($1->fnctptr)(&yyval, &yyvsp[-3], yyvsp[-1].text)); yyval.type = STR;}
;
range:
str_exp {;}
- |VAR COLR VAR {if(yyval.text = PushString(" "))
- sprintf(yyval.text, "%s:%s", $1->name, $3->name); yyval.type = STR;}
;
-arr: ARR
+arr: ARR {;}
|exp {if(!yyval.a_data) {yyval.a_data = PushArray((double*)malloc(sizeof(double))); yyval.a_count = 1; yyval.a_data[0] = yyval.val;}}
|arr ',' arr {push(&yyval, &yyvsp[0]);yyval.type = ARR;}
- |arr CLAUSE exp {exec_clause(&yyval);yyval.type = ARR;}
+ |arr CLAUSE exp {exec_clause(&yyval);yyval.type = ARR;}
|range {range_array(&yyval, yyvsp[0].text);yyval.type = ARR;}
|NUM SER NUM {if($1 < $3 && (yyval.a_data = PushArray((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 ); yyval.type = ARR;}
;
bool: BOOLVAL
- |BFNCT '(' exp ')' {$$ = (($1->fnctptr)($3)); yyval.type = BOOLVAL;}
+ |BFNCT '(' exp ')' {$$ = $1->fnctptr ? (($1->fnctptr)($3)): 0.0; yyval.type = BOOLVAL;}
|BTRUE {$$ = 1.0; yyval.type = BOOLVAL;}
|BFALSE {$$ = 0.0; yyval.type = BOOLVAL;}
|exp AND exp {$$ = (($1 != 0) && ($3 != 0))? 1 : 0; yyval.type = BOOLVAL;}
@@ -183,59 +194,55 @@ bool: BOOLVAL
|exp LE exp {$$ = ($1 <= $3) ? 1 : 0; yyval.type = BOOLVAL;}
;
+block: BLOCK | IBLOCK;
+
+anyarg: exp | str_exp;
+
exp: NUM {$$ = $1; yyval.type = NUM;}
- |bool {$$ = $1; yyval.type = BOOLVAL;}
+ |RANGEARR {yyval.type = ARR;}
+ |bool {$$ = $1; yyval.type = BOOLVAL;}
|TXT {$$ = 0.0;}
|CLVAL {$$ = syntax_level ? syntax_level->clval : 0.0; yyval.type = NUM;}
|PI {$$ = _PI; yyval.type = NUM;}
|E {$$ = 2.71828182845905; yyval.type = NUM;}
- |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)); yyval.type = NUM;}
- |AFNCT '(' arr ')' {$$ = (($1->fnctptr)(proc_clause(&yyvsp[-1]))); yyval.type = NUM;}
+ |VAR {if($1)$1->GetValue(&yyval);}
+ |block {if(block_res = eval(&yyval, &yyvsp[0]))return block_res;}
+ |VAR '=' exp {if($1)$1->SetValue(&yyval, &yyvsp[0]);}
+ |VAR '=' str_exp {if($1)$1->SetValue(&yyval, &yyvsp[0]);}
+ |VAR ADDEQ exp {if($1){$1->GetValue(&yyval); $1->SetValue(yyval.val + $3);}}
+ |VAR SUBEQ exp {if($1){$1->GetValue(&yyval); $1->SetValue(yyval.val - $3);}}
+ |VAR MULEQ exp {if($1){$1->GetValue(&yyval); $1->SetValue(yyval.val * $3);}}
+ |VAR DIVEQ exp {if($1){$1->GetValue(&yyval); $1->SetValue($3 != 0.0 ? yyval.val / $3 :
+ (getsym(HashValue((unsigned char*)"zdiv"), Hash2((unsigned char*)"zdiv")))->GetValue());}}
+ |FNCT '(' exp ')' {$$ = $1->fnctptr ? (($1->fnctptr)($3)): 0.0; yyval.type = NUM;}
+ |AFNCT '(' arr ')' {$$ = $1->fnctptr ? (($1->fnctptr)(proc_clause(&yyvsp[-1]))) : 0.0; yyval.type = NUM; yyval.a_data = 0L; yyval.a_count = 0; yyval.text = 0L;}
|AFNCT '(' exp PSEP arr ')' { if(!yyval.a_data){yyval.a_data=PushArray((double*)malloc(sizeof(double)));yyval.a_data[0]=$3;yyval.a_count=1;}
- push(&yyval, &yyvsp[-1]);$$ = (($1->fnctptr)(&yyval)); yyval.type = NUM;}
+ push(&yyval, &yyvsp[-1]);$$ = $1->fnctptr ?(($1->fnctptr)(&yyval)):0.0; yyval.type = NUM;}
|AFNCT '(' exp PSEP exp PSEP exp ')' { yyval.a_data = PushArray((double*)malloc(3*sizeof(double)));
yyval.a_count = 3; yyval.a_data[0] = $3; yyval.a_data[1] = $5; yyval.a_data[2] = $7;
- $$ = (($1->fnctptr)(&yyval)); yyval.type = NUM;}
- |SFNCT '(' str_exp ')' {yyval.type = NUM; $$ = (($1->fnctptr)(&yyvsp[-1], &yyval, 0L));}
- |SFNCT '(' exp ')' {yyval.type = NUM; yyvsp[-1].text = string_value(&yyvsp[-1]); $$ = (($1->fnctptr)(&yyvsp[-1], &yyval, 0L));}
- |SFNCT '(' str_exp PSEP str_exp ')' {$$ = (($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;}
- |SFNCT '(' exp PSEP str_exp ')' {$$ = (($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;}
- |SFNCT '(' exp PSEP exp ')' {$$ = (($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;}
- |SFNCT '(' str_exp PSEP exp ')' {$$ = (($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;}
- |SFNCT '(' str_exp ',' str_exp ')' {$$ = (($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;}
- |SFNCT '(' exp ',' str_exp ')' {$$ = (($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;}
- |SFNCT '(' str_exp ',' exp ')' {$$ = (($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;}
- |SFNCT '(' exp ',' exp ')' {$$ = (($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)); yyval.type = NUM;}
- |FUNC2 '(' range PSEP range ')' {range_array2(&yyvsp[-3], &yyvsp[-1]);$$ = ((*$1->fnctptr)(&yyvsp[-3], &yyvsp[-1], 0L)); yyval.type = NUM;}
- |FUNC2 '(' range PSEP range PSEP range ')' {range_array2(&yyvsp[-5], &yyvsp[-3]); $$ = ((*$1->fnctptr)(&yyvsp[-5], &yyvsp[-3], yyvsp[-1].text)); yyval.type = NUM;}
- |FUNC3 '(' arr PSEP arr ')' {$$=((*$1->fnctptr)(proc_clause(&yyvsp[-3]), proc_clause(&yyvsp[-1]), 0L));}
- |FUNC3 '(' arr PSEP arr PSEP range ')' {$$=((*$1->fnctptr)(proc_clause(&yyvsp[-5]), proc_clause(&yyvsp[-3]), yyvsp[-1].text));}
- |FUNC4 '(' exp PSEP exp PSEP arr PSEP range ')' {proc_clause(&yyvsp[-3]); $$=(*$1->fnctptr)($3, $5, &yyvsp[-3], &yyvsp[-1]); yyval.type = NUM;}
- |FUNC1 '(' arr PSEP range ')' {$$ = ((*$1->fnctptr)(proc_clause(&yyvsp[-3]), yyvsp[-1].text)); yyval.type = NUM;}
- |YYFNC '(' ')' {(*$1->fnctptr)(&yyval, 0L);}
- |YYFNC '(' arr ')' {(*$1->fnctptr)(&yyval, &yyvsp[-1]);}
- |YYFNC2 '(' exp PSEP exp ')' {(*$1->fnctptr)(&yyval, &yyvsp[-3], &yyvsp[-1]);}
- |YYFNC2 '(' str_exp PSEP exp ')' {(*$1->fnctptr)(&yyval, &yyvsp[-3], &yyvsp[-1]);}
- |YYFNC2 '(' exp PSEP str_exp ')' {(*$1->fnctptr)(&yyval, &yyvsp[-3], &yyvsp[-1]);}
- |YYFNC2 '(' str_exp PSEP str_exp ')' {(*$1->fnctptr)(&yyval, &yyvsp[-3], &yyvsp[-1]);}
- |YYFNC3 '(' str_exp PSEP str_exp PSEP str_exp')' {(*$1->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);}
- |YYFNC3 '(' exp PSEP str_exp PSEP str_exp')' {(*$1->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);}
- |YYFNC3 '(' str_exp PSEP exp PSEP str_exp')' {(*$1->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);}
- |YYFNC3 '(' str_exp PSEP str_exp PSEP exp')' {(*$1->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);}
- |YYFNC3 '(' exp PSEP exp PSEP str_exp')' {(*$1->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);}
- |YYFNC3 '(' exp PSEP str_exp PSEP exp')' {(*$1->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);}
- |YYFNC3 '(' str_exp PSEP exp PSEP exp')' {(*$1->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);}
- |YYFNC3 '(' exp PSEP exp PSEP exp')' {(*$1->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);}
- |IF '(' exp ')' BLOCK {if($3 != 0.0)eval(&yyval, &yyvsp[0]);}
- |IF '(' exp ')' BLOCK ELSE BLOCK {$3 != 0.0 ? eval(&yyval, &yyvsp[-2]) : eval(&yyval, &yyvsp[0]);}
- |WHILE PBLOCK BLOCK {for(int i=0; i< yy_maxiter; i++){
- eval(&yyval, &yyvsp[-1]);
- if(yyval.val != 0.0)eval(&yyval, &yyvsp[0]);
- else break;}}
+ $$ = $1->fnctptr ? (($1->fnctptr)(&yyval)) : 0.0; yyval.type = NUM;}
+ |SFNCT '(' str_exp ')' {yyval.type = NUM; $$ = $1->fnctptr ? (($1->fnctptr)(&yyvsp[-1], &yyval, 0L)) : 0.0;}
+ |SFNCT '(' exp ')' {yyval.type = NUM; yyvsp[-1].text = string_value(&yyvsp[-1]); $$ = $1->fnctptr ? (($1->fnctptr)(&yyvsp[-1], &yyval, 0L)) : 0.0;}
+ |SFNCT '(' str_exp PSEP str_exp ')' {$$ = $1->fnctptr ? (($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;}
+ |SFNCT '(' exp PSEP str_exp ')' {$$ = $1->fnctptr ?(($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;}
+ |SFNCT '(' exp PSEP exp ')' {$$ = $1->fnctptr ? (($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;}
+ |SFNCT '(' str_exp PSEP exp ')' {$$ = $1->fnctptr ? (($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;}
+ |SFNCT '(' str_exp ',' str_exp ')' {$$ = $1->fnctptr ? (($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;}
+ |SFNCT '(' exp ',' str_exp ')' {$$ = $1->fnctptr ? (($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;}
+ |SFNCT '(' str_exp ',' exp ')' {$$ = $1->fnctptr ? (($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;}
+ |SFNCT '(' exp ',' exp ')' {$$ = $1->fnctptr ? (($1->fnctptr)(&yyvsp[-3], &yyval, yyvsp[-1].text)) : 0.0; yyval.type = NUM;}
+ |FUNC2 '(' anyarg PSEP anyarg ')' {range_array2(&yyvsp[-3], &yyvsp[-1]);$$ = $1->fnctptr ? ((*$1->fnctptr)(&yyvsp[-3], &yyvsp[-1], 0L)) : 0.0; yyval.type = NUM;}
+ |FUNC2 '(' anyarg PSEP anyarg PSEP anyarg ')' {range_array2(&yyvsp[-5], &yyvsp[-3]); $$ = $1->fnctptr ? ((*$1->fnctptr)(&yyvsp[-5], &yyvsp[-3], yyvsp[-1].text)) : 0.0; yyval.type = NUM;}
+ |FUNC3 '(' arr PSEP arr ')' {$$= $1->fnctptr ? ((*$1->fnctptr)(proc_clause(&yyvsp[-3]), proc_clause(&yyvsp[-1]), 0L)) : 0.0;}
+ |FUNC3 '(' arr PSEP arr PSEP range ')' {$$=$1->fnctptr ? ((*$1->fnctptr)(proc_clause(&yyvsp[-5]), proc_clause(&yyvsp[-3]), yyvsp[-1].text)) : 0.0;}
+ |FUNC4 '(' exp PSEP exp PSEP arr PSEP range ')' {proc_clause(&yyvsp[-3]); $$=$1->fnctptr ? (*$1->fnctptr)($3, $5, &yyvsp[-3], &yyvsp[-1]) : 0.0; yyval.type = NUM;}
+ |FUNC1 '(' arr PSEP range ')' {$$ = $1->fnctptr ? ((*$1->fnctptr)(proc_clause(&yyvsp[-3]), yyvsp[-1].text)) : 0.0; yyval.type = NUM;}
+ |FUNC1 '(' arr PSEP RANGEARR ')' {$$ = $1->fnctptr ? ((*$1->fnctptr)(proc_clause(&yyvsp[-3]), yyvsp[-1].text)) : 0.0; yyval.type = NUM;}
+ |YYFNC '(' ')' {if($1->fnctptr)(*$1->fnctptr)(&yyval, 0L);}
+ |YYFNC '(' arr ')' {if($1->fnctptr)(*$1->fnctptr)(&yyval, &yyvsp[-1]);}
+ |YYFNC2 '(' anyarg PSEP anyarg ')' {if($1->fnctptr)(*$1->fnctptr)(&yyval, &yyvsp[-3], &yyvsp[-1]);}
+ |YYFNC2 '(' anyarg ')' {if($1->fnctptr)(*$1->fnctptr)(&yyval, &yyvsp[-1], 0L);}
+ |YYFNC3 '(' anyarg PSEP anyarg PSEP anyarg')' {if($1->fnctptr)(*$1->fnctptr)(&yyval, &yyvsp[-5], &yyvsp[-3], &yyvsp[-1]);}
|exp '+' exp {$$ = $1 + $3; yyval.type = NUM;
if(yyvsp[0].type == DATE1 || yyvsp[-2].type == DATE1) yyval.type = DATE1;
else if(yyvsp[0].type == TIME1 || yyvsp[-2].type == TIME1) yyval.type = TIME1;
@@ -253,16 +260,27 @@ exp: NUM {$$ = $1; yyval.type = NUM;}
|DEC VAR %prec PDEC {$$=$2->GetValue(); $2->SetValue($$-1.0); yyval.type = NUM;}
|exp '^' exp {$$ = ($3 >0 && $3/2.0 == floor($3/2.0)) ? fabs(pow($1,$3) ): pow($1, $3); yyval.type = NUM;}
|'-' exp %prec NEG {$$ = -$2; yyval.type = NUM;}
- |'(' arr ')' {memcpy(&yyval, &yyvsp[-1], sizeof(YYSTYPE)); yyvsp[-1].a_data = 0L; yyvsp[-1].a_count = 0;}
+ |'(' anyarg ')' {memcpy(&yyval, &yyvsp[-1], sizeof(YYSTYPE)); yyvsp[-1].a_data = 0L; yyvsp[-1].a_count = 0;}
|DIM VAR %prec PDIM '[' exp ']' {yyval.a_data = PushArray((double*)calloc((int)$4, sizeof(double))); yyval.a_count=(int)($4);
yyval.type = ARR; $2->SetValue(&yyval,&yyval);}
|exp '[' exp ']' {if(yyvsp[-3].a_data && yyvsp[-1].val >= 0.0 && yyvsp[-1].val < yyvsp[-3].a_count) $$ = yyvsp[-3].a_data[(int)yyvsp[-1].val];
else {$$ = 0.0; last_err_desc = "#INDEX";} yyval.type = NUM;}
|exp '[' exp ']' '=' exp {if(yyvsp[-5].a_data && yyvsp[-3].val >= 0.0 && yyvsp[-3].val < yyvsp[-5].a_count) $$ = yyvsp[-5].a_data[(int)yyvsp[-3].val] = $6;
else {$$ = 0.0; last_err_desc = "#INDEX";} yyval.type = NUM;}
- |NUM COLR NUM COLR NUM {make_time(&yyval, $1, $3, $5+1.0e-10);}
+ |exp '[' exp ']' ADDEQ exp {if(yyvsp[-5].a_data && yyvsp[-3].val >= 0.0 && yyvsp[-3].val < yyvsp[-5].a_count)
+ $$ = yyvsp[-5].a_data[(int)yyvsp[-3].val] += $6;
+ else {$$ = 0.0; last_err_desc = "#INDEX";} yyval.type = NUM;}
+ |exp '[' exp ']' SUBEQ exp {if(yyvsp[-5].a_data && yyvsp[-3].val >= 0.0 && yyvsp[-3].val < yyvsp[-5].a_count)
+ $$ = yyvsp[-5].a_data[(int)yyvsp[-3].val] -= $6;
+ else {$$ = 0.0; last_err_desc = "#INDEX";} yyval.type = NUM;}
+ |exp '[' exp ']' MULEQ exp {if(yyvsp[-5].a_data && yyvsp[-3].val >= 0.0 && yyvsp[-3].val < yyvsp[-5].a_count)
+ $$ = yyvsp[-5].a_data[(int)yyvsp[-3].val] *= $6;
+ else {$$ = 0.0; last_err_desc = "#INDEX";} yyval.type = NUM;}
+ |exp '[' exp ']' DIVEQ exp {if(yyvsp[-5].a_data && yyvsp[-3].val >= 0.0 && yyvsp[-3].val < yyvsp[-5].a_count){
+ if($6 != 0.0) $$ = yyvsp[-5].a_data[(int)yyvsp[-3].val] /= $6;
+ else {$$ = (getsym(HashValue((unsigned char*)"zdiv"), Hash2((unsigned char*)"zdiv")))->GetValue();}}
+ else {$$ = 0.0; last_err_desc = "#INDEX";} yyval.type = NUM;}
|NUM ':' NUM ':' NUM {make_time(&yyval, $1, $3, $5+1.0e-10);}
- |NUM COLR NUM {make_time(&yyval, $1, $3, 1.0e-10);}
|NUM ':' NUM {make_time(&yyval, $1, $3, 1.0e-10);}
|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))}
@@ -336,7 +354,7 @@ symrec::GetValue(void *re)
res->text = 0L; break;
case ET_TEXT:
res->type = STR; res->val = 0.0;
- if(ares.text) res->text = PushString(text = strdup(ares.text));
+ if(ares.text) res->text = PushString(text = (char*)memdup(ares.text, (int)strlen(ares.text)+1, 0));
else res->text = 0L; break;
default:
res->type = NUM; res->val = var;
@@ -350,15 +368,19 @@ symrec::GetValue(void *re)
}
if(!isValid) NoInit();
if(a_data && a_count) {
+ if(text && text[0]) res->text = PushString(text);
+ else res->text = 0L;
res->a_data = a_data; res->a_count = a_count;
res->val = 0.0; res->type = ARR;
}
else if(text && text[0]) {
res->text = PushString(text);
- res->val = var; res->type = STR;
+ res->a_data = 0L; res->a_count = 0;
+ res->val = 0.0; res->type = STR;
}
else {
res->type = NUM; res->val = var;
+ res->a_data = 0L; res->a_count = 0;
res->text = 0L;
}
}
@@ -392,7 +414,13 @@ symrec::SetValue(void* d, void* s)
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);
+ else {
+ if(curr_data->SetValue(row, col, src->val))
+ switch(src->type) {
+ case BOOLVAL:
+ curr_data->etRows[row][col]->type = ET_BOOL; break;
+ }
+ }
curr_data->Command(CMD_UPDATE, 0L, 0L);
}
isValid = true;
@@ -494,7 +522,7 @@ static void store_res(YYSTYPE *res)
if(last_err_desc) {
line_res.type = ET_TEXT;
line_res.value = 0.0;
- strcpy(res_txt, last_err_desc);
+ rlp_strcpy(res_txt, 1000, last_err_desc);
}
else if(res->type == NUM){
line_res.type = ET_VALUE;
@@ -519,7 +547,7 @@ static void store_res(YYSTYPE *res)
else if(res->type == STR) {
line_res.type = ET_TEXT;
line_res.value = 0.0;
- if(res->text) strcpy(res_txt, res->text);
+ if(res->text) rlp_strcpy(res_txt, 1000, res->text);
}
else if((res->type == ARR || (res->a_data)) && res->a_count == 1) {
line_res.type = ET_VALUE;
@@ -532,12 +560,14 @@ static void store_res(YYSTYPE *res)
else if(res->type == ARR || (res->a_data)) {
line_res.type = ET_TEXT;
line_res.value = 0.0;
- strcpy(res_txt, "#ARRAY");
+ line_res.a_data = res->a_data;
+ line_res.a_count = res->a_count;
+ rlp_strcpy(res_txt, 1000, "#ARRAY");
}
else if(res->tptr && res->tptr->type == TXT) {
line_res.type = ET_TEXT;
line_res.value = 0.0;
- if(res->tptr->text) strcpy(res_txt, res->tptr->text);
+ if(res->tptr->text) rlp_strcpy(res_txt, 1000, res->tptr->text);
}
else {
line_res.type = ET_VALUE;
@@ -579,7 +609,11 @@ static char *string_value(YYSTYPE *exp)
st1 = exp->tptr->text;
}
else {
+#ifdef USE_WIN_SECURE
+ sprintf_s(tmp, 50, "%g", exp->val);
+#else
sprintf(tmp,"%g", exp->val);
+#endif
st1 = tmp;
}
return PushString(st1);
@@ -606,51 +640,53 @@ static void pop_syntax()
}
}
-static void eval(YYSTYPE *dst, YYSTYPE *sr)
+static int eval(YYSTYPE *dst, YYSTYPE *sr)
{
char *s_buffer;
- int s_buff_pos, s_yychar, s_yynerrs, length;
+ int s_buff_pos, s_yychar, s_yynerrs, length, parse_res;
anyResult *ar;
- if(!sr || !sr->text) return;
- parse_level++;
+ if(!sr || !sr->text || !sr->text[0]) return 1;
s_buffer = buffer; s_buff_pos = buff_pos;
- s_yychar = yychar; s_yynerrs = yynerrs;
- if (sr->text && (length=(int)strlen(sr->text)) && (buffer = (char*)malloc(length+2))) {
- strcpy(buffer, sr->text); buffer[length++] = ';';
- buffer[length] = 0; buff_pos = 0;
- do {
- yyparse();
- }while(buff_pos < length);
- free(buffer); ar = &line_res;
+ s_yychar = yychar; s_yynerrs = yynerrs;
+ if(!(length = (int)strlen(sr->text)))return 1;
+ parse_level++;
+ if(sr->text[length-1] == ';') buffer = sr->text;
+ else {
+ buffer = (char*)malloc(length+2);
+ rlp_strcpy(buffer, length+1, sr->text);
+ buffer[length++] = ';'; buffer[length] = 0;
+ }
+ if(buffer && buffer[0]){
+ buff_pos = 0;
+ while(!(parse_res = yyparse()) && buff_pos < length);
+ if(buffer != sr->text) free(buffer);
+ ar = &line_res;
buffer = s_buffer; buff_pos = s_buff_pos;
- yychar = s_yychar; yynerrs = s_yynerrs;
+ yychar = s_yychar; yynerrs = s_yynerrs;
}
- else return;
- yylval.a_data = 0L; yylval.a_count = 0;
+ else return 1;
+ dst->a_data = ar->a_data; dst->a_count = ar->a_count;
+ if(parse_res == 2) return 2;
+ else if(parse_res == 3 && sr->type == IBLOCK) return 3;
+ else if(parse_res == 1) return 1;
switch(ar->type) {
case ET_BOOL:
- dst->type = BOOLVAL;
- dst->val = ar->value;
- dst->text = 0L;
- break;
+ dst->type = BOOLVAL; dst->val = ar->value;
+ dst->text = 0L; break;
case ET_VALUE:
- dst->type = NUM;
- dst->val = ar->value;
- dst->text = 0L;
- break;
+ dst->type = NUM; dst->val = ar->value;
+ dst->text = 0L; break;
case ET_TEXT:
- dst->type = STR;
- dst->val = 0.0;
+ 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;
+ dst->type = NUM; dst->val = 0.0;
+ dst->text = 0L; break;
}
parse_level--;
+ return 0;
}
// more functions
@@ -1023,7 +1059,7 @@ static double lognorminv(YYSTYPE *sr)
if(!sr) return 0.0;
sr->val = 0.0;
if(sr->a_data && sr->a_count == 3) {
- sr->val = distinv(lognorm_dist, sr->a_data[1], sr->a_data[2], sr->a_data[0], sr->a_data[1]);
+ sr->val = distinv(lognorm_dist, sr->a_data[1], sr->a_data[2], sr->a_data[0], exp(sr->a_data[1]));
}
else yyargserr("Wrong number of arguments\nin call to lognorminv(p, mean, SD).");
return sr->val;
@@ -1153,12 +1189,23 @@ static double finv(YYSTYPE *sr)
return sr->val;
}
+static double ksdist(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0.0;
+ if(sr->a_data && sr->a_count == 2){
+ sr->val = ks_dist((int)sr->a_data[0], sr->a_data[1]);
+ }
+ else yyargserr("Wrong number of arguments\nin call to ksdist(n, D).");
+ 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);
+ sr1->val = sr2->val = d_pearson(sr1->a_data, sr2->a_data, sr1->a_count, dest, curr_data, 0L);
}
else yyargserr("Bad arguments in call to function\npearson(range1; range2 [;\"dest\"]).");
return sr1->val;
@@ -1169,7 +1216,7 @@ 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);
+ sr1->val = sr2->val = d_spearman(sr1->a_data, sr2->a_data, sr1->a_count, dest, curr_data, 0L);
}
else yyargserr("Bad arguments in call to function\nspearman(range1; range2 [;\"dest\"]).");
return sr1->val;
@@ -1180,7 +1227,7 @@ static double kendall(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_kendall(sr1->a_data, sr2->a_data, sr1->a_count, dest, curr_data);
+ sr1->val = sr2->val = d_kendall(sr1->a_data, sr2->a_data, sr1->a_count, dest, curr_data, 0L);
}
else yyargserr("Bad arguments in call to function\nkendall(range1; range2 [;\"dest\"]).");
return sr1->val;
@@ -1253,6 +1300,34 @@ static double ftest(YYSTYPE *sr1, YYSTYPE *sr2, char *dest)
return sr1->val;
}
+static double p_tukey(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0;
+ if(sr->a_data && sr->a_count == 4){
+ sr->val = ptukey(sr->a_data[0], sr->a_data[3], sr->a_data[1], sr->a_data[2], 1, 0);
+ }
+ else if(sr->a_data && sr->a_count == 3){
+ sr->val = ptukey(sr->a_data[0], 1.0, sr->a_data[1], sr->a_data[2], 1, 0);
+ }
+ else yyargserr("Wrong number of arguments\nin call to ptukey(q, nm, df[, nr = 1]).");
+ return sr->val;
+}
+
+static double q_tukey(YYSTYPE *sr)
+{
+ if(!sr) return 0.0;
+ sr->val = 0;
+ if(sr->a_data && sr->a_count == 4){
+ sr->val = qtukey(sr->a_data[0], sr->a_data[3], sr->a_data[1], sr->a_data[2], 1, 0);
+ }
+ else if(sr->a_data && sr->a_count == 3){
+ sr->val = qtukey(sr->a_data[0], 1.0, sr->a_data[1], sr->a_data[2], 1, 0);
+ }
+ else yyargserr("Wrong number of arguments\nin call to qtukey(p, nm, df[, nr = 1]).");
+ return sr->val;
+}
+
static double fill(YYSTYPE *sr, char *dest)
{
AccRange *ar;
@@ -1396,10 +1471,11 @@ static void ftime(YYSTYPE *dst, YYSTYPE *src)
dst->type = TIME1; dst->val = src->val;
}
-static void asort(YYSTYPE *dst, YYSTYPE *src)
+static void invert(YYSTYPE *dst, YYSTYPE *src)
{
+ int i;
+
if(!dst || !src) return;
- dst->type = ARR;
switch(src->a_count) {
case 0:
dst->a_data = PushArray((double*)malloc(sizeof(double)));
@@ -1412,46 +1488,70 @@ static void asort(YYSTYPE *dst, YYSTYPE *src)
default:
dst->a_data = PushArray((double*)memdup(src->a_data, src->a_count * sizeof(double), 0));
dst->a_count = src->a_count;
- SortArray(dst->a_count, dst->a_data);
+ for(i = 0; i < src->a_count; i++) dst->a_data[i] = src->a_data[src->a_count-1-i];
}
}
-static void _crank(YYSTYPE *dst, YYSTYPE *src)
+static void asort(YYSTYPE *dst, YYSTYPE *src)
{
- double tmp;
-
if(!dst || !src) return;
dst->type = ARR;
switch(src->a_count) {
- case 0: case 1:
+ case 0:
+ dst->a_data = PushArray((double*)malloc(sizeof(double)));
+ dst->a_count = 1; dst->a_data[0] = dst->val = src->val;
+ break;
+ case 1:
dst->a_data = PushArray((double*)malloc(sizeof(double)));
- dst->a_count = 1; dst->a_data[0] = dst->val = 1;
+ dst->a_count = 1; dst->a_data[0] = dst->val = src->a_data[0];
break;
default:
dst->a_data = PushArray((double*)memdup(src->a_data, src->a_count * sizeof(double), 0));
dst->a_count = src->a_count;
- crank(dst->a_count, dst->a_data, &tmp);
+ SortArray(dst->a_count, dst->a_data);
}
}
+static void asort2(YYSTYPE *res, YYSTYPE *sr1, YYSTYPE *sr2, char *fmt)
+{
+ int n;
+
+ res->val = 0.0; res->type = NUM;
+ if(!sr1 || !sr2 || !sr1->a_data || !sr2->a_data) return;
+ n = sr1->a_count > sr2->a_count ? sr2->a_count : sr1->a_count;
+ res->val = (double)n;
+ if(n >1) SortArray2(n, sr1->a_data, sr2->a_data);
+ return;
+}
+
+static double _crank(YYSTYPE *src)
+{
+ double tmp = -1.0;
+
+ if(!src) return tmp;
+ tmp = 0.0;
+ if(src->a_data && src->a_count > 1.0)crank(src->a_count, src->a_data, &tmp);
+ return tmp;
+}
+
static void ltrim(YYSTYPE *dst, YYSTYPE *src)
{
if(!src || !dst || !src->text) return;
- dst->text = PushString(str_ltrim(strdup(src->text)));
+ dst->text = PushString(str_ltrim(src->text));
dst->type = STR; dst->val = 0.0;
}
static void rtrim(YYSTYPE *dst, YYSTYPE *src)
{
if(!src || !dst || !src->text) return;
- dst->text = PushString(str_rtrim(strdup(src->text)));
+ dst->text = PushString(str_rtrim(src->text));
dst->type = STR; dst->val = 0.0;
}
static void trim(YYSTYPE *dst, YYSTYPE *src)
{
if(!src || !dst || !src->text) return;
- dst->text = PushString(str_trim(strdup(src->text)));
+ dst->text = PushString(str_trim(src->text));
dst->type = STR; dst->val = 0.0;
}
@@ -1554,6 +1654,59 @@ static void uc_word(YYSTYPE *dst, YYSTYPE *src)
else dst->text = 0L;
}
+static void exec(YYSTYPE *dst, YYSTYPE *src1, YYSTYPE *src2)
+{
+ char *cmd = 0L;
+ int cmd_pos = 0, cmd_size, r, c;
+ AccRange *ar = 0L;
+ anyResult res, *eres;
+
+ if(!src1 || !src1->text || !src1->text[0]) return;
+ if((cmd =(char*)malloc((cmd_size = 1000) * sizeof(char))) && (ar = new AccRange(src1->text))) {
+ if(src2 && src2->text[0] && src2->text[0]) {
+ add_to_buff(&cmd, &cmd_pos, &cmd_size, src2->text, 0);
+ while(cmd_pos && cmd[cmd_pos-1] < 33) cmd_pos--;
+ if(cmd_pos && cmd[cmd_pos-1] != ';') cmd[cmd_pos++] = ';';
+ }
+ cmd[cmd_pos] = 0;
+ ar->GetFirst(&c, &r); ar->GetNext(&c, &r);
+ do {
+ curr_data->GetResult(&res, r, c, false);
+ switch(res.type) {
+ case ET_VALUE: //numerical value
+ if(res.value == -HUGE_VAL)
+ add_to_buff(&cmd, &cmd_pos, &cmd_size, "-inf", 4);
+ else if(res.value == HUGE_VAL)
+ add_to_buff(&cmd, &cmd_pos, &cmd_size, "inf", 3);
+ else add_dbl_to_buff(&cmd, &cmd_pos, &cmd_size, res.value, false);
+ break;
+ case ET_TEXT: //text cell
+ if(res.text && res.text[0]) {
+ if(res.text[0] == res.text[1] && res.text[0] == '/') ar->NextRow(&r);
+ else add_to_buff(&cmd, &cmd_pos, &cmd_size, res.text, 0);
+ }
+ break;
+ }
+ }while(ar->GetNext(&c, &r));
+ eres = do_formula(curr_data, cmd);
+ switch(eres->type) {
+ case ET_BOOL:
+ dst->type = BOOLVAL; dst->val = eres->value;
+ dst->text = 0L; break;
+ case ET_VALUE:
+ dst->type = NUM; dst->val = eres->value;
+ dst->text = 0L; break;
+ case ET_TEXT:
+ dst->type = STR; dst->val = 0.0;
+ dst->text = PushString(eres->text); break;
+ default:
+ dst->type = NUM; dst->val = 0.0;
+ dst->text = 0L; break;
+ }
+ }
+ if(cmd) free(cmd); if(ar) delete ar;
+}
+
// Store strings in a list
static char **str_list = 0L;
static int n_str = 0;
@@ -1562,7 +1715,7 @@ static char *PushString(char *text)
{
if(text && text[0]) {
if(str_list = (char**)realloc(str_list, sizeof(char*)*(n_str+1)))
- str_list[n_str] = strdup(text);
+ str_list[n_str] = (char*)memdup(text, (int)strlen(text)+1, 0);
return str_list[n_str++];
}
return 0L;
@@ -1575,9 +1728,10 @@ static int n_arr = 0;
static double *PushArray(double *arr)
{
if(arr) {
- if(arr_list = (double**)realloc(arr_list, sizeof(double*)*(n_arr+1)))
+ if(arr_list = (double**)realloc(arr_list, sizeof(double*)*(n_arr+1))){
arr_list[n_arr] = arr;
- return arr_list[n_arr++];
+ return arr_list[n_arr++];
+ }
}
return 0L;
}
@@ -1644,6 +1798,7 @@ void InitArithFuncs(DataObj *d)
double (*fnct)(double);
};
fdef fncts[] = {
+ INIT_SYM(AFNCT, "ptukey", p_tukey), INIT_SYM(AFNCT, "qtukey", q_tukey),
INIT_SYM(YYFNC, "toupper", to_upper), INIT_SYM(YYFNC, "tolower", to_lower),
INIT_SYM(YYFNC, "ucfirst", uc_first), INIT_SYM(YYFNC, "ucword", uc_word),
INIT_SYM(SFNCT, "asc", asc), INIT_SYM(YYFNC, "chr", chr),
@@ -1651,7 +1806,7 @@ void InitArithFuncs(DataObj *d)
INIT_SYM(YYFNC2, "strpos",_strpos), INIT_SYM(FUNC4, "classes", classes),
INIT_SYM(AFNCT, "rank", rank), INIT_SYM(YYFNC, "ltrim", ltrim),
INIT_SYM(YYFNC, "rtrim", rtrim), INIT_SYM(YYFNC, "trim", trim),
- INIT_SYM(YYFNC, "asort", asort), INIT_SYM(YYFNC, "crank", _crank),
+ INIT_SYM(YYFNC, "asort", asort), INIT_SYM(AFNCT, "crank", _crank),
INIT_SYM(SRFUNC, "datestr", datestr), INIT_SYM(SFNCT, "dateval", dateval),
INIT_SYM(BFNCT, "leapyear", leapyear), INIT_SYM(YYFNC, "today", today),
INIT_SYM(YYFNC, "now", now), INIT_SYM(FNCT, "year", year),
@@ -1663,7 +1818,7 @@ void InitArithFuncs(DataObj *d)
INIT_SYM(FUNC1, "fill", fill), INIT_SYM(FUNC2, "pearson", pearson),
INIT_SYM(FUNC2, "spearman", spearman), INIT_SYM(FUNC2, "kendall", kendall),
INIT_SYM(FUNC2, "correl", pearson), INIT_SYM(FUNC2, "regression", regression),
- INIT_SYM(FUNC2, "covar", covar),
+ INIT_SYM(FUNC2, "covar", covar), INIT_SYM(YYFNC2, "exec", exec),
INIT_SYM(FUNC3, "utest", utest), INIT_SYM(FUNC2, "ttest2", ttest2),
INIT_SYM(FUNC3, "ttest", ttest), INIT_SYM(FUNC3, "ftest", ftest),
INIT_SYM(AFNCT, "variance", variance), INIT_SYM(AFNCT, "stdev", stdev),
@@ -1674,24 +1829,21 @@ void InitArithFuncs(DataObj *d)
INIT_SYM(AFNCT, "median", quartile2), INIT_SYM(AFNCT, "quartile1", quartile1),
INIT_SYM(AFNCT, "quartile2",quartile2), INIT_SYM(AFNCT, "quartile3", quartile3),
INIT_SYM(AFNCT, "gmean", gmean), INIT_SYM(AFNCT, "hmean", hmean),
- INIT_SYM(AFNCT, "tdist", tdist),
- INIT_SYM(AFNCT, "tfreq", tfreq),
- INIT_SYM(AFNCT, "tinv", tinv),
+ INIT_SYM(AFNCT, "tdist", tdist), INIT_SYM(AFNCT, "tfreq", tfreq),
+ INIT_SYM(AFNCT, "tinv", tinv), INIT_SYM(YYFNC, "invert", invert),
INIT_SYM(AFNCT, "poisdist", poisdist), INIT_SYM(AFNCT, "poisfreq", poisfreq),
INIT_SYM(AFNCT, "expdist", expdist), INIT_SYM(AFNCT, "expfreq", expfreq),
- INIT_SYM(AFNCT, "expinv", expinv),
- INIT_SYM(AFNCT, "fdist", fdist),
- INIT_SYM(AFNCT, "ffreq", ffreq),
+ INIT_SYM(AFNCT, "expinv", expinv), INIT_SYM(AFNCT, "fdist", fdist),
+ INIT_SYM(AFNCT, "ffreq", ffreq), INIT_SYM(AFNCT, "ksdist", ksdist),
INIT_SYM(AFNCT, "finv", finv), INIT_SYM(AFNCT, "gammp", _gammp),
INIT_SYM(AFNCT, "gammq", _gammq), INIT_SYM(AFNCT, "beta", beta),
INIT_SYM(AFNCT, "betai", _betai), INIT_SYM(AFNCT, "bincof", _bincof),
- INIT_SYM(AFNCT, "binomdist",binomdist),
- INIT_SYM(AFNCT, "binomfreq",binomfreq),
+ INIT_SYM(AFNCT, "binomdist",binomdist), INIT_SYM(AFNCT, "binomfreq",binomfreq),
INIT_SYM(AFNCT, "normdist", normdist),
INIT_SYM(AFNCT, "norminv", norminv), INIT_SYM(AFNCT, "normfreq", normfreq),
INIT_SYM(AFNCT, "lognormdist", lognormdist), INIT_SYM(AFNCT, "lognormfreq", lognormfreq),
INIT_SYM(AFNCT, "lognorminv",lognorminv), INIT_SYM(AFNCT, "chidist", chidist),
- INIT_SYM(AFNCT, "chifreq", chifreq),
+ INIT_SYM(AFNCT, "chifreq", chifreq), INIT_SYM(YYFNC2, "asort2", asort2),
INIT_SYM(AFNCT, "chiinv", chiinv), INIT_SYM(SFNCT, "strlen", _strlen),
INIT_SYM(YYFNC, "eval", eval), INIT_SYM(FNCT, "erf", errf),
INIT_SYM(FNCT, "erfc", errfc), INIT_SYM(FNCT, "sign", sign),
@@ -1894,7 +2046,7 @@ static YYSTYPE *proc_clause(YYSTYPE *res)
if(!syntax_level) break;
syntax_level->clval = res->a_data[i];
yyparse();
- if(line_res.type == ET_VALUE && line_res.value != 0.0) n_data[n++] = res->a_data[i];
+ if((line_res.type == ET_VALUE || line_res.type == ET_BOOL) && line_res.value != 0.0) n_data[n++] = res->a_data[i];
}
res->a_data = n_data; res->a_count = n;
res->text=0L;
@@ -2006,16 +2158,28 @@ static int is_ttoken(unsigned int h_nam, unsigned int h2_nam)
if(h2_nam == 5220) return CLVAL;
break;
case 362:
- if(h2_nam == 42878) return IF;
+ if(h2_nam == 42878) return (syntax_level->last_tok = IF);
break;
case 28421:
if(h2_nam == 82147317) return (syntax_level->last_tok = WHILE);
break;
+ case 1518:
+ if(h2_nam == 20654586) return (syntax_level->last_tok = FOR);
+ break;
+ case 370:
+ if(h2_nam == 46206) return INARR;
+ break;
case 1457:
if(h2_nam == 18357885) return DIM;
break;
+ case 108774:
+ if(h2_nam == 0x27d5d1fe) return (syntax_level->last_tok = RETURN);
+ break;
+ case 23583:
+ if(h2_nam == 0x954f67ff) return BREAK;
+ break;
case 6033:
- if((h2_nam & 0x7fffffff) == 0x6371377d) return ELSE;
+ if((h2_nam & 0x7fffffff) == 0x6371377d) return (syntax_level->last_tok = ELSE);
break;
case 7097:
if((h2_nam & 0x7fffffff) == 0x550a2d65) return BTRUE;
@@ -2038,6 +2202,8 @@ static char *copy_block()
first[0] = '{'; last[0] = '}'; break;
case '(':
first[0] = '('; last[0] = ')'; break;
+ default:
+ first[0] = '\0'; last[0] = ';'; break;
}
if(!(res = (char*)malloc(strlen(src)+2))) return 0L;
for(i = 1, level = mode = j = 0; src[i]; i++) {
@@ -2052,7 +2218,7 @@ static char *copy_block()
if(src[i] == last[level]) {
if(level) level--;
else {
- res[j-1] = 0; buff_pos += j;
+ res[j-1] = ';'; res[j] = 0; buff_pos += j;
return res;
}
}
@@ -2068,25 +2234,103 @@ static char *copy_block()
}
}
}
+ res[j] = ';'; res[j+1] = 0; buff_pos += j;
return res;
}
static symrec *curr_sym;
-static int yylex (void)
+static double for_loop(char *block1, char *block2)
+{
+ char *last_buffer, *bb1, *bb2, *bb3;
+ int i, a_count, last_buff_pos, cb1;
+ double *a_data;
+ YYSTYPE yyres, yysrc;
+ symrec *var;
+
+ if(!block1 || !block1[0]) return 0.0;
+ bb1 = bb2 = bb3 = 0L; parse_level++;
+ cb1 = (int)strlen(block1);
+ last_buffer = buffer; last_buff_pos = buff_pos;
+ buffer = block1; buff_pos = 0;
+ //test for syntax 1
+ bb1 = copy_block();
+ if(buff_pos < cb1) bb2 = copy_block();
+ if(buff_pos < cb1) bb3 = copy_block();
+ if(bb1 && bb2 && bb3) { //syntax 1 found !
+ yysrc.text = bb1; if(bb1[0]) eval(&yyres, &yysrc);
+ for(i = 0; i < yy_maxiter; i++) {
+ yysrc.text = bb2;
+ if(bb2[0]) {
+ eval(&yyres, &yysrc);
+ if(yyres.type != NUM && yyres.type != BOOLVAL) yyres.val = 0.0;
+ }
+ else yyres.val = 1.0;
+ if(yyres.val != 0.0) {
+ if(block2 && block2[0]) {
+ yysrc.text = block2;
+ eval(&yyres, &yysrc);
+ }
+ yysrc.text = bb3;
+ eval(&yyres, &yysrc);
+ }
+ else break;
+ }
+ if(i) last_error = 0L;
+ }
+ //test for syntax 2
+ else if(!bb2) {
+ buff_pos = 0;
+ if (VAR == yylex() && (var = curr_sym) && INARR == yylex() && buffer[buff_pos]){
+ yysrc.text = buffer + buff_pos;
+ eval(&yyres, &yysrc);
+ a_count = yyres.a_count;
+ a_data = yyres.a_data;
+ for(i = 0; i < a_count && i < yy_maxiter; i++) {
+ var->SetValue(a_data[i]);
+ if(block2 && block2[0]) {
+ yysrc.text = block2;
+ eval(&yyres, &yysrc);
+ }
+ }
+ last_error = 0;
+ }
+ else yyerror("parse error");
+ }
+ else yyerror("parse error");
+ if(bb1) free(bb1); if(bb2) free(bb2); if(bb3) free(bb3);
+ buffer = last_buffer; buff_pos = last_buff_pos;
+ parse_level--;
+ return 0.0;
+}
+
+static int yylex()
{
int i, c, tok;
unsigned int h_nam, h2_nam;
char tmp_txt[80], *block;
symrec *s;
+ memset(&yylval, 0, sizeof(YYSTYPE));
while((c = buffer[buff_pos++]) == ' ' || c == '\t'); //get first nonwhite char
if(!c) return 0;
+ //test for implicit block statement
+ if(syntax_level && (syntax_level->last_tok == PBLOCK
+ || syntax_level->last_tok == ELSE || syntax_level->last_tok == RETURN) && c != '{'){
+ buff_pos--;
+ if(block = copy_block()) {
+ yylval.text = PushString(block);
+ free(block);
+ }
+ syntax_level->last_tok = 0;
+ return yylval.type = IBLOCK;
+ }
//test for block statement
if(c == '{') {
if(block = copy_block()) {
yylval.text = PushString(block);
free(block);
}
+ syntax_level->last_tok = 0;
return yylval.type = BLOCK;
}
//test for '..' operator
@@ -2108,14 +2352,30 @@ static int yylex (void)
}
}
tmp_txt[i] = 0;
+#ifdef USE_WIN_SECURE
+ sscanf_s(tmp_txt, "%lf", &yylval.val);
+#else
sscanf(tmp_txt, "%lf", &yylval.val);
+#endif
return yylval.type = NUM;
}
//test for name or stringtoken
- if(c > 31 && (isalpha(c) || c=='$')) {
- for(buff_pos--, i = 0; i < 79 && ((c = buffer[buff_pos]) && c > 31 && (isalnum(c) || c == '$')); buff_pos++) {
+ if(c > 31 && (isalpha(c) || c=='$' || c =='_')) {
+ for(buff_pos--, i = 0; i < 79 && ((c = buffer[buff_pos]) && c > 31 && (isalnum(c) || c == '$' || c == '_')); buff_pos++) {
tmp_txt[i++] = (char)c;
}
+ while(buffer[buff_pos] == ' ' || buffer[buff_pos] == '\t') buff_pos++;
+ if(buffer[buff_pos] == ':' && !(syntax_level && syntax_level->last_tok == '?')){
+ tmp_txt[i++] = buffer[buff_pos++];
+ for(; i < 79 && ((c = buffer[buff_pos]) && c > 31 && (isalnum(c) || c == '$')); buff_pos++) {
+ tmp_txt[i++] = (char)c;
+ }
+ tmp_txt[i] = 0;
+ yylval.text = PushString(tmp_txt);
+ range_array(&yylval, yylval.text);
+ yylval.val = 0.0;
+ return yylval.type = RANGEARR;
+ }
tmp_txt[i] = 0;
h_nam = HashValue((unsigned char*)tmp_txt);
h2_nam = Hash2((unsigned char*)tmp_txt);
@@ -2127,8 +2387,7 @@ static int yylex (void)
if(!(s = getsym(h_nam, h2_nam, tmp_txt))){
s = putsym(h_nam, h2_nam, VAR);
s->SetName(tmp_txt);
- }
-
+ }
curr_sym = yylval.tptr = s; return s->type;
}
//test for string
@@ -2174,33 +2433,45 @@ static int yylex (void)
pop_syntax();
break;
case '(':
- if(syntax_level->last_tok == WHILE){
+ if(syntax_level->last_tok == WHILE || syntax_level->last_tok == FOR
+ || syntax_level->last_tok == IF){
if(block = copy_block()) {
yylval.text = PushString(block);
free(block);
}
- return yylval.type = PBLOCK;
+ return yylval.type = syntax_level->last_tok = PBLOCK;
}
push_syntax();
+ if(syntax_level) syntax_level->last_tok = c;
+ break;
case '?':
if(syntax_level) syntax_level->last_tok = c;
break;
case ':':
if(syntax_level) {
- if(syntax_level->last_tok == '(') return COLR;
- else if(syntax_level->last_tok == '?') return COLC;
+ if(syntax_level->last_tok == '?') return COLC;
}
break;
case ';':
+ if(buff_pos <2)return yylex();
if(syntax_level) {
if(syntax_level->last_tok == '(') return PSEP;
+ else syntax_level->last_tok = 0;
}
break;
+ case '*':
+ if(buffer[buff_pos] == '=') tok = MULEQ;
+ break;
+ case '/':
+ if(buffer[buff_pos] == '=') tok = DIVEQ;
+ break;
case '+':
if(buffer[buff_pos] == '+') tok = INC;
+ else if(buffer[buff_pos] == '=') tok = ADDEQ;
break;
case '-':
if(buffer[buff_pos] == '-') tok = DEC;
+ else if(buffer[buff_pos] == '=') tok = SUBEQ;
break;
}
if(tok) {
@@ -2224,7 +2495,7 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
symrec *sx, *sy;
lfPOINT *new_points;
long npoints = 0;
- int length, res_mode = 0;
+ int length, parse_res, res_mode = 0;
if(x1 < x2) step = fabs(step);
else step = -fabs(step);
@@ -2239,11 +2510,10 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
pop_parser();
return false;
}
- strcpy(buffer, param); buffer[length++] = ';';
+ rlp_strcpy(buffer, length+1, param);
+ buffer[length++] = ';';
buffer[length] = 0; buff_pos = 0;
- do {
- yyparse();
- }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
free(buffer); buffer = 0L;
}
length = (int)strlen(expr);
@@ -2251,9 +2521,7 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
for(x = x1; step > 0.0 ? x <= x2 : x >= x2; x += step) {
if(sx){
sx->SetValue(x); buff_pos = 0;
- do {
- yyparse();
- }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
switch (res_mode) {
case 1:
y = sy->GetValue(); break;
@@ -2275,9 +2543,9 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
*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);
+ if(d) {
+ d->Command(CMD_CLEAR_ERROR, 0L, 0L);
+ d->Command(CMD_REDRAW, 0L, 0L);
}
return true;
}
@@ -2285,7 +2553,7 @@ bool do_xyfunc(DataObj *d, double x1, double x2, double step, char *expr, lfPOIN
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;
+ int length, parse_res, nr, nc, r, c, res_mode=0;
symrec *sx, *sz, *sy;
double x, y, z;
@@ -2298,11 +2566,10 @@ bool do_func3D(DataObj *d, double x1, double x2, double xstep, double z1, double
pop_parser();
return false;
}
- strcpy(buffer, param); buffer[length++] = ';';
+ rlp_strcpy(buffer, length+1, param);
+ buffer[length++] = ';';
buffer[length] = 0; buff_pos = 0;
- do {
- yyparse();
- }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
free(buffer); buffer = 0L;
}
length = (int)strlen(expr); buffer = expr;
@@ -2312,9 +2579,7 @@ bool do_func3D(DataObj *d, double x1, double x2, double xstep, double z1, double
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);
+ while(!(parse_res = yyparse()) && buff_pos < length);
switch (res_mode) {
case 1:
y = sy->GetValue(); break;
@@ -2339,13 +2604,15 @@ bool do_func3D(DataObj *d, double x1, double x2, double xstep, double z1, double
anyResult *do_formula(DataObj *d, char *expr)
{
- int length;
+ int length, parse_res;
static anyResult ret, *pret = 0L;
if(d) curr_data = d;
ret.type = ET_ERROR; ret.text = 0L;
+ ret.a_data = 0L; ret.a_count = 0;
if(!expr || !expr[0]) {
if(!sym_table) InitArithFuncs(0L);
+ last_error = 0L;
return &ret;
}
push_parser(); //make code reentrant
@@ -2354,14 +2621,13 @@ anyResult *do_formula(DataObj *d, char *expr)
pop_parser();
return &ret;
}
- strcpy(buffer, expr); if(buffer[length-1] != ';') buffer[length++] = ';';
+ rlp_strcpy(buffer, length+1, expr);
+ if(buffer[length-1] != ';') buffer[length++] = ';';
buffer[length] = 0; buff_pos = 0;
- do {
- yyparse();
- }while(buff_pos < length);
+ while(!(parse_res= yyparse()) && buff_pos < length);
ret.type = ET_ERROR; ret.text = 0L;
- if(curr_data && last_error) {
- if(!(strcmp(last_error, "parse error"))) curr_data->Command(CMD_ERROR, 0L, 0L);
+ if(parse_res == 1 && curr_data) {
+ if(last_error && (!(strcmp(last_error, "parse error")))) curr_data->Command(CMD_ERROR, 0L, 0L);
if(last_err_desc) pret = &line_res;
else pret = &ret;
}
@@ -2373,7 +2639,7 @@ anyResult *do_formula(DataObj *d, char *expr)
return pret;
}
-bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy, int r0, int c0)
+bool MoveFormula(DataObj *d, char *of, char *nf, int nfsize, int dx, int dy, int r0, int c0)
{
int length, length2, tok, pos, i;
char *res, desc1[2], desc2[2];
@@ -2386,7 +2652,7 @@ bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy, int r0, int c0)
pop_parser();
return false;
}
- strcpy(buffer, of); buffer[length++] = ';';
+ rlp_strcpy(buffer, length+1, of); buffer[length++] = ';';
buffer[length] = 0; buff_pos = pos = 0;
if(!(res = (char *)calloc(length2 = (length*2+10), sizeof(char))))return false;
length2--;
@@ -2409,7 +2675,7 @@ bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy, int r0, int c0)
case YYFNC2: case YYFNC3:
pos += rlp_strcpy(res+pos, length2-pos, curr_sym->name);
break;
- case COLR: case COLC:
+ case COLC:
res[pos++] = ':';
break;
case PSEP:
@@ -2441,7 +2707,9 @@ bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy, int r0, int c0)
else pos += rlp_strcpy(res+pos, length2-pos, curr_sym->name);
break;
case STR:
- pos += sprintf(res+pos, "\"%s\"", yylval.text && yylval.text[0] ? yylval.text : "");
+ pos += rlp_strcpy(res+pos, length2-pos, "\"");
+ pos += rlp_strcpy(res+pos, length2-pos, yylval.text);
+ pos += rlp_strcpy(res+pos, length2-pos, "\"");
break;
case SER:
res[pos++] = '.'; res[pos++] = '.';
@@ -2491,31 +2759,67 @@ bool MoveFormula(DataObj *d, char *of, char *nf, int dx, int dy, int r0, int c0)
case IF:
res[pos++] = 'i'; res[pos++] = 'f';
break;
+ case ADDEQ:
+ res[pos++] = '+'; res[pos++] = '=';
+ break;
+ case SUBEQ:
+ res[pos++] = '-'; res[pos++] = '=';
+ break;
+ case MULEQ:
+ res[pos++] = '*'; res[pos++] = '=';
+ break;
+ case DIVEQ:
+ res[pos++] = '/'; res[pos++] = '=';
+ break;
case WHILE:
pos += rlp_strcpy(res+pos, length2-pos, "while");
break;
+ case FOR:
+ pos += rlp_strcpy(res+pos, length2-pos, "for");
+ break;
+ case INARR:
+ pos += rlp_strcpy(res+pos, length2-pos, "in");
+ break;
case ELSE:
pos += rlp_strcpy(res+pos, length2-pos, "else");
break;
+ case RETURN:
+ pos += rlp_strcpy(res+pos, length2-pos, " return");
+ break;
+ case BREAK:
+ pos += rlp_strcpy(res+pos, length2-pos, " break");
+ break;
+ case RANGEARR:
+ for(i = 0; yylval.text[i]; i++) if(yylval.text[i] == ':') {
+ yylval.text[i] = ';'; break;
+ }
+ MoveFormula(d, yylval.text, res+pos, nfsize-pos-2, dx, dy, r0, c0);
+ while(res[pos]) {
+ pos++; if(res[pos] == ';') res[pos] = ':';
+ }
+ break;
case BLOCK:
-#ifdef USE_WIN_SECURE
- pos += sprintf_s(res+pos, TMP_TXT_SIZE-pos, "{%s}", yylval.text && yylval.text[0] ? yylval.text : "");
-#else
- pos += sprintf(res+pos, "{%s}", yylval.text && yylval.text[0] ? yylval.text : "");
-#endif
+ res[pos++] = '{';
+ MoveFormula(d, yylval.text, res+pos, nfsize-pos-2, dx, dy, r0, c0);
+ pos += (int)strlen(res+pos);
+ res[pos++] = '}';
+ break;
+ case IBLOCK:
+ MoveFormula(d, yylval.text, res+pos, nfsize-pos-2, dx, dy, r0, c0);
+ pos += (int)strlen(res+pos);
+ res[pos++] = ';';
break;
case PBLOCK:
-#ifdef USE_WIN_SECURE
- pos += sprintf_s(res+pos, TMP_TXT_SIZE-pos, "(%s)", yylval.text && yylval.text[0] ? yylval.text : "");
-#else
- pos += sprintf(res+pos, "(%s)", yylval.text && yylval.text[0] ? yylval.text : "");
-#endif
+ res[pos++] = '(';
+ MoveFormula(d, yylval.text, res+pos, nfsize-pos-2, dx, dy, r0, c0);
+ pos += (int)strlen(res+pos);
+ res[pos++] = ')';
break;
}
res[pos] = 0;
}while(buff_pos < length);
while((res[pos-1] == ';' || res[pos-1] == ' ') && pos > 0) { res[pos-1] = 0; pos--;}
- strcpy(nf, res); free(res);
+ rlp_strcpy(nf, nfsize, res); free(res);
free(buffer); buffer = 0L;
clear_table();
pop_parser();
@@ -2526,7 +2830,7 @@ static char *txt_formula; //function to fit
static double **parval; //pointers to parameter values
static void fcurve(double x, double z, double **a, double *y, double dyda[], int ma)
{
- int i, length;
+ int i, length, parse_res;
double tmp, y1, y2;
symrec *symx, *symz, *sy=0L;
@@ -2540,7 +2844,7 @@ static void fcurve(double x, double z, double **a, double *y, double dyda[], int
symx->SetValue(x); symz->SetValue(z);
buffer = txt_formula;
buff_pos = 0; length = (int)strlen(txt_formula);
- do { yyparse(); }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
if(sy = getsym(hn_y, h2_y)) *y = sy->GetValue();
else *y = line_res.value;
if(*y == HUGE_VAL || *y == -HUGE_VAL) {
@@ -2553,11 +2857,11 @@ static void fcurve(double x, double z, double **a, double *y, double dyda[], int
tmp = *parval[i];
*parval[i] = tmp*.995;
buff_pos = 0;
- do { yyparse(); }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
y1 = sy ? sy->GetValue() : line_res.value;
*parval[i] = tmp*1.005;
buff_pos = 0;
- do { yyparse(); }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
y2 = sy ? sy->GetValue() : line_res.value;
*parval[i] = tmp;
dyda[i] = (y2-y1)*100.0/tmp;
@@ -2572,7 +2876,8 @@ static void fcurve(double x, double z, double **a, double *y, double dyda[], int
int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr, double conv, int maxiter, double *chi_2)
{
- int length, i, j, k, l, ndata, nparam, r1, r2, r3, c1, c2, c3, *lista, itst, itst1;
+ int length, i, j, k, l, ndata, nparam, r1, r2, r3, c1, c2, c3;
+ int *lista, itst, itst1, parse_res;
symrec *tab1, *tab2, *csr, **parsym;
AccRange *arx, *ary, *arz;
double *x, *y, *z, currx, curry, currz, alamda, chisq, ochisq;
@@ -2632,12 +2937,10 @@ int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr,
free(y); free(x); delete arx; delete ary;
return 0;
}
- strcpy(buffer, *par); buffer[length++] = ';';
+ rlp_strcpy(buffer, length, *par); buffer[length++] = ';';
buffer[length] = 0; buff_pos = 0;
tab1 = sym_table;
- do {
- yyparse();
- }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
tab2 = sym_table; free(buffer); buffer =0L;
for(nparam = 0, csr=tab2; csr != tab1; nparam++, csr = csr->next);
parsym = (symrec**)malloc((nparam+1)*sizeof(symrec*));
@@ -2667,10 +2970,18 @@ int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr,
if(k > 20) {
if(tmp_txt[j-1] == ' ') j--;
if(tmp_txt[j-1] == ';') j--;
+#ifdef USE_WIN_SECURE
+ l = sprintf_s(tmp_txt+j, 500-j, "\n");
+#else
l = sprintf(tmp_txt+j, "\n");
+#endif
j += l; k = 0;
}
+#ifdef USE_WIN_SECURE
+ l += sprintf_s(tmp_txt+j, 500-j, "%s%s=%g;", j && k ? " " : "", parsym[i]->name, parsym[i]->GetValue());
+#else
l += sprintf(tmp_txt+j, "%s%s=%g;", j && k ? " " : "", parsym[i]->name, parsym[i]->GetValue());
+#endif
j += l; k += l;
}
free(*par);
@@ -2678,9 +2989,7 @@ int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr,
if(chi_2) *chi_2 = chisq;
//write back spreadsheet data if necessary
buffer = *par; length = (int)strlen(buffer);
- do {
- yyparse();
- }while(buff_pos < length);
+ while(!(parse_res = yyparse()) && buff_pos < length);
buffer = 0L;
free_dmatrix(alpha, 1, nparam, 1, nparam);
free_dmatrix(covar, 1, nparam, 1, nparam);
@@ -2689,10 +2998,12 @@ int do_fitfunc(DataObj *d, char *rx, char *ry, char *rz, char **par, char *expr,
if(parval) free(parval); if(parsym) free(parsym);
clear_table();
pop_parser();
- if(curr_data){
- curr_data->Command(CMD_CLEAR_ERROR, 0L, 0L);
- curr_data->Command(CMD_REDRAW, 0L, 0L);
+ if(d){
+ d->Command(CMD_CLEAR_ERROR, 0L, 0L);
+ d->Command(CMD_REDRAW, 0L, 0L);
}
return itst < maxiter ? itst+1 : maxiter;
}
+
+
diff --git a/no_gui.cpp b/no_gui.cpp
index eee8d1d..2195534 100755
--- a/no_gui.cpp
+++ b/no_gui.cpp
@@ -1,4 +1,4 @@
-//no_gui.cpp, Copyright 2000-2006 R.Lackner
+//no_gui.cpp, Copyright 2000-2007 R.Lackner
//
// This file is part of RLPlot.
//
@@ -420,6 +420,16 @@ bool FitFunc::PropertyDlg()
return false;
}
+bool NormQuant::PropertyDlg()
+{
+ return false;
+}
+
+bool Plot3D::AddAxis()
+{
+ return false;
+}
+
bool Plot3D::PropertyDlg()
{
return false;
@@ -465,6 +475,11 @@ bool Tick::PropertyDlg()
return false;
}
+void
+Axis::DoMark(anyOutput *o, bool mark)
+{
+}
+
bool Axis::PropertyDlg()
{
return false;
@@ -538,6 +553,16 @@ void ShowTextCursor(anyOutput *out, RECT *disp, DWORD color)
return;
}
+void InvalidateOutput(anyOutput *o)
+{
+ return;
+}
+
+void SuspendAnimation(anyOutput *o, bool bSusp)
+{
+ return;
+}
+
anyOutput *NewDispClass(GraphObj *g)
{
return 0L;
diff --git a/reports.cpp b/reports.cpp
index ab73a4d..42e8b9c 100755
--- a/reports.cpp
+++ b/reports.cpp
@@ -1,4 +1,4 @@
-//reports.cpp, Copyright (c) 2006 R.Lackner
+//reports.cpp, Copyright (c) 2006, 2007 R.Lackner
//
// This file is part of RLPlot.
//
@@ -48,7 +48,7 @@ static char SymLineStr[40];
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static void rep_init()
{
- curr_id = 1;
+ curr_id = 1; defs.cUnits = defs.dUnits;
txtdef1.ColTxt = txtdef2.ColTxt = 0x0L;
txtdef1.ColBg = txtdef2.ColBg = 0x00ffffffL;
txtdef1.fSize = defs.GetSize(SIZE_TEXT);
@@ -99,6 +99,40 @@ static char* mk_label(double x, double y, bool moveable, int align, TextDEF *td,
add_to_buff(&res, &pos, &csize, "\"\n", 2);
return res;
}
+static void rep_DrawText(GraphObj *parent, double x, double y, bool moveable, int align, TextDEF *td, char*text)
+{
+ char *txt_obj;
+
+ if(txt_obj = mk_label(x, y, false, align, td, text)) {
+ OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
+ free(txt_obj);
+ }
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// draw a rectangle
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static char* mk_rect(double x1, double y1, double x2, double y2, DWORD lcol, DWORD fcol)
+{
+ int csize, pos = 0;
+ char *res;
+
+ if(!(res = (char*)malloc(csize = 1000)))return 0L;
+ res[pos++] = '\n'; res[pos++] = '[';
+ add_int_to_buff(&res, &pos, &csize, curr_id++, false, 0);
+ add_to_buff(&res, &pos, &csize, "=rectangle]\np1=", 0);
+ add_dbl_to_buff(&res, &pos, &csize, x1, true);
+ add_dbl_to_buff(&res, &pos, &csize, y1, true);
+ add_to_buff(&res, &pos, &csize, "\np2=", 0);
+ add_dbl_to_buff(&res, &pos, &csize, x2, true);
+ add_dbl_to_buff(&res, &pos, &csize, y2, true);
+ add_to_buff(&res, &pos, &csize, "\nLine= 0 1", 0);
+ add_hex_to_buff(&res, &pos, &csize, lcol, true);
+ add_to_buff(&res, &pos, &csize, " 0x0\nFillLine= 0 1 0x0 0x0\nFill= 0", 0);
+ add_hex_to_buff(&res, &pos, &csize, fcol, true);
+ add_to_buff(&res, &pos, &csize, " 1 0x0 0x00ffffff\n", 0);
+ return res;
+}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// print values to string
@@ -127,35 +161,25 @@ static int dbl_to_str2(char *dest, int size, char* fmt, double val1, double val2
static void mk_header(Page *page, char* desc)
{
time_t ti = time(0L);
- char *txt_obj, label[80];
+ char label[80];
double rpos;
int cb;
if(!page) return;
rpos = page->GetSize(SIZE_GRECT_RIGHT) - txtdef1.fSize*5.0;
- if(txt_obj = mk_label(txtdef1.fSize*5.0, page->GetSize(SIZE_GRECT_TOP)+txtdef2.fSize*6.0,
- false, TXA_HLEFT, &txtdef2, desc)) {
- OpenGraph(page, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(page, txtdef1.fSize*5.0, page->GetSize(SIZE_GRECT_TOP)+txtdef2.fSize*6.0,
+ false, TXA_HLEFT, &txtdef2, desc);
#ifdef USE_WIN_SECURE
ctime_s(label, 32, &ti);
#else
rlp_strcpy(label, 25, ctime(&ti));
#endif
label[24] = 0;
- if(txt_obj = mk_label(rpos, page->GetSize(SIZE_GRECT_TOP)+txtdef1.fSize*5.0,
- false, TXA_HRIGHT, &txtdef1, label)) {
- OpenGraph(page, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
- cb = rlp_strcpy(label, 80, "RLPlot ");
- cb += rlp_strcpy(label+cb, 80-cb, SZ_VERSION);
- if(txt_obj = mk_label(rpos, page->GetSize(SIZE_GRECT_BOTTOM)-txtdef1.fSize*6.0,
- false, TXA_HRIGHT, &txtdef1, label)) {
- OpenGraph(page, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(page, rpos, page->GetSize(SIZE_GRECT_TOP)+txtdef1.fSize*5.0,
+ false, TXA_HRIGHT, &txtdef1, label);
+ cb = rlp_strcpy(label, 80, "RLPlot "); cb += rlp_strcpy(label+cb, 80-cb, SZ_VERSION);
+ rep_DrawText(page, rpos, page->GetSize(SIZE_GRECT_BOTTOM)-txtdef1.fSize*6.0,
+ false, TXA_HRIGHT, &txtdef1, label);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -189,17 +213,16 @@ static double mk_mean_report(GraphObj *parent, double x, double y, double *da, i
{
static char *mean_fmts[] = {"Mean = %g", "Std.Dev. = %g", "N = %g", "Std.Err. = %g", 0L,
"Kurtosis = %g", "Skewness = %g"};
- char *txt_obj, desc[80];
+ char desc[80];
int i, cb;
double v, t, res[10];
- cb = rlp_strcpy(desc, 20, "<b>"); cb += rlp_strcpy(desc+cb, 20-cb, name);
- cb += rlp_strcpy(desc+cb, 20-cb, ":</b>");
- if(txt_obj = mk_label(x, y, false, TXA_HLEFT, &txtdef1, desc)) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj); y += linsp1;
+ if(name && name[0]) {
+ cb = rlp_strcpy(desc, 40, "<b>"); cb += rlp_strcpy(desc+cb, 40-cb, name);
+ cb += rlp_strcpy(desc+cb, 40-cb, ":</b>");
+ rep_DrawText(parent, x, y, false, TXA_HLEFT, &txtdef1, desc);
+ y += linsp1; x += (txtdef1.fSize*3.0);
}
- x += (txtdef1.fSize*3.0);
cb = dbl_to_str1(desc, 80, "%g%%%% C.I. = %%g", ci*100.0);
mean_fmts[4] = (char*)malloc(cb+2);
rlp_strcpy(mean_fmts[4], cb+1, desc); t = distinv(t_dist, n-1, 1, 1.0-ci, 2.0);
@@ -209,11 +232,8 @@ static double mk_mean_report(GraphObj *parent, double x, double y, double *da, i
res[6] = d_skew(n, da);
for(i = 0; i < 7; i++) {
dbl_to_str1(desc, 80, mean_fmts[i], res[i]);
- if(txt_obj = mk_label(x, y, false, TXA_HLEFT, &txtdef1, desc)) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj); y += linsp1/1.2;
- }
- if(i == 2) y += linsp1/3.6;
+ rep_DrawText(parent, x, y, false, TXA_HLEFT, &txtdef1, desc);
+ y += (i==2 ? linsp1/0.9 : linsp1/1.2);
}
free(mean_fmts[4]); mean_fmts[4] = 0L;
return y;
@@ -225,18 +245,17 @@ static double mk_mean_report(GraphObj *parent, double x, double y, double *da, i
static double mk_median_report(GraphObj *parent, double x, double y, double *da, int n, double ci, char *name)
{
static char *mean_fmts[] = {"Median = %g", "25%% = %g", "75%% = %g", "N = %g", "Min. = %g", "Max. = %g" };
- char *txt_obj, desc[80];
+ char desc[80];
int i, cb;
double res[6];
if(!da || !parent || !n) return y;
- cb = rlp_strcpy(desc, 20, "<b>"); cb += rlp_strcpy(desc+cb, 20-cb, name);
- cb += rlp_strcpy(desc+cb, 20-cb, ":</b>");
- if(txt_obj = mk_label(x, y, false, TXA_HLEFT, &txtdef1, desc)) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj); y += linsp1;
+ if(name && name[0]) {
+ cb = rlp_strcpy(desc, 40, "<b>"); cb += rlp_strcpy(desc+cb, 40-cb, name);
+ cb += rlp_strcpy(desc+cb, 40-cb, ":</b>");
+ rep_DrawText(parent, x, y, false, TXA_HLEFT, &txtdef1, desc);
+ y += linsp1; x += (txtdef1.fSize*3.0);
}
- x += (txtdef1.fSize*3.0);
d_quartile(n, da, &res[1], &res[0], &res[2]);
res[4] = res[5] = *da;
for(i = 1; i < n; i++) {
@@ -245,10 +264,8 @@ static double mk_median_report(GraphObj *parent, double x, double y, double *da,
res[3] = (double)n;
for(i = 0; i < 6; i++) {
dbl_to_str1(desc, 80, mean_fmts[i], res[i]);
- if(txt_obj = mk_label(x, y, false, TXA_HLEFT, &txtdef1, desc)) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj); y += linsp1/1.2;
- }
+ rep_DrawText(parent, x, y, false, TXA_HLEFT, &txtdef1, desc);
+ y += linsp1/1.2;
}
return y;
}
@@ -264,7 +281,6 @@ static void mk_table(GraphObj *parent, double x, double y, int type, double **dd
char *cfmt[8];
int i, j, nl, nc[8];
double posc[8], cinc;
- char *txt_obj;
#ifdef _WINDOWS
cinc = txtdef1.fSize;
@@ -284,42 +300,27 @@ static void mk_table(GraphObj *parent, double x, double y, int type, double **dd
default: return;
}
if(type == 1 || type == 2) {
- if(txt_obj = mk_label(x, y, false, TXA_HLEFT, &txtdef1, rheaders[0])) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(parent, x, y, false, TXA_HLEFT, &txtdef1, rheaders[0]);
for(i = 0; i < 5; i++) {
- if(txt_obj = mk_label(posc[i], y, false, TXA_HRIGHT, &txtdef1, cheaders[i])) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(parent, posc[i], y, false, TXA_HRIGHT, &txtdef1, cheaders[i]);
if(i) posc[i] += linsp1;
}
- mk_hr(parent, x, posc[4], y + linsp1);
- y += linsp2;
+ mk_hr(parent, x, posc[4], y + linsp1); y += linsp2;
}
for(i = 0; i < nl; i++) {
- if(txt_obj = mk_label(x, y, false, TXA_HLEFT, &txtdef1, rheaders[i+1])) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(parent, x, y, false, TXA_HLEFT, &txtdef1, rheaders[i+1]);
for(j = 0; j < nc[i]; j++) {
- if(j == 4 && dda[i][j] > 0.0 && dda[i][j] < 0.0001)
- rlp_strcpy(TmpTxt, 10, "< 0.0001");
+ if(j == 4 && dda[i][j] > 0.0 && dda[i][j] < 0.0001) rlp_strcpy(TmpTxt, 10, "< 0.0001");
#ifdef USE_WIN_SECURE
else sprintf_s(TmpTxt, 20, cfmt[j], dda[i][j]);
#else
else sprintf(TmpTxt, cfmt[j], dda[i][j]);
#endif
- if(txt_obj = mk_label(posc[j], y, false, TXA_HRIGHT, &txtdef1, TmpTxt)) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(parent, posc[j], y, false, TXA_HRIGHT, &txtdef1, TmpTxt);
}
if(i < (nl-2)) y += linsp1;
else {
- mk_hr(parent, x, posc[4], y + linsp1);
- y += linsp2;
+ mk_hr(parent, x, posc[4], y + linsp1); y += linsp2;
}
}
}
@@ -346,8 +347,7 @@ static char* mk_boxplot(double *x, double *y, double *by1, double *by2, double *
add_to_buff(&res, &pos, &csize,"\nLow=", 5);
add_dbl_to_buff(&res, &pos, &csize, x ? x[i] : (double)(i+1), true);
add_dbl_to_buff(&res, &pos, &csize, by1[i], true);
- add_to_buff(&res, &pos, &csize,"\nSize= 60\n", 10);
- add_to_buff(&res, &pos, &csize, "\nName= \"", 8);
+ add_to_buff(&res, &pos, &csize,"\nSize= 60\nName= \"", 17);
add_to_buff(&res, &pos, &csize, b_nam, 0);
add_to_buff(&res, &pos, &csize, "\"\n", 2);
}
@@ -409,21 +409,21 @@ static char* mk_boxplot(double *x, double *y, double *by1, double *by2, double *
add_int_to_buff(&res,&pos,&csize, first_b, false, 0); add_to_buff(&res,&pos,&csize, ",", 1);
if(i && (i%16)== 0 && first_b < (curr_id-2)) add_to_buff(&res, &pos, &csize, "\n ", 4);
}
- while(res[pos-1] == ',' || res[pos-1] < 33) pos --; add_to_buff(&res, &pos, &csize, "}\n", 2);
+ while(res[pos-1] == ',' || res[pos-1] < 33) pos --; add_to_buff(&res, &pos, &csize, "}", 2);
add_to_buff(&res,&pos,&csize, "\nWhiskers=(", 0); add_int_to_buff(&res,&pos,&csize, n, false, 0);
add_to_buff(&res,&pos,&csize, "){", 2);
for(i = 0; i < n; i++, first_w++) {
add_int_to_buff(&res,&pos,&csize, first_w, false, 0); add_to_buff(&res,&pos,&csize, ",", 1);
if(i && (i%16)== 0 && first_b < (curr_id-2)) add_to_buff(&res, &pos, &csize, "\n ", 4);
}
- while(res[pos-1] == ',' || res[pos-1] < 33) pos --; add_to_buff(&res, &pos, &csize, "}\n", 2);
+ while(res[pos-1] == ',' || res[pos-1] < 33) pos --; add_to_buff(&res, &pos, &csize, "}", 2);
add_to_buff(&res,&pos,&csize, "\nSymbols=(", 10); add_int_to_buff(&res,&pos,&csize, n, false, 0);
add_to_buff(&res,&pos,&csize, "){", 2);
for(i = 0; i < n; i++, first_s++) {
add_int_to_buff(&res,&pos,&csize, first_s, false, 0); add_to_buff(&res,&pos,&csize, ",", 1);
if(i && (i%16)== 0 && first_s < (curr_id-2)) add_to_buff(&res, &pos, &csize, "\n ", 4);
}
- while(res[pos-1] == ',' || res[pos-1] < 33) pos --; add_to_buff(&res, &pos, &csize, "}\n", 2);
+ while(res[pos-1] == ',' || res[pos-1] < 33) pos --; add_to_buff(&res, &pos, &csize, "}", 2);
add_to_buff(&res,&pos,&csize, "\nLabels=(", 9); add_int_to_buff(&res,&pos,&csize, n, false, 0);
add_to_buff(&res,&pos,&csize, "){", 2);
for(i = 0; i < n; i++, first_l++) {
@@ -457,10 +457,6 @@ static char* mk_scatt(double *x, double *y, double *ss, int *ny, int n, char *s_
add_to_buff(&res, &pos, &csize, "\n", 1);
add_to_buff(&res, &pos, &csize, SymLineStr, cbSymLineStr);
add_to_buff(&res, &pos, &csize, "FillCol= 0x00ffffff\n", 20);
- if(s_nam) {
- add_to_buff(&res, &pos, &csize, "Name=\"", 6);
- add_to_buff(&res, &pos, &csize, s_nam, 0); add_to_buff(&res, &pos, &csize, "\"\n", 2);
- }
}
if(ss && ny) {
for(i = 0; i < n && res; i++) {
@@ -531,57 +527,69 @@ static char* mk_scatt(double *x, double *y, double *ss, int *ny, int n, char *s_
add_to_buff(&res,&pos,&csize, "y_info= \"", 9); add_to_buff(&res,&pos,&csize, y_desc, 0);
add_to_buff(&res,&pos,&csize, "\"\n", 2);
}
+ if(s_nam && s_nam[0]) {
+ add_to_buff(&res, &pos, &csize, "DataDesc=\"", 10);
+ add_to_buff(&res, &pos, &csize, s_nam, 0); add_to_buff(&res, &pos, &csize, "\"\n", 2);
+ }
return res;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// one way anova
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-static char *AnovaDlg_Tmpl =
- "1,2,,DEFAULT,PUSHBUTTON,-1,148,10,45,12\n"
- "2,3,,,PUSHBUTTON,-2,148,25,45,12\n"
- "3,,4,ISPARENT | CHECKED,GROUP,0,0,0,0,0\n"
- "4,10,100,ISPARENT | CHECKED,SHEET,1,5,10,130,80\n"
- "10,,,CHECKED,CHECKPIN,0,5,0,12,8\n"
- "100,101,,,LTEXT,2,10,30,60,8\n"
- "101,102,,,RANGEINPUT,-15,20,40,100,10\n"
- "102,103,,CHECKED,RADIO1,3,10,55,60,9\n"
- "103,,,LASTOBJ,RADIO1,4,10,65,60,9";
-void
-rep_anova(GraphObj *parent, DataObj *data)
+static char *AnovaDlg_Tmpl =
+ "1,2,,DEFAULT,PUSHBUTTON,-1,158,10,45,12\n"
+ "2,3,,,PUSHBUTTON,-2,158,25,45,12\n"
+ "3,,10,ISPARENT | CHECKED,GROUP,0,0,0,0,0\n"
+ "10,20,152,ISPARENT | CHECKED, SHEET,1,5,10,140,70\n"
+ "20,,,CHECKED,CHECKPIN,0,5,0,12,8\n"
+ "152,153,,ISPARENT | CHECKED,GROUPBOX,2,12,30,128,45\n"
+ "153,154,,,LTEXT,0,25,35,60,8\n"
+ "154,155,,,RANGEINPUT,0,25,45,100,10\n"
+ "155,156,0,,PUSHBUTTON,-8,95,57,30,12\n"
+ "156,,,LASTOBJ,PUSHBUTTON,-9,60,57,35,12";
+
+void rep_anova(GraphObj *parent, DataObj *data)
{
TabSHEET tab1 = {0, 45, 10, "Anova Input"};
DlgInfo *AnovaDlg;
- void *dyndata[] = {(void*)&tab1, (void*)"rectangular range for variables",
- (void*)"variables arranged in columns", (void*)" -\"- -\"- in rows"};
+ void *dyndata[] = {(void*)&tab1, (void*)" select one range for every variable "};
DlgRoot *Dlg;
void *hDlg;
double **cols = 0L, tmp, *csums=0L, mtot, *css=0L, ssa, ssw, sst;
double **res_tab = 0L;
- int i, j, res, nr, nc, ntot, *ncols = 0L;;
- bool bContinue = false;
+ int i, j, n, c, r, res, nc, ntot, currYR = 0, maxYR=0, ny, *ncols = 0L;;
+ bool bContinue = false, updateYR = true;
+ anyResult ares;
AccRange *rD =0L;
- char *mrk, *txt_obj;
- RECT rec;
+ char **rd = 0L, **names, *txt_obj;
Graph *graph;
Page *page;
if(!parent || !data) return;
+ if(!UseRangeMark(data, 2, TmpTxt, TmpTxt+100, TmpTxt+200, TmpTxt+300, TmpTxt+400,
+ TmpTxt+500, TmpTxt+600, TmpTxt+700, TmpTxt+800, TmpTxt+900, TmpTxt+1000)) return;
if(!(AnovaDlg = CompileDialog(AnovaDlg_Tmpl, dyndata))) return;
- if(data->Command(CMD_GETMARK, &mrk, 0L))rlp_strcpy(TmpTxt, TMP_TXT_SIZE, mrk);
- else {
- data->ValueRec(&rec);
-#ifdef USE_WIN_SECURE
- i = sprintf_s(TmpTxt, TMP_TXT_SIZE, "%s%d", Int2ColLabel(rec.left,false), rec.top + 1);
- sprintf_s(TmpTxt+i, TMP_TXT_SIZE-i, ":%s%d", Int2ColLabel(rec.right, false), rec.bottom+1);
-#else
- i = sprintf(TmpTxt,"%s%d", Int2ColLabel(rec.left,false), rec.top + 1);
- sprintf(TmpTxt+i, ":%s%d", Int2ColLabel(rec.right, false), rec.bottom+1);
-#endif
+ if(TmpTxt[0] && TmpTxt[100] && (rd = (char**)calloc(12, sizeof(char*)))) {
+ for(i=j=0; i <= 1000; i +=100) if(TmpTxt[i])
+ rd[j++] = (char*)memdup(TmpTxt+i, ((int)strlen(TmpTxt+i))+2, 0); maxYR = j-1;
}
+ if(!rd && !(rd = (char**)calloc(1, sizeof(char*))))return;
if(!(Dlg = new DlgRoot(AnovaDlg, data)))return;
- hDlg = CreateDlgWnd("One Way Anova", 50, 50, 420, 220, Dlg, 0x0L);
+ if(rd && rd[currYR] && *(rd[currYR])) Dlg->SetText(154, rd[currYR]);
+ hDlg = CreateDlgWnd("Single-Classification Anova", 50, 50, 420, 200, Dlg, 0x0L);
do {
+ if(updateYR) {
+ if(currYR >0) Dlg->ShowItem(156, true);
+ else Dlg->ShowItem(156, false);
+#ifdef USE_WIN_SECURE
+ sprintf_s(TmpTxt, TMP_TXT_SIZE, "variable # %d/%d", currYR+1, maxYR+1);
+#else
+ sprintf(TmpTxt,"variable # %d/%d", currYR+1, maxYR+1);
+#endif
+ Dlg->SetText(153, TmpTxt);
+ updateYR = false;
+ }
LoopDlgWnd();
res = Dlg->GetResult();
switch (res) {
@@ -592,90 +600,422 @@ rep_anova(GraphObj *parent, DataObj *data)
case -1:
bContinue = false;
break;
+ case 155: case 156:
+ res = com_StackDlg(res, Dlg, 0L, 0L, &rd, &currYR,
+ &rD, &bContinue, &ny, &maxYR, &updateYR);
+ break;
}
}while (res < 0);
- if(res == 1 && Dlg->GetText(101, TmpTxt, TMP_TXT_SIZE) &&(rD = new AccRange(TmpTxt))
- && rD->BoundRec(&rec) && (res_tab = (double**)calloc(3, sizeof(double*)))
+ if(res == 1 && (res_tab = (double**)calloc(3, sizeof(double*)))
&& (res_tab[0] = (double*) malloc(5*sizeof(double)))
&& (res_tab[1] = (double*) malloc(5*sizeof(double)))
- && (res_tab[2] = (double*) malloc(5*sizeof(double)))) {
- rep_init();
- if(Dlg->GetCheck(102)) {
- nr = rec.bottom - rec.top +1; nc = rec.right - rec.left +1;
- if((cols = (double**)malloc(nc * sizeof(double*))) && (ncols = (int*)malloc(nc * sizeof(int)))) {
- for(i = rec.left; i <= rec.right; i++) {
- ncols[i-rec.left] = 0; cols[i-rec.left] = (double*)malloc(nr * sizeof(double));
- if(cols[i-rec.left]) for(j = rec.top; j <= rec.bottom; j++) {
- if(data->GetValue(j, i, &tmp)) cols[i-rec.left][ncols[i-rec.left]++] = tmp;
+ && (res_tab[2] = (double*) malloc(5*sizeof(double)))
+ && (cols = (double**)calloc(maxYR+1, sizeof(double*)))
+ && (names = (char**)calloc(maxYR+1, sizeof(char*)))
+ && (ncols = (int*)calloc(maxYR+1, sizeof(int)))
+ && (csums = (double*)calloc(maxYR+1, sizeof(double)))
+ && (css = (double*)calloc(maxYR+1, sizeof(double)))) {
+ rep_init(); if(rD) delete rD; rD = 0L;
+ dBounds.Ymin = HUGE_VAL; dBounds.Ymax = -HUGE_VAL;
+ // get data into two dimensional array
+ for(nc = maxYR+1, i = ntot = 0, mtot = 0.0; i < nc; i++) {
+ if((rD = new AccRange(rd[i])) && (n = rD->CountItems()) && (cols[i] = (double*)malloc(n*sizeof(double)))) {
+ names[i] = rD->RangeDesc(data, 1);
+ for(n = 0, rD->GetFirst(&c, &r); rD->GetNext(&c, &r); ) {
+ if(data->GetResult(&ares, r, c, false) && ares.type == ET_VALUE) {
+ if(ares.value < dBounds.Ymin) dBounds.Ymin = ares.value;
+ if(ares.value > dBounds.Ymax) dBounds.Ymax = ares.value;
+ cols[i][n] = ares.value; csums[i] += cols[i][n++];
}
}
+ ncols[i] = n; ntot += n; mtot += csums[i];
+ if(ncols[i]) csums[i] /= ((double)ncols[i]);
+ delete(rD); rD = 0L;
+ }
+ if(!names[i] && (names[i] = (char*)malloc(20*sizeof(char)))){
+#ifdef USE_WIN_SECURE
+ sprintf_s(names[i], 20, "Group %d", i+1);
+#else
+ sprintf(names[i], "Group %d", i+1);
+#endif
}
}
- else {
- nr = rec.right - rec.left +1; nc = rec.bottom - rec.top +1;
- if((cols = (double**)malloc(nc * sizeof(double*))) && (ncols = (int*)malloc(nc * sizeof(int)))) {
- for(i = rec.top; i <= rec.bottom; i++) {
- ncols[i-rec.top] = 0; cols[i-rec.top] = (double*)malloc(nr * sizeof(double));
- if(cols[i-rec.top]) for(j = rec.left; j <= rec.right; j++) {
- if(data->GetValue(i, j, &tmp)) cols[i-rec.top][ncols[i-rec.top]++] = tmp;
- }
+ // check for unique names
+ for(i = 0; i < (nc-1); i++) for(j = i+1; j < nc; j++) {
+ if(!strcmp(names[i], names[j])) {
+ names[i] = (char*) realloc(names[i], 20 *sizeof(char));
+ names[j] = (char*) realloc(names[j], 20 *sizeof(char));
+#ifdef USE_WIN_SECURE
+ sprintf_s(names[i], 20, "Group %d", i+1); sprintf_s(names[j], 20, "Group %d", j+1);
+#else
+ sprintf(names[i], "Group %d", i+1); sprintf(names[j], "Group %d", j+1);
+#endif
+ }
+ }
+ dBounds.Xmin = 0.5; dBounds.Xmax = ((double)nc)+0.5;
+ if(ntot) mtot /= ((double)ntot);
+ for(i = 0; i < nc; i++) {
+ for(j = 0, css[i] = 0.0; j < ncols[i]; j++) {
+ tmp = cols[i][j] - csums[i]; css[i] += (tmp*tmp);
+ }
+ }
+ for(i = 0, ssa = ssw = sst = 0.0; i < nc; i++) {
+ tmp =(csums[i] - mtot); ssa += (tmp*tmp) * ((double)ncols[i]);
+ ssw += css[i];
+ }
+ sst = ssa + ssw;
+ res_tab[0][0] = nc - 1; res_tab[1][0] = ntot - nc;
+ res_tab[2][0] = ntot -1; res_tab[0][1] = ssa;
+ res_tab[1][1] = ssw; res_tab[2][1] = sst;
+ res_tab[0][2] = ssa/res_tab[0][0]; res_tab[1][2] = ssw/res_tab[1][0];
+ res_tab[0][3] = res_tab[0][2]/res_tab[1][2];
+ res_tab[0][4] = f_dist(res_tab[0][3], res_tab[0][0], res_tab[1][0]);
+ page = new Page(parent, data);
+ mk_header(page, "<b>Single-Classification ANOVA</b>");
+ if((graph = new Graph(parent, data, 0L)) && (txt_obj = mk_scatt(0L, csums, css, ncols, nc, "Mean", "Groups", "Means <u>+</u> S.D."))){
+ OpenGraph(graph, 0L, (unsigned char*)txt_obj, false);
+ if(LastOpenGO && LastOpenGO->Id == GO_PLOTSCATT) {
+ if(((PlotScatt*)LastOpenGO)->x_tv = new TextValue()){
+ for(i = 0; i < nc; i++) ((PlotScatt*)LastOpenGO)->x_tv->GetValue(names[i]);
}
}
+ free(txt_obj); graph->moveable = 0;
+ graph->GRect.Xmin += (txtdef1.fSize*5.0); graph->GRect.Xmax += (txtdef1.fSize*5.0);
+ graph->GRect.Ymin += (txtdef1.fSize*10.0); graph->GRect.Ymax += (txtdef1.fSize*10.0);
+ page->Command(CMD_DROP_GRAPH, graph, 0L);
+ }
+ mk_table(page, graph->GRect.Xmin, graph->GetSize(SIZE_GRECT_BOTTOM)+txtdef2.fSize*3.0, 1, res_tab);
+ parent->Command(CMD_DROP_GRAPH, page, 0L);
+ for(i = 0; i < nc; i++){
+ if(cols[i]) free(cols[i]); if(names[i]) free(names[i]);
}
- if(cols && nr >1 && nc >1 && (csums = (double*)malloc(nc *sizeof(double)))
- && (css = (double*)malloc(nc *sizeof(double)))) {
- dBounds.Ymin = HUGE_VAL; dBounds.Ymax = -HUGE_VAL;
- for(i = ntot = 0, mtot = 0.0; i < nc; i++) {
- for(j = 0, csums[i] = 0.0; j < ncols[i]; j++) {
- csums[i] += cols[i][j];
- if(dBounds.Ymin > cols[i][j]) dBounds.Ymin = cols[i][j];
- if(dBounds.Ymax < cols[i][j]) dBounds.Ymax = cols[i][j];
+ for(i = 0; i < 3; i++) if(res_tab[i]) free(res_tab[i]);
+ free(cols); free(ncols); free(names);
+ free(res_tab); free(css); free(csums);
+ }
+ if(rD) delete rD; CloseDlgWnd(hDlg);
+ delete Dlg; free(AnovaDlg);
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Kruskal-Wallis Test for Differences of Location
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static char *RepKruskal_DlgTmpl =
+ "1,2,,DEFAULT,PUSHBUTTON,-1,158,10,45,12\n"
+ "2,3,,,PUSHBUTTON,-2,158,25,45,12\n"
+ "3,,10,ISPARENT | CHECKED,GROUP,0,0,0,0,0\n"
+ "10,20,152,ISPARENT | CHECKED, SHEET,1,5,10,140,70\n"
+ "20,,,CHECKED,CHECKPIN,0,5,0,12,8\n"
+ "152,153,,ISPARENT | CHECKED,GROUPBOX,2,12,30,128,45\n"
+ "153,154,,,LTEXT,0,25,35,60,8\n"
+ "154,155,,,RANGEINPUT,0,25,45,100,10\n"
+ "155,156,0,,PUSHBUTTON,-8,95,57,30,12\n"
+ "156,,,LASTOBJ,PUSHBUTTON,-9,60,57,35,12";
+
+void rep_kruskal(GraphObj *parent, DataObj *data)
+{
+ TabSHEET tab1 = {0, 25, 10, "Data"};
+
+ void *dyndata[] = {(void*)&tab1, (void*)" select one range for every variable "};
+ DlgInfo *KruskalDlg;
+ DlgRoot *Dlg;
+ void *hDlg;
+ int i, j, n, c, r, nt, res, currYR = 0, maxYR = 0, ny, nr, *nvals;
+ bool updateYR = true, bContinue = false;
+ double h, h1, p, **vals, *x, *y, *by1, *by2, *wy1, *wy2, *ranks, *ridx, *rsums, th, cy, cx[10];
+ char **rd = 0L, **names, *txt_obj;
+ char *headings[] = {"<i>Groups</i>", "<i>N</i>", "<i>Median</i>", "<i>25% - 75%</i>",
+ "<i>Range</i>","<i>Rank Sums</i>"};
+ scaleINFO scale = {{0.0, 1.0}, {0.0, 1.0}, {0.0, 1.0}};
+ AccRange *rV1 = 0L;
+ anyResult ares;
+ Page *page;
+ Graph *graph;
+
+ if(!parent || !data) return;
+ if(!UseRangeMark(data, 2, TmpTxt, TmpTxt+100, TmpTxt+200, TmpTxt+300, TmpTxt+400,
+ TmpTxt+500, TmpTxt+600, TmpTxt+700, TmpTxt+800, TmpTxt+900, TmpTxt+1000)) return;
+ if(!(KruskalDlg = CompileDialog(RepKruskal_DlgTmpl, dyndata))) return;
+ if(TmpTxt[0] && TmpTxt[100] && (rd = (char**)calloc(12, sizeof(char*)))) {
+ for(i=j=0; i <= 1000; i +=100) if(TmpTxt[i])
+ rd[j++] = (char*)memdup(TmpTxt+i, ((int)strlen(TmpTxt+i))+2, 0); maxYR = j-1;
+ }
+ if(!rd && !(rd = (char**)calloc(1, sizeof(char*))))return;
+ if(!(Dlg = new DlgRoot(KruskalDlg, data))) return;
+ if(rd && rd[currYR] && *(rd[currYR])) Dlg->SetText(154, rd[currYR]);
+ hDlg = CreateDlgWnd("Kruskal-Wallis Nonparametric Anova", 50, 50, 420, 200, Dlg, 0x0L);
+ do {
+ if(updateYR) {
+ if(currYR >0) Dlg->ShowItem(156, true);
+ else Dlg->ShowItem(156, false);
+#ifdef USE_WIN_SECURE
+ sprintf_s(TmpTxt, TMP_TXT_SIZE, "variable # %d/%d", currYR+1, maxYR+1);
+#else
+ sprintf(TmpTxt,"variable # %d/%d", currYR+1, maxYR+1);
+#endif
+ Dlg->SetText(153, TmpTxt);
+ updateYR = false;
+ }
+ LoopDlgWnd();
+ res = Dlg->GetResult();
+ switch(res) {
+ case 0:
+ if(bContinue || Dlg->GetCheck(20)) res = -1;
+ break;
+ case -1:
+ bContinue = false;
+ break;
+ case 155: case 156:
+ res = com_StackDlg(res, Dlg, 0L, 0L, &rd, &currYR,
+ &rV1, &bContinue, &ny, &maxYR, &updateYR);
+ break;
+ }
+ }while (res < 0);
+ if(res == 1 && (vals = (double**)calloc(sizeof(double*), maxYR+1)) && (nvals = (int*)calloc(sizeof(int), maxYR+1))
+ && (names = (char**)calloc(maxYR+1, sizeof(char*))) && (x = (double*)calloc(maxYR+1, sizeof(double)))
+ && (y = (double*)calloc(maxYR+1, sizeof(double))) && (by1 = (double*)calloc(maxYR+1, sizeof(double)))
+ && (by2 = (double*)calloc(maxYR+1, sizeof(double))) && (wy1 = (double*)calloc(maxYR+1, sizeof(double)))
+ && (wy2 = (double*)calloc(maxYR+1, sizeof(double)))
+ && (rsums = (double*)calloc(maxYR+1, sizeof(double)))) {
+ maxYR++; rep_init(); page = new Page(parent, data);
+ dBounds.Xmin = 0.5; dBounds.Xmax = (double)maxYR+0.3;
+ if(rV1) delete rV1; rV1 = 0L; ranks = ridx = 0L;
+ cy = txtdef1.fSize*10.0;
+ mk_header(page, "<b>Kruskal-Wallis Test for Differences of Location</b>");
+ dBounds.Ymin = HUGE_VAL; dBounds.Ymax = -HUGE_VAL;
+ // get data into two dimensional array
+ for(nr = maxYR, i = nt = 0; i < nr; i++) {
+ x [i] = y[i] = by1[i] = by2[i] = wy1[i] = wy2[i] = 0.0; nvals[i] = 0;
+ if((rV1 = new AccRange(rd[i])) && (n = rV1->CountItems()) && (vals[i] = (double*)malloc(n*sizeof(double)))) {
+ names[i] = rV1->RangeDesc(data, 1);
+ for(n = 0, rV1->GetFirst(&c, &r); rV1->GetNext(&c, &r); ) {
+ if(data->GetResult(&ares, r, c, false) && ares.type == ET_VALUE) {
+ if(!n) wy1[i] = wy2[i] = ares.value;
+ else {
+ if(ares.value < wy1[i]) wy1[i] = ares.value;
+ if(ares.value > wy2[i]) wy2[i] = ares.value;
+ }
+ if(ares.value < dBounds.Ymin) dBounds.Ymin = ares.value;
+ if(ares.value > dBounds.Ymax) dBounds.Ymax = ares.value;
+ vals[i][n] = ares.value; n++;
+ }
}
- mtot += csums[i]; ntot += ncols[i];
- if(ncols[i]) csums[i] /= ((double)ncols[i]);
+ nvals[i] = n; nt += n; delete rV1; rV1 = 0;
}
- dBounds.Xmin = 0.5; dBounds.Xmax = nc;
- if(ntot) mtot /= ((double)ntot);
- for(i = 0; i < nc; i++) {
- for(j = 0, css[i] = 0.0; j < ncols[i]; j++) {
- tmp = cols[i][j] - csums[i]; css[i] += (tmp*tmp);
+ if(!names[i] && (names[i] = (char*)malloc(20*sizeof(char)))){
+#ifdef USE_WIN_SECURE
+ sprintf_s(names[i], 20, "Group %d", i+1);
+#else
+ sprintf(names[i], "Group %d", i+1);
+#endif
+ }
+ }
+ // rank sums
+ if(nt && (ranks=(double*)malloc(nt*sizeof(double))) && (ridx=(double*)malloc(nt*sizeof(double)))) {
+ for(i = n = 0; i < nr; i++) {
+ for(j = 0; j < nvals[i]; j++) {
+ ridx[n] = (double)(i); ranks[n] = vals[i][j]; n++;
}
}
- for(i = 0, ssa = ssw = sst = 0.0; i < nc; i++) {
- tmp =(csums[i] - mtot); ssa += (tmp*tmp) * ((double)ncols[i]);
- ssw += css[i];
+ SortArray2(n, ranks, ridx); crank(n, ranks, &th);
+ for(i = 0; i < n; i++) rsums[(int)ridx[i]] += ranks[i];
+ //statistics on range sums
+ for(i = 0, h = 0.0; i < nr; i++) h += rsums[i]*rsums[i]/((double)nvals[i]);
+ h = h * 12.0/(((double)n)*((double)(n+1))) - 3.0*((double)n+1);
+ h1 = h / (1.0 - th/(((double)(n-1)) * ((double)n)* ((double)(n+1))));
+ }
+ else h = h1 = -1.0;
+ // check for unique names
+ for(i = 0; i < (nr-1); i++) for(j = i+1; j < nr; j++) {
+ if(!strcmp(names[i], names[j])) {
+ names[i] = (char*) realloc(names[i], 20 *sizeof(char));
+ names[j] = (char*) realloc(names[j], 20 *sizeof(char));
+#ifdef USE_WIN_SECURE
+ sprintf_s(names[i], 20, "Group %d", i+1); sprintf_s(names[j], 20, "Group %d", j+1);
+#else
+ sprintf(names[i], "Group %d", i+1); sprintf(names[j], "Group %d", j+1);
+#endif
}
- sst = ssa + ssw;
- res_tab[0][0] = nc - 1; res_tab[1][0] = ntot - nc;
- res_tab[2][0] = ntot -1; res_tab[0][1] = ssa;
- res_tab[1][1] = ssw; res_tab[2][1] = sst;
- res_tab[0][2] = ssa/res_tab[0][0]; res_tab[1][2] = ssw/res_tab[1][0];
- res_tab[0][3] = res_tab[0][2]/res_tab[1][2];
- res_tab[0][4] = f_dist(res_tab[0][3], res_tab[0][0], res_tab[1][0]);
- page = new Page(parent, data);
- mk_header(page, "<b>One Way ANOVA</b>");
- if((graph = new Graph(parent, data, 0L)) && (txt_obj = mk_scatt(0L, csums, css, ncols, nc, "Mean", 0L, "Means <u>+</u> S.D."))){
- OpenGraph(graph, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj); graph->moveable = 0;
- graph->GRect.Xmin += (txtdef1.fSize*5.0); graph->GRect.Xmax += (txtdef1.fSize*5.0);
- graph->GRect.Ymin += (txtdef1.fSize*10.0); graph->GRect.Ymax += (txtdef1.fSize*10.0);
- page->Command(CMD_DROP_GRAPH, graph, 0L);
+ }
+ // simple group statistics
+ for(i = 0; i < nr; i++) {
+ x[i] = (double)(i+1); d_quartile(nvals[i], vals[i], by1+i, y+i, by2+i);
+ }
+ // create boxplot
+ if((graph = new Graph(parent, data, 0L)) && (txt_obj = mk_boxplot(x, y, by1, by2, wy1, wy2,
+ nvals, nr,"Median","25-75%","Min./Max."))){
+ scale.sx.fx = (txtdef1.fSize*5.0); scale.sy.fx = (txtdef1.fSize*10.0);
+ OpenGraph(graph, 0L, (unsigned char*)txt_obj, false);
+ if(LastOpenGO && LastOpenGO->Id == GO_BOXPLOT) {
+ if(((BoxPlot*)LastOpenGO)->x_tv = new TextValue()){
+ for(i = 0; i < nr; i++) ((BoxPlot*)LastOpenGO)->x_tv->GetValue(names[i]);
+ }
+ if(((BoxPlot*)LastOpenGO)->x_info = (char*)malloc(20*sizeof(char)))
+ rlp_strcpy(((BoxPlot*)LastOpenGO)->x_info, 20, "Groups");
+ if(((BoxPlot*)LastOpenGO)->y_info = (char*)malloc(20*sizeof(char)))
+ rlp_strcpy(((BoxPlot*)LastOpenGO)->y_info, 20, "Location");
}
- mk_table(page, graph->GRect.Xmin, graph->GetSize(SIZE_GRECT_BOTTOM)+txtdef2.fSize*3.0,
- 1, res_tab);
- parent->Command(CMD_DROP_GRAPH, page, 0L);
+ free(txt_obj); graph->Command(CMD_SCALE, &scale, 0L);
+ cy = graph->GetSize(SIZE_GRECT_BOTTOM)+txtdef1.fSize*2.0;
+ page->Command(CMD_DROP_GRAPH, graph, 0L);
+ }
+ parent->Command(CMD_DROP_GRAPH, page, 0L);
+ //report statistics
+ cx[0] = txtdef1.fSize*5.0; cx[1] = cx[0] + linsp1*5.0;
+ cx[2] = cx[1] + linsp1*2.5; cx[3] = cx[2] + linsp1*4.0;
+ cx[4] = cx[3] + linsp1*5.0; cx[5] = cx[4] + linsp1*7.0;
+ cx[6] = cx[5] + linsp1*8.0;
+ rep_DrawText(page, cx[0], cy, false, TXA_HLEFT, &txtdef1, "<b>Test Statistics:</b>");
+ cy += linsp2; p = chi_dist(h,(double)(nr-1), 0.0);
+ dbl_to_str2(TmpTxt, 100, p < 0.0001 ?(char*)"H = %.2lf, P < 0.0001" : (char*)"H = %.2lf, P = %.4lf", h, p);
+ rep_DrawText(page, cx[1], cy, false, TXA_HLEFT, &txtdef1, TmpTxt);
+ cy += linsp1; p = chi_dist(h1,(double)(nr-1), 0.0);
+ dbl_to_str2(TmpTxt, 100, p < 0.0001 ?(char*)"H(corr.) = %.2lf, P < 0.0001" : (char*)"H(corr.) = %.2lf, P = %.4lf", h1, p);
+ if(th >= 1.0) {
+ rep_DrawText(page, cx[1], cy, false, TXA_HLEFT, &txtdef1, TmpTxt);
+ cy += linsp1;
+ }
+ cy += linsp2;
+ // create summary table
+ rep_DrawText(page, cx[0], cy, false, TXA_HLEFT, &txtdef1, "<b>Summary:</b>");
+ for(i = 0, cy += linsp2; i < 6; i++) { //column headers
+ c = (i == 3 || i == 4) ? TXA_HCENTER : TXA_HRIGHT;
+ rep_DrawText(page, cx[i+1], cy, false, c, &txtdef1, headings[i]);
+ }
+ mk_hr(page, cx[0], cx[6]+txtdef1.fSize*2.0, cy +linsp1);
+ for(i = 0, cy += linsp2; i < nr; i++, cy += linsp1) {
+ for(j = 0; j < 6; j++) {
+ switch(j) {
+ default: rlp_strcpy(TmpTxt, 20, names[i]); break;
+ case 1: dbl_to_str1(TmpTxt, 20, "%.0lf", (double)nvals[i]); break;
+ case 2: dbl_to_str1(TmpTxt, 20, "%g", y[i]); break;
+ case 3: dbl_to_str2(TmpTxt, 20, "%g - %g", by1[i], by2[i]); break;
+ case 4: dbl_to_str2(TmpTxt, 20, "%g - %g", wy1[i], wy2[i]); break;
+ case 5: dbl_to_str1(TmpTxt, 20, "%g", rsums[i]); break;
+ }
+ c = (j == 3 || j == 4) ? TXA_HCENTER : TXA_HRIGHT;
+ rep_DrawText(page, cx[j+1], cy, false, c, &txtdef1,TmpTxt);
+ }
+ }
+ mk_hr(page, cx[0], cx[6]+txtdef1.fSize*2.0, cy+txtdef1.fSize*0.2);
+ for(i= 0; i< nr; i++) {
+ if(vals[i]) free(vals[i]); if(names[i]) free(names[i]);
}
+ free(vals); free(nvals); free(names);
+ free(x); free(y); free(by1);
+ free(by2); free(wy1); free(wy2);
+ free(rsums);
}
- if(cols) {
- for(i = 0; i < nc; i++) if(cols[i]) free(cols[i]);
- free(cols);
+ CloseDlgWnd(hDlg);
+ delete Dlg;
+ if(rd) {
+ for (i = 0; i < maxYR; i++) if(rd[i]) free(rd[i]);
+ free(rd);
}
- if(res_tab) {
- for(i = 0; i < 3; i++) if(res_tab[i]) free(res_tab[i]);
- free(res_tab);
+ if(ranks)free(ranks); if(ridx)free(ridx);
+ if(rV1) delete rV1; free(KruskalDlg);
+ return;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// simple sample statistics
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static char *SmplStatDlg_Tmpl =
+ "1,2,,DEFAULT,PUSHBUTTON,-1,148,10,45,12\n"
+ "2,3,,,PUSHBUTTON,-2,148,25,45,12\n"
+ "3,,4,ISPARENT | CHECKED,GROUP,0,0,0,0,0\n"
+ "4,10,100,ISPARENT | CHECKED,SHEET,1,5,10,130,80\n"
+ "10,,,CHECKED,CHECKPIN,0,5,0,12,8\n"
+ "100,101,,,LTEXT,2,10,30,60,8\n"
+ "101,,,LASTOBJ,RANGEINPUT,-15,20,40,100,10";
+void rep_samplestats(GraphObj *parent, DataObj *data)
+{
+ TabSHEET tab1 = {0, 40, 10, "Input Data"};
+ DlgInfo *SmplStatDlg;
+ void *dyndata[] = {(void*)&tab1, (void*)"rectangular range for variables"};
+ DlgRoot *Dlg;
+ void *hDlg;
+ int res, nr, nc, ntot, cb;
+ double val, *src_data, cx, cy, ksprob, ksd, sww, swp, mean, sd;
+ bool bContinue = false;
+ AccRange *rD =0L;
+ char *mrk, *x_info, *y_info;
+ RECT rec;
+ Plot *plot;
+ Graph *graph;
+ Page *page;
+
+ if(!parent || !data) return;
+ if(!(SmplStatDlg = CompileDialog(SmplStatDlg_Tmpl, dyndata))) return;
+ if(data->Command(CMD_GETMARK, &mrk, 0L))rlp_strcpy(TmpTxt, TMP_TXT_SIZE, mrk);
+ else {
+ data->ValueRec(&rec);
+ rlp_strcpy(TmpTxt, 100, mkRangeRef(rec.top, rec.left, rec.bottom, rec.right));
}
- if(rD) delete rD; if(ncols) free(ncols); if(csums) free(csums);
- if(css) free(css); CloseDlgWnd(hDlg); delete Dlg; free(AnovaDlg);
+ if(!(Dlg = new DlgRoot(SmplStatDlg, data)))return;
+ hDlg = CreateDlgWnd("Sample Statistics", 50, 50, 420, 220, Dlg, 0x0L);
+ do {
+ LoopDlgWnd();
+ res = Dlg->GetResult();
+ switch (res) {
+ case 0:
+ if(bContinue) res = -1;
+ else if(Dlg->GetCheck(10)) res = -1;
+ break;
+ case -1:
+ bContinue = false;
+ break;
+ }
+ }while (res < 0);
+ if(res == 1 && Dlg->GetText(101, TmpTxt+200, TMP_TXT_SIZE) &&(rD = new AccRange(TmpTxt+200))
+ && rD->BoundRec(&rec) && (ntot = rD->CountItems()) && (src_data = (double*)malloc(ntot*sizeof(double)))){
+ rep_init();
+ x_info = rD->RangeDesc(data, 2);
+ if(y_info = (char*)malloc(20)) rlp_strcpy(y_info, 20, "Normal quantiles");
+ page = new Page(parent, data);
+ cb = rlp_strcpy(TmpTxt, 100, "<b>Sample Statistics for \"");
+ if(x_info && x_info[0]) cb += rlp_strcpy(TmpTxt+cb, 100-cb, x_info);
+ else cb += rlp_strcpy(TmpTxt+cb, 100-cb, TmpTxt+200);
+ rlp_strcpy(TmpTxt+cb,100-cb, "\"</b>"); mk_header(page, TmpTxt);
+ for(ntot = 0, rD->GetFirst(&nc, &nr); rD->GetNext(&nc, &nr); ) {
+ if(data->GetValue(nr, nc, &val)) src_data[ntot++] = val;
+ }
+ if(ntot > 5 && (graph = new Graph(page, data, 0L))) {
+ if(plot = new NormQuant(page, data, src_data, ntot)) {
+ plot->x_info = x_info; plot->y_info = y_info;
+ }
+ if(!(graph->Command(CMD_DROP_PLOT, (void *)plot, 0L))) {
+ delete plot; plot =0L;
+ }
+ graph->moveable = 0; graph->GRect.Xmin += (txtdef1.fSize*5.0);
+ graph->GRect.Xmax += (txtdef1.fSize*5.0); graph->GRect.Ymin += (txtdef1.fSize*10.0);
+ graph->GRect.Ymax += (txtdef1.fSize*10.0); page->Command(CMD_DROP_GRAPH, graph, 0L);
+ }
+ cy = graph->GetSize(SIZE_GRECT_BOTTOM)+txtdef1.fSize*3;
+ rep_DrawText(page, graph->GRect.Xmin, cy, false, TXA_HLEFT, &txtdef1, "<b>Descriptive Statistics:</b>");
+ cy += txtdef1.fSize*1.5; cx = graph->GetSize(SIZE_GRECT_LEFT)+txtdef1.fSize*25.0;
+ mk_median_report(page, cx, cy, src_data, ntot, .95, 0L);
+ cx = graph->GetSize(SIZE_GRECT_LEFT)+txtdef1.fSize*2.0;
+ cy = mk_mean_report(page, cx, cy, src_data, ntot, .95, 0L);
+ //data are sorted by the mk_median_report();
+ d_variance(ntot, src_data, &mean, &sd);
+ sd = sqrt(sd/((double)(ntot-1)));
+ KolSmir(ntot, src_data, norm_dist, mean, sd, true, &ksd, &ksprob);
+ cy += txtdef1.fSize*1.5; cx = graph->GRect.Xmin;
+ rep_DrawText(page, cx , cy, false, TXA_HLEFT, &txtdef1, "<b>Test for Normal Distribution:</b>");
+ cy += linsp1; cx += (txtdef1.fSize*2.0);
+ cb = dbl_to_str1(TmpTxt, 100, "Kolmogorov-Smirnov D = %.4lf, P ", ksd);
+ dbl_to_str1(TmpTxt+cb, 100-cb, ksprob >= 0.0001 ? (char*)"= %.4lf" : (char*)"< 0.0001", ksprob);
+ rep_DrawText(page, cx , cy, false, TXA_HLEFT, &txtdef1,TmpTxt); cy += linsp1/1.2;
+ swilk1(ntot, src_data, norm_dist, 0.0, 1.0, true, &sww, &swp);
+ if(sww >= 0.0 && swp >= 0.0 && (cb = dbl_to_str1(TmpTxt, 100, "Shapiro-Wilk W = %.4lf, P ", sww))
+ && (dbl_to_str1(TmpTxt+cb, 100-cb, swp >= 0.0001 ? (char*)"= %.4lf" : (char*)"< 0.0001", swp))){
+ rep_DrawText(page, cx , cy, false, TXA_HLEFT, &txtdef1,TmpTxt); cy += linsp1/1.2;
+ }
+ parent->Command(CMD_DROP_GRAPH, page, 0L);
+ delete rD; free(src_data);
+ }
+ CloseDlgWnd(hDlg); delete Dlg; free(SmplStatDlg);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -683,71 +1023,40 @@ rep_anova(GraphObj *parent, DataObj *data)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static double mk_regr_summary(GraphObj *parent, double x, double y, double *dres, double ci, int n)
{
- char *txt_obj;
char *fmts[] = {"slope = %g", "intercept = %g", "observations = %g", "r<sup> 2</sup> = %g", "r = %g"};
char *ci_fmt = "%g - %g";
char lbl[80];
double z, s;
double x1 = x + txtdef1.fSize*3.0;
- double x2 = x + txtdef1.fSize*20.0;
+ double x2 = x + txtdef1.fSize*25.0;
#ifdef _WINDOWS
double hrw = txtdef1.fSize*38.0;
#else
double hrw = txtdef1.fSize*1.3*38.0;
#endif
- if(txt_obj = mk_label(x, y, false, TXA_HLEFT, &txtdef1, "<b>Regression:</b>")) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(parent, x, y, false, TXA_HLEFT, &txtdef1, "<b>Regression:</b>");
dbl_to_str1(lbl, 80, "%g%% C.I.", ci);
- if(txt_obj = mk_label(x2, y, false, TXA_HCENTER, &txtdef1, lbl)) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(parent, x2, y, false, TXA_HCENTER, &txtdef1, lbl);
mk_hr(parent, x, x+hrw, y+txtdef1.fSize*1.2);
y += linsp1*1.5; dbl_to_str1(lbl, 80, fmts[0], dres[0]);
- if(txt_obj = mk_label(x1, y, false, TXA_HLEFT, &txtdef1, lbl)) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(parent, x1, y, false, TXA_HLEFT, &txtdef1, lbl);
dbl_to_str2(lbl, 80, ci_fmt, dres[0]-dres[10], dres[0]+dres[10]);
- if(txt_obj = mk_label(x2, y, false, TXA_HCENTER, &txtdef1, lbl)) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(parent, x2, y, false, TXA_HCENTER, &txtdef1, lbl);
y += linsp1; dbl_to_str1(lbl, 80, fmts[1], dres[1]);
- if(txt_obj = mk_label(x1, y, false, TXA_HLEFT, &txtdef1, lbl)) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(parent, x1, y, false, TXA_HLEFT, &txtdef1, lbl);
dbl_to_str2(lbl, 80, ci_fmt, dres[1]-dres[11], dres[1]+dres[11]);
- if(txt_obj = mk_label(x2, y, false, TXA_HCENTER, &txtdef1, lbl)) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(parent, x2, y, false, TXA_HCENTER, &txtdef1, lbl);
y += linsp1; dbl_to_str1(lbl, 80, fmts[2], (double)n);
- if(txt_obj = mk_label(x1, y, false, TXA_HLEFT, &txtdef1, lbl)) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(parent, x1, y, false, TXA_HLEFT, &txtdef1, lbl);
y += linsp1; dbl_to_str1(lbl, 80, fmts[3], dres[12]);
- if(txt_obj = mk_label(x1, y, false, TXA_HLEFT, &txtdef1, lbl)) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(parent, x1, y, false, TXA_HLEFT, &txtdef1, lbl);
y += linsp1; dbl_to_str1(lbl, 80, fmts[4], sqrt(dres[12]));
- if(txt_obj = mk_label(x1, y, false, TXA_HLEFT, &txtdef1, lbl)) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(parent, x1, y, false, TXA_HLEFT, &txtdef1, lbl);
z = 0.5 * log((1.0+sqrt(dres[12])+_PREC)/(1.0-sqrt(dres[12])+_PREC)); //Fishers z-transform
s = distinv(t_dist, 1.0E+10, 1.0, (100-ci)/100.0, 2.0)/sqrt((double)(n-3));
dbl_to_str2(lbl, 80, ci_fmt, tanh(z-s), tanh(z+s));
- if(txt_obj = mk_label(x2, y, false, TXA_HCENTER, &txtdef1, lbl)) {
- OpenGraph(parent, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(parent, x2, y, false, TXA_HCENTER, &txtdef1, lbl);
mk_hr(parent, x, x+hrw, y+txtdef1.fSize*1.2);
return y + linsp1*3.0;
}
@@ -763,8 +1072,8 @@ static char *RegrDlg_Tmpl =
"102,103,,,LTEXT,3,10,55,60,8\n"
"103,104,,,RANGEINPUT,-16,20,65,100,10\n"
"104,105,,,LTEXT,4,10,80,60,8\n"
- "105,106,,,EDVAL1,5,70,80,25,10\n"
- "106,107,,,LTEXT,-10,97,80,60,8\n"
+ "105,106,,,EDVAL1,5,74,80,25,10\n"
+ "106,107,,,LTEXT,-10,101,80,60,8\n"
"107,,,LASTOBJ,CHECKBOX,6,10,95,100,8";
void
@@ -929,11 +1238,8 @@ rep_regression(GraphObj *parent, DataObj *data)
if(!bParZ) sprintf(TmpTxt, "y = %g %c %g * x",dres[1],(dres[0] < 0.0 ? '-' : '+'), fabs(dres[0]));
else sprintf(TmpTxt, "y = %g * x", fabs(dres[0]));
#endif
- if(txt_obj = mk_label((graph->GetSize(SIZE_DRECT_LEFT) + graph->GetSize(SIZE_DRECT_RIGHT))/2.0,
- graph->GetSize(SIZE_DRECT_TOP)+txtdef1.fSize/2.0, true, TXA_HCENTER, &txtdef1, TmpTxt)) {
- OpenGraph(graph, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj);
- }
+ rep_DrawText(graph, (graph->GetSize(SIZE_DRECT_LEFT) + graph->GetSize(SIZE_DRECT_RIGHT))/2.0,
+ graph->GetSize(SIZE_DRECT_TOP)+txtdef1.fSize/2.0, true, TXA_HCENTER, &txtdef1, TmpTxt);
page = new Page(parent, data); page->Command(CMD_DROP_GRAPH, graph, 0L);
graph->moveable = 0;
graph->GRect.Xmin += (txtdef1.fSize*5.0); graph->GRect.Xmax += (txtdef1.fSize*5.0);
@@ -948,11 +1254,8 @@ rep_regression(GraphObj *parent, DataObj *data)
c_y = graph->GetSize(SIZE_GRECT_BOTTOM)+txtdef2.fSize*3.0;
c_x = graph->GRect.Xmin;
c_y = mk_regr_summary(page, c_x, c_y, dres, ci, n);
- if(txt_obj = mk_label(c_x, c_y, false, TXA_HLEFT, &txtdef1, "<b>Anova:</b>")) {
- OpenGraph(page, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj); c_y += txtdef1.fSize*1.5;
- }
- mk_table(page, c_x, c_y, 2, res_tab);
+ rep_DrawText(page, c_x, c_y, false, TXA_HLEFT, &txtdef1, "<b>Anova:</b>");
+ c_y += txtdef1.fSize*1.5; mk_table(page, c_x, c_y, 2, res_tab);
parent->Command(CMD_DROP_GRAPH, page, 0L);
}
}
@@ -965,6 +1268,293 @@ rep_regression(GraphObj *parent, DataObj *data)
if(x) free(x); if(y) free(y);
if(rX) delete rX; if(rY) delete rY; free(RegrDlg);
}
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Correlation reports
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static char *RepCorrel_DlgTmpl =
+ "1,2,,DEFAULT,PUSHBUTTON,-1,158,10,45,12\n"
+ "2,3,,,PUSHBUTTON,-2,158,25,45,12\n"
+ "3,,10,ISPARENT | CHECKED,GROUP,0,0,0,0,0\n"
+ "10,11,152,ISPARENT | CHECKED, SHEET,1,5,10,140,70\n"
+ "11,20,200,ISPARENT | TOUCHEXIT,SHEET,2,5,10,140,70\n"
+ "20,21,,CHECKED,CHECKPIN,0,5,0,12,8\n"
+ "21,22,,CHECKED,CHECKBOX,7,25,85,130,9\n"
+ "22,23,,,LTEXT,8,35,95,50,9\n"
+ "23,24,,,EDVAL1,9,87,95,30,10\n"
+ "24,,,,LTEXT,-10,120,95,10,9\n"
+ "152,153,,ISPARENT | CHECKED,GROUPBOX,3,12,30,128,45\n"
+ "153,154,,,LTEXT,0,25,35,60,8\n"
+ "154,155,,,RANGEINPUT,0,25,45,100,10\n"
+ "155,156,0,,PUSHBUTTON,-8,95,57,30,12\n"
+ "156,,,,PUSHBUTTON,-9,60,57,35,12\n"
+ "200,201,,TOUCHEXIT,RADIO1,4,25,30,60,8\n"
+ "201,202,,TOUCHEXIT,RADIO1,5,25,45,60,8\n"
+ "202,,,TOUCHEXIT,RADIO1,6,25,60,60,8\n"
+ "300,,,LASTOBJ,NONE,0,0,0,0,0";
+static int use_corr = 2;
+static double use_ci = 95.0;
+
+void rep_correl(GraphObj *parent, DataObj *data, int style)
+{
+ TabSHEET tab1 = {0, 25, 10, "Data"};
+ TabSHEET tab2 = {25, 57, 10, "Method"};
+
+ void *dyndata[] = {(void*)&tab1, (void*)&tab2,
+ (void*)" select one range for every variable ", (void*)" Pearsons product moment",
+ (void*)" Spearmans rank correlation", (void*)" Kendalls Tau", (void*)" highlight significant correlations,",
+ (void*)"sigificance level", (void*)&use_ci};
+ DlgInfo *CorrelDlg;
+ DlgRoot *Dlg;
+ void *hDlg;
+ int i, j, res, nr, currYR = 0, maxYR = 0, ny, corr;
+ int r1, c1, r2, c2, n, cb;
+ bool updateYR = true, bContinue = false, bMtab = false, bHiLite;
+ double lmarg, line_inc, *v1, *v2, val1, val2, cx, cy, r,dn, p, sf, ra[20], cl;
+ char **rd = 0L, *txt_obj, *info1, *info2;
+ scaleINFO scale = {{0.0, 0.14}, {0.0, 0.14}, {0.0, 0.14}};
+ AccRange *rV1 = 0L, *rV2 = 0L;
+ TextDEF mtext;
+ Plot *plot;
+ Graph *graph;
+ Page *page;
+
+ if(!parent || !data) return;
+ info1 = info2 = 0L;
+ if(!UseRangeMark(data, 2, TmpTxt, TmpTxt+100, TmpTxt+200, TmpTxt+300, TmpTxt+400,
+ TmpTxt+500, TmpTxt+600, TmpTxt+700, TmpTxt+800, TmpTxt+900, TmpTxt+1000)) return;
+ if(!(CorrelDlg = CompileDialog(RepCorrel_DlgTmpl, dyndata))) return;
+ if(TmpTxt[0] && TmpTxt[100] && (rd = (char**)calloc(12, sizeof(char*)))) {
+ for(i=j=0; i <= 1000; i +=100) if(TmpTxt[i])
+ rd[j++] = (char*)memdup(TmpTxt+i, ((int)strlen(TmpTxt+i))+2, 0); maxYR = j-1;
+ }
+ if(!rd && !(rd = (char**)calloc(1, sizeof(char*))))return;
+ if(!(Dlg = new DlgRoot(CorrelDlg, data))) return;
+ if(rd && rd[currYR] && *(rd[currYR])) Dlg->SetText(154, rd[currYR]);
+ switch(use_corr) {
+ case 1: Dlg->SetCheck(200, 0L, true); corr = 1; break;
+ default: Dlg->SetCheck(201, 0L, true); corr = 2; break;
+ case 3: Dlg->SetCheck(202, 0L, true); corr = 3; break;
+ }
+ hDlg = CreateDlgWnd(style? (char*)"Create Tiled Correlation Plots" :
+ (char*)"Create a Correlation Matrix", 50, 50, 420, 252, Dlg, 0x0L);
+ do {
+ if(updateYR) {
+ if(currYR >0) Dlg->ShowItem(156, true);
+ else Dlg->ShowItem(156, false);
+#ifdef USE_WIN_SECURE
+ sprintf_s(TmpTxt, TMP_TXT_SIZE, "variable # %d/%d", currYR+1, maxYR+1);
+#else
+ sprintf(TmpTxt,"variable # %d/%d", currYR+1, maxYR+1);
+#endif
+ Dlg->SetText(153, TmpTxt);
+ updateYR = false;
+ }
+ LoopDlgWnd();
+ res = Dlg->GetResult();
+ switch(res) {
+ case 0:
+ if(bContinue || Dlg->GetCheck(20)) res = -1;
+ break;
+ case -1:
+ bContinue = false;
+ break;
+ case 11: //select correlation method
+ bMtab = true; res =-1; break;
+ case 200: //select pearson
+ case 201: //select spearman
+ case 202: //select kendall
+ corr = res-199; res =-1; break;
+ case 1:
+ if(!bMtab) {
+ Dlg->SetCheck(11, 0L, true);
+ bMtab = true; res = -1;
+ break;
+ }
+ case 155: case 156:
+ res = com_StackDlg(res, Dlg, 0L, 0L, &rd, &currYR,
+ &rV1, &bContinue, &ny, &maxYR, &updateYR);
+ break;
+ }
+ }while (res < 0);
+
+ if(res ==1) {
+ if(bHiLite = Dlg->GetCheck(21)) {
+ Dlg->GetValue(23, &use_ci); cl = 1.0 - use_ci/100.0;
+ }
+ maxYR++; rep_init(); page = new Page(parent, data);
+ if(rV1) delete rV1; rV1 = 0L; use_corr = corr;
+ switch(corr) {
+ case 1:
+ mk_header(page, "<b>Pearsons product moment correlations</b>");
+ break;
+ case 2:
+ mk_header(page, "<b>Spearmans rank correlations</b>");
+ break;
+ case 3:
+ mk_header(page, "<b>Kendalls non parametric correlations</b>");
+ break;
+ default:
+ mk_header(page, "<b>### Correlation Error ###</b>");
+ break;
+ }
+ memcpy(&mtext, &txtdef1, sizeof(TextDEF));
+ if(style == 0) {
+ lmarg = txtdef1.fSize*12.0;
+ cy = txtdef1.fSize*13.0; cx = txtdef1.fSize*6.0;
+ line_inc = linsp1;
+ sf = (page->GetSize(SIZE_GRECT_RIGHT)-lmarg-linsp1)/(cx *(double)maxYR);
+ if(sf< 1.0) {
+ cx *= sf; line_inc *= sf; lmarg *= sf;
+ mtext.fSize *= sf; mtext.iSize = 0;
+ }
+ }
+ else {
+ lmarg = txtdef1.fSize*8.0;
+ cy = txtdef1.fSize*13.0;
+ cx = (page->GetSize(SIZE_GRECT_RIGHT)-txtdef1.fSize*3.0-lmarg)/maxYR;
+ switch(defs.cUnits) {
+ default:
+ scale.sx.fy = scale.sy.fy = scale.sz.fy = cx/165.0; break;
+ case 1:
+ scale.sx.fy = scale.sy.fy = scale.sz.fy = cx/16.50; break;
+ case 2:
+ scale.sx.fy = scale.sy.fy = scale.sz.fy = cx/6.49606; break;
+ }
+ line_inc = cx/1.44;
+ }
+ for(nr = maxYR, i = 0; i < nr; i++) for(j = 0; j < nr; j++) {
+ if(i == 0 &&(rV1 = new AccRange(rd[j]))) { //first row
+ if(info1 = rV1->RangeDesc(data, style == 0 || nr > 5 ? 1 : 2)) {
+ if(style == 0)
+ rep_DrawText(page, lmarg+cx*j, cy-txtdef1.fSize*2.0, false, TXA_HCENTER, &mtext, info1);
+ else if(style == 1)
+ rep_DrawText(page, lmarg+cx*j+cx/2.0, cy-txtdef1.fSize*2.0, false, TXA_HCENTER, &mtext, info1);
+ free(info1); info1 = 0L;
+ }
+ delete rV1; rV1 = 0L;
+ }
+ if(j == 0 &&(rV1 = new AccRange(rd[i]))) { //first column
+ if(info1 = rV1->RangeDesc(data, 1)) {
+ if(style == 0)
+ rep_DrawText(page, lmarg-cx/2.0-txtdef1.fSize, cy+line_inc, false, TXA_HRIGHT, &mtext, info1);
+ else if(style == 1)
+ rep_DrawText(page, lmarg-txtdef1.fSize, cy+line_inc/2.0-mtext.fSize/2.0, false, TXA_HRIGHT, &mtext, info1);
+ free(info1); info1 = 0L;
+ }
+ delete rV1; rV1 = 0L;
+ }
+ if(i == j) { //self correlation: do something else ...
+ if(style == 0) { //correlation matrix
+ rep_DrawText(page, lmarg+cx*j, cy+line_inc, false, TXA_HCENTER, &mtext, "---");
+ }
+ else if(style = 1) { //tiled plots
+ graph = new Graph(parent, data, 0L);
+ scale.sx.fx = lmarg+cx*j; scale.sy.fx = cy;
+ if(plot = new FreqDist(graph, data, rd[i], true)){
+ if(rV1 = new AccRange(rd[i])){
+ plot->x_info = rV1->RangeDesc(data, 2);
+ delete rV1; rV1 = 0L;
+ }
+ if(!(graph->Command(CMD_DROP_PLOT, plot, 0L))) delete(plot);
+ }
+ graph->Command(CMD_SCALE, &scale, 0L);
+ page->Command(CMD_DROP_GRAPH, graph, 0L);
+ }
+ }
+ else {
+ rV1 = new AccRange(rd[i]); rV2 = new AccRange(rd[j]);
+ v1 = (double*)malloc((rV1->CountItems()+1) * sizeof(double));
+ v2 = (double*)malloc((rV2->CountItems()+1) * sizeof(double));
+ dBounds.Xmin = dBounds.Ymin = HUGE_VAL; dBounds.Xmax = dBounds.Ymax = -HUGE_VAL;
+ rV1->GetFirst(&c1, &r1); rV2->GetFirst(&c2, &r2);
+ //copy values into arrays
+ for(n = 0; rV1->GetNext(&c1, &r1) && rV2->GetNext(&c2, &r2); ) {
+ if(data->GetValue(r1, c1, &val1) && data->GetValue(r2, c2, &val2)) {
+ if(dBounds.Xmin > val1) dBounds.Xmin = val1;
+ if(dBounds.Xmax < val1) dBounds.Xmax = val1;
+ if(dBounds.Ymin > val2) dBounds.Ymin = val2;
+ if(dBounds.Ymax < val2) dBounds.Ymax = val2;
+ v1[n] = val1; v2[n] = val2; n++;
+ }
+ }
+ //do correlation
+ dn = n; r = 0.0;
+ if(n) switch(corr) {
+ case 1:
+ d_pearson(v1, v2, n, 0L, 0L, ra);
+ r = ra[0]; p = ra[2]; dn = ra[3];
+ break;
+ case 2:
+ d_spearman(v1, v2, n, 0L, 0L, ra);
+ r = ra[3]; p = ra[4]; dn = ra[5];
+ break;
+ case 3:
+ d_kendall(v1, v2, n, 0L, 0L, ra);
+ r = ra[0]; p = ra[2]; dn = ra[3];
+ break;
+ default:
+ r = 0.0; dn = 0.0; p = 1.0; break;
+ }
+ //process result
+ if(style == 0) { //correlation matrix
+ if(bHiLite && p < cl && (txt_obj = mk_rect(lmarg+cx*j-cx/2.1, cy-line_inc/4.0, lmarg+cx*j+cx/2.1,
+ cy+line_inc*3.25, 0x0000ffffL, 0x0080ffffL))) {
+ OpenGraph(page, 0L, (unsigned char*)txt_obj, false);
+ free(txt_obj);
+ }
+ dbl_to_str1(TmpTxt, 80, "%g", r);
+ rep_DrawText(page, lmarg+cx*j, cy, false, TXA_HCENTER, &mtext, TmpTxt);
+ dbl_to_str1(TmpTxt, 80, "n = %g", dn);
+ rep_DrawText(page, lmarg+cx*j, cy+line_inc, false, TXA_HCENTER, &mtext, TmpTxt);
+ dbl_to_str1(TmpTxt, 80, p < 0.001 ? (char*)"P < 0.0001" : (char*)"P = %.4lf", p);
+ rep_DrawText(page, lmarg+cx*j, cy+line_inc*2.0, false, TXA_HCENTER, &mtext, TmpTxt);
+ if(j == (nr-1)) cy += (line_inc*4.0);
+ }
+ else if(style = 1) { //tiled plots
+ graph = new Graph(parent, data, 0L);
+ scale.sx.fx = lmarg+cx*j; scale.sy.fx = cy;
+ info1 = rV1->RangeDesc(data, 2); info2 = rV2->RangeDesc(data, 2);
+ if(txt_obj = mk_scatt(v1, v2, 0L, 0L, n, "Data", info1, info2)){
+ OpenGraph(graph, 0L, (unsigned char*)txt_obj, false);
+ free(txt_obj);
+ }
+ if(info1) free(info1); if(info2) free(info2);
+ info1 = info2 = 0L;
+ if(bHiLite && p < cl) {
+ graph->SetColor(COL_GRECT, 0x0000ffffL); graph->SetColor(COL_DRECT, 0x00c0ffffL);
+ }
+ switch(corr) {
+ case 1:
+ cb = dbl_to_str2(TmpTxt, 80, "r = %.4lf, n = %g, ", r, dn); break;
+ case 2:
+ cb = dbl_to_str2(TmpTxt, 80, "r<sub>S</sub> = %.4lf, n = %g, ", r, dn); break;
+ case 3:
+ cb = dbl_to_str2(TmpTxt, 80, "r<sub>K</sub> = %.4lf, n = %g, ", r, dn); break;
+ default:
+ TmpTxt[0] = 0; cb = 0; break;
+ }
+ dbl_to_str1(TmpTxt+cb, 80, p < 0.001 ? (char*)"P < 0.0001" : (char*)"P = %.4lf", p);
+ rep_DrawText(graph, graph->GetSize(SIZE_DRECT_LEFT)+txtdef1.fSize,
+ graph->GetSize(SIZE_DRECT_TOP)+txtdef1.fSize, false, TXA_HLEFT, &txtdef1, TmpTxt);
+ if(LastOpenGO)LastOpenGO->SetColor(COL_TEXT, 0x00cb0000L);
+ graph->Command(CMD_SCALE, &scale, 0L);
+ page->Command(CMD_DROP_GRAPH, graph, 0L);
+ if(j == (nr-1)) cy += line_inc;
+ }
+ free(v1); free(v2);
+ if(rV1)delete rV1; if(rV2)delete rV2; rV1 = rV2 = 0L;
+ }
+ }
+ parent->Command(CMD_DROP_GRAPH, page, 0L);
+ }
+ CloseDlgWnd(hDlg);
+ delete Dlg;
+ if(rd) {
+ for (i = 0; i < maxYR; i++) if(rd[i]) free(rd[i]);
+ free(rd);
+ }
+ if(rV2) delete rV2; if(rV1) delete rV1; free(CorrelDlg);
+}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 2x2 table
@@ -1004,25 +1594,30 @@ void rep_twowaytable(GraphObj *parent, DataObj *data)
(void*)"Group B", (void*)"A + B", (void*)"C1+C2", (void*)"Fisher's exact:"};
DlgRoot *Dlg;
void *hDlg;
- int i, level, res;
+ int i, r, c, level, res, wcc;
int v_idx[] = {101,102,400,103,104,401,402,403,404};
- double v[9], chi2, p, dn, pf;
+ double tmp, v[9], chi2, p, dn, pf, pfa[128];
+ char *rng;
+ AccRange *ar;
if(!parent || !data) return;
if(!(twDlg = CompileDialog(twDlg_Tmpl, dyndata))) return;
if(!(Dlg = new DlgRoot(twDlg, data)))return;
for(i = 400; i < 405; i++) Dlg->Activate(i, false);
- level = 0;
- if (!level) {
- Dlg->ShowItem(2, false); Dlg->ShowItem(4, false);
- Dlg->ShowItem(5, false);
- hDlg = CreateDlgWnd("2x2 Table", 50, 50, 450, 200, Dlg, 0);
- ResizeDlgWnd(hDlg, 370, 150);
- }
- else {
- Dlg->ShowItem(3, false);
- hDlg = CreateDlgWnd("2x2 Table", 50, 50, 450, 200, Dlg, 0);
+ if(data->Command(CMD_GETMARK, &rng, 0L) && rng && rng[0] && (ar = new AccRange(rng)) && ar->GetFirst(&c, &r)) {
+ for(i = 0; i < 4 && ar->GetNext(&c, &r); ) {
+ if(data->GetValue(r, c, &tmp)) {
+ Dlg->SetValue(101+i, tmp); i++;
+ }
+ }
+ delete ar;
+ if(i == 4) Dlg->ItemCmd(600, CMD_ENDDIALOG, 0L);
}
+ level = wcc = 0;
+ Dlg->ShowItem(2, false); Dlg->ShowItem(4, false);
+ Dlg->ShowItem(5, false);
+ hDlg = CreateDlgWnd("2x2 Table", 50, 50, 450, 200, Dlg, 0);
+ ResizeDlgWnd(hDlg, 370, 150);
do {
LoopDlgWnd();
res = Dlg->GetResult();
@@ -1043,21 +1638,37 @@ void rep_twowaytable(GraphObj *parent, DataObj *data)
v[2] = v[0] + v[1]; v[5] = v[3] + v[4];
v[6] = v[0] + v[3]; v[7] = v[1] + v[4];
v[8] = v[6] + v[7]; chi2 = v[0]*v[4]-v[1]*v[3];
- if(v[2] < 32.0 && v[5] < 32.0 && v[6] < 32.0 && v[7] < 32.0) {
+ for(i = wcc = 0; i < 9; i++) {
+ dbl_to_str1(TmpTxt, TMP_TXT_SIZE, "%g", v[i]);
+ Dlg->SetText(v_idx[i], TmpTxt);
+ }
+ if(v[8] < 128.0) do {
pf = factrl((int)v[2])/factrl((int)v[0])*factrl((int)v[5])/factrl((int)v[1])
*factrl((int)v[6])/factrl((int)v[3])*factrl((int)v[7])/factrl((int)v[4]);
pf /= factrl((int)v[8]);
- dbl_to_str1(TmpTxt, TMP_TXT_SIZE, "P = %g", pf);
+ pfa[wcc++] = pf;
+ //worse case correction
+ //RR Sokal & FJ Rohlf: Biometry, 3rd ed., pp. 734 ff.
+ if((v[0]*v[4]- v[1]*v[3]) < 0.0) {
+ v[0]-=1.0; v[4]-=1.0; v[1]+=1.0; v[3]+=1.0;
+ }
+ else if((v[0]*v[4]- v[1]*v[3]) > 0.0) {
+ v[0]+=1.0; v[4]+=1.0; v[1]-=1.0; v[3]-=1.0;
+ }
+ else break;
+ }while(v[0]>=0.0 && v[1]>=0.0 && v[3]>=0.0 && v[4]>=0.0 && wcc < 128);
+ if(wcc){
+ for(i = 1, pf = pfa[0]; i < wcc; i++){
+ pf += pfa[i];
+ }
+ if(pf > 1.0) pf = 1.0;
+ dbl_to_str1(TmpTxt, TMP_TXT_SIZE, "P(one sided) = %.4lf", pf);
Dlg->SetText(410, pf >= 0.001 ? TmpTxt : (char*)"P < 0.001");
}
else Dlg->SetText(410, "- - -");
dn = (v[2]*v[5]*v[6]*v[7]);
chi2 = dn > 0.0 ? (chi2*chi2*v[8])/dn : 0.0;
p = chi_dist(chi2, 1.0, 1.0);
- for(i = 0; i < 9; i++) {
- dbl_to_str1(TmpTxt, TMP_TXT_SIZE, "%g", v[i]);
- Dlg->SetText(v_idx[i], TmpTxt);
- }
dbl_to_str1(TmpTxt, TMP_TXT_SIZE, "Chi2 = %g", chi2);
Dlg->SetText(407, TmpTxt);
if(p >= 0.001) {
@@ -1075,7 +1686,7 @@ void rep_twowaytable(GraphObj *parent, DataObj *data)
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// compare means of two groups
+// compare means / medians of two groups
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void rep_compmeans(GraphObj *parent, DataObj *data)
{
@@ -1087,14 +1698,15 @@ void rep_compmeans(GraphObj *parent, DataObj *data)
(void*)&ci, (void*)" "};
char *ttest[] = {"Student's t = %g", "P = %g", "P(corr.) = %g"};
char *utest[] = {"Mann-Whitney U = %g", "z = %g", "P = %g", "z(corr.) = %g", "P(corr.) = %g"};
- char g1_nam[20], g2_nam[20], *c_name;
+ char g1_nam[30], g2_nam[30], *c_name;
DlgRoot *Dlg;
void *hDlg;
int i, j, res, n1, n2, r, c, *ny;
bool bContinue = false;
- double *d1, *d2, *rs, dtmp, cx, cy, min1,max1, min2, max2;
+ double *d1, *d2, dtmp, *rs, cx, cy, min1,max1, min2, max2;
scaleINFO scale = {{0.0, 0.9}, {0.0, 0.9}, {0.0, 0.9}};
char *txt_obj;
+ anyResult ares;
AccRange *rD;
Graph *graph;
Page *page;
@@ -1122,36 +1734,39 @@ void rep_compmeans(GraphObj *parent, DataObj *data)
min1 = min2 = dBounds.Ymin = HUGE_VAL; max1 = max2 = dBounds.Ymax = -HUGE_VAL;
if(Dlg->GetText(101,TmpTxt,TMP_TXT_SIZE)&&(rD=new AccRange(TmpTxt))&&(n1=rD->CountItems())&&(d1=(double*)malloc(n1*sizeof(double)))){
if(c_name = rD->RangeDesc(data, 2)) {
- rlp_strcpy(g1_nam, 20, c_name); g1_nam[0] = toupper(g1_nam[0]);
+ rlp_strcpy(g1_nam, 30, c_name); g1_nam[0] = toupper(g1_nam[0]);
free(c_name);
}
- else rlp_strcpy(g1_nam, 20, "Group 1");
+ else rlp_strcpy(g1_nam, 30, "Group 1");
for(n1 = 0, rD->GetFirst(&c, &r); rD->GetNext(&c, &r); ) {
- if(data->GetValue(r, c, &dtmp)){
- if(dBounds.Ymin > dtmp) dBounds.Ymin = dtmp;
- if(dBounds.Ymax < dtmp) dBounds.Ymax = dtmp;
- if(min1 > dtmp) min1 = dtmp; if(max1 < dtmp) max1 = dtmp;
- d1[n1++] = dtmp;
+ if(data->GetResult(&ares, r, c, false) && ares.type == ET_VALUE){
+ if(dBounds.Ymin > ares.value) dBounds.Ymin = ares.value;
+ if(dBounds.Ymax < ares.value) dBounds.Ymax = ares.value;
+ if(min1 > ares.value) min1 = ares.value; if(max1 < ares.value) max1 = ares.value;
+ d1[n1++] = ares.value;
}
}
delete rD;
}
- if(Dlg->GetText(103,TmpTxt,TMP_TXT_SIZE)&&(rD=new AccRange(TmpTxt))&&(n2=rD->CountItems())&&(d2=(double*)malloc(n1*sizeof(double)))){
+ if(Dlg->GetText(103,TmpTxt,TMP_TXT_SIZE)&&(rD=new AccRange(TmpTxt))&&(n2=rD->CountItems())&&(d2=(double*)malloc(n2*sizeof(double)))){
if(c_name = rD->RangeDesc(data, 2)) {
- rlp_strcpy(g2_nam, 20, c_name); g2_nam[0] = toupper(g2_nam[0]);
+ rlp_strcpy(g2_nam, 30, c_name); g2_nam[0] = toupper(g2_nam[0]);
free(c_name);
}
- else rlp_strcpy(g2_nam, 20, "Group 2");
+ else rlp_strcpy(g2_nam, 30, "Group 2");
for(n2 = 0, rD->GetFirst(&c, &r); rD->GetNext(&c, &r); ) {
- if(data->GetValue(r, c, &dtmp)){
- if(dBounds.Ymin > dtmp) dBounds.Ymin = dtmp;
- if(dBounds.Ymax < dtmp) dBounds.Ymax = dtmp;
- if(min2 > dtmp) min2 = dtmp; if(max2 < dtmp) max2 = dtmp;
- d2[n2++] = dtmp;
+ if(data->GetResult(&ares, r, c, false) && ares.type == ET_VALUE){
+ if(dBounds.Ymin > ares.value) dBounds.Ymin = ares.value;
+ if(dBounds.Ymax < ares.value) dBounds.Ymax = ares.value;
+ if(min2 > ares.value) min2 = ares.value; if(max2 < ares.value) max2 = ares.value;
+ d2[n2++] = ares.value;
}
}
delete rD;
}
+ if(g1_nam[0] && g2_nam[0] && 0==strcmp(g1_nam, g2_nam)) {
+ rlp_strcpy(g1_nam, 30, "Group 1"); rlp_strcpy(g2_nam, 30, "Group 2");
+ }
if(!d1 || !d2 || n1 < 2 || n2 < 2) {
InfoBox("Insufficient data to calculate means!");
bContinue = true;
@@ -1182,25 +1797,24 @@ void rep_compmeans(GraphObj *parent, DataObj *data)
graph->DRect.Xmin *= 0.8; graph->moveable = 0;
graph->DRect.Xmax = graph->GRect.Xmax - (txtdef1.fSize*2.0);
OpenGraph(graph, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj); graph->Command(CMD_SCALE, &scale, 0L);
+ if(LastOpenGO && LastOpenGO->Id == GO_BOXPLOT) {
+ if(((BoxPlot*)LastOpenGO)->x_tv = new TextValue()){
+ ((BoxPlot*)LastOpenGO)->x_tv->GetValue(g1_nam);
+ ((BoxPlot*)LastOpenGO)->x_tv->GetValue(g2_nam);
+ }
+ }
+ free(txt_obj); graph->Command(CMD_SCALE, &scale, 0L);
cx = graph->GetSize(SIZE_GRECT_RIGHT)+txtdef1.fSize*3.0;
cy = mk_mean_report(page, cx, graph->GetSize(SIZE_GRECT_TOP), d1, n1, ci, g1_nam);
cy = mk_mean_report(page, cx, cy + txtdef1.fSize, d2, n2, ci, g2_nam);
cy += linsp1;
- if(txt_obj = mk_label(graph->GetSize(SIZE_GRECT_RIGHT)+txtdef1.fSize*3.0, cy, false, TXA_HLEFT,
- &txtdef1, "<b>t-Test:</b>")) {
- OpenGraph(page, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj); cy += linsp1;
- }
- d_ttest(d1, d2, n1, n2, 0L, 0L, rs+15);
+ rep_DrawText(page, graph->GetSize(SIZE_GRECT_RIGHT)+txtdef1.fSize*3.0, cy, false, TXA_HLEFT, &txtdef1, "<b>t-Test:</b>");
+ cy += linsp1; d_ttest(d1, d2, n1, n2, 0L, 0L, rs+15);
for(i = 0; i < 3; i++) {
switch(i) {
- case 0:
- dtmp = rs[24]; break;
- case 1:
- dtmp = rs[21]; break;
- case 2:
- dtmp = rs[23]; break;
+ case 0: dtmp = rs[24]; break;
+ case 1: dtmp = rs[21]; break;
+ case 2: dtmp = rs[23]; break;
}
#ifdef USE_WIN_SECURE
j = sprintf_s(TmpTxt, 80, ttest[i], dtmp);
@@ -1211,10 +1825,8 @@ void rep_compmeans(GraphObj *parent, DataObj *data)
while(TmpTxt[j] != '=' && j) j--;
rlp_strcpy(TmpTxt+j, 10, "< 0.0001");
}
- if(txt_obj = mk_label(cx+(txtdef1.fSize*3.0), cy, false, TXA_HLEFT, &txtdef1, TmpTxt)) {
- OpenGraph(page, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj); cy += linsp1/1.2;
- }
+ rep_DrawText(page, cx+(txtdef1.fSize*3.0), cy, false, TXA_HLEFT, &txtdef1, TmpTxt);
+ cy += linsp1/1.2;
}
page->Command(CMD_DROP_GRAPH, graph, 0L);
}
@@ -1229,28 +1841,25 @@ void rep_compmeans(GraphObj *parent, DataObj *data)
graph->DRect.Xmin *= 0.8; graph->moveable = 0;
graph->DRect.Xmax = graph->GRect.Xmax - (txtdef1.fSize*2.0);
OpenGraph(graph, 0L, (unsigned char*)txt_obj, false);
+ if(LastOpenGO && LastOpenGO->Id == GO_BOXPLOT) {
+ if(((BoxPlot*)LastOpenGO)->x_tv = new TextValue()){
+ ((BoxPlot*)LastOpenGO)->x_tv->GetValue(g1_nam);
+ ((BoxPlot*)LastOpenGO)->x_tv->GetValue(g2_nam);
+ }
+ }
free(txt_obj); graph->Command(CMD_SCALE, &scale, 0L);
cy = mk_median_report(page, cx, graph->GetSize(SIZE_GRECT_TOP), d1, n1, .95, g1_nam);
cy = mk_median_report(page, cx, cy + txtdef1.fSize, d2, n2, .95, g2_nam);
cy += linsp1;
- if(txt_obj = mk_label(graph->GetSize(SIZE_GRECT_RIGHT)+txtdef1.fSize*3.0, cy, false, TXA_HLEFT,
- &txtdef1, "<b>u-Test:</b>")) {
- OpenGraph(page, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj); cy += linsp1;
- }
- d_utest(d1, d2, n1, n2, 0L, 0L, rs+15);
+ rep_DrawText(page, graph->GetSize(SIZE_GRECT_RIGHT)+txtdef1.fSize*3.0, cy, false, TXA_HLEFT, &txtdef1, "<b>u-Test:</b>");
+ cy += linsp1; d_utest(d1, d2, n1, n2, 0L, 0L, rs+15);
for(i = 0; i < 5; i++) {
switch(i) {
- case 0:
- dtmp = rs[17]; break;
- case 1:
- dtmp = rs[18]; break;
- case 2:
- dtmp = rs[21]; break;
- case 3:
- dtmp = rs[22]; break;
- case 4:
- dtmp = rs[23]; break;
+ case 0: dtmp = rs[17]; break;
+ case 1: dtmp = rs[18]; break;
+ case 2: dtmp = rs[21]; break;
+ case 3: dtmp = rs[22]; break;
+ case 4: dtmp = rs[23]; break;
}
#ifdef USE_WIN_SECURE
j = sprintf_s(TmpTxt, 80, utest[i], dtmp);
@@ -1261,15 +1870,14 @@ void rep_compmeans(GraphObj *parent, DataObj *data)
while(TmpTxt[j] != '=' && j) j--;
rlp_strcpy(TmpTxt+j, 10, "< 0.0001");
}
- if(txt_obj = mk_label(cx+(txtdef1.fSize*3.0), cy, false, TXA_HLEFT, &txtdef1, TmpTxt)) {
- OpenGraph(page, 0L, (unsigned char*)txt_obj, false);
- free(txt_obj); cy += linsp1/1.2;
- }
+ rep_DrawText(page, cx+(txtdef1.fSize*3.0), cy, false, TXA_HLEFT, &txtdef1, TmpTxt);
+ cy += linsp1/1.2;
}
page->Command(CMD_DROP_GRAPH, graph, 0L);
}
- parent->Command(CMD_DROP_GRAPH, page, 0L); free(rs);
+ parent->Command(CMD_DROP_GRAPH, page, 0L);
+ free(rs); free(ny);
}
- CloseDlgWnd(hDlg); delete Dlg;
- free(MeanDlg); if(d1) free(d1); if(d2) free(d2);
+ CloseDlgWnd(hDlg); delete Dlg; free(MeanDlg);
+ if(d1) free(d1); if(d2) free(d2);
}
diff --git a/rlp_math.cpp b/rlp_math.cpp
index 0f6d86f..80b1def 100755
--- a/rlp_math.cpp
+++ b/rlp_math.cpp
@@ -1,4 +1,4 @@
-//rlp_math.cpp, Copyright (c) 2004-2006 R.Lackner
+//rlp_math.cpp, Copyright (c) 2004-2007 R.Lackner
//
// This file is part of RLPlot.
//
@@ -230,7 +230,7 @@ bool Check_MRQerror()
//---------------------------------------------------------------------------
//Use heap sort to sort elements of an float array
-//W.H. pres, B.P. Flannery, S.A. Teukolsky, W.T. Vetterling (1988/1989)
+//W.H. Press, B.P. Flannery, S.A. Teukolsky, W.T. Vetterling (1988/1989)
//Numerical Recipes in C, Cambridge University Press, ISBN 0-521-35465-X
// p. 245
void SortArray(int n, double *vals)
@@ -685,6 +685,206 @@ double f_freq(double x, double df1, double df2)
return exp(a-b+c+d);
}
+// Shapiro-Wilk W test and its significance level
+// Algorithm AS 394, 1995, Appl. Statist. 44(4), 547-551
+//
+static int do_swilk(double (*func)(double, double, double), double p1, double p2,
+ double *x, int n, int n1, int n2, double *a, double *w, double *pw)
+{
+
+//initialized data
+const static double z90 = 1.2816; //tinv(0.2, inf)
+const static double z95 = 1.6449; //tinv(0.1, inf)
+const static double z99 = 2.3263; //tinv(.05, inf)
+const static double zm = 1.7509; //(z90 + z95 + z99)/3
+const static double zss = 0.56268;
+const static double bf1 = 0.8378;
+const static double xx90 = 0.556;
+const static double xx95 = 0.622;
+const static double sqrth = 0.70711; //sqrt(0.5)
+const static double smal = 1.0e-19; //small value
+const static double pi6 = 1.909859;
+const static double stqr = 1.047198; //pi / 3
+
+//polynomial coefficients
+static double g[2] = {-2.273, 0.459};
+static double c1[6] = {0.0, 0.221157, -0.147981, -2.07119, 4.434685, -2.706056};
+static double c2[6] = {0.0, 0.042981, -0.293762, -1.752461, 5.682633, -3.582633};
+static double c3[4] = {0.544, -0.39978, 0.025054, -6.714e-4};
+static double c4[4] = {1.3822, -0.77857, 0.062767, -0.0020322};
+static double c5[4] = {-1.5861, -0.31082, -0.083751, 0.0038915};
+static double c6[3] = {-0.4803, -0.082676, 0.0030302};
+static double c7[2] = {0.164, 0.533};
+static double c8[2] = {0.1736, 0.315};
+static double c9[2] = {0.256, -0.00635};
+
+ //local variables
+ int i, j, ncens, i1, nn2;
+ double zbar, ssassx, summ2, ssumm2, gamma, delta, range;
+ double a1, a2, an, bf, ld, m, s, sa, xi, sx, xx, y, w1;
+ double fac, asa, an25, ssa, z90f, sax, zfm, z95f, zsd, z99f, rsn, ssx, xsx;
+
+ //parameter adjustment
+ --a;
+
+ *pw = 1.0;
+ if(*w >= 0.0) *w = 1.0;
+ an = (double)(n); nn2 = n>>1;
+ if(n2 < nn2) return 3;
+ if(n < 3) return 1;
+ // calculate coefficients a[]
+ if(true) {
+ if(n == 3) a[1] = sqrth;
+ else {
+ for(i = 1, summ2 = 0.0, an25 = an + 0.25; i <= n2; ++i) {
+ a[i] = distinv(func, p1, p2, (i-0.375)/an25, 0);
+ summ2 += (a[i] * a[i]);
+ }
+ summ2 *= 2.0; ssumm2 = sqrt(summ2);
+ rsn = 1.0 / sqrt(an); a1 = devlpl(c1, 6, rsn) -a[1]/ssumm2;
+ //normalize a[]
+ if(n > 5) {
+ i1 = 3;
+ a2 = -a[2] / ssumm2 + devlpl(c2, 6, rsn);
+ fac = sqrt((summ2 - 2.0*a[1]*a[1] - 2.0*a[2]*a[2])
+ / (1.0 - 2.0*a1*a1 - 2.0*a2*a2));
+ a[2] = a2;
+ }
+ else {
+ i1 = 2;
+ fac = sqrt((summ2 -2.0*a[1]*a[1]) / (1.0 - 2.0*a1*a1));
+ }
+ a[1] = a1;
+ for(i = i1; i <= nn2; ++i) a[i] /= -fac;
+ }
+ }
+ if(n1 < 3) return 1;
+ ncens = n - n1;
+ if(ncens < 0 || (ncens > 0 && n < 20)) return 4;
+ delta = (double)ncens / an;
+ if(delta > 0.8) return 5;
+ //if w input as negative, calculate significance level of -w
+ if(*w < 0.0) {
+ w1 = 1.0 + *w;
+ goto sw_prob;
+ }
+ //check for zero range
+ if((range = x[n1-1] -x[0]) < smal) return 6;
+ //check for sort order
+ xx = x[0]/range; sx = xx; sa = -a[1]; j = n -1;
+ for(i = 1; i < n1; --j) {
+ xi = x[i] / range; sx += xi; ++i;
+ if(i != j) sa += i > j ? a[i < j ? i : j] : -a[i < j ? i : j];
+ xx = xi;
+ }
+ //calculate w statistic as squared correlation between data and coefficients
+ sa /= n1; sx /= n1; ssa = ssx = sax = 0.0; j = n -1;
+ for(i = 0; i < n1; ++i, --j) {
+ if(i > j) asa = a[1+j] - sa;
+ else if(i < j) asa = -a[1+i] - sa;
+ else asa = -sa;
+ xsx = x[i] / range - sx; ssa += asa * asa;
+ ssx += xsx * xsx; sax += asa * xsx;
+ }
+ ssassx = sqrt(ssa * ssx);
+ w1 = (ssassx - sax) * (ssassx + sax) / (ssa * ssx);
+sw_prob:
+ *w = 1.0 - w1; //reduce rounding errors
+ if(n == 3) {
+ *pw = pi6 * (asin(sqrt(*w)) - stqr);
+ return 0;
+ }
+ y = log(w1);
+ xx = log(an);
+ if(n <= 11) {
+ gamma = devlpl(g, 2, an);
+ if(y >= gamma) {
+ *pw = smal; return 0;
+ }
+ y = -log(gamma - y); m = devlpl(c3, 4, an);
+ s = exp(devlpl(c4, 4, an));
+ }
+ else { //n >= 12
+ m = devlpl(c5, 4, xx); s = exp(devlpl(c6, 3, xx));
+ }
+ //Censoring by proportion NCENS/N
+ if(ncens > 0) {
+ ld = -log(delta); bf = 1.0 + xx * bf1;
+ z90f = z90 + bf * pow(devlpl(c7, 2, pow(xx90, xx)), ld);
+ z95f = z95 + bf * pow(devlpl(c8, 2, pow(xx95, xx)), ld);
+ z99f = z99 + bf * pow(devlpl(c9, 2, xx), ld);
+ //Regress z90f ... z99f on normal deviates z90 ... z99
+ // to get pseudo-mean and pseudo-sd of z as the slope and intercept
+ zfm = (z90f + z95f + z99f)/3.0;
+ zsd = (z90 * (z90f - zfm) + z95 * (z95f - zfm) + z99 * (z99f - zfm)) / zss;
+ zbar = zfm - zsd * zm; m += zbar * s; s *= zsd;
+ }
+ *pw = 1.0 - norm_dist(y, m, s);
+ return 0;
+}
+
+void swilk1(int n, double *v0, double (*func)(double, double, double), double p1, double p2,
+ bool bsorted, double *w, double *p)
+{
+ double *v, *a;
+
+ if(!n || !w || !p) return; *w = *p = 1.0;
+ if(!(a = (double*)malloc(n *sizeof(double)))) return;
+ if(!bsorted && (v = (double*)memdup(v0, n*sizeof(double), 0)))SortArray(n, v);
+ else if(bsorted) v = v0;
+ else return;
+ if(do_swilk(func, p1, p2, v, n, n, n>>1, a, w, p)){
+ //an error occured
+ *w = *p = -1.0;
+ }
+ free(a); if(v != v0) free(v);
+}
+
+//Kolmogorov-Smirnov's test and distribution of D
+// (1) Miller L. (1956) Journal of the American Statistical Association. 51: 111-121
+// (2) Mises R. (1964) Mathematical Theory of Probability and Statistics (New York: Academic Press)
+// Chapters IX(C) and IX(E)
+// (3) Press W.H., Flannery B.P.,Teukolsky S.A., Vetterling W.T. (1988/1989)
+// Numerical Recipes in C, Cambridge University Press, ISBN 0-521-35465-X, pp. 490 ff.
+//
+double ks_dist(int n, double d)
+{
+ double j, jn, sum, las, q, r, s, dn = (double)n;
+
+ las = floor(dn - dn * d);
+ for (j = sum = 0.0; j <= las; j += 1.0) {
+ jn = j / dn; q = gammln(dn+1) - gammln(j+1) - gammln(dn-j+1.0);
+ r = (dn - j) * log( 1 - d - jn ); s = (j - 1.0) * log( d + jn );
+ sum += exp(q + r + s);
+ }
+ return(d*sum);
+}
+
+void KolSmir(int n, double *v0, double (*func)(double, double, double), double p1, double p2,
+ bool bsorted, double *d, double *p)
+{
+ int i;
+ double *v, *dev, *x, ff, dt, dt1, dt2;
+ double dn = (double)n, f0 = 0.0;
+
+ if(!n || !d || !p) return; *d = *p = 0.0;
+ if(!(dev = (double*)malloc(n*sizeof(double)))) return;
+ if(!(x = (double*)malloc(n*sizeof(double)))){
+ free(dev); return;
+ }
+ if(!bsorted && (v = (double*)memdup(v0, n*sizeof(double), 0)))SortArray(n, v);
+ else if(bsorted) v = v0;
+ else return;
+ for(i = 0, *d = 0.0; i < n; i++) {
+ x[i] = (double)(i+1)/dn; ff = (*func)(v[i], p1, p2);
+ dt1 = fabs(f0-ff); dt2 = fabs(dev[i] = (f0 = x[i])-ff);
+ dt = dt1 > dt2 ? dt1 : dt2; if(dt > *d) *d = dt;
+ }
+ free(dev); free(x);
+ *p = ks_dist(n, *d);
+ if(v != v0) free(v);
+}
+
//---------------------------------------------------------------------------
// Inverse of statitistical functions:
// funcd supplies the function value fn and the derivative df of the function sf at x
@@ -698,10 +898,9 @@ void funcd(double x, double *fn, double *df, double (*sf)(double, double, double
else if(sf == chi_dist) *df = -chi_freq(x, df1);
else if(sf == t_dist) *df = -2.0 * t_freq(x, df1);
else if(sf == f_dist) *df = -1.0 * f_freq(x, df1, df2);
-// if(true){
+ else if(sf == lognorm_dist) *df = lognorm_freq(x, df1, df2);
else {
- y1 = (sf)(x * 0.995, df1, df2);
- y2 = (sf)(x * 1.005, 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;
@@ -711,19 +910,19 @@ void funcd(double x, double *fn, double *df, double (*sf)(double, double, double
double distinv(double (*sf)(double, double, double), double df1, double df2, double p, double x0)
{
int i, j;
- double df, dx, f, rtn;
+ double df, df0, adf, dx, f, rtn;
- for(j = 0, rtn = dx = x0; j < 100; j++) {
- for( i= 0; i < 100; i++) {
+ for(j = 0, rtn = dx = x0; j < 200; j++) {
+ for(i = 0, df0 = 0.0; i < 20; i++) {
funcd(rtn, &f, &df, sf, df1, df2, p);
- if(fabs(df) > 1.0e-12) break;
- rtn += (dx = dx/2.0);
- if(i >= 99) return HUGE_VAL;
+ if((adf=fabs(df)) > 1.0e-12 || df0 > adf) break;
+ rtn += (dx = dx/2.0); df0 = adf;
+ if(i >= 19) return HUGE_VAL;
}
- dx = f/df*(0.01*(double)(100-j)); rtn -= dx;
- if(fabs(dx) < _PREC && j > 3) return rtn;
+ dx = f/df*(0.01*(double)(100-j)); rtn -= dx;
+ if(fabs(dx) < _PREC && j > 3)return rtn;
}
- return rtn;
+ return HUGE_VAL;
}
//---------------------------------------------------------------------------
@@ -842,14 +1041,7 @@ double d_skew(int n, double *v)
{
double sum, avg, sd, tmp, dn = n;
int i;
-// double x, skew;
-
-// sd = sqrt(d_variance(n, v, &avg, 0L));
-// for(i = 0, skew = 0.0; i < n; i++){
-// x = (v[i]-avg)/sd;
-// skew += (x*x*x - skew)/((double)(i+1));
-// }
-// return skew;
+
for(i = 0, avg = 0.0; i < n; i++) avg += ((v[i]-avg)/((double)(i+1)));
for(i = 0, sum = 0.0; i < n; i++) sum += (tmp = v[i]-avg) * tmp;
for(i = 0, sd = sqrt(sum/(dn-1.0)), sum=0.0; i < n; i++) sum += ((tmp = (v[i]-avg)/sd)*tmp*tmp);
@@ -886,13 +1078,14 @@ double d_classes(DataObj *d, double start, double step, double *v, int nv, char
// Numerical Rcipies in C. The Art of Scientific Computing,
// Cambridge University Press, ISBN 0-521-35465, pp. 503 ff.
// (2) B. Gough (2000), linear.c, gsl-1.7 the GNU scientific library
-double d_pearson(double *x, double *y, int n, char *dest, DataObj *data)
+double d_pearson(double *x, double *y, int n, char *dest, DataObj *data, double *ra)
{
int j, r, c;
double yt, xt, t, df, res[4];
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] - ax) / (j+1); ay += (y[j] - ay) / (j+1);
}
@@ -902,7 +1095,7 @@ double d_pearson(double *x, double *y, int n, char *dest, DataObj *data)
sxy += (xt*yt-sxy) / (j+1);
}
res[0] = sxy/sqrt(sxx*syy); //pearsons r
- if(dest) {
+ if(dest || ra) {
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
@@ -917,6 +1110,9 @@ double d_pearson(double *x, double *y, int n, char *dest, DataObj *data)
data->Command(CMD_UPDATE, 0L, 0L);
delete rD;
}
+ if (ra){
+ memcpy(ra, res, 4 * sizeof(double));
+ }
return res[0];
}
@@ -968,35 +1164,40 @@ void crank(int n, double *w0, double *s)
}
//the actual rank correlation
-double d_spearman(double *x, double *y, int n, char *dest, DataObj *data)
+double d_spearman(double *sx, double *sy, int n, char *dest, DataObj *data, double *ra)
{
int j, r, c;
- double vard, t, sg, sf, fac, en3n, en, df, aved, tmp;
+ double *x, *y, vard, t, sg, sf, fac, en3n, en, df, aved, tmp;
double res[6];
AccRange *rD;
- SortArray2(n, x, y); crank(n, x, &sf);
- SortArray2(n, y, x); crank(n, y, &sg);
+ if(!(x = (double*)memdup(sx, n*sizeof(double), 0))
+ || !(y = (double*)memdup(sy, n*sizeof(double), 0)))return 0.0;
+ 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;
+ df = en-2.0; res[5] = (double)n;
res[4] = betai(0.5*df, 0.5, df/(df+t*t));
if((dest) && (data) && (rD = new AccRange(dest))) {
- rD->GetFirst(&c, &r); res[5] = n;
+ rD->GetFirst(&c, &r);
for(j = 0; j < 6 && rD->GetNext(&c, &r); j++) {
data->SetValue(r, c, res[j]);
}
data->Command(CMD_UPDATE, 0L, 0L);
delete rD;
}
+ if(ra) {
+ memcpy(ra, res, 6 * sizeof(double));
+ }
+ free(x); free(y);
return res[3];
}
@@ -1006,7 +1207,7 @@ double d_spearman(double *x, double *y, int n, char *dest, DataObj *data)
// Numerical Recipies in C. The Art of Scientific Computing,
// Cambridge University Press, ISBN 0-521-35465, pp. 510 ff.
-double d_kendall(double *x, double *y, int n, char *dest, DataObj *data)
+double d_kendall(double *x, double *y, int n, char *dest, DataObj *data, double *ra)
{
int j, k, n1, n2, is, r, c;
double aa, a1, a2, sv, res[4];
@@ -1026,16 +1227,20 @@ double d_kendall(double *x, double *y, int n, char *dest, DataObj *data)
}
}
res[0] = ((double)is)/(sqrt((double)n1) * sqrt((double)n2));
+ sv = (4.0 * ((double)n) + 10.0)/(9.0*((double)n)*((double)(n-1)));
+ res[1] = res[0]/sqrt(sv); res[2] = errfc(fabs(res[1])/_SQRT2);
+ res[3] = n;
if((dest) && (data) && (rD = new AccRange(dest))) {
- sv = (4.0 * ((double)n) + 10.0)/(9.0*((double)n)*((double)(n-1)));
- res[1] = res[0]/sqrt(sv); res[2] = errfc(fabs(res[1])/_SQRT2);
- res[3] = n; rD->GetFirst(&c, &r);
+ rD->GetFirst(&c, &r);
for(j = 0; j < 4 && rD->GetNext(&c, &r); j++) {
data->SetValue(r, c, res[j]);
}
data->Command(CMD_UPDATE, 0L, 0L);
delete rD;
}
+ if (ra){
+ memcpy(ra, res, 4 * sizeof(double));
+ }
return res[0];
}
@@ -1246,9 +1451,367 @@ double d_ftest(double *x, double *y, int n1, int n2, char *dest, DataObj *data)
}
return p;
}
+//---------------------------------------------------------------------------
+// Modules from the R-project
+//
+//---------------------------------------------------------------------------
+#define M_1_SQRT_2PI 0.398942280401432677939946059934 /* 1/sqrt(2pi) */
+#define M_LN2 log(2.0)
+/*
+ * Copyright (C) 1998 Ross Ihaka
+ * Copyright (C) 2000--2005 The R Development Core Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * DESCRIPTION
+ * Computes the probability that the maximum of rr studentized
+ * ranges, each based on cc means and with df degrees of freedom
+ * for the standard error, is less than q.
+ * The algorithm is based on that of the reference.
+ *
+ * REFERENCE
+ * Copenhaver, Margaret Diponzio & Holland, Burt S.
+ * Multiple comparisons of simple effects in
+ * the two-way analysis of variance with fixed effects.
+ * Journal of Statistical Computation and Simulation,
+ * Vol.30, pp.1-15, 1988.
+ */
+
+double wprob(double w, double rr, double cc)
+{
+/* wprob() :
+
+ This function calculates probability integral of Hartley's
+ form of the range.
+
+ w = value of range
+ rr = no. of rows or groups
+ cc = no. of columns or treatments
+ ir = error flag = 1 if pr_w probability > 1
+ pr_w = returned probability integral from (0, w)
+
+ program will not terminate if ir is raised.
+
+ bb = upper limit of legendre integration
+ iMax = maximum acceptable value of integral
+ nleg = order of legendre quadrature
+ ihalf = int ((nleg + 1) / 2)
+ wlar = value of range above which wincr1 intervals are used to
+ calculate second part of integral,
+ else wincr2 intervals are used.
+ C1, C2, C3 = values which are used as cutoffs for terminating
+ or modifying a calculation.
+ xleg = legendre 12-point nodes
+ aleg = legendre 12-point coefficients
+ */
+#define nleg 12
+#define ihalf 6
+
+ /* looks like this is suboptimal for double precision.
+ (see how C1-C3 are used) <MM> */
+ /* const double iMax = 1.; not used if = 1*/
+ const static double C1 = -30.0, C2 = -50.0, C3 = 60.;
+ const static double bb = 8.0, wlar = 3.0, wincr1 = 2.0, wincr2 = 3.;
+ const static double xleg[ihalf] = { 0.981560634246719250690549090149,
+ 0.904117256370474856678465866119, 0.769902674194304687036893833213,
+ 0.587317954286617447296702418941, 0.367831498998180193752691536644,
+ 0.125233408511468915472441369464};
+ const static double aleg[ihalf] = { 0.047175336386511827194615961485,
+ 0.106939325995318430960254718194, 0.160078328543346226334652529543,
+ 0.203167426723065921749064455810, 0.233492536538354808760849898925,
+ 0.249147045813402785000562436043};
+ double a, ac, pr_w, b, binc, blb, bub, c, cc1, einsum, elsum,
+ pminus, pplus, qexpo, qsqz, rinsum, wi, wincr, xx;
+ int j, jj;
+
+ qsqz = w * 0.5;
+
+ // if w >= 16 then the integral lower bound (occurs for c=20)
+ // is 0.99999999999995 so return a value of 1
+ if (qsqz >= bb) return 1.0;
+
+ // find (f(w/2) - 1) ^ cc
+ // (first term in integral of hartley's form).
+ pr_w = 2.0 * norm_dist(qsqz, 0.0, 1.0) -1.0;
+ // if pr_w ^ cc < 2e-22 then set pr_w = 0
+ if (pr_w >= exp(C2 / cc)) pr_w = pow(pr_w, cc);
+ else pr_w = 0.0;
+ // if w is large then the second component of the
+ // integral is small, so fewer intervals are needed.
+ if (w > wlar) wincr = wincr1;
+ else wincr = wincr2;
+
+ /* find the integral of second term of hartley's form */
+ /* for the integral of the range for equal-length */
+ /* intervals using legendre quadrature. limits of */
+ /* integration are from (w/2, 8). two or three */
+ /* equal-length intervals are used. */
+ /* blb and bub are lower and upper limits of integration. */
+ blb = qsqz; binc = (bb - qsqz) / wincr;
+ bub = blb + binc; einsum = 0.0;
+
+ // integrate over each interval
+ cc1 = cc - 1.0;
+ for (wi = 1; wi <= wincr; wi++) {
+ elsum = 0.0; a = 0.5 * (bub + blb);
+ // legendre quadrature with order = nleg
+ b = 0.5 * (bub - blb);
+ for (jj = 1; jj <= nleg; jj++) {
+ if (ihalf < jj) {
+ j = (nleg - jj) + 1; xx = xleg[j-1];
+ }
+ else {
+ j = jj; xx = -xleg[j-1];
+ }
+ c = b * xx; ac = a + c;
+ // if exp(-qexpo/2) < 9e-14, then doesn't contribute to integral
+ if ((qexpo = ac * ac) > C3) break;
+ pplus = 2.0 * norm_dist(ac, 0.0, 1.0); pminus= 2.0 * norm_dist(ac, w, 1.0);
+ // if rinsum ^ (cc-1) < 9e-14, then doesn't contribute to integral
+ rinsum = (pplus * 0.5) - (pminus * 0.5);
+ if (rinsum >= exp(C1 / cc1)) {
+ rinsum = (aleg[j-1] * exp(-(0.5 * qexpo))) * pow(rinsum, cc1);
+ elsum += rinsum;
+ }
+ }
+ elsum *= (((2.0 * b) * cc) * M_1_SQRT_2PI);
+ einsum += elsum; blb = bub; bub += binc;
+ }
+ // if pr_w ^ rr < 9e-14, then return 0 */
+ pr_w = einsum + pr_w;
+ if (pr_w <= exp(C1 / rr))return 0.;
+ pr_w = pow(pr_w, rr);
+ return pr_w < 1.0 ? pr_w : 1.0;
+}
+
+double ptukey(double q, double rr, double cc, double df, int lower_tail, int log_p)
+{
+/* q = value of studentized range
+ rr = no. of rows or groups
+ cc = no. of columns or treatments
+ df = degrees of freedom of error term
+ ir[0] = error flag = 1 if wprob probability > 1
+ ir[1] = error flag = 1 if qprob probability > 1
+
+ All references in wprob to Abramowitz and Stegun
+ are from the following reference:
+ Abramowitz, Milton and Stegun, Irene A.
+ Handbook of Mathematical Functions.
+ New York: Dover publications, Inc. (1970).
+ All constants taken from this text are given to 25 significant digits.
+
+ nlegq = order of legendre quadrature
+ ihalfq = int ((nlegq + 1) / 2)
+ eps = max. allowable value of integral
+ eps1 & eps2 = values below which there is no contribution to integral.
+
+ d.f. <= dhaf: integral is divided into ulen1 length intervals. else
+ d.f. <= dquar: integral is divided into ulen2 length intervals. else
+ d.f. <= deigh: integral is divided into ulen3 length intervals. else
+ d.f. <= dlarg: integral is divided into ulen4 length intervals.
+
+ d.f. > dlarg: the range is used to calculate integral.
+
+ xlegq = legendre 16-point nodes
+ alegq = legendre 16-point coefficients
+
+ The coefficients and nodes for the legendre quadrature used in
+ qprob and wprob were calculated using the algorithms found in:
+ Stroud, A. H. and Secrest, D., Gaussian Quadrature Formulas.
+ Englewood Cliffs, New Jersey: Prentice-Hall, Inc, 1966.
+
+ All values matched the tables (provided in same reference)
+ to 30 significant digits.
+
+ f(x) = .5 + erf(x / sqrt(2)) / 2 for x > 0
+ f(x) = erfc( -x / sqrt(2)) / 2 for x < 0
+ where f(x) is standard normal c. d. f.
+
+ if degrees of freedom large, approximate integral with range distribution.
+ */
+#define nlegq 16
+#define ihalfq 8
+
+/* const double eps = 1.0; not used if = 1 */
+ const static double eps1 = -30.0, eps2 = 1.0e-14;
+ const static double dhaf = 100.0, dquar = 800.0, deigh = 5000.0, dlarg = 25000.0;
+ const static double ulen1 = 1.0, ulen2 = 0.5, ulen3 = 0.25, ulen4 = 0.125;
+ const static double xlegq[ihalfq] = { 0.989400934991649932596154173450,
+ 0.944575023073232576077988415535, 0.865631202387831743880467897712,
+ 0.755404408355003033895101194847, 0.617876244402643748446671764049,
+ 0.458016777657227386342419442984, 0.281603550779258913230460501460,
+ 0.950125098376374401853193354250e-1};
+ const static double alegq[ihalfq] = {0.271524594117540948517805724560e-1,
+ 0.622535239386478928628438369944e-1, 0.951585116824927848099251076022e-1,
+ 0.124628971255533872052476282192, 0.149595988816576732081501730547,
+ 0.169156519395002538189312079030, 0.182603415044923588866763667969,
+ 0.189450610455068496285396723208};
+ double ans, f2, f21, f2lf, ff4, otsum, qsqz, rotsum, t1, twa1, ulen, wprb;
+ int i, j, jj;
+
+ if (df > dlarg) return wprob(q, rr, cc);
+ f2 = df * 0.5; // calculate leading constant
+ f2lf = ((f2 * log(df)) - (df * M_LN2)) - gammln(f2);
+ f21 = f2 - 1.0;
+ // integral is divided into unit, half-unit, quarter-unit, or eighth-unit length intervals
+ // depending on the value of the degrees of freedom.
+ ff4 = df * 0.25;
+ if (df <= dhaf) ulen = ulen1;
+ else if (df <= dquar) ulen = ulen2;
+ else if (df <= deigh) ulen = ulen3;
+ else ulen = ulen4;
+ f2lf += log(ulen);
+ for (i = 1, ans = 0.0; i <= 50; i++) { // integrate over each subinterval
+ otsum = 0.0;
+ // legendre quadrature with order = nlegq, nodes (stored in xlegq) are symmetric around zero.
+ twa1 = (2 * i - 1) * ulen;
+ for (jj = 1; jj <= nlegq; jj++) {
+ if (ihalfq < jj) {
+ j = jj - ihalfq - 1;
+ t1 = (f2lf + (f21 * log(twa1 + (xlegq[j] * ulen)))) - (((xlegq[j] * ulen) + twa1) * ff4);
+ }
+ else {
+ j = jj - 1;
+ t1 = (f2lf + (f21 * log(twa1 - (xlegq[j] * ulen)))) + (((xlegq[j] * ulen) - twa1) * ff4);
+ }
+ if (t1 >= eps1) { // if exp(t1) < 9e-14, then doesn't contribute to integral
+ if (ihalfq < jj) qsqz = q * sqrt(((xlegq[j] * ulen) + twa1) * 0.5);
+ else qsqz = q * sqrt(((-(xlegq[j] * ulen)) + twa1) * 0.5);
+ wprb = wprob(qsqz, rr, cc); // call wprob to find integral of range portion
+ rotsum = (wprb * alegq[j]) * exp(t1); otsum += rotsum;
+ }
+ } // end legendre integral for interval i
+ // If integral for interval i < 1e-14, then stop. However, in order to avoid small area
+ // under left tail, at least 1 / ulen intervals are calculated.
+ if (i * ulen >= 1.0 && otsum <= eps2) break;
+ ans += otsum; //end of interval i
+ }
+ return ans > 1.0 ? 1.0 : ans;
+ }
+
+ /*
+ * Copyright (C) 1998 Ross Ihaka
+ * Copyright (C) 2000--2005 The R Development Core Team
+ * based in part on AS70 (C) 1974 Royal Statistical Society
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * DESCRIPTION
+ * Computes the quantiles of the maximum of rr studentized
+ * ranges, each based on cc means and with df degrees of freedom
+ * for the standard error, is less than q.
+ * The algorithm is based on that of the reference.
+ *
+ * REFERENCE
+ * Copenhaver, Margaret Diponzio & Holland, Burt S., Multiple comparisons of simple
+ * effects in the two-way analysis of variance with fixed effects.
+ * Journal of Statistical Computation and Simulation, Vol.30, pp.1-15, 1988.
+ */
+
+/* qinv() :
+ * this function finds percentage point of the studentized range
+ * which is used as initial estimate for the secant method.
+ * function is adapted from portion of algorithm as 70
+ * from applied statistics (1974) ,vol. 23, no. 1
+ * by odeh, r. e. and evans, j. o.
+ * p = percentage point
+ * c = no. of columns or treatments
+ * v = degrees of freedom
+ * qinv = returned initial estimate
+ * vmax is cutoff above which degrees of freedom
+ * is treated as infinity.
+ */
+
+static double qinv(double p, double c, double v)
+{
+ const static double p0 = 0.322232421088, q0 = 0.993484626060e-01;
+ const static double p1 = -1.0, q1 = 0.588581570495;
+ const static double p2 = -0.342242088547, q2 = 0.531103462366;
+ const static double p3 = -0.204231210125, q3 = 0.103537752850;
+ const static double p4 = -0.453642210148e-04, q4 = 0.38560700634e-02;
+ const static double c1 = 0.8832, c2 = 0.2368, c3 = 1.214, c4 = 1.208, c5 = 1.4142;
+ const static double vmax = 120.0;
+ double ps, q, t, yi;
+
+ ps = 0.5 - 0.5 * p;
+ yi = sqrt (log (1.0 / (ps * ps)));
+ t = yi + (((( yi * p4 + p3) * yi + p2) * yi + p1) * yi + p0)
+ / (((( yi * q4 + q3) * yi + q2) * yi + q1) * yi + q0);
+ if (v < vmax) t += (t * t * t + t) / v / 4.0;
+ q = c1 - c2 * t;
+ if (v < vmax) q += -c3 / v + c4 * t / v;
+ return t * (q * log (c - 1.0) + c5);
+}
+
+/*
+ * Copenhaver, Margaret Diponzio & Holland, Burt S.
+ * Multiple comparisons of simple effects in
+ * the two-way analysis of variance with fixed effects.
+ * Journal of Statistical Computation and Simulation,
+ * Vol.30, pp.1-15, 1988.
+ *
+ * Uses the secant method to find critical values.
+ *
+ * p = confidence level (1 - alpha)
+ * rr = no. of rows or groups
+ * cc = no. of columns or treatments
+ * df = degrees of freedom of error term
+ *
+ */
+double qtukey(double p, double rr, double cc, double df, int lower_tail, int log_p)
+{
+ const int maxiter = 50;
+ double ans = HUGE_VAL, valx0, valx1, x0, x1;
+ int iter;
+
+ // df must be > 1 ; there must be at least two values
+ if(p >= 1.0 || df < 2 || rr < 1 || cc < 2) return HUGE_VAL;
+ if(p < 0.0) p = 0.0;
+ x0 = qinv(p, cc, df); // Initial value
+ valx0 = ptukey(x0, rr, cc, df, true, false) - p; // Find prob(value < x0)
+ // Find the second iterate and prob(value < x1). If the first iterate has probability value
+ // exceeding p then second iterate is 1 less than first iterate; otherwise it is 1 greater.
+ x1 = valx0 > 0.0 ? (x1 = x0 > 1.0 ? x0-1.0 : 0.0) : (x0 + 1.0);
+ valx1 = ptukey(x1, rr, cc, df, true, false) - p;
+ for(iter=1; iter < maxiter ; iter++) { // Iterate
+ ans = x1 - ((valx1 * (x1 - x0)) / (valx1 - valx0));
+ valx0 = valx1; x0 = x1;
+ if (ans < 0.0) { // New iterate must be >= 0
+ ans = 0.0; valx1 = -p;
+ }
+ valx1 = ptukey(ans, rr, cc, df, true, false) - p; // Find prob(value < new iterate)
+ x1 = ans;
+ if (fabs(x1 - x0) < _PREC) return ans; // Convergence ?
+ }
+ //The process did not converge in 'maxiter' iterations
+ return ans;
+}
+//---------------------------------------------------------------------------
+// END Modules from the R-project
+
//---------------------------------------------------------------------------
-// Calendar, Date- and time functions
+// Calendar, Date- and Time functions
// The following characters are used as format specifiers in a format string,
// all other characters are either ignored or copyied to the output
//
diff --git a/rlplot.cpp b/rlplot.cpp
index 5084b18..aa95e1e 100755
--- a/rlplot.cpp
+++ b/rlplot.cpp
@@ -223,7 +223,6 @@ Symbol::DoPlot(anyOutput *target)
POINT pts[5];
FillDEF cf;
- if(size <= 0.001) return;
atype = (type & 0xfff);
memcpy(&cf, &SymFill, sizeof(FillDEF));
if(atype == SYM_CIRCLEF || atype == SYM_RECTF || atype == SYM_TRIAUF ||
@@ -240,22 +239,23 @@ Symbol::DoPlot(anyOutput *target)
default:
case SYM_CIRCLE: //circle
case SYM_CIRCLEF: //filled circle
- rx = target->un2ix(size/2.0); ry = target->un2iy(size/2.0);
+ rx = target->un2ix(size/2.0); ry = target->un2iy(size/2.0);
+ if(rx < 5) rx = 1; if(ry < 5) ry = 1;
target->SetFill(&cf);
target->oCircle(ix-rx, iy-ry, ix+rx+1, iy+ry+1, name);
rx--;ry--; //smaller marking rectangle
break;
case SYM_RECT: //rectange (square)
case SYM_RECTF: //filled rectangle
- rx = target->un2ix(size/2.25676);
- ry = target->un2iy(size/2.25676);
+ rx = target->un2ix(size/2.25676); ry = target->un2iy(size/2.25676);
+ if(rx < 5) rx = 1; if(ry < 5) ry = 1;
target->SetFill(&cf);
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:
- rx = target->un2ix(size/1.48503);
- ry = target->un2iy(size/1.48503);
+ rx = target->un2ix(size/1.48503); ry = target->un2iy(size/1.48503);
+ if(rx < 5) rx = 1; if(ry < 5) ry = 1;
target->SetFill(&cf);
pts[0].x = pts[3].x = ix - rx; pts[1].x = ix; pts[2].x = ix+rx;
if(atype == SYM_TRIAU || atype == SYM_TRIAUF) { //patch by anonymous
@@ -270,8 +270,8 @@ Symbol::DoPlot(anyOutput *target)
rx--; ry--;
break;
case SYM_DIAMOND: case SYM_DIAMONDF:
- rx = target->un2ix(size/1.59588f);
- ry = target->un2iy(size/1.59588f);
+ rx = target->un2ix(size/1.59588f); ry = target->un2iy(size/1.59588f);
+ if(rx < 5) rx = 1; if(ry < 5) ry = 1;
target->SetFill(&cf);
pts[0].x = pts[2].x = pts[4].x = ix;
pts[0].y = pts[4].y = iy -ry;
@@ -283,8 +283,8 @@ Symbol::DoPlot(anyOutput *target)
case SYM_STAR: //star is a combination of + and x symbols
case SYM_PLUS: //draw a + sign
case SYM_HLINE: case SYM_VLINE:
- rx = target->un2ix(size/2.0f);
- ry = target->un2iy(size/2.0f);
+ rx = target->un2ix(size/2.0f); ry = target->un2iy(size/2.0f);
+ if(rx < 5) rx = 1; if(ry < 5) ry = 1;
pts[0].x = pts[1].x = ix;
pts[0].y = iy - ry; pts[1].y = iy + ry +1;
if(type != SYM_HLINE) target->oPolyline(pts, 2);
@@ -295,8 +295,8 @@ Symbol::DoPlot(anyOutput *target)
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);
+ rx = target->un2ix(size/2.5); ry = target->un2iy(size/2.5);
+ if(rx < 5) rx = 1; if(ry < 5) ry = 1;
pts[0].x = ix - rx; pts[1].x = ix + rx;
pts[0].y = iy - ry; pts[1].y = iy + ry;
target->oPolyline(pts, 2);
@@ -1034,8 +1034,10 @@ DataLine::DoPlot(anyOutput *target)
if (nPntSet >= nPnt) nPntSet = nPnt-1;
if(mo) DelBitmapClass(mo); mo = 0L;
if(pts) free(pts); pts = 0L;
- if((type & 0xff) == 9 || (type & 0xff) == 10) //splines
+ if((type & 0xff) == 9 || (type & 0xff) == 10) //splines
pts = (POINT *)malloc(sizeof(POINT)*1000);
+ else if((type & 0xff) == 11) // curve
+ pts = (POINT *) malloc(sizeof(POINT)* (nPntSet+2)*192);
else if(type & 0xff) pts = (POINT *)malloc(sizeof(POINT)*(nPntSet+2)*2);
else pts = (POINT *)malloc(sizeof(POINT)*(nPntSet+2));
if(!pts) return;
@@ -1137,6 +1139,9 @@ DataLine::DoPlot(anyOutput *target)
case 9: case 10:
DrawSpline(target);
break;
+ case 11:
+ DrawCurve(target);
+ break;
}
if(cp < 2) return;
if(isPolygon) { //for mark polygon only !!
@@ -1307,13 +1312,33 @@ DataLine::LineData(lfPOINT *val, long nval)
}
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;
+ if(pts) free(pts); pts = 0L; dirty = true;
free(val); nPnt = nval; nPntSet = nPnt-1;
}
void
DataLine::DrawCurve(anyOutput *target)
{
+ lfPOINT *sdata, *bdata;
+ POINT *tmppts;
+ int i, j, n;
+
+ if(!(sdata = (lfPOINT *)malloc(nPnt * sizeof(lfPOINT))))return;
+ sdata[0].fx = Values[0].fx; sdata[0].fy = Values[0].fy;
+ for(i = j = 1; i < nPnt; i++) {
+ if(Values[i].fx != sdata[j-1].fx || Values[i].fy != sdata[j-1].fy) {
+ sdata[j].fx = Values[i].fx; sdata[j++].fy = Values[i].fy;
+ }
+ }
+ n = mkCurve(sdata, j, &bdata, false);
+ if(!(tmppts = (POINT*)malloc((n+2)*sizeof(POINT))))return;
+ for(i = 0; i < n; i++){
+ tmppts[i].x = target->fx2ix(bdata[i].fx); tmppts[i].y = target->fy2iy(bdata[i].fy);
+ }
+ for(i = cp = 0; i< (n-2); i += 3) {
+ DrawBezier(&cp, pts, tmppts[i], tmppts[i+1], tmppts[i+2], tmppts[i+3], 0);
+ }
+ if(bdata) free(bdata); free(sdata);
}
void
@@ -3881,7 +3906,7 @@ Plane3D::DoPlot(anyOutput *o)
if(ipl) delete ipl; ipl = 0L;
if(pts) free(pts); pts = 0L;
- o->ActualSize(&rDims);
+ if(!(o->ActualSize(&rDims)))return;
rDims.left = rDims.right; rDims.top = rDims.bottom;
rDims.right = rDims.bottom = 0;
if((pts = (fPOINT3D*)malloc(sizeof(fPOINT3D)*ndt))){
@@ -3923,7 +3948,10 @@ Plane3D::Command(int cmd, void *tmpl, anyOutput *o)
return true;
case CMD_LEGEND:
if(!tmpl || ((GraphObj*)tmpl)->Id != GO_LEGEND) return false;
- ((Legend*)tmpl)->HasFill(&Line, &Fill, 0L);
+ if(parent && parent->Id > GO_PLOT && parent->Id < GO_GRAPH) {
+ ((Legend*)tmpl)->HasFill(&Line, &Fill, ((Plot*)parent)->data_desc);
+ }
+ else ((Legend*)tmpl)->HasFill(&Line, &Fill, 0L);
break;
case CMD_MRK_DIRTY:
if(parent) return parent->Command(cmd, tmpl, o);
@@ -4193,7 +4221,10 @@ Brick::Command(int cmd, void *tmpl, anyOutput *o)
return true;
case CMD_LEGEND:
if(!tmpl || ((GraphObj*)tmpl)->Id != GO_LEGEND) return false;
- ((Legend*)tmpl)->HasFill(&Line, &Fill, 0L);
+ if(parent && parent->Id > GO_PLOT && parent->Id < GO_GRAPH) {
+ ((Legend*)tmpl)->HasFill(&Line, &Fill, ((Plot*)parent)->data_desc);
+ }
+ else ((Legend*)tmpl)->HasFill(&Line, &Fill, 0L);
break;
case CMD_BAR_FILL:
if(tmpl) {
@@ -5323,7 +5354,7 @@ Label::Command(int cmd, void *tmpl, anyOutput *o)
return true;
}
return false;
- case CMD_ADDCHAR:
+ case CMD_ADDCHAR: case CMD_ADDCHARW:
SetModified();
if(tmpl && 8 != *((int*)tmpl)) return AddChar(*((int*)tmpl), o);
//value 8 == backspace
@@ -6463,6 +6494,7 @@ void
TextFrame::AddChar(anyOutput *o, unsigned char c)
{
int i, j, h, w, maxw;
+ bool brd;
if(cur_pos.y >= nlines) return;
if(!lines || !lines[cur_pos.y]) return;
@@ -6489,8 +6521,12 @@ TextFrame::AddChar(anyOutput *o, unsigned char c)
}
}
fmt_txt.SetText(0L, (char*)lines[cur_pos.y], &j, &j);
- fmt_txt.oGetTextExtent(o, &w, &h, i);
- if(w >= maxw || c == '\n' || (c == ' ' && w >=(maxw>>1))) {
+ fmt_txt.oGetTextExtent(o, &w, &h, i); brd = false;
+ if(cur_pos.x > 2 && (c == '>' || c == ';')) {
+ if(c == '>' && fmt_txt.leftTag((char*)lines[cur_pos.y],cur_pos.x-1) >= 0) brd =true;
+ if(c == ';' && fmt_txt.ucLeft((char*)lines[cur_pos.y],cur_pos.x-1, 0L, 0L) > 0) brd =true;
+ }
+ if(brd || w >= maxw || c == '\n' || (c == ' ' && w >=(maxw>>1))) {
c_char = lines[cur_pos.y][cur_pos.x]; lines[cur_pos.y][cur_pos.x] = 0x01;
if(!c_char) lines[cur_pos.y][cur_pos.x+1] = 0x00;
lines2text(); Undo.TextBuffer(this, &csize, &cpos, &text, 0L, o); text2lines(o);
@@ -8493,6 +8529,10 @@ Legend::HasSym(LineDEF *ld, GraphObj *sy, char *desc)
else if(sy->name && sy->name[0]) {
ns->name = (char*)memdup(sy->name,(int)strlen(sy->name)+1, 0);
}
+ else if(sy->parent && sy->parent->Id < GO_GRAPH && sy->parent->Id >= GO_PLOT) {
+ if(((Plot*)(sy->parent))->data_desc) ns->name = (char*)memdup(((Plot*)(sy->parent))->data_desc,
+ (int)strlen(((Plot*)(sy->parent))->data_desc)+1, 0);
+ }
else if(sy->parent && sy->parent->name && sy->parent->name[0]) {
ns->name = (char*)memdup(sy->parent->name,(int)strlen(sy->parent->name)+1, 0);
}
@@ -8599,11 +8639,24 @@ Graph::GetColor(int select)
switch(select & 0xfff) {
case COL_AXIS: return ColAX;
case COL_BG: return ColDR;
+ case COL_DRECT: return ColDR;
+ case COL_GRECT: return ColGR;
}
if(parent) return parent->GetColor(select);
else return defs.Color(select);
}
+bool
+Graph::SetColor(int select, DWORD col)
+{
+ switch(select) {
+ case COL_DRECT:
+ ColDR = col; return true;
+ case COL_GRECT:
+ ColGR = col; return true;
+ }
+ return false;
+}
void
Graph::DoPlot(anyOutput *target)
@@ -8616,6 +8669,8 @@ Graph::DoPlot(anyOutput *target)
rc_mrk.left = rc_mrk.right = rc_mrk.top = rc_mrk.bottom = -1;
CurrAxes = Axes;
if(data) do_formula(data, 0L); //init mfcalc
+ //every graph needs axes!
+ if(type == GT_STANDARD && !NumAxes) CreateAxes(AxisTempl);
//verify ownership of axes
if(Axes) for (i = 0; i < NumAxes; i++){
if(Axes[i] && (ax = Axes[i]->GetAxis()))
@@ -8636,12 +8691,6 @@ Graph::DoPlot(anyOutput *target)
Disp->VPorg.fy = (double)Disp->MenuHeight;
Disp->CheckMenu(ToolMode, true);
OwnDisp = true; defs.SetDisp(Disp);
- if(GRect.Xmin > 0.0001 || GRect.Xmin < -0.0001) {
- GRect.Xmax -= GRect.Xmin; GRect.Xmin = 0.0;
- }
- if(GRect.Ymin > 0.0001 || GRect.Ymin < -0.0001) {
- GRect.Ymax -= GRect.Ymin; GRect.Ymin = 0.0;
- }
bModified = false; //first graph is not modified!
Undo.SetDisp(Disp);
}
@@ -8839,14 +8888,13 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
return false;
case CMD_REDRAW:
if(!CurrDisp) {
- DoPlot(CurrDisp);
- return true;
+ DoPlot(CurrDisp); return true;
}
+ if(Disp)CurrDisp = Disp;
if(parent && (parent->Id == GO_PAGE || parent->Id == GO_GRAPH)) return parent->Command(cmd, tmpl, o);
if(CurrDisp && CurrDisp->Erase(ColBG)) CurrDisp->StartPage();
CurrDisp->MrkMode = MRK_NONE; DoPlot(CurrDisp);
- if(CurrDisp) CurrDisp->EndPage();
- if(CurrGO == this) CurrGO = 0L;
+ if(CurrDisp) CurrDisp->EndPage(); if(CurrGO == this) CurrGO = 0L;
if(CurrGO && CurrGO == CurrLabel && CurrLabel->Id == GO_LABEL)
CurrDisp->ShowMark(CurrLabel, MRK_GODRAW);
return true;
@@ -8856,9 +8904,10 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
if(o)o->MouseCursor(PasteObj ? MC_PASTE : MC_ARROW, false);
return true;
case CMD_AXIS: //one of the plots has changed scaling: reset
+ CurrAxes = Axes;
if(o)o->SetRect(CurrRect, units, &x_axis, &y_axis);
return true;
- case CMD_REG_AXISPLOT: //notification: plot can hnadle its own axes
+ case CMD_REG_AXISPLOT: //notification: plot can handle its own axes
if(nscp > 0 && nscp <= NumPlots && Sc_Plots) {
for(i = 0; i < nscp; i++)
if(Sc_Plots[i] == (GraphObj*)tmpl) return true;
@@ -9019,6 +9068,7 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
default:
o->MouseCursor(MC_ARROW, true); break;
}
+ if((ToolMode & 0x0f) != TM_TEXT) HideTextCursor();
return Command(CMD_REDRAW, 0L, CurrDisp);
case CMD_ADDPLOT:
Undo.SetDisp(o ? o : CurrDisp);
@@ -9048,10 +9098,11 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
return false;
case CMD_MRK_DIRTY:
return (dirty = true);
- case CMD_CURRLEFT: case CMD_CURRIGHT: case CMD_ADDCHAR:
+ case CMD_CURRLEFT: case CMD_CURRIGHT: case CMD_ADDCHAR: case CMD_ADDCHARW:
case CMD_BACKSP: case CMD_POS_FIRST: case CMD_POS_LAST:
defs.SetDisp(o);
if(tmpl && *((int*)tmpl) == 27) { //Escape
+ HideCopyMark();
if(CurrGO && CurrGO->Id == GO_TEXTFRAME) {
CurrGO->DoMark(o, false); o->MrkMode = MRK_NONE;
CurrGO = 0L;
@@ -9188,7 +9239,6 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
}
NiceAxis(&x_axis, 4); NiceAxis(&y_axis, 4);
NumPlots = 1;
- if(type == GT_STANDARD && !NumAxes) CreateAxes(AxisTempl);
dirty = false;
return true;
}
@@ -9255,7 +9305,7 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
}
else if(mev->Action == MOUSE_LBDOWN){
if(CurrGO && CurrGO->Id == GO_TEXTFRAME && CurrGO->Command(cmd, tmpl, o)) return true;
- CurrGO = 0L;
+ CurrGO = 0L; SuspendAnimation(o, true);
if((ToolMode & 0xff) == TM_STANDARD || (ToolMode & 0xff) == TM_ZOOMIN){
rc_mrk.left = mev->x; rc_mrk.top = mev->y;
}
@@ -9291,8 +9341,8 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
if(CurrGO == this) CurrGO = 0L;
return false;
case MOUSE_LBUP:
- Undo.SetDisp(o);
- if(Id == GO_GRAPH){
+ Undo.SetDisp(o); SuspendAnimation(o, false);
+ if(Id == GO_GRAPH && parent && parent->Id == GO_SPREADDATA){
CurrGO = TrackGO = 0L;
CurrGraph = this;
}
@@ -9303,7 +9353,9 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
if(Axes[i] && Axes[i]->Command(cmd, tmpl,o)) return true;
//do all plots
if(Plots)for(i = NumPlots-1; i>=0; i--)
- if(Plots[i] && Plots[i]->Command(cmd, tmpl,o)) return true;
+ if(Plots[i] && Plots[i]->Command(cmd, tmpl,o)){
+ if(Id == GO_GRAPH)CurrGraph = this; return true;
+ }
if(frm_d && frm_d->Command(cmd, tmpl, o)) return true;
if(frm_g && frm_g->Command(cmd, tmpl, o)) return true;
if(mev->Action == MOUSE_MOVE && ToolMode == TM_STANDARD &&
@@ -9314,7 +9366,7 @@ Graph::Command(int cmd, void *tmpl, anyOutput *o)
break;
case CMD_SETSCROLL:
if(o) {
- o->ActualSize(&rc);
+ if(!(o->ActualSize(&rc)))return false;
i = o->un2iy(GRect.Ymax);
o->SetScroll(true, -(i>>3), i+(i>>3), (rc.bottom -rc.top)>>1, - iround(o->VPorg.fy));
i = o->un2ix(GRect.Xmax);
@@ -9360,6 +9412,7 @@ Graph::DefSize(int select)
case SIZE_BOUNDS_XMAX: return Bounds.Xmax;
case SIZE_BOUNDS_YMIN: return Bounds.Ymin;
case SIZE_BOUNDS_YMAX: return Bounds.Ymax;
+ case SIZE_SCALE: return scale > 0.0 ? scale : 1.0;
case SIZE_BOUNDS_LEFT: return x_axis.flags & AXIS_INVERT ? x_axis.max : x_axis.min;
case SIZE_BOUNDS_RIGHT: return x_axis.flags & AXIS_INVERT ? x_axis.min : x_axis.max;
case SIZE_BOUNDS_TOP: return y_axis.flags & AXIS_INVERT ? y_axis.min : y_axis.max;
@@ -9730,29 +9783,34 @@ Graph::CreateAxes(int templ)
NumAxes = 2;
break;
}
+ if(Plots[0] && Plots[0]->Id >= GO_PLOT && Plots[0]->Id < GO_GRAPH && NumAxes > 1) {
+ if(((Plot*)Plots[0])->x_tv) if(Axes[0])Axes[0]->atv = ((Plot*)Plots[0])->x_tv->Copy();
+ if(((Plot*)Plots[0])->y_tv) if(Axes[1])Axes[1]->atv = ((Plot*)Plots[0])->y_tv->Copy();
+ }
}
bool
Graph::DoScale(scaleINFO* sc, anyOutput *o)
{
int i;
- double x0, y0, z0;
+ scaleINFO sc0;
- if(sc->sy.fy > 0.0) {
- scale = scale > 0.0 ? scale * sc->sy.fy : sc->sy.fy;
- }
- else return false;
+ if(sc->sy.fy <= 0.0) return false;
GRect.Xmax = sc->sx.fx + GRect.Xmax* sc->sx.fy;
GRect.Xmin = sc->sx.fx + GRect.Xmin * sc->sx.fy;
GRect.Ymax = sc->sy.fx + GRect.Ymax * sc->sy.fy;
GRect.Ymin = sc->sy.fx + GRect.Ymin * sc->sy.fy;
DRect.Xmax *= sc->sx.fy; DRect.Xmin *= sc->sx.fy;
DRect.Ymax *= sc->sy.fy; DRect.Ymin *= sc->sy.fy;
- x0 = sc->sx.fx; y0 = sc->sy.fx; z0= sc->sz.fx;
- sc->sx.fx = sc->sy.fx = sc->sz.fx = 0.0; sc->sx.fy = sc->sz.fy = sc->sy.fy;
- if(Axes) for(i = 0; i< NumAxes; i++) if(Axes[i]) Axes[i]->Command(CMD_SCALE, sc, o);
- if(Plots) for(i = 0; i < NumPlots; i++) if(Plots[i]) Plots[i]->Command(CMD_SCALE, sc, o);
- sc->sx.fx = x0; sc->sy.fx = y0; sc->sz.fx = z0;
+ if(sc->sx.fy == 1.0 && sc->sx.fy == sc->sy.fy && sc->sx.fy == sc->sz.fy) return true;
+ memcpy(&sc0, sc, sizeof(scaleINFO));
+ sc0.sx.fx = sc0.sy.fx = sc0.sz.fx = 0.0; sc0.sx.fy = sc0.sz.fy = sc->sy.fy;
+ if(Axes) for(i = 0; i< NumAxes; i++) if(Axes[i]) Axes[i]->Command(CMD_SCALE, &sc0, o);
+ if(Plots) for(i = 0; i < NumPlots; i++) if(Plots[i]){
+ if(Plots[i]->Id == GO_GRAPH || Plots[i]->Id == GO_PAGE) Plots[i]->Command(CMD_SCALE, sc, o);
+ else Plots[i]->Command(CMD_SCALE, &sc0, o);
+ }
+ scale = scale > 0.0 ? scale * sc->sy.fy : sc->sy.fy;
return true;
}
diff --git a/rlplot.h b/rlplot.h
index 25ac873..70d1971 100755
--- a/rlplot.h
+++ b/rlplot.h
@@ -1,4 +1,4 @@
-//RLPlot.h, Copyright (c) 2000-2006 R.Lackner
+//RLPlot.h, Copyright (c) 2000-2007 R.Lackner
//
// This file is part of RLPlot.
//
@@ -29,27 +29,22 @@ inline int iround(double a) {return a < 0.0 ?(int)(a-0.499) : (int)(a+0.499);}
#define _SQRT2 1.4142135623730950488016887242096980785696718753769
#ifdef _WINDOWS //platform is windows
-#pragma warning( disable : 4996 )
+#pragma warning( disable : 4997 )
#include <windows.h>
#if _MSC_VER >= 1400
#define USE_WIN_SECURE
#endif
-#define w_char unsigned short
+#define w_char WCHAR
#define _SBINC 1 //scrollbox extra space/line
#define _TXH 4.0 //graph text default size in mm
#else //platform is *nix
#include <sys/types.h>
#define DWORD u_int32_t
-#define w_char unsigned short
+#define w_char wchar_t
#define _SBINC 8 //scrollbox extra space/line
#define _TXH 3.0 //graph text default size in mm
#define RLP_PORT 4321 //clipboard server
-#define _strdup strdup
-#define _open open
-#define _write write
-#define _close close
-#define _lseek lseek
typedef struct tagPOINT { // pt
long x;
@@ -86,13 +81,13 @@ 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_LSPC};
+ SIZE_CURSOR_XMAX, SIZE_CURSOR_YMAX, SIZE_XSTEP, SIZE_LSPC, SIZE_SCALE};
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,
COL_DRECT, COL_GRECT, COL_GRECTLINE, COL_POLYLINE, COL_POLYGON};
enum {MRK_NONE, MRK_INVERT, MRK_GODRAW, MRK_SSB_DRAW};
-enum {CMD_NONE, CMD_ADDCHAR, CMD_SETFOCUS, CMD_KILLFOCUS, CMD_DELETE,
+enum {CMD_NONE, CMD_ADDCHAR, CMD_ADDCHARW, CMD_SETFOCUS, CMD_KILLFOCUS, CMD_DELETE,
CMD_BACKSP, CMD_CURRLEFT, CMD_CURRIGHT, CMD_CURRUP, CMD_CURRDOWN,
CMD_SHIFTLEFT, CMD_SHIFTRIGHT, CMD_SHIFTUP, CMD_SHIFTDOWN,
CMD_NEWGRAPH, CMD_DELGRAPH, CMD_DELOBJ, CMD_DROP_PLOT, CMD_DROP_GRAPH, CMD_OPEN,
@@ -144,8 +139,9 @@ enum {GO_UNKNOWN, GO_AXIS, GO_TICK, GO_GRIDLINE, GO_SYMBOL, GO_BUBBLE, GO_BAR,
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_FUNC3D,
- GO_XYSTAT, GO_FITFUNC3D,
+ GO_XYSTAT, GO_FITFUNC3D, GO_NORMQUANT,
GO_GRAPH = 0x200, GO_PAGE, GO_SPREADDATA = 0x300, GO_DEFRW};
+enum {OC_UNKNOWN, OC_HIMETRIC};
enum {FILL_NONE, FILL_HLINES, FILL_VLINES, FILL_HVCROSS, FILL_DLINEU, FILL_DLINED,
FILL_DCROSS, FILL_STIPPLE1, FILL_STIPPLE2, FILL_STIPPLE3, FILL_STIPPLE4,
FILL_STIPPLE5, FILL_ZIGZAG, FILL_COMBS, FILL_BRICKH, FILL_BRICKV, FILL_BRICKDU,
@@ -161,7 +157,7 @@ enum {TM_STANDARD, TM_DRAW, TM_POLYLINE, TM_POLYGON, TM_RECTANGLE, TM_ELLIPSE,
TM_PASTE=0x200};
enum {MC_LAST, MC_ARROW, MC_CROSS, MC_TEXT, MC_WAIT, MC_MOVE, MC_NORTH,
MC_NE, MC_EAST, MC_SE, MC_SALL, MC_ZOOM, MC_PASTE, MC_DRAWPEN, MC_DRAWREC,
- MC_DRAWRREC, MC_DRAWELLY};
+ MC_DRAWRREC, MC_DRAWELLY, MC_TXTFRM, MC_COLWIDTH};
enum {FILE_ERROR, FILE_READ, FILE_WRITE, INIT_VARS, SAVE_VARS};
enum {ARROW_NOCAP, ARROW_LINE, ARROW_TRIANGLE, ARROW_UNITS = 0x100};
enum {MENU_NONE, MENU_SPREAD, MENU_GRAPH, MENU_PAGE};
@@ -333,6 +329,8 @@ typedef struct {
int type;
double value;
char *text;
+ double *a_data;
+ int a_count;
} anyResult;
//the AccRange class allows to access data objects with a 'a1:b1' style
@@ -348,6 +346,7 @@ public:
bool IsInRange(int x, int y);
bool BoundRec(RECT *rec);
char *RangeDesc(void *d, int style); //d points to a DataObj class
+ int DataTypes(void *d, int *numerical, int *strings, int *datetime);
private:
char *txt;
@@ -391,6 +390,7 @@ class anyOutput{
public:
int units; //use units mm, inch ...
int MrkMode; //existing mark on screen
+ int OC_type; //specify display, printer clipboard ...
void *MrkRect; //pointer to e.g. the marked rectangle
fRECT Box1; //User drawing rectangle
lfPOINT Box1z; // add 3D to Box1
@@ -420,6 +420,7 @@ public:
anyOutput();
void SetRect(fRECT rec, int units, AxisDEF *x_ax, AxisDEF *y_ax);
+ void UseAxis(AxisDEF *ax, int type);
void SetSpace(fPOINT3D*,fPOINT3D*,int,double*,fPOINT3D*,AxisDEF*,AxisDEF*,AxisDEF*);
void LightSource(double x, double y);
DWORD VecColor(double *plane_vec, DWORD col1, DWORD col2);
@@ -474,14 +475,15 @@ public:
virtual bool oGetPix(int x, int y, DWORD *col){return false;};
virtual bool oDrawIcon(int type, int x, int y) {return false;};
virtual bool oGetTextExtent(char *text, int cb, int *width, int *height);
+ virtual bool oGetTextExtentW(w_char *text, int cb, int *width, int *height);
virtual bool oCircle(int x1, int y1, int x2, int y2, char *nam = 0L){return false;};
virtual bool oSphere(int cx, int cy, int r, POINT *pts, int cp, char *nam = 0L);
virtual bool oPolyline(POINT * pts, int cp, char *nam = 0L){return false;};
virtual bool oRectangle(int x1, int y1, int x2, int y2, char *nam = 0L){return false;};
virtual bool oSolidLine(POINT *p){return false;};
virtual bool oTextOut(int x, int y, char *txt, int cb){return false;};
+ virtual bool oTextOutW(int x, int y, w_char *txt, int cb){return false;};
virtual bool oPolygon(POINT *pts, int cp, char *nam = 0L){return false;};
- virtual bool oArc(int x1, int y1, int x2, int y2, int quads){return false;};
};
enum {ET_UNKNOWN, ET_VALUE, ET_TEXT, ET_FORMULA, ET_ERROR, ET_BOOL,
@@ -533,7 +535,7 @@ private:
class fmtText {
typedef struct _fmt_txt_info {
- int tag;
+ int tag, uc, uc_len;
char *txt;
}fmt_txt_info;
@@ -544,6 +546,8 @@ public:
bool StyleAt(int idx, TextDEF *txt_def, int *style, int *font);
int rightTag(char *txt, int cb);
int leftTag(char *txt, int cb);
+ int ucTag(char *txt, int cb, int *tl, int *ucc);
+ int ucLeft(char *txt, int cb, int *tl, int *ucc);
void cur_right(int *pos);
void cur_left(int *pos);
bool oGetTextExtent(anyOutput *o, int *width, int *height, int cb);
@@ -564,6 +568,30 @@ private:
fmt_txt_info *split_text;
};
+class TextValue {
+
+typedef struct _TxtValItem {
+ unsigned int hv1, hv2;
+ char *text;
+ double val;
+}TextValItem;
+
+public:
+ TextValue();
+ TextValue(TextValItem **tvi, int ntvi);
+ ~TextValue();
+ double GetValue(char* txt);
+ bool GetItem(int idx, char **text, double *value);
+ void Reset();
+ TextValue *Copy();
+ int Count() {return nitems;};
+
+private:
+ TextValItem **items;
+ int nitems;
+ double next, inc;
+};
+
class RangeInfo {
public:
int col_width, row_height, first_width;
@@ -577,6 +605,8 @@ public:
int GetWidth(int col);
int GetHeight(int row);
int GetFirstWidth();
+ int Type(){return r_type;};
+ RangeInfo *Next(){return ri_next;};
private:
int r_type; // 0 default
@@ -588,18 +618,19 @@ private:
class DataObj{
public:
- int cRows, cCols;
+ int cRows, cCols, c_disp, r_disp;
RangeInfo *ri;
EditText ***etRows;
DataObj();
~DataObj();
virtual bool Init(int nRows, int nCols);
+ virtual bool mpos2dpos(POINT *mp, POINT *dp, bool can_scroll){return false;};
virtual bool SetValue(int row, int col, double val);
virtual bool SetText(int row, int col, char *txt);
virtual bool GetValue(int row, int col, double *v);
virtual bool GetText(int row, int col, char *txt, int len, bool bTranslate = true);
- char ** GetTextPtr(int row, int col);
+ char **GetTextPtr(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 isEmpty(int row, int col);
@@ -1642,10 +1673,12 @@ class Plot:public GraphObj{
public:
fRECT Bounds; //contains minima and maxima for x and y
bool dirty; //rescale before redraw;
- int use_xaxis, use_yaxis; //this plot uses its own axes
+ int use_xaxis, use_yaxis, use_zaxis; //this plot uses its own axes
lfPOINT xBounds, yBounds, zBounds; //like Bounds but in 3D space
int hidden; //plot (layer) is not visible
char *x_info, *y_info, *z_info; //descriptor used e.g. for axis label or legend
+ char *data_desc; //descriptor for data, used for legend etc
+ TextValue *x_tv, *y_tv; //TextValue object for ordinal axes
Plot(GraphObj *par, DataObj *d);
virtual double GetSize(int select);
@@ -1727,6 +1760,7 @@ public:
class FreqDist:public Plot {
public:
FreqDist(GraphObj *par, DataObj *d);
+ FreqDist(GraphObj *par, DataObj *d, char* range, bool bOnce);
FreqDist(int src);
~FreqDist();
void DoPlot(anyOutput *o);
@@ -1736,7 +1770,7 @@ public:
bool FileIO(int rw);
private:
- double start, step;
+ double dmin, dmax, start, step;
long nPlots;
char *ssRef;
LineDEF BarLine, HatchLine;
@@ -2108,6 +2142,27 @@ private:
Function *dl;
};
+class NormQuant:public Plot{
+public:
+ NormQuant(GraphObj *par, DataObj *d, char* range);
+ NormQuant(GraphObj *par, DataObj *d, double *data, int ndata);
+ NormQuant(int src);
+ ~NormQuant();
+ void DoPlot(anyOutput *o);
+ bool Command(int cmd, void *tmpl, anyOutput *o);
+ bool PropertyDlg();
+ bool FileIO(int rw);
+
+private:
+ char *ssRef;
+ int nData, nValidData;
+ double *x_vals, *y_vals, *src_data;
+ Symbol *sy;
+
+ bool ProcessData();
+};
+
+
class GridLine:public GraphObj{
public:
DWORD flags;
@@ -2183,6 +2238,7 @@ class Axis:public GraphObj{
public:
AxisDEF *axis;
LineDEF axline;
+ TextValue *atv;
Axis(GraphObj *par, DataObj *d, AxisDEF *ax, DWORD flags);
Axis(int src);
@@ -2242,9 +2298,10 @@ class Plot3D:public Plot{
public:
long nPlots, nAxes;
Axis **Axes;
- GraphObj **plots;
+ GraphObj **plots, **Sc_Plots;
double *RotDef;
fPOINT3D cub1, cub2, rotC;
+ int nscp;
Plot3D(GraphObj *par, DataObj *d, DWORD flags);
Plot3D(int src);
@@ -2266,6 +2323,7 @@ public:
bool AcceptObj(GraphObj *go);
void SortObj();
bool Rotate(double dx, double dy, double dz, anyOutput *o, bool accept);
+ bool AddAxis();
private:
long nObs, nmaxObs;
@@ -2368,6 +2426,7 @@ public:
double GetSize(int select);
bool SetSize(int select, double value);
DWORD GetColor(int select);
+ bool SetColor(int select, DWORD col);
virtual void DoPlot(anyOutput *o);
virtual bool Command(int cmd, void *tmpl, anyOutput *o);
bool PropertyDlg();
@@ -2641,6 +2700,8 @@ void HideTextCursorObj(anyOutput *out);
void ShowTextCursor(anyOutput *out, RECT *disp, DWORD color);
void HideCopyMark();
void ShowCopyMark(anyOutput *out, RECT *mrk, int nRec);
+void InvalidateOutput(anyOutput *o);
+void SuspendAnimation(anyOutput *o, bool bSusp);
void InitTextCursor(bool init);
void EmptyClip();
void CopyText(char *txt, int len);
@@ -2710,7 +2771,9 @@ bool Txt2Flt(char *txt, double *val);
void RmTrail(char *txt);
double NiceValue(double fv);
char *Int2ColLabel(int nr, bool uc);
-char *str2xml(char *str);
+char *mkCellRef(int row, int col);
+char *mkRangeRef(int r1, int c1, int r2, int c2);
+char *str2xml(char *str, bool bGreek);
char **split(char *str, char sep, int *nl);
char *fit_num_rect(anyOutput *o, int max_width, char *num_str);
void add_to_buff(char** dest, int *pos, int *csize, char *txt, int len);
@@ -2727,6 +2790,7 @@ bool IsInPolygon(POINT *p, POINT *pts, int cp);
bool OverlapRect(RECT *rc1, RECT *rc2);
void AddToPolygon(long *cp, POINT *pts, POINT *np);
void DrawBezier(long *cp, POINT *pts, POINT p0, POINT p1, POINT p2, POINT p3, int depth=0);
+int mkCurve(lfPOINT *src, int n1, lfPOINT **dst, bool bClosed);
POINT *MakeArc(int ix, int iy, int r, int qad, long *npts);
void InvertPolygon(POINT*, int, LineDEF*, FillDEF*, RECT*, anyOutput*, bool);
void InvertLine(POINT*, int, LineDEF*, RECT*, anyOutput*, bool);
@@ -2757,6 +2821,7 @@ DWORD CheckNewFloat(double *loc, double old_v, double new_v, GraphObj *par, DWOR
DWORD CheckNewInt(int *loc, int old_v, int new_v, GraphObj *par, DWORD flags);
DWORD CheckNewDword(DWORD *loc, DWORD old_v, DWORD new_v, GraphObj *par, DWORD flags);
DWORD CheckNewLFPoint(lfPOINT *loc, lfPOINT *old_v, lfPOINT *new_v, GraphObj *par, DWORD flags);
+DWORD CheckNewString(char **loc, char *s_old, char *s_new, GraphObj *par, DWORD flags);
void clip_line_sphere(GraphObj *par, POINT3D **li, int r, int cx, int cy, int cz);
void clip_line_plane(GraphObj *par, POINT3D **li, POINT3D *pg, int np, double *vec);
void clip_sphline_sphere(GraphObj *par, POINT3D *lim1, POINT3D *lim2, POINT3D *cent,
@@ -2780,7 +2845,7 @@ bool do_xyfunc(DataObj *, double, double, double, char *, lfPOINT **, long *, ch
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, int r0, int c0);
+bool MoveFormula(DataObj *d, char *of, char *nf, int nfsize, 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);
@@ -2791,6 +2856,7 @@ bool mrqmin(double *, double *, double *, int, double **, int, int *, int, doubl
void (*funcs)(double, double, double **, double *, double *, int), double *);
bool Check_MRQerror();
void SortArray(int n, double *vals);
+void SortArray2(int n, double *a1, double *a2);
void SortFpArray(int n, lfPOINT *vals);
void spline(lfPOINT *v, int n, double *y2);
double gammln(double x);
@@ -2817,6 +2883,11 @@ double t_freq(double t, double df);
double pois_dist(double x, double m, double);
double f_dist(double f, double df1, double df2);
double f_freq(double f, double df1, double df2);
+double ks_dist(int n, double d);
+void swilk1(int n, double *v0, double (*func)(double, double, double), double p1, double p2,
+ bool bsorted, double *w, double *p);
+void KolSmir(int n, double *v0, double (*func)(double, double, double),
+ double p1, double p2, bool bsorted, double *d, double *p);
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_variance(int n, double *v, double *mean = 0L, double *ss = 0L);
@@ -2826,17 +2897,20 @@ double d_skew(int n, double *v);
double d_gmean(int n, double *v);
double d_hmean(int n, double *v);
double d_classes(DataObj *d, double start, double step, double *v, int nv, char *range);
-double d_pearson(double *x, double *y, int n, char *dest, DataObj *data);
+double d_pearson(double *x, double *y, int n, char *dest, DataObj *data, double *ra);
double d_rank(int n, double *v, double v1);
void crank(int n, double *w0, double *s);
-double d_spearman(double *x, double *y, int n, char *dest, DataObj *data);
-double d_kendall(double *x, double *y, int n, char *dest, DataObj *data);
+double d_spearman(double *x, double *y, int n, char *dest, DataObj *data, double *ra);
+double d_kendall(double *x, double *y, int n, char *dest, DataObj *data, double *ra);
double d_regression(double *x, double *y, int n, char *dest, DataObj *data);
double d_covar(double *x, double *y, int n, char *dest, DataObj *data);
double d_utest(double *x, double *y, int n1, int n2, char *dest, DataObj *data, double *results);
double d_ttest(double *x, double *y, int n1, int n2, char *dest, DataObj *data, double *results);
double d_ttest2(double *x, double *y, int n, char *dest, DataObj *data);
double d_ftest(double *x, double *y, int n1, int n2, char *dest, DataObj *data);
+double wprob(double w, double rr, double cc);
+double ptukey(double q, double rr, double cc, double df, int lower_tail, int log_p);
+double qtukey(double p, double rr, double cc, double df, int lower_tail, int log_p);
bool date_value(char *desc, char *fmt, double *value);
char *value_date(double dv, char *fmt);
double now_today();
@@ -2846,7 +2920,10 @@ Ribbon *SurfTria(GraphObj *parent, DataObj *data, char *text1, char *text2, char
//prototypes reports.cpp
void rep_anova(GraphObj *parent, DataObj *data);
+void rep_kruskal(GraphObj *parent, DataObj *data);
+void rep_samplestats(GraphObj *parent, DataObj *data);
void rep_regression(GraphObj *parent, DataObj *data);
void rep_twowaytable(GraphObj *parent, DataObj *data);
void rep_compmeans(GraphObj *parent, DataObj *data);
+void rep_correl(GraphObj *parent, DataObj *data, int style);
diff --git a/rlplot.spec b/rlplot.spec
index 88e95c3..b63355e 100755
--- a/rlplot.spec
+++ b/rlplot.spec
@@ -1,5 +1,5 @@
Name: rlplot
-Version: 1.2
+Version: 1.3
Release: 1
Summary: A plotting program to create high quality graphs from data.
License: GPL
@@ -16,7 +16,7 @@ graphs of your choice. The Graphs are displayed as you get them (WYSIWIG).
Double click any element of the graph (or a single click with the right
mouse button) to modify its properties. RLPlot is a cross platform
development for Linux and Windows. Exported file formats include
-Scalable Vector Graphics (SVG), Windows Metafile (WMF), Encapsulated
+Scalable Vector Graphics (SVG), Encapsulated
Postscript (EPS).
%prep
@@ -41,6 +41,9 @@ rm -rf "$RPM_BUILD_ROOT"
%{_bindir}/exprlp
%changelog
+* Sun Feb 25 2007 Reinhard Lackner
+- release 1.3
+
* Thu Oct 19 2006 Reinhard Lackner
- release 1.2
@@ -63,3 +66,5 @@ rm -rf "$RPM_BUILD_ROOT"
- initial
+
+
diff --git a/spreadwi.cpp b/spreadwi.cpp
index 72a5740..776d74b 100755
--- a/spreadwi.cpp
+++ b/spreadwi.cpp
@@ -178,7 +178,6 @@ SpreadWin::SpreadWin(GraphObj *par, DataObj *Data):GraphObj(par, Data)
else if(d && d->ri) {
d->ri->SetHeight(19); d->ri->SetDefWidth(76); d->ri->SetFirstWidth(32);
}
- cButtons = rButtons = 0L;
Id = GO_SPREADDATA;
is_modified = bDoColWidth = false;
}
@@ -209,7 +208,7 @@ SpreadWin::~SpreadWin()
void
SpreadWin::DoPlot(anyOutput *o)
{
- o->ActualSize(&currRC);
+ if(!(o->ActualSize(&currRC)))return;
o->StartPage();
d->Command(CMD_DOPLOT, (void*)this, o);
o->EndPage();
@@ -222,7 +221,7 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
Graph *g2;
int i, j, k;
MouseEvent *mev;
- POINT p1;
+ POINT p1, p2;
if(d) {
if(!o) o = w;
@@ -248,6 +247,7 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
w->UpdateRect(&urc, false);
}
}
+ else return false;
return true;
case CMD_CAN_CLOSE:
HideTextCursor();
@@ -327,7 +327,8 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
if((Name = SaveDataAsName(filename)) && Name[0]){
if(o) o->FileHistory();
if(Name && d->WriteData(Name)) {
- if(filename) free(filename); filename = _strdup(Name);
+ if(filename) free(filename);
+ filename = (char*)memdup(Name, (int)strlen(Name)+1, 0);
}
else return false;
}
@@ -337,19 +338,20 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
if(!Command(CMD_CAN_CLOSE, 0L, o)) return false;
if(IsRlpFile((char*)tmpl)) return OpenGraph(this, (char*)tmpl, 0L, false);
else if(d->ReadData((char*)tmpl, 0L, FF_UNKNOWN)){
- if(filename) free(filename); filename = _strdup((char*)tmpl);
+ if(filename) free(filename);
+ filename = (char*)memdup(tmpl, (int)strlen((char*)tmpl)+1, 0);
return Command(CMD_SETSCROLL, 0L, w);
}
return false;
case CMD_OPEN:
if(!Command(CMD_CAN_CLOSE, 0L, o)) return false;
- Undo.KillDisp(o);
- Undo.SetDisp(o);
+ Undo.KillDisp(o); Undo.SetDisp(o);
if((Name = OpenDataName(filename)) && Name[0]){
if(o) o->FileHistory();
if(IsRlpFile(Name)) return OpenGraph(this, Name, 0L, false);
else if(d->ReadData(Name, 0L, FF_UNKNOWN)){
- if(filename) free(filename); filename = _strdup(Name);
+ if(filename) free(filename);
+ filename = (char*)memdup(Name, (int)strlen(Name)+1, 0);
return Command(CMD_SETSCROLL, 0L, w);
}
}
@@ -361,18 +363,19 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
if(o && cButtons && rButtons && (mev = (MouseEvent*)tmpl) && mev->y > o->MenuHeight) {
for(i = 0; cButtons[i]; i++){
if(bDoColWidth) {
- o->MouseCursor(MC_EAST, false);
+ o->MouseCursor(MC_COLWIDTH, false);
}
else if(mev->x > cButtons[i]->rDims.left && mev->x < cButtons[i]->rDims.right+2){
if(mev->x > cButtons[i]->rDims.right-4) {
- o->MouseCursor(MC_EAST, false);
switch(mev->Action) {
case MOUSE_LBDOWN:
CurrCol = i; line[0].x = line[1].x = mev->x;
line[0].y = o->MenuHeight; line[1].y = currRC.bottom;
d->Command(CMD_TOOLMODE, tmpl, o);
+ o->MouseCursor(MC_COLWIDTH, false);
return bDoColWidth = true;
}
+ o->MouseCursor(MC_COLWIDTH, false);
}
else o->MouseCursor(MC_ARROW, false);
return false;
@@ -398,11 +401,7 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
bDoColWidth = false;
k = line[0].x - cButtons[CurrCol]->rDims.left;
if(abs(k - cButtons[CurrCol]->rDims.right + cButtons[CurrCol]->rDims.left)>3) {
-#ifdef USE_WIN_SECURE
- sprintf_s(TmpTxt, TMP_TXT_SIZE, "%s1:%s1", Int2ColLabel(CurrCol + ssOrg.x, false), Int2ColLabel(CurrCol + ssOrg.x, false));
-#else
- sprintf(TmpTxt, "%s1:%s1", Int2ColLabel(CurrCol + ssOrg.x, false), Int2ColLabel(CurrCol + ssOrg.x, false));
-#endif
+ rlp_strcpy(TmpTxt, 40, mkRangeRef(0, CurrCol + ssOrg.x, 0, CurrCol + ssOrg.x));
d->ri = new RangeInfo(1, TmpTxt, d->ri);
d->ri->SetWidth(k >=20 ? k : 20);
}
@@ -415,20 +414,25 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
else o->MouseCursor(MC_ARROW, false);
return false;
case CMD_MOUSE_EVENT:
- if(!tmpl) return false;
+ if(!(mev =(MouseEvent*)tmpl)) return false;
if(bDoColWidth)return Command(CMD_COL_MOUSE, tmpl, o);
- if((mev = (MouseEvent*)tmpl)->y < o->MenuHeight) o->MouseCursor(MC_ARROW, false);
+ p1.x = mev->x; p1.y = mev->y;
+ if(mev->y < o->MenuHeight) o->MouseCursor(MC_ARROW, false);
else if(o && cButtons && rButtons) {
if(mev->x < d->ri->GetFirstWidth() && mev->y < (o->MenuHeight + d->ri->GetHeight(-1)) && aButton) {
aButton->Command(cmd, tmpl, o);
}
else if(mev->x < d->ri->GetFirstWidth() && rButtons) {
- i = (mev->y - o->MenuHeight - d->ri->GetHeight(-1))/d->ri->GetHeight(-1);
- if(rButtons[i]) rButtons[i]->Command(cmd, tmpl, o);
+ if(!(d->mpos2dpos(&p1, &p2, false)))return false;
+ p2.x -= ssOrg.x; p2.y -= ssOrg.y;
+ if (p2.y < 0 || p2.y >= (d->r_disp-1)) return false;
+ if(rButtons[p2.y]) rButtons[p2.y]->Command(cmd, tmpl, o);
}
else if(mev->y < (o->MenuHeight + d->ri->GetHeight(-1)) && cButtons) {
- i = (mev->x - d->ri->GetFirstWidth())/d->ri->GetWidth(-1);
- if(cButtons[i]) cButtons[i]->Command(cmd, tmpl, o);
+ if(!(d->mpos2dpos(&p1, &p2, false)))return false;
+ p2.x -= ssOrg.x; p2.y -= ssOrg.y;
+ if (p2.x < 0 || p2.x >= (d->c_disp-1)) return false;
+ if(cButtons[p2.x]) cButtons[p2.x]->Command(cmd, tmpl, o);
}
else if(o->MrkMode == MRK_SSB_DRAW) o->HideMark();
}
@@ -454,7 +458,7 @@ SpreadWin::Command(int cmd, void *tmpl, anyOutput *o)
if(o)o->MouseCursor(MC_ARROW, false);
return true;
case CMD_SETSCROLL:
- HideTextCursor(); o->ActualSize(&currRC);
+ HideTextCursor(); if(!(o->ActualSize(&currRC)))return false;
k = (currRC.bottom-currRC.top)/d->ri->GetHeight(-1);
d->GetSize(&i, &j);
o->SetScroll(true, 0, j, k, ssOrg.y); k = (currRC.right-currRC.left)/d->ri->GetWidth(-1);
@@ -529,7 +533,7 @@ SpreadWin::ShowGrid(int CellWidth, int CellHeight, int FirstWidth, POINT *cp)
ButtText.Align = TXA_HCENTER | TXA_VCENTER;
w->GetSize(&rc);
if(!cButtons) {
- c = ((rc.right/CellWidth)<<2) +1;
+ c = d->c_disp; if(c < 40 || c > 200) d->c_disp = c = 40;
cButtons = (ssButton **)calloc(c, sizeof(ssButton*));
for(i = 0, cx = FirstWidth; i < (c-1); i++) {
cw = d->ri->GetWidth(i+ssOrg.x);
@@ -545,7 +549,7 @@ SpreadWin::ShowGrid(int CellWidth, int CellHeight, int FirstWidth, POINT *cp)
}
}
if(!rButtons) {
- c = (rc.bottom/CellHeight)+1;
+ c = d->r_disp; if(c < 60 || c > 300) d->c_disp = c = 60;
rButtons = (ssButton**)calloc(c, sizeof(ssButton*));
for(i = 0; i < (c-1); i++) rButtons[i] =
new ssButton(this, 0, i*CellHeight+CellHeight+w->MenuHeight,
@@ -777,7 +781,7 @@ SpreadWin::PrintData(anyOutput *o)
o->oTextOut(rc.right-margin.right, rc.bottom-(margin.bottom>>1), TmpTxt, 0);
tdp.Align = TXA_HCENTER | TXA_VCENTER; o->SetTextSpec(&tdp);
#ifdef USE_WIN_SECURE
- ctime_s(TmpTxt, 24, &ti);
+ ctime_s(TmpTxt, 50, &ti); TmpTxt[24] = 0;
#else
sprintf(TmpTxt, "%s", ctime(&ti)); TmpTxt[24] = 0;
#endif
@@ -801,7 +805,7 @@ SpreadWin::PrintData(anyOutput *o)
o->oTextOut(rc.right-margin.right, rc.bottom-(margin.bottom>>1), TmpTxt, 0);
tdp.Align = TXA_HCENTER | TXA_VCENTER; o->SetTextSpec(&tdp);
#ifdef USE_WIN_SECURE
- ctime_s(TmpTxt, 24, &ti);
+ ctime_s(TmpTxt, 50, &ti); TmpTxt[24] = 0;
#else
sprintf(TmpTxt, "%s", ctime(&ti)); TmpTxt[24] = 0;
#endif
@@ -870,7 +874,7 @@ public:
bool MemList(unsigned char **ptr, int type);
private:
- int CellHeight, CellWidth, FirstWidth, r_disp, c_disp, mrk_offs;
+ int CellHeight, CellWidth, FirstWidth, mrk_offs;
RECT cp_src_rec; //bounding rectangle for copy range
bool bActive, new_mark, bCopyCut, bUpdate, isRowMark, isColMark;
POINT currpos, currpos2;
@@ -887,9 +891,9 @@ private:
SpreadData::SpreadData(GraphObj *par)
{
Disp = 0L; m_range = 0L; c_range = 0L; w = 0L; err_msg=last_err=rlw_file = 0L;
- g_parent = par; CellWidth = CellHeight = FirstWidth = 0;
- et_racc = 0L;
- currpos.x = currpos.y = r_disp = c_disp = mrk_offs = 0;
+ g_parent = par; CellWidth = 76; CellHeight = 19; FirstWidth = 32;
+ et_racc = 0L; currpos.x = currpos.y = mrk_offs = 0;
+ r_disp = 60; c_disp = 40;
bActive = bCopyCut = bUpdate = isRowMark = isColMark = false;
cp_src_rec.left = cp_src_rec.right = cp_src_rec.top = cp_src_rec.bottom = 0;
if(defs.IniFile && FileExist(defs.IniFile)) {
@@ -913,17 +917,21 @@ SpreadData::Init(int nRows, int nCols)
{
int i, j;
RECT rc;
+ RangeInfo *o_ri;
cRows = nRows; cCols = nCols; currpos.x = currpos.y = 0;
new_mark = bCopyCut = false; if(w && m_range) HideMark(true);
+ while(ri->Type()) {
+ o_ri = ri; ri = ri->Next(); delete(o_ri);
+ }
if(!Disp) {
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)/defs.ss_txt) + 2;
- FirstWidth = 32;
- w->GetSize(&rc);
+ if(CellHeight < 12)CellHeight = 19; if(CellWidth < 40)CellWidth = 76;
+ FirstWidth = 32; w->GetSize(&rc);
r_disp = (rc.bottom-rc.top)/CellHeight;
c_disp = (rc.right-rc.left)/CellWidth+1;
}
@@ -968,28 +976,30 @@ SpreadData::mpos2dpos(POINT *mp, POINT *dp, bool can_scroll)
dp->y = (mp->y - w->MenuHeight - CellHeight)/CellHeight + Disp->ssOrg.y;
dp->x = Disp->ssOrg.x;
for(mx = mp->x - ri->GetFirstWidth() - ri->GetWidth(dp->x); mx > 0; dp->x++, mx -= ri->GetWidth(dp->x));
- if(can_scroll && dp->x < cCols && mp->x < (ri->GetFirstWidth()+10) && mp->x > ri->GetFirstWidth() && Disp->ssOrg.x >0) {
- Disp->ssOrg.x -= 1;
- if(CurrText) CurrText->Update(2, w, mp); CurrText = 0L;
- Disp->Command(CMD_SETSCROLL, 0L, w);
- }
- if(can_scroll && 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);
- }
- if(can_scroll && mp->x > (Disp->currRC.right-w->MenuHeight-10) && Disp->ssOrg.x < (cCols-2)) {
- Disp->ssOrg.x += 1;
- if(CurrText) CurrText->Update(2, w, mp); CurrText = 0L;
- Disp->Command(CMD_SETSCROLL, 0L, w);
- }
- if(can_scroll && mp->y > (Disp->currRC.bottom-10) && Disp->ssOrg.y < (cRows-5)) {
- Disp->ssOrg.y += 1;
- do {
- mp->y -= CellHeight;
- } while(mp->y > (Disp->currRC.bottom-CellHeight));
- if(CurrText) CurrText->Update(2, w, mp); CurrText = 0L;
- Disp->Command(CMD_SETSCROLL, 0L, w); CurrText = 0L;
+ if(can_scroll) {
+ if(dp->x < cCols && mp->x < (ri->GetFirstWidth()+10) && mp->x > ri->GetFirstWidth() && Disp->ssOrg.x >0) {
+ Disp->ssOrg.x -= 1;
+ if(CurrText) CurrText->Update(2, w, mp); CurrText = 0L;
+ Disp->Command(CMD_SETSCROLL, 0L, w);
+ }
+ 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);
+ }
+ if(mp->x > (Disp->currRC.right-w->MenuHeight-10) && Disp->ssOrg.x < (cCols-2)) {
+ Disp->ssOrg.x += 1;
+ if(CurrText) CurrText->Update(2, w, mp); CurrText = 0L;
+ Disp->Command(CMD_SETSCROLL, 0L, w);
+ }
+ if(mp->y > (Disp->currRC.bottom-10) && Disp->ssOrg.y < (cRows-5)) {
+ Disp->ssOrg.y += 1;
+ do {
+ mp->y -= CellHeight;
+ } while(mp->y > (Disp->currRC.bottom-CellHeight));
+ if(CurrText) CurrText->Update(2, w, mp); CurrText = 0L;
+ Disp->Command(CMD_SETSCROLL, 0L, w); CurrText = 0L;
+ }
}
if(dp->y >= cRows) dp->y = cRows-1; if(dp->x >= cCols) dp->x = cCols-1;
return true;
@@ -1004,7 +1014,7 @@ SpreadData::Select(POINT *p)
if(CurrText->isFormula() && CurrText->hasMark()) et_racc = CurrText;
return true;
}
- mpos2dpos(p, &currpos, false);
+ if(!(mpos2dpos(p, &currpos, false)))return false;
if(currpos.y < cRows && currpos.x < cCols && currpos.y >= 0 && currpos.x >= 0) {
if(etRows[currpos.y][currpos.x]) {
if(etRows[currpos.y][currpos.x] == CurrText) CurrText->Update(1, w, p);
@@ -1115,7 +1125,8 @@ SpreadData::WriteData(char *FileName)
MemList(&buff, FF_RLW);
if(buff){
if(rlw_file != FileName) {
- if(rlw_file) free(rlw_file); rlw_file = _strdup(FileName);
+ if(rlw_file) free(rlw_file);
+ rlw_file = (char*)memdup(FileName, (int)strlen(FileName)+1, 0);
}
if(fprintf(File, "%s", buff) <= 0) bErr = true;
free(buff); fclose(File);
@@ -1171,11 +1182,12 @@ SpreadData::ReadData(char *FileName, unsigned char *buffer, int type)
0 == strcmp(".rlw", FileName+strlen(FileName)-4) ||
0 == strcmp(".RLW", FileName+strlen(FileName)-4) ||
IsXmlFile(FileName)){
+ Disp->Command(CMD_DELGRAPH, 0L, w);
if(ReadXML(FileName, buffer, type, 0L)){
if(0 == strcmp(".rlw", FileName+strlen(FileName)-4) ||
0 == strcmp(".RLW", FileName+strlen(FileName)-4)) {
- if(rlw_file) free(rlw_file);
- rlw_file = _strdup(FileName);
+ if(rlw_file) free(rlw_file);
+ rlw_file = (char*)memdup(FileName, (int)strlen(FileName)+1, 0);
}
return true;
}
@@ -1375,7 +1387,7 @@ SpreadData::DeleteCols()
etRows[i][j-dc]->type = ET_VALUE;
break;
case ET_FORMULA:
- MoveFormula(this, etRows[i][j]->text, TmpTxt, -dc, 0, -1, c0);
+ MoveFormula(this, etRows[i][j]->text, TmpTxt, TMP_TXT_SIZE, -dc, 0, -1, c0);
etRows[i][j-dc]->SetText(TmpTxt); etRows[i][j]->type = ET_FORMULA;
break;
}
@@ -1391,11 +1403,11 @@ SpreadData::DeleteCols()
}
}
cCols -= dc;
- MoveFormula(this, m_range, TmpTxt, -dc, 0, -1, c0+1); free(m_range);
+ MoveFormula(this, m_range, TmpTxt, TMP_TXT_SIZE, -dc, 0, -1, c0+1); free(m_range);
m_range = (char*)memdup(TmpTxt, (int)strlen(TmpTxt)+1, 0); 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);
+ MoveFormula(this, etRows[i][j]->text, TmpTxt, TMP_TXT_SIZE, -dc, 0, -1, c0);
etRows[i][j]->SetText(TmpTxt); etRows[i][j]->type = ET_FORMULA;
}
}
@@ -1452,7 +1464,7 @@ SpreadData::InsertCols()
etRows[i][j]->type = ET_VALUE;
break;
case ET_FORMULA:
- MoveFormula(this, etRows[i][j-dc]->text, TmpTxt, dc, 0, -1, c0);
+ MoveFormula(this, etRows[i][j-dc]->text, TmpTxt, TMP_TXT_SIZE, dc, 0, -1, c0);
etRows[i][j]->SetText(TmpTxt); etRows[i][j]->type = ET_FORMULA;
break;
}
@@ -1460,11 +1472,11 @@ SpreadData::InsertCols()
}
}
}
- MoveFormula(this, m_range, TmpTxt, dc, 0, -1, c0); free(m_range);
+ MoveFormula(this, m_range, TmpTxt, TMP_TXT_SIZE, dc, 0, -1, c0); free(m_range);
m_range = (char*)memdup(TmpTxt, (int)strlen(TmpTxt)+1, 0); 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);
+ MoveFormula(this, etRows[i][j]->text, TmpTxt, TMP_TXT_SIZE, dc, 0, -1, c0);
etRows[i][j]->SetText(TmpTxt); etRows[i][j]->type = ET_FORMULA;
}
}
@@ -1521,7 +1533,7 @@ SpreadData::DeleteRows()
etRows[i-dr][j]->type = ET_VALUE;
break;
case ET_FORMULA:
- MoveFormula(this, etRows[i][j]->text, TmpTxt, 0, -dr, r0, -1);
+ MoveFormula(this, etRows[i][j]->text, TmpTxt, TMP_TXT_SIZE, 0, -dr, r0, -1);
etRows[i-dr][j]->SetText(TmpTxt); etRows[i-dr][j]->type = ET_FORMULA;
break;
}
@@ -1535,11 +1547,11 @@ SpreadData::DeleteRows()
}
}
cRows -= dr;
- MoveFormula(this, m_range, TmpTxt, 0, -dr, r0+1, -1); free(m_range);
+ MoveFormula(this, m_range, TmpTxt, TMP_TXT_SIZE, 0, -dr, r0+1, -1); free(m_range);
m_range = (char*)memdup(TmpTxt, (int)strlen(TmpTxt)+1, 0); 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);
+ MoveFormula(this, etRows[i][j]->text, TmpTxt, TMP_TXT_SIZE, 0, -dr, r0, -1);
etRows[i][j]->SetText(TmpTxt); etRows[i][j]->type = ET_FORMULA;
}
}
@@ -1598,7 +1610,7 @@ SpreadData::InsertRows()
etRows[i][j]->type = ET_VALUE;
break;
case ET_FORMULA:
- MoveFormula(this, etRows[i-dr][j]->text, TmpTxt, 0, dr, r0, -1);
+ MoveFormula(this, etRows[i-dr][j]->text, TmpTxt, TMP_TXT_SIZE, 0, dr, r0, -1);
etRows[i][j]->SetText(TmpTxt); etRows[i][j]->type = ET_FORMULA;
break;
}
@@ -1606,11 +1618,11 @@ SpreadData::InsertRows()
}
}
}
- MoveFormula(this, m_range, TmpTxt, 0, dr, r0, -1); free(m_range);
+ MoveFormula(this, m_range, TmpTxt, TMP_TXT_SIZE, 0, dr, r0, -1); free(m_range);
m_range = (char*)memdup(TmpTxt, (int)strlen(TmpTxt)+1, 0); 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);
+ MoveFormula(this, etRows[i][j]->text, TmpTxt, TMP_TXT_SIZE, 0, dr, r0, -1);
etRows[i][j]->SetText(TmpTxt); etRows[i][j]->type = ET_FORMULA;
}
}
@@ -1637,12 +1649,13 @@ SpreadData::DoPlot(anyOutput *o)
AccRange *ar;
if(!w || !Disp) return;
- w->Erase(0x00e8e8e8L); w->ActualSize(&rc);
+ w->Erase(0x00e8e8e8L); if(!(w->ActualSize(&rc)))return;
w->SetTextSpec(&ssText); et_racc = 0L;
r_disp = (rc.bottom-rc.top)/CellHeight;
- for(c = Disp->ssOrg.x, j=rc.left, c_disp = 1; c < cCols && j <= rc.right; c++, c_disp++) {
+ for(c = Disp->ssOrg.x, j=rc.left, c_disp = 1; c < cCols && j <= (rc.right-rc.left) && c_disp < cCols; c++, c_disp++) {
j += ri->GetWidth(c);
}
+ if(j >= (rc.right-rc.left))c_disp--;
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++) {
@@ -1682,7 +1695,8 @@ SpreadData::DoPlot(anyOutput *o)
delete (ar);
}
if(c_range) InitCopy(0, 0L, w); //move animated rectangle
- w->ActualSize(&rc); rc.bottom += CellHeight; w->UpdateRect(&rc, false);
+ if(!(w->ActualSize(&rc))) return;
+ rc.bottom += CellHeight; w->UpdateRect(&rc, false);
if(err_msg && (!last_err || strcmp(err_msg,last_err))) {
ErrorBox(last_err = err_msg);
}
@@ -1751,7 +1765,7 @@ SpreadData::PasteRange(int cmd, char *txt)
bool
SpreadData::InitCopy(int cmd, void *tmpl, anyOutput *o)
{
- int i, r, c;
+ int r, c;
AccRange *ar;
RECT rc_band, rcCopy;
bool bRet = false;
@@ -1772,14 +1786,9 @@ SpreadData::InitCopy(int cmd, void *tmpl, anyOutput *o)
else if (CurrText) {
if(CurrText->hasMark()) return CurrText->Command(CMD_COPY, o, 0L);
else {
- if(m_range) free(m_range); m_range=0L;
-#ifdef USE_WIN_SECURE
- i = sprintf_s(TmpTxt, TMP_TXT_SIZE, "%s%d:", Int2ColLabel(currpos.x, false), currpos.y+1);
-#else
- i = sprintf(TmpTxt, "%s%d:", Int2ColLabel(currpos.x, false), currpos.y+1);
-#endif
- m_range = (char*)malloc(i*2+2); rlp_strcpy(m_range, i+1, TmpTxt);
- rlp_strcpy(m_range +i, i, TmpTxt); DoPlot(o);
+ if(m_range = (char*)realloc(m_range, 40*sizeof(char)))
+ rlp_strcpy(m_range, 40, mkRangeRef(currpos.y, currpos.x, currpos.y, currpos.x));
+ DoPlot(o);
return InitCopy(cmd, tmpl, o);
}
}
@@ -1840,6 +1849,7 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
static int move_cr = CMD_CURRDOWN;
MouseEvent *mev;
POINT p, cp;
+ RECT rc;
if(!o) o = w;
switch(cmd) {
@@ -1847,7 +1857,7 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
mev = (MouseEvent *) tmpl;
p.x = mev->x; p.y = mev->y;
if((mev->StateFlags & 1) || mev->Action == MOUSE_LBUP || p.y < (w->MenuHeight+CellHeight)) {
- mpos2dpos(&p, &cp, (mev->StateFlags & 1) == 1);
+ if(!(mpos2dpos(&p, &cp, (mev->StateFlags & 1) == 1))) return false;
if(cp.y >= cRows || cp.x >= cCols || cp.y < 0 || cp.x < 0) return false;
}
else cp.x = cp.y = 0;
@@ -1879,27 +1889,19 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
if(!et_racc && !m_range && CurrText) {
CurrText->Update(2, w, &p); CurrText = 0L;
}
+ if(mrk_offs && m_range && m_range[0]){
+ mrk_offs = rlp_strcpy(TmpTxt, mrk_offs+1, m_range);
+ }
+ else mrk_offs = 0;
if(p.x < FirstWidth || p.y < (w->MenuHeight+CellHeight)) {
-#ifdef USE_WIN_SECURE
- i = sprintf_s(TmpTxt+mrk_offs, TMP_TXT_SIZE - 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_s(TmpTxt+mrk_offs+i, TMP_TXT_SIZE - 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+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+mrk_offs+i, "%s%d", Int2ColLabel(p.x < FirstWidth ? cCols-1 : cp.x, false),
- p.y < (w->MenuHeight+CellHeight) ? cRows : cp.y+1);
-#endif
+ if(mrk_offs && TmpTxt[mrk_offs-1] != ';')TmpTxt[mrk_offs++] = ';';
+ rlp_strcpy(TmpTxt+mrk_offs, TMP_TXT_SIZE - mrk_offs, mkRangeRef(
+ p.y < (w->MenuHeight+CellHeight) ? 0 : currpos.y, p.x < FirstWidth ? 0 : currpos.x,
+ p.y < (w->MenuHeight+CellHeight) ? cRows : cp.y, p.x < FirstWidth ? cCols-1 : cp.x));
}
else {
-#ifdef USE_WIN_SECURE
- i = sprintf_s(TmpTxt+mrk_offs, TMP_TXT_SIZE - mrk_offs, "%s%s%d:", mrk_offs? ";" : "", Int2ColLabel(currpos.x, false), currpos.y+1);
- sprintf_s(TmpTxt+mrk_offs+i, TMP_TXT_SIZE - mrk_offs-i, "%s%d", Int2ColLabel(cp.x, false), cp.y+1);
-#else
- 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);
-#endif
+ if(mrk_offs && TmpTxt[mrk_offs-1] != ';')TmpTxt[mrk_offs++] = ';';
+ rlp_strcpy(TmpTxt+mrk_offs, TMP_TXT_SIZE - mrk_offs, mkRangeRef(currpos.y, currpos.x, cp.y, cp.x));
}
if(!CurrText || et_racc)MarkRange(TmpTxt, &cp);
return true;
@@ -1926,15 +1928,13 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
if(p.y < (w->MenuHeight+CellHeight)) {
currpos.y = 0; cp.y = cRows-1;
}
-#ifdef USE_WIN_SECURE
- i = sprintf_s(TmpTxt+mrk_offs, TMP_TXT_SIZE-mrk_offs, "%s%s%d:", mrk_offs? ";" : "", Int2ColLabel(currpos.x, false), currpos.y+1);
- sprintf_s(TmpTxt+mrk_offs+i, TMP_TXT_SIZE-mrk_offs-i, "%s%d", Int2ColLabel(cp.x, false), cp.y+1);
-#else
- 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);
-#endif
- MarkRange(TmpTxt);
- currpos2.x = cp.x; currpos2.y = cp.y + 1;
+ if(mrk_offs && m_range && m_range[0]){
+ mrk_offs = rlp_strcpy(TmpTxt, mrk_offs+1, m_range);
+ }
+ else mrk_offs = 0;
+ if(mrk_offs && TmpTxt[mrk_offs-1] != ';')TmpTxt[mrk_offs++] = ';';
+ rlp_strcpy(TmpTxt+mrk_offs, TMP_TXT_SIZE - mrk_offs, mkRangeRef(currpos.y, currpos.x, cp.y, cp.x));
+ MarkRange(TmpTxt); currpos2.x = cp.x; currpos2.y = cp.y + 1;
}
else if((m_range) && !new_mark) HideMark(false);
if(et_racc && !et_racc->isInRect(&p)) {
@@ -1943,14 +1943,9 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
CurrText->Command(CMD_ADDTXT, o, (DataObj*) m_range);
}
else {
- if(!m_range) m_range = (char*)malloc(20);
-#ifdef USE_WIN_SECURE
- sprintf_s(m_range, 20, "%s%d%", Int2ColLabel(currpos.x, false), currpos.y+1);
-#else
- sprintf(m_range, "%s%d%", Int2ColLabel(currpos.x, false), currpos.y+1);
-#endif
+ m_range = (char*)realloc(m_range, 40*sizeof(char));
+ rlp_strcpy(m_range, 40, mkCellRef(currpos.y, currpos.x));
CurrText->Command(CMD_ADDTXT, o, (DataObj*) m_range);
- free(m_range); m_range = 0L;
}
}
else if(m_range) {
@@ -2059,8 +2054,7 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
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);
+ rlp_strcpy(TmpTxt, 40, mkRangeRef(currpos.y, currpos.x, currpos2.y, currpos2.x));
MarkRange(TmpTxt); HideTextCursor();
break;
case CMD_SHIFTRIGHT: case CMD_SHIFTLEFT:
@@ -2075,8 +2069,7 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
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);
+ rlp_strcpy(TmpTxt, 40, mkRangeRef(currpos.y, currpos.x, currpos2.y, currpos2.x));
MarkRange(TmpTxt); HideTextCursor();
break;
case CMD_SHPGUP:
@@ -2085,8 +2078,7 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
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);
+ rlp_strcpy(TmpTxt, 40, mkRangeRef(currpos.y, currpos.x, currpos2.y, currpos2.x));
MarkRange(TmpTxt); HideTextCursor();
}
break;
@@ -2098,13 +2090,12 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
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);
+ rlp_strcpy(TmpTxt, 40, mkRangeRef(currpos.y, currpos.x, currpos2.y, currpos2.x));
MarkRange(TmpTxt); HideTextCursor();
}
break;
case CMD_CURRIGHT: case CMD_CURRDOWN:
- move_cr = cmd;
+ move_cr = cmd; w->ActualSize(&rc);
case CMD_CURRLEFT: case CMD_CURRUP: case CMD_POS_FIRST: case CMD_POS_LAST:
if(cmd == CMD_CURRUP && Disp->ssOrg.y && CurrText && currpos.y == Disp->ssOrg.y) {
Disp->ssOrg.y --; currpos.y --;
@@ -2121,9 +2112,9 @@ SpreadData::Command(int cmd, void *tmpl, anyOutput *o)
}
DoPlot(o); return false;
}
- if(cmd == CMD_CURRIGHT && c_disp > 3 && (currpos.x-Disp->ssOrg.x) >= (c_disp-3)) {
+ if(CurrText && cmd == CMD_CURRIGHT && c_disp > 3 && ((currpos.x-Disp->ssOrg.x) >= (c_disp-1) || CurrText->GetRX() >= (rc.right-rc.left-10))) {
Disp->ssOrg.x ++; currpos.y ++; DoPlot(o);
- if(CurrText) CurrText->Command(CMD_POS_FIRST, o, this);
+ CurrText->Command(CMD_POS_FIRST, o, this);
}
if(cmd == CMD_CURRDOWN && r_disp > 3 && (currpos.y-Disp->ssOrg.y) >= (r_disp-3)) {
Disp->ssOrg.y ++; currpos.y ++; DoPlot(o);
@@ -2249,8 +2240,8 @@ SpreadData::ReadXML(char *file, unsigned char *buffer, int type, DWORD undo_flag
if(!(XMLcache = new ReadCache())) return false;
if(! XMLcache->Open(file)) {
delete XMLcache;
- sprintf(TmpTxt, "Error open file\n\"%s\"", file);
- ErrorBox(TmpTxt);
+ i = rlp_strcpy(TmpTxt, 40, "Error open file\n\""); i = rlp_strcpy(TmpTxt+i, 200, file);
+ rlp_strcpy(TmpTxt+i, 2, "\""); ErrorBox(TmpTxt);
return false;
}
bUndo_done = true;
@@ -2294,13 +2285,20 @@ SpreadData::ReadXML(char *file, unsigned char *buffer, int type, DWORD undo_flag
}while(TmpTxt[i-1] > 31 && TmpTxt[i-1] != '>');
TmpTxt[i] = 0;
row = col = 0;
- if(TmpTxt[17] = '=' && TmpTxt[13] == 'r') {
- strcpy(TmpTxt, TmpTxt+19);
+ if(TmpTxt[17] == '=' && TmpTxt[13] == 'r') {
+#ifdef USE_WIN_SECURE
+ sscanf_s(TmpTxt+19, "%d", &row);
+#else
+ sscanf(TmpTxt+19, "%d", &row);
+#endif
}
else break;
- sscanf(TmpTxt, "%d", &row);
- for(i = 0; TmpTxt[i] && TmpTxt[i] != '='; i++);
+ for(i = 20; TmpTxt[i] && TmpTxt[i] != '='; i++);
+#ifdef USE_WIN_SECURE
+ sscanf_s(TmpTxt+i+2, "%d", &col);
+#else
sscanf(TmpTxt+i+2, "%d", &col);
+#endif
if(row && col) {
AddCols(col); AddRows(row);
}
@@ -2351,15 +2349,18 @@ SpreadData::ReadXML(char *file, unsigned char *buffer, int type, DWORD undo_flag
for(i = 1; i < 6; TmpTxt[i++] = XMLcache->Getc());
TmpTxt[i] = 0;
if(bContinue =(0 == strcmp("<text>", TmpTxt))) {
- for(i = 0; i < 1023 && ('<' != (TmpTxt[i] =XMLcache->Getc())); i++);
- TmpTxt[i] = 0;
+ for(i = 0; i < 1023; i++) {
+ if(!(TmpTxt[i] =XMLcache->Getc())) break;
+ if(i >1 && TmpTxt[i-2] == '<' && TmpTxt[i-1] == '/' && TmpTxt[i] == 't') break;
+ }
+ i -=2; TmpTxt[i] = 0;
//xml indices start at 1:1 !
row += currpos.y-1; col += currpos.x-1;
if(row >= cRows)AddRows(row+1);
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, -1, -1);
+ MoveFormula(this, TmpTxt, TmpTxt, TMP_TXT_SIZE, currpos.x-mov.x, currpos.y-mov.y, -1, -1);
}
etRows[row][col]->SetText(TmpTxt);
etRows[row][col]->Update(20, 0L, &pt);
@@ -2389,7 +2390,9 @@ SpreadData::ReadTSV(char *file, unsigned char *buffer, int type)
if(!(TSVcache = new ReadCache())) return false;
if(! TSVcache->Open(file)) {
delete TSVcache;
- sprintf(TmpTxt, "Error open file\n\"%s\"", file);
+ i = rlp_strcpy(TmpTxt, 200, "Error open file\n\"");
+ i += rlp_strcpy(TmpTxt+i, 200-i, file);
+ i += rlp_strcpy(TmpTxt+i, 200-i, "\"\n");
ErrorBox(TmpTxt);
return false;
}
@@ -2442,20 +2445,25 @@ TSVError:
return bRet;
}
+static void sylk_cell_ref(char** ptr, int *cbd, int *size, char *first, char* trail, int row, int col)
+{
+ if(first && first[0]) add_to_buff(ptr, cbd, size, first, 0);
+ add_to_buff(ptr, cbd, size, "Y", 1); add_int_to_buff(ptr, cbd, size, row+1, false, 0);
+ add_to_buff(ptr, cbd, size, ";X", 2); add_int_to_buff(ptr, cbd, size, col+1, false, 0);
+ if(trail && trail[0]) add_to_buff(ptr, cbd, size, trail, 0);
+}
+
bool
SpreadData::MemList(unsigned char **ptr, int type)
{
- int i, j, k, nc, nl, cb = 0;
- long cbd = 0, size;
- char tmptxt[8000];
- *ptr = (unsigned char *)malloc(size = 10000);
- unsigned char *tmpptr;
+ int i, j, nc, nl;
+ int cbd = 0, size;
bool bLimit = true;
AccRange *ar;
anyResult res;
RECT rcCopy;
- if(!(*ptr))return false;
+ if(!(*ptr = (unsigned char *)malloc(size = 10000)))return false;
if (c_range && c_range[0]) {
ar = new AccRange(c_range); ar->BoundRec(&rcCopy);
if(bCopyCut) Undo.DataObject(Disp, w, this, &rcCopy, 0L);
@@ -2466,34 +2474,45 @@ SpreadData::MemList(unsigned char **ptr, int type)
}
if(rcCopy.left < 0) rcCopy.left = 0; if(rcCopy.right >= cCols) rcCopy.right = cCols-1;
if(rcCopy.top < 0) rcCopy.top = 0; if(rcCopy.bottom >= cRows) rcCopy.bottom = cRows-1;
- if(type == FF_SYLK) cbd = sprintf((char*)*ptr, "ID;PWXL;N;E\r\n"
- "P;Pdd/mm/yyyy\r\nP;Phh:mm:ss\r\nP;Pdd/mm/yyyy hh:mm:ss\r\n");
+ if(type == FF_SYLK) cbd = rlp_strcpy((char*)*ptr, size, "ID;PWXL;N;E\n"
+ "P;Pdd/mm/yyyy\nP;Phh:mm:ss\nP;Pdd/mm/yyyy hh:mm:ss\n");
else if(type == FF_XML) {
- cbd = sprintf((char*)*ptr, "<?xml version=\"1.0\"?><!DOCTYPE spreadsheet-snippet>"
- "<spreadsheet-snippet rows=\"%d\" columns=\"%d\" >\n", cRows, cCols);
+ cbd = rlp_strcpy((char*)*ptr, 100, "<?xml version=\"1.0\"?><!DOCTYPE spreadsheet-snippet>"
+ "<spreadsheet-snippet rows=\"");
+ add_int_to_buff((char**)ptr, &cbd, &size, cRows, false, 0);
+ add_to_buff((char**)ptr, &cbd, &size, "\" columns=\"", 11);
+ add_int_to_buff((char**)ptr, &cbd, &size, cCols, false, 0);
+ add_to_buff((char**)ptr, &cbd, &size, "\">\n", 3);
if(rcCopy.left || rcCopy.top || rcCopy.bottom || rcCopy.right){
- cbd += sprintf((char*)*ptr+cbd, " <pos1 row=\"%d\" "
- "column=\"%d\"></pos1>\n", rcCopy.top, rcCopy.left);
- cbd += sprintf((char*)*ptr+cbd, " <pos2 row=\"%d\" "
- "column=\"%d\"></pos2>\n", rcCopy.bottom, rcCopy.right);
+ add_to_buff((char**)ptr, &cbd, &size, " <pos1 row=\"", 12);
+ add_int_to_buff((char**)ptr, &cbd, &size, rcCopy.top, false, 0);
+ add_to_buff((char**)ptr, &cbd, &size, "\" column=\"", 10);
+ add_int_to_buff((char**)ptr, &cbd, &size, rcCopy.left, false, 0);
+ add_to_buff((char**)ptr, &cbd, &size, "\"></pos1>\n <pos2 row=\"", 22);
+ add_int_to_buff((char**)ptr, &cbd, &size, rcCopy.bottom, false, 0);
+ add_to_buff((char**)ptr, &cbd, &size, "\" column=\"", 10);
+ add_int_to_buff((char**)ptr, &cbd, &size, rcCopy.right, false, 0);
+ add_to_buff((char**)ptr, &cbd, &size, "\"></pos2>\n", 10);
}
}
else if(type == FF_RLW) {
- cbd = sprintf((char*)*ptr, "<?xml version=\"1.0\"?><!DOCTYPE RLPlot-workbook>\n"
- "<RLPlot-data rows=\"%d\" columns=\"%d\" >\n", cRows, cCols);
+ cbd = rlp_strcpy((char*)*ptr, size, "<?xml version=\"1.0\"?><!DOCTYPE RLPlot-workbook>\n<RLPlot-data rows=\"");
+ add_int_to_buff((char**)ptr, &cbd, &size, cRows, false, 0);
+ add_to_buff((char**)ptr, &cbd, &size, "\" columns=\"", 11);
+ add_int_to_buff((char**)ptr, &cbd, &size, cCols, false, 0);
+ add_to_buff((char**)ptr, &cbd, &size, "\">\n", 3);
}
for(nl =0, i = rcCopy.top; i <= rcCopy.bottom; i++, nl++) {
- for(nc = 0, j = rcCopy.left; j <= rcCopy.right; cb = 0, j++, nc++) {
+ for(nc = 0, j = rcCopy.left; j <= rcCopy.right; j++, nc++) {
switch (type) {
case FF_TSV:
- if(nl || nc) cb = sprintf(tmptxt,"%s", nc ? "\t" : "\n");
+ if(nl || nc) add_to_buff((char**)ptr, &cbd, &size, nc ? (char*)"\t" : (char*)"\n", 1);
if(etRows[i] && etRows[i][j]){
if((ar && ar->IsInRange(j,i)) || !ar) {
etRows[i][j]->GetResult(&res, false);
TranslateResult(&res);
- cb += sprintf(tmptxt+cb, "%s", res.text);
+ add_to_buff((char**)ptr, &cbd, &size, res.text, 0);
}
- tmptxt[cb] = 0;
}
break;
case FF_SYLK:
@@ -2502,64 +2521,62 @@ SpreadData::MemList(unsigned char **ptr, int type)
TranslateResult(&res);
switch(res.type) {
case ET_VALUE: case ET_BOOL:
- cb = sprintf(tmptxt, "C;Y%d;X%d;K", nl+1, nc+1);
- cb += sprintf(tmptxt+cb, "%s\r\n", res.text);
+ sylk_cell_ref((char**) ptr, &cbd, &size, "C;", ";K", nl, nc);
+ add_to_buff((char**)ptr, &cbd, &size, res.text, 0);
break;
case ET_DATE:
- cb = sprintf(tmptxt, "F;P0;FG0G;Y%d;X%d\r\n", nl+1, nc+1);
- cb += sprintf(tmptxt+cb, "C;K%g\r\n", res.value+1.0);
+ sylk_cell_ref((char**) ptr, &cbd, &size, "F;P0;FG0G;", "\nC;K", nl, nc);
+ add_dbl_to_buff((char**)ptr, &cbd, &size, res.value+1, false);
break;
case ET_DATETIME:
- cb = sprintf(tmptxt, "F;P2;FG0G;Y%d;X%d\r\n", nl+1, nc+1);
- cb += sprintf(tmptxt+cb, "C;K%g\r\n", res.value+1.0);
+ sylk_cell_ref((char**) ptr, &cbd, &size, "F;P2;FG0G;", "\nC;K", nl, nc);
+ add_dbl_to_buff((char**)ptr, &cbd, &size, res.value+1, false);
break;
case ET_TIME:
- cb = sprintf(tmptxt, "F;P1;FG0G;Y%d;X%d\r\n", nl+1, nc+1);
- cb += sprintf(tmptxt+cb, "C;K%g\r\n", res.value-floor(res.value));
+ sylk_cell_ref((char**) ptr, &cbd, &size, "F;P1;FG0G;", "\nC;K", nl, nc);
+ add_dbl_to_buff((char**)ptr, &cbd, &size, res.value, false);
break;
case ET_TEXT:
- cb = sprintf(tmptxt, "C;Y%d;X%d;K", nl+1, nc+1);
- cb += sprintf(tmptxt+cb, "\"%s\"\r\n", res.text);
+ sylk_cell_ref((char**) ptr, &cbd, &size, "C;", ";K\"", nl, nc);
+ add_to_buff((char**)ptr, &cbd, &size, res.text, 0);
+ add_to_buff((char**)ptr, &cbd, &size, "\"", 1);
break;
}
+ add_to_buff((char**)ptr, &cbd, &size, "\n", 1);
if(bCopyCut) etRows[i][j]->SetText("");
}
break;
case FF_RLW: case FF_XML:
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");
+ add_to_buff((char**)ptr, &cbd, &size, " <cell row=\"", 12);
+ add_int_to_buff((char**)ptr, &cbd, &size, nl+1, false, 0);
+ add_to_buff((char**)ptr, &cbd, &size, "\" column=\"", 10);
+ add_int_to_buff((char**)ptr, &cbd, &size, nc+1, false, 0);
+ add_to_buff((char**)ptr, &cbd, &size, "\">\n <text>", 11);
+ add_to_buff((char**)ptr, &cbd, &size, etRows[i][j]->text, 0);
+ add_to_buff((char**)ptr, &cbd, &size, "</text>\n </cell>\n", 17);
if(bCopyCut) etRows[i][j]->SetText("");
}
break;
}
- if((cbd+cb+100) > size){
- if(tmpptr = (unsigned char*)realloc(*ptr, size+10000)) {
- *ptr = tmpptr; size += 10000;
- }
- else return true; //not all but something on clipboard
- }
- memcpy(*ptr+cbd, tmptxt, cb+1);
- cbd += cb;
}
- if(type == FF_SYLK) {
- if(!bLimit) {
- cbd += sprintf((char*)*ptr+cbd, "C;Y%d;X1;K\"long strings were"
- " truncated to 256 characters due to limitations of the SYLK format!\"\n", i+2);
- }
- sprintf((char*)*ptr+cbd, "E\n");
+ }
+ if(type == FF_SYLK) {
+ if(!bLimit) {
+ add_to_buff((char**)ptr, &cbd, &size, "C;Y", 3);
+ add_int_to_buff((char**)ptr, &cbd, &size, i+2, false, 0);
+ add_to_buff((char**)ptr, &cbd, &size, ";X1;K\"long strings were"
+ " truncated to 256 characters due to limitations of the SYLK format!\"\n", 92);
}
- else if(type == FF_TSV) sprintf((char*)*ptr+cbd,"\n");
+ add_to_buff((char**)ptr, &cbd, &size, "E\n", 2);
}
- if(type == FF_XML) sprintf((char*)*ptr+cbd,"</spreadsheet-snippet>\n");
+ else if(type == FF_TSV) add_to_buff((char**)ptr, &cbd, &size, "\n", 1);
+ else if(type == FF_XML) add_to_buff((char**)ptr, &cbd, &size, "</spreadsheet-snippet>\n", 23);
else if(type == FF_RLW){
Disp->Command(CMD_WRITE_GRAPHS, ptr, (anyOutput*)&cbd);
- sprintf((char*)*ptr+cbd,"</RLPlot-data>\n");
//note: cbd may be greater than size !
+ add_to_buff((char**)ptr, &cbd, &size, "</RLPlot-data>\n", 15);
}
if(ar) delete ar;
if(bCopyCut && type == FF_XML || type == FF_SYLK || type == FF_RLW){
diff --git a/use_gui.cpp b/use_gui.cpp
index 30dce9a..b78b780 100755
--- a/use_gui.cpp
+++ b/use_gui.cpp
@@ -962,21 +962,41 @@ Label::AddChar(int ci, anyOutput *o)
if(!parent->Command(CMD_MUTATE, golist, o)) DeleteGO(golist[1]);
return false;
}
- if(ci < 254 && ci > 31) c = (char)ci;
+ if(TextDef.text && TextDef.text[0]) i = (int)strlen(TextDef.text);
+ else i = 0; if(CursorPos > i)CursorPos = i;
+ if(ci > 254) {
+ Undo.String(this, &TextDef.text, 0L);
+ Undo.ValInt(this, &CursorPos, UNDO_CONTINUE);
+ txt1 = (char*)malloc((i+12)*sizeof(char));
+ if(txt1) {
+ if(j=CursorPos) k = rlp_strcpy(txt1, CursorPos+1, TextDef.text);
+ else k = 0;
+#ifdef USE_WIN_SECURE
+ k += sprintf_s(txt1+k, i+12-k, "&#%d;",ci);
+#else
+ k += sprintf(txt1+k, "&#%d;",ci);
+#endif
+ CursorPos = k;
+ k += rlp_strcpy(txt1+k, i+12-k, TextDef.text+j);
+ if(TextDef.text) free(TextDef.text);
+ TextDef.text = txt1; RedrawEdit(o);
+ }
+ return true;
+ }
+ else if( ci > 31) c = (char)ci;
else return false;
if(!TextDef.text || CursorPos < 10 || c == ' ') {
Undo.String(this, &TextDef.text, 0L);
Undo.ValInt(this, &CursorPos, UNDO_CONTINUE);
}
- if(TextDef.text) txt1 = (char*)calloc((i = (int)strlen(TextDef.text))+2, sizeof(char));
- else txt1 = (char*)calloc((i = 0)+2, sizeof(char));
+ txt1 = (char*)malloc((i+4)* sizeof(char));
if(txt1) {
- for(j = k = 0; j< i && j < CursorPos; txt1[k++] = TextDef.text[j++]);
- txt1[k++] = c;
- for(; j< i; txt1[k++] = TextDef.text[j++]);
+ if(j=CursorPos) k = rlp_strcpy(txt1, CursorPos+1, TextDef.text);
+ else k = 0; txt1[k++] = c;
+ k += rlp_strcpy(txt1+k, i+12-k, TextDef.text+j);
if(TextDef.text) free(TextDef.text);
- TextDef.text = txt1;
- CursorPos++; RedrawEdit(o);
+ TextDef.text = txt1; txt1[k] = 0;
+ CursorPos++; RedrawEdit(o);
}
return true;
}
@@ -1066,6 +1086,40 @@ TextFrame::CalcCursorPos(int x, int y, anyOutput *o)
else cur_pos.x = i;
}
+void
+Axis::DoMark(anyOutput *o, bool mark)
+{
+ LineDEF mrkLine;
+ double minw = DefSize(SIZE_DATA_LINE);
+ POINT *arc;
+ long narc = 0;
+
+ if(axis->flags & AXIS_ANGULAR) {
+ if(mark) {
+ o->GetSize(&mrc); mo = GetRectBitmap(&mrc, o);
+ memcpy(&mrkLine, &axline, sizeof(LineDEF));
+ mrkLine.width = axline.width < minw ? minw * 3.0 : axline.width *3.0;
+ o->SetLine(&mrkLine);
+ if(arc = MakeArc(pts[0].x, pts[0].y, pts[1].x, 0x0f, &narc)) {
+ o->oPolyline(arc, (int)narc, 0L);
+ mrkLine.color ^= 0x00ffffffL; mrkLine.width = axline.width;
+ o->SetLine(&mrkLine); o->oPolyline(arc, (int)narc, 0L);
+ free(arc);
+ }
+ o->UpdateRect(&mrc, false);
+ }
+ else RestoreRectBitmap(&mo, &mrc, o);
+ return;
+ }
+ if(mark){
+ memcpy(&mrc, &rDims, sizeof(RECT));
+ IncrementMinMaxRect(&mrc, 6 + o->un2ix(axline.width));
+ mo = GetRectBitmap(&mrc, o);
+ InvertLine(pts, 2, &axline, &rDims, o, mark);
+ }
+ else RestoreRectBitmap(&mo, &mrc, o);
+}
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Graphs are graphic objects containing plots, axes, and drawn objects
bool
@@ -1082,7 +1136,7 @@ Graph::ExecTool(MouseEvent *mev)
double x, y;
if(!mev || !CurrDisp) return false;
- td = 0L;
+ td = 0L; if(mev->Action == MOUSE_LBUP) SuspendAnimation(CurrDisp, false);
if(ToolMode & TM_MOVE) switch (mev->Action) {
case MOUSE_LBDOWN:
pl.x = pc.x = mev->x; pl.y = pc.y = mev->y;
@@ -1450,7 +1504,7 @@ Graph::ExecTool(MouseEvent *mev)
return true;
case MOUSE_MOVE:
if(mev->StateFlags &1) {
- CurrDisp->MouseCursor(MC_CROSS, false);
+ CurrDisp->MouseCursor(MC_TXTFRM, false);
if(rcUpd.left != rcUpd.right && rcUpd.top != rcUpd.bottom)
CurrDisp->UpdateRect(&rcUpd, false);
line[0].x = line[4].x = pl.x; line[0].y = line[4].y = pl.y;
@@ -1582,6 +1636,7 @@ Graph::DoZoom(char *z)
Graph *cg;
if(!z) return false;
+ HideCopyMark();
if(0==strcmp("fit", z)) {
if(CurrGraph) cg = CurrGraph;
else cg = this;
@@ -1591,7 +1646,7 @@ Graph::DoZoom(char *z)
rc_mrk.top = CurrDisp->un2ix(cg->GetSize(SIZE_GRECT_TOP))-4
- iround(CurrDisp->MenuHeight);
rc_mrk.bottom = CurrDisp->un2ix(cg->GetSize(SIZE_GRECT_BOTTOM))+4;
- CurrDisp->ActualSize(&cw);
+ if(!(CurrDisp->ActualSize(&cw)))return false;
f1 = (double)(cw.bottom - cw.top)/(double)(rc_mrk.bottom - rc_mrk.top);
f2 = ((double)(cw.right - cw.left)/(double)(rc_mrk.right - rc_mrk.left));
fac = f1 < f2 ? f1 : f2;
@@ -1624,7 +1679,7 @@ Graph::DoZoom(char *z)
ToolMode = TM_STANDARD; Command(CMD_TOOLMODE, &ToolMode, CurrDisp);
return false;
}
- CurrDisp->ActualSize(&cw);
+ if(!(CurrDisp->ActualSize(&cw)))return false;
fac = (double)(cw.bottom - cw.top)/(double)(rc_mrk.bottom - rc_mrk.top);
fac += ((double)(cw.right - cw.left)/(double)(rc_mrk.right - rc_mrk.left));
fac /= 2.0;
--
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