/* 2D graphic window class functions. They need not to be reenterable but MUST be reusable. */ #include "common.h" #if LINKIN #include "large.h" #include "datalib0.h" #include "visual.h" #include "tsprintf.h" #undef MemNew #undef MemMore #undef MemFree #undef StringSave #define MemNew _MemNew #define MemMore _MemMore #define MemFree _MemFree #define StringSave _StringSave #else /* LINKIN */ #include "corefunc.h" #include "inter.h" #endif /*LINKIN */ #define GET_CLASS_TABLE g2d_GetClassTable /* Unique name of the 'Get Class Table' function */ #include "window.h" /* GetClassTable is generated by window.h */ /* Texts */ Local(CharPtr) Text[]={ "Compute{", "Forward", "Backward", "Extend", "Window{", "Redraw diagram", "Redraw curve", "Clear", "Fit diagram", "Fit curve", "Undo scale", "Layout...", "Hardcopy...", "Duplicate", "Hide", "Attributes{", "Current...", "Curve...", "Mouse{", "Pick up coordinates?", "Immediate forward?", "Immediate backward?", "Help{", "This window", "Search", "-", "}", "Abscissa", "Ordinate", "Waiting for attributes setting", "Attributes of graphic window", "Current drawing attributes", "Drawing attributes of current curve", "4,11,(6,13)", /* NumLen,TextLen,(ListLines,LineLen) */ "Min", "Max", "Tick", "Scale", "Label", "Grid", "Axis", "Draw unit circle", "Colors", "Change color", "Foreground", "Background", "Show palette in window", "The first point", "The last point", "Show in window", "Points", "Traces", "Paths", "Shifts", "Graphic attributes", "Set attributes of", "Curve segment", "From point", "To point", "Functions along axes", "New functions", "Delete functions", "Attributes set", "Add attributes", "Delete attributes", "Join", "Width", "No", "Solid", "Dotted", "Options", "Clear before each point", "Hardcopy options", "Waiting for hardcopy options", "File", "Browse", "Picture", "Width", "Height", "mm cm in", "Font", "Options", "Curve width scale factor", "Line width scale factor", "Marker scale factor", "Try to preserve colors", #if _UNIX "Show on screen", "Send to printer", #endif "Sample of window", "1/1 ", "Window title", NULL }; enum { COMPUTE_M, FORWARD_I, BACKWARD_I, EXTEND_I, WINDOW_M, REDRAWD_I, REDRAWC_I, CLEAR_I, FITD_I, /* Fit diagram */ FITC_I, /* Fit curve */ UNDOSCALE_I, /* Undo scale */ LAYOUT_I, /* Layout */ HARDCOPY_I, /* Hardcopy */ DUPLICATE_I, /* Duplicate */ HIDE_I, ATTRIBUTES_M, /* Attributes{ */ CURRENTATR_I, /* Current... */ CURVEATR_I, /* Curve... */ MOUSE_M, /* Mouse{ */ MOUSEPICK_I, /* Pick up coordinates? */ MOUSEIMMEDF_I,/* Immediate forward? */ MOUSEIMMEDB_I,/* Immediate backward? */ HELP_M, HELP_I, SEARCH_I, SEPARATOR_I, DUMMYEND_I, ABS_P, /* Abscissa */ ORD_P, /* Ordinate */ WAITATTR_C, /* Waiting for attributes setting */ LAYOUT_T, /* Attributes of graphic window */ DRAWATTR_T, /* Current drawing attributes */ CURVEATTR_T, /* Drawing attributes of current curve */ SIZES, /* 4,11,(6,13) ! NumLen,TextLen,(ListLines,LineLen) */ MIN_P, /* Min */ MAX_P, /* Max */ TICK_P, /* Tick */ SCALE_P, /* Scale */ FUNC_P, /* Label */ GRID_P, /* Grid */ AXIS_P, /* Axis */ CIRCLE_P, /* Draw unit circle */ COLORS_T, /* Colors */ COLOR_B, /* Change color */ FG_P, /* Foreground */ BG_P, /* Background */ SHOWPAL_P, /* Show palette in window */ FP_P, /* The first point */ LP_P, /* The last point */ SHOWOPT_P, /* Show in window */ POINTS_P, /* Points */ TRACES_P, /* Traces */ PATHS_P, /* Paths */ SHIFTS_P, /* Shifts */ ATTR_T, /* Graphic attributes */ ATTROF_T, /* Set attributes of */ SEG_P, /* Curve segment */ SPF_P, /* From point */ SPT_P, /* To point */ CURVES_P, /* Functions along axes */ ADDFUN_B, /* New functions */ DELFUN_B, /* Delete functions */ AN_P, /* Attributes set */ AA_B, /* Add attributes */ DA_B, /* Delete attributes */ JOIN_T, /* Join points along */ WIDTH_P, /* Width */ NO_B, /* No */ SOLID_B, /* Solid */ DOTTED_B, /* Dotted */ OPTIONS_P, /* Options */ CLEAR_P, /* Clear before each point */ HARDCOPY_T, /* Hardcopy options */ HARDCOPY_C, /* Waiting for hardcopy options */ HCFILE_G, /* File */ HCFILELIST_B, /* Browse */ HCPIC_P, /* Picture */ HCWIDTH_P, /* Width */ HCHEIGHT_P, /* Height */ HCUNITS, /* mm cm in */ HCFONTG_P, /* Font */ HCOPT_P, /* Options */ HCCWIDF_P, /* Curve width scale factor */ HCLWIDF_P, /* Line width scale factor */ HCMF_P, /* Marker scale factor */ HCOPTCOL_P, /* Try to preserve colors */ #if _UNIX HCOPTPRE_P, /* Show on screen */ HCOPTPRI_P, /* Send to printer */ #endif SAMPLE_WIN, /* Sample of window */ FUNCNUM_P, /* "1/1 " */ WINTITLE_P, /* Window title */ _L_A_S_T_ }; #define DEFAULT_TITLE "2D graphic" /* default title of window */ #define HK_2DWIN "kh_2DWin" /* Help key for the window */ #define HK_LAYOUTWIN "kh_2DWinLayout" /* Help key for layout dialog box */ #define HK_HARDCOPYWIN "kh_2DWinHardcopy" /* Help key for hardcopy dialog box */ #define KH_CURRENTATTR "kh_2DWinCurrentAttr" /* Help key for current attributes dialog box */ #define KH_CURVEATTR "kh_2DWinCurveAttr" /* Help key for curve's attributes dialog box */ /* Settings file section name */ #define SECTION "Window_2DGraphic" #define SECTION_COM "Visual" /* Axis function */ typedef EntryPtr(FloatHi,WinFloatValue,(FloatHiPtr PNTR PNTR ptr)); /* Axis descriptor */ typedef struct { CharPtr pFunc; /* user-specified function along the axis */ union { /* depends on FuncKind */ struct { Int2 IndirectIndex; /* index to IndirectValues */ Uint2 Offset; /* offset in values vector */ } Simple; /* Simple value */ struct { WinFloatValue FloatFunc; /* ptr to axis's function */ } General; /* General case */ } Func; FloatHi hcWcoord; /* Hardcopy: math coords of previous point */ Int2 Wcoord; /* windows coords of previous point */ Int1 FuncKind; /* 0 - simple variable, 1 - must be compiled, -1 - undefined */ Boolean Gdim; /* TRUE - Gdim(pFunc)==1 */ Int2 Eip; /* Echo Initial Point coord */ } AxisFunc, PNTR AxisFuncPtr; /* Hardcopy */ typedef struct { FloatLo x,y; } MathPoint, PNTR MathPointPtr; /* Draw attributes of points, traces, and paths */ typedef struct { DrawAttr Point; DrawAttr Trace; /* style>0 => join along traces */ DrawAttr Path; /* style>0 => join along paths */ PointPtr PrevPath; /* used if Attr[].Path.style>0 and points to 2 vectors */ PointPtr CurPath; /* with windows coordinates of M-points on prev and cur G-points */ MathPointPtr hcPrevPath, hcCurPath; /* Hardcopy */ Int2 PrevNum,CurNum; /* number of PoinTs in PrevPath and CurPath */ Int2 flags; /* func-specific flags */ #define PATH_CHANGE 0x0001 /* Path.style has been chaged from <0 to >0 */ } FuncAttr, PNTR FuncAttrPtr; /* Options unrelated to axes, traces and paths */ typedef struct { DrawAttr Shift; /* style>0 => join along shifts */ Uint1 Flags; #define GWIN_PALETTE 0x01 #define GWIN_CLEAR 0x02 #define GWIN_CIRCLE 0x04 #define GWIN_FLAGS 0x80 /* DO NOT CHANGE: save/restore gd->flags */ Uint1 Reserve; /* unused now */ } ShowOptions; /* Element of the undo scale buffer */ typedef struct { FloatHi xMin,xMax,yMin,yMax; } UndoElem, PNTR UndoElemPtr; /* Private data structure which describes window's controls */ typedef struct { /* Description of controls */ struct { CharPtr pText[4]; #define pMin pText[0] /* Min */ #define pMax pText[1] /* Max */ #define pCurFunc pText[2] /* Current Function along the axis */ #define FUNCINDEX 2 #define FuncIndex(i) (i==FUNCINDEX) #define pTick pText[3] /* Tick */ AxisFuncPtr Funcs; /* to array of axis function */ Boolean Prop[6]; /* Properties */ #define bLimits Prop[0] #define bTick Prop[1] #define bScale Prop[2] #define bFunc Prop[3] #define bGrid Prop[4] #define bAxis Prop[5] } Axis[2]; /* 0 - abs, 1 - ord */ FuncAttrPtr Attr; /* to array of attributes of points,traces,paths */ FuncAttrPtr SaveAttr;/* used for temporary storage of attrs */ ShowOptions Options; /* Work area */ Int2 flags; #define DONT_SCALE 0x0001 /* don't draw scale; set by MInit for DrawProc */ #define MOUSE_PICK 0x0002 /* Mouse click sets up initial point */ #define MOUSE_IMMB 0x0004 /* and starts backward */ #define MOUSE_IMMF 0x0008 /* and starts forward */ #define FIT_IN_PROGRESS 0x0010 /* Fit diagram/curve in progress */ GrouP grLimits; /* Limits SpeedBar group */ GrouP grPalette; /* Palette SpeedBar group */ #if MYSWITCH Switch swNum; /* Palette: number of current curve */ #else SwitcH swNum; /* Palette: number of current curve */ #endif PaneL paSample; /* Palette: sample of curve color */ struct { TexT teLimits[4]; /* 0 - Min, 1 - Max, 2 - Func, 3 - Tick */ PrompT prompt; } teAxis[2]; /* Limits SpeedBar controls */ /* A list of window coordinates of special points */ ByteStorePtr SpecialPoints; /* Drawing area */ PaneL paPanel; /* Graphics drawing area */ RecT Slate; /* coincides with the Panel if scales are off */ ButtoN buRefr; /* invisible default button */ TexT teAct; /* invisible; actvie while compute */ FloatHi DeltaX,DeltaY; Int2 FuncNum; /* number of function pairs; usually 1 */ Int2 FuncCur; /* current function pair (from 0) */ Int2 SaveFuncNum; /* temp store FuncNum: Push/Pop attr */ Int2 InitLevel; /* depth of GInit nested calls (redraw in pause) */ struct { FloatHi Limits[4]; #define Min Limits[0] #define Max Limits[1] /* Limits[2] (Func) used only to align Tick to have the same index as pTick */ /* From 15.07.94 it is overlayed by Step */ #define Step Limits[2] #define Tick Limits[3] FloatHi FitLimits[2]; /* used by fit diagram/curve only */ #define FitMin FitLimits[0] #define FitMax FitLimits[1] } RAxis[2]; /* Used by conversion routines. May differ from Axis[].pText[] in cases the user set invalid Min and/or Max and/or Tick */ Int2 ix_min,ix_max,iy_min,iy_max; /* windows coords of Slate */ Boolean joinpath; /* OR'ed Attr[0..FuncNum-1].Path.style>0 */ /* Undo scale */ UndoElemPtr UndoBuf; Int2 UndoNum; /* Hardcopy */ FILE PNTR HardFile; /* output for hardcopy */ Boolean Hardcopy; /* set when in hardcopy progress for this window */ Int2 hcMarkerNo; /* Ordinal number of current marker */ /* Grid */ #if _UNIX /* no bitmaps, SetPenDash is used */ #else Uint1Ptr GridVert; Uint1Ptr GridHor; #endif /* Click-hold-release */ PoinT ptClick,ptLast; Boolean bDrag; /* Multi-point paths */ Int2 PrevNum,Q,Qs,Q1s,JoinIndex,JoinNum; } GraphicData, PNTR GraphicDataPtr; /* Head and tail of window functions */ typedef EntryPtr(void,WinFuncPtr,(FloatHiPtr PNTR PNTR ptr)); #define WIN_HEAD \ "double" \ " $("SFS_COMPILER".RHSATTR)" \ " %s" \ " (double * * * $("SFS_VISUAL".WINPAR)) {"STR_NL \ " return "STR_EMPTY #define WIN_TAIL \ ";"STR_NL"}"STR_NL #define UNDODEPTH 10 /* undo scale buffer's length */ #if _WIN #pragma argsused #endif Callback(Boolean) AlwaysStatus(Int2 indx) { return TRUE; } Callback(void) lRedrawD(Int2 indx); Callback(void) lRedrawC(Int2 indx); Callback(void) lClear(Int2 indx); Callback(void) lFitDiagram(Int2 indx); Callback(void) lFitCurve(Int2 indx); Callback(void) lLayout(Int2 indx); Callback(void) lUndoScale(Int2 index); Callback(Boolean) lUndoScale_Status(Int2 index); Callback(void) lHardcopy(Int2 indx); Callback(void) lDuplicate(Int2 index); Callback(void) lCurrentAtr(Int2 indx); Callback(void) lCurveAtr(Int2 indx); Callback(void) lPickCoord(Int2 index); Callback(Boolean) lPickCoord_Status(Int2 index); Callback(void) lImmedFComp(Int2 index); Callback(Boolean) lImmedFComp_Status(Int2 index); Callback(void) lImmedBComp(Int2 index); Callback(Boolean) lImmedBComp_Status(Int2 index); Callback(void) lHelp(Int2 indx); Callback(void) lHelpSearch(Int2 indx); /* Menu */ Local(MenuItem) GraphicMenu[]={ {COMPUTE_M, NULL, NULL}, { FORWARD_I, NULL, NULL}, { BACKWARD_I, NULL, NULL}, { SEPARATOR_I, NULL, NULL}, { EXTEND_I, NULL, NULL}, { DUMMYEND_I, NULL, NULL}, {WINDOW_M, NULL, NULL}, { REDRAWD_I, lRedrawD, NULL,0,MNFL_ACTIVEINPAUSE}, { REDRAWC_I, lRedrawC, NULL,0,MNFL_ACTIVEINPAUSE}, { SEPARATOR_I, NULL, NULL}, { CLEAR_I, lClear, AlwaysStatus,0,MNFL_ACTIVEINPAUSE}, { SEPARATOR_I, NULL, NULL}, { FITD_I, lFitDiagram, NULL,0,MNFL_ACTIVEINPAUSE}, { FITC_I, lFitCurve, NULL,0,MNFL_ACTIVEINPAUSE}, { SEPARATOR_I, NULL, NULL}, { UNDOSCALE_I, lUndoScale, lUndoScale_Status,0,MNFL_ACTIVEINPAUSE}, { SEPARATOR_I, NULL, NULL}, { LAYOUT_I, lLayout, AlwaysStatus}, { SEPARATOR_I, NULL, NULL}, { HARDCOPY_I, lHardcopy, NULL}, { SEPARATOR_I, NULL, NULL}, { DUPLICATE_I, lDuplicate, AlwaysStatus}, { SEPARATOR_I, NULL, NULL}, { HIDE_I, NULL, AlwaysStatus,0,MNFL_ACTIVEINPAUSE}, { DUMMYEND_I, NULL, NULL}, {ATTRIBUTES_M, NULL, NULL}, { CURRENTATR_I, lCurrentAtr, AlwaysStatus,0,MNFL_ACTIVEINPAUSE}, { CURVEATR_I, lCurveAtr, NULL,2,MNFL_ACTIVEINPAUSE}, { DUMMYEND_I, NULL, NULL}, {MOUSE_M, NULL, NULL}, { MOUSEPICK_I, lPickCoord, lPickCoord_Status}, { MOUSEIMMEDF_I, lImmedFComp, lImmedFComp_Status}, { MOUSEIMMEDB_I, lImmedBComp, lImmedBComp_Status}, { DUMMYEND_I, NULL, NULL}, {HELP_M, NULL, NULL}, { HELP_I, lHelp, AlwaysStatus,0,MNFL_ACTIVEINPAUSE}, { SEPARATOR_I, NULL, NULL}, { SEARCH_I, lHelpSearch, AlwaysStatus,0,MNFL_ACTIVEINPAUSE}, { DUMMYEND_I, NULL, NULL} }; Local(void) UndoRecord(WinComDataPtr wcd); #define GetComDataI ((WinComDataPtr)GetWindowExtra(CurrentWindow())) #define GetComDataC(h) ((WinComDataPtr)GetWindowExtra(ParentWindow(h))) ClassMember(void) BuildDefaultDescription(WinComDataPtr wcd) { GraphicDataPtr gd; DrawAttr da; CharPtr p; Char buf[100]; Int2 i,j,dim; wcd->WinTitle=StringSave(DEFAULT_TITLE); if (!wcd->Private) wcd->Private=MemNew(sizeof(GraphicData)); gd=(GraphicDataPtr)wcd->Private; gd->FuncNum=1; /* number of V-curves */ gd->FuncCur=0; /* the 1st is the current */ for (i=0; iAxis); i++) { gd->Axis[i].pMin=StringSave("0"); gd->Axis[i].pMax=StringSave("1"); GetNameAndDim(1-i,1,&p,&dim); if (dim>1) { StrCpy(buf,p); StrCat(buf,"[0]"); p=buf; } gd->Axis[i].Funcs=MemNew(ARRAYSIZE(AxisFunc,1)); gd->Axis[i].Funcs[0].pFunc=StringSave(p); gd->Axis[i].pTick=StringSave("0"); /* default: choose tick automatically */ for (j=0; jAxis[0].Prop); j++) gd->Axis[i].Prop[j]=TRUE; /* All on by default */ gd->Axis[i].bTick=FALSE; /* except for ticks */ gd->Axis[i].Funcs[0].FuncKind=0; /* Simple */ } gd->Attr=MemNew(ARRAYSIZE(FuncAttr,1)); da.color=wcd->Foreground; da.width=2; da.style=-1; /* don't join; when negated - solid line */ gd->Attr[0].Point=da; gd->Attr[0].Trace=da; gd->Options.Shift=da; da.style=1; /* Solid */ gd->Attr[0].Path=da; gd->Options.Flags=0; gd->Options.Reserve=0; gd->SpecialPoints=BSNew(0); } ClassMember(void) ReadDescription(WinComDataPtr wcd, DataLibPtr arch){ GraphicDataPtr gd; Int2 i,j,un; if (!wcd->Private) wcd->Private=MemNew(sizeof(GraphicData)); gd=(GraphicDataPtr)wcd->Private; DataLibRead(arch,(CharPtr)&gd->FuncNum,sizeof(gd->FuncNum)); DataLibRead(arch,(CharPtr)&gd->FuncCur,sizeof(gd->FuncCur)); for (i=0; iAxis); i++) { for (j=0; jAxis[i].pText); j++) if (!FuncIndex(j)) gd->Axis[i].pText[j]=DataLibReadVRecord(arch,NULL); gd->Axis[i].Funcs=MemNew(ARRAYSIZE(AxisFunc,gd->FuncNum)); for (j=0; jFuncNum; j++) gd->Axis[i].Funcs[j].pFunc=DataLibReadVRecord(arch,NULL); DataLibRead(arch,(CharPtr)gd->Axis[i].Prop,sizeof(gd->Axis[i].Prop)); } gd->Attr=MemNew(ARRAYSIZE(FuncAttr,gd->FuncNum)); for (i=0; iFuncNum; i++) { DataLibRead(arch,(CharPtr)&gd->Attr[i].Point,sizeof(DrawAttr)); DataLibRead(arch,(CharPtr)&gd->Attr[i].Trace,sizeof(DrawAttr)); DataLibRead(arch,(CharPtr)&gd->Attr[i].Path,sizeof(DrawAttr)); } DataLibRead(arch,(CharPtr)&gd->Options,sizeof(gd->Options)); gd->SpecialPoints=BSNew(0); DataLibRead(arch,(CharPtr)&un,sizeof(un)); gd->UndoNum=un ? un-1 : 0; if (un) { gd->UndoBuf=MemNew(ARRAYSIZE(UndoElem,UNDODEPTH)); DataLibRead(arch,(CharPtr)gd->UndoBuf,ARRAYSIZE(UndoElem,un)); } if (gd->Options.Flags&GWIN_FLAGS) DataLibRead(arch,(CharPtr)&gd->flags,sizeof(gd->flags)); } ClassMember(void) WriteDescription(WinComDataPtr wcd, DataLibPtr arch) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Int2 i,j,un; DataLibWrite(arch,(CharPtr)&gd->FuncNum,sizeof(gd->FuncNum)); DataLibWrite(arch,(CharPtr)&gd->FuncCur,sizeof(gd->FuncCur)); for (i=0; iAxis); i++) { for (j=0; jAxis[i].pText); j++) if (!FuncIndex(j)) { DataLibWriteVRecord(arch,NULL,gd->Axis[i].pText[j], StrLen(gd->Axis[i].pText[j])+1); MemFree(gd->Axis[i].pText[j]); } for (j=0; jFuncNum; j++) { DataLibWriteVRecord(arch,NULL,gd->Axis[i].Funcs[j].pFunc, StrLen(gd->Axis[i].Funcs[j].pFunc)+1); MemFree(gd->Axis[i].Funcs[j].pFunc); } MemFree(gd->Axis[i].Funcs); DataLibWrite(arch,(CharPtr)gd->Axis[i].Prop,sizeof(gd->Axis[i].Prop)); } for (i=0; iFuncNum; i++) { DataLibWrite(arch,(CharPtr)&gd->Attr[i].Point,sizeof(DrawAttr)); DataLibWrite(arch,(CharPtr)&gd->Attr[i].Trace,sizeof(DrawAttr)); DataLibWrite(arch,(CharPtr)&gd->Attr[i].Path,sizeof(DrawAttr)); } MemFree(gd->Attr); gd->Options.Flags|=GWIN_FLAGS; DataLibWrite(arch,(CharPtr)&gd->Options,sizeof(gd->Options)); BSFree(gd->SpecialPoints); un=gd->UndoBuf ? gd->UndoNum+1 : 0; DataLibWrite(arch,(CharPtr)&un,sizeof(un)); DataLibWrite(arch,(CharPtr)gd->UndoBuf,ARRAYSIZE(UndoElem,un)); MemFree(gd->UndoBuf); DataLibWrite(arch,(CharPtr)&gd->flags,sizeof(gd->flags)); } #define round(x) ((Int2)floor(x+0.5)) /* to the nearest integer */ /* Makes a FloatHi number looking "good" */ #define VZERO 1e-10 /* x printed as '0' if abs(x)INT4_MAX Local(FloatHi) ApplyArtificialIntellectX(FloatHi min, FloatHi max, Int2 len) { /* Embedded parameter of this part of the ArtificialIntellectX: The minimal horizontal spacing between two numbers. */ #define MININTVL (2*sysCharWidth) #define NO_MORE_THAN 20 /* No more intervals than this number */ FloatHi d,w; Int2 maxn,power,width,width0,i; Char buf[50]; d=max-min; sprintf(buf,"%g",max); len+=StringWidth(buf)>>1; sprintf(buf,"%g",min); len+=StringWidth(buf)>>1; maxn=MIN(len/(StringWidth(buf)+MININTVL),NO_MORE_THAN); if (!maxn) maxn=1; if (OutOfRange(d)) return d/maxn; for (power=0; !IsMultiple10(d); power++) { if (OutOfRange(d)) return d/maxn/pow(10,power); else d*=10; } sprintf(buf,"%g",min); width0=StringWidth(buf)>>1; sprintf(buf,"%g",max); width0+=StringWidth(buf)>>1; for (; maxn; maxn--) { if (IsInteger(d/maxn)) { width=width0+maxn*MININTVL; for (i=1; i=len) break; } if (i==maxn) return d/maxn/pow(10,power); } } /* To be on the safe side. Control may comes here */ return (max-min)/2; #undef MININTVL #undef NO_MORE_THAN } Local(FloatHi) ApplyArtificialIntellectY(FloatHi min, FloatHi max, Int2 len) { /* Embedded parameter of this part of the ArtificialIntellectY: The minimal vertical spacing (2*sysLineHeight now). */ #define MININTVL (3*sysLineHeight/2) /* Min allowable interval between lines */ #define NO_MORE_THAN 20 /* No more intervals than this number */ FloatHi d; Int2 maxn,power; d=max-min; maxn=MIN((len+sysLineHeight)/(sysLineHeight+MININTVL),NO_MORE_THAN); if (!maxn) maxn=1; if (OutOfRange(d)) return d/maxn; for (power=0; !IsMultiple10(d); power++) { if (OutOfRange(d)) return d/maxn/pow(10,power); else d*=10; } for (; maxn; maxn--) { if (IsInteger(d/maxn)) return d/maxn/pow(10,power); } /* To be on the safe side. Control never comes here */ return (max-min)/2; #undef MININTVL #undef NO_MORE_THAN } /* Check limits along axis */ Local(void) CheckLimits(WinComDataPtr wcd, Int2 axis) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; FloatHi min,max,tick,d; min=max=tick=0; /* for a case sscanf fails */ (ComputeExpr(gd->Axis[axis].pMin,&min) | /* not || */ ComputeExpr(gd->Axis[axis].pMax,&max) | /* not || */ ComputeExpr(gd->Axis[axis].pTick,&tick) ? Disable : Enable) (gd->teAxis[axis].prompt); gd->RAxis[axis].Tick=tick; d=max-min; if (d<0) { gd->RAxis[axis].Max=min; gd->RAxis[axis].Min=max; } else if (d==0) { gd->RAxis[axis].Min=min; gd->RAxis[axis].Max=min+1; } else { gd->RAxis[axis].Min=min; gd->RAxis[axis].Max=max; } } #if _UNIX #define HOFF 1 /* difference from Windows: right and bottom are included */ #define VOFF 1 #else #define HOFF 0 #define VOFF 0 #endif /* Compute Deltas for MathToWin. */ Local(void) GetNumbers(WinComDataPtr wcd) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; /* As the user might set wrong min and/or max. we'll better check them */ CheckLimits(wcd,0); /* Abscissa */ CheckLimits(wcd,1); /* Ordinate */ gd->DeltaX=(gd->Slate.right-1+HOFF-gd->Slate.left)/ (gd->RAxis[0].Max-gd->RAxis[0].Min); gd->DeltaY=(gd->Slate.top-gd->Slate.bottom+1-VOFF)/ (gd->RAxis[1].Max-gd->RAxis[1].Min); } /* Converts mathematical coordinates to window coordinates */ #define SM 20 Local(Int2) MathToWinX(FloatHi x, GraphicDataPtr gd) { FloatHi d; d=gd->Slate.left+gd->DeltaX*(x-gd->RAxis[0].Min); if (dSlate.left-SM; if (d>INT2_MAX) d=gd->Slate.right+SM; return round(d); } Local(Int2) MathToWinY(FloatHi y, GraphicDataPtr gd) { FloatHi d; d=gd->Slate.bottom-1+VOFF+gd->DeltaY*(y-gd->RAxis[1].Min); if (dSlate.top-SM; if (d>INT2_MAX) d=gd->Slate.bottom+SM; return round(d); } #undef SM /* Converts window coordinates to mathematical coordinates */ Local(FloatHi) WinToMathX(Int2 x, GraphicDataPtr gd) { return gd->RAxis[0].Min+(x-gd->Slate.left)/gd->DeltaX; } Local(FloatHi) WinToMathY(Int2 y, GraphicDataPtr gd) { return gd->RAxis[1].Min+(y-gd->Slate.bottom+1-VOFF)/gd->DeltaY; } /* Makes calculations needed to draw scales */ Local(void) CalculateScales(WinComDataPtr wcd) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; FloatHi xstep,ystep,y,ymax; Int2 i,width; Boolean hc=gd->Hardcopy; /* is hardcopy requested for this window */ Char buf[50]; SelectFont(SystemFont); if (hc) { fprintf(gd->HardFile,"/GP?MW { [ 0 0 0 0]\n"); } if (gd->Axis[0].bScale) { /* horizontal */ gd->Slate.bottom-=sysLineHeight+sysDescent; if (hc) fprintf(gd->HardFile," 1 1 GPBMW\n"); } if (gd->Axis[1].bScale || gd->Axis[1].bGrid) { /* vertical */ if (gd->Axis[1].bScale) { gd->Slate.top+=sysLineHeight/2; if (hc) fprintf(gd->HardFile," 1 1 GPTMW\n"); } if (!gd->Axis[0].bScale && gd->Axis[1].bScale) { gd->Slate.bottom-=(sysLineHeight/2)+sysDescent; if (hc) fprintf(gd->HardFile," 0.5 0 GPBMW\n"); } ystep=gd->RAxis[1].Tick; if (ystep<=0 || ystep>gd->RAxis[1].Max-gd->RAxis[1].Min) ystep=ApplyArtificialIntellectY(gd->RAxis[1].Min,gd->RAxis[1].Max, gd->Slate.bottom+VOFF-gd->Slate.top); gd->RAxis[1].Step=ystep; if (gd->Axis[1].bScale) { ymax=dtos(buf,"%g",gd->RAxis[1].Max); /* round it, if necessary */ if (hc) fprintf(gd->HardFile," ["); for (width=i=0; (y=dtos(buf,"%g",i*ystep+gd->RAxis[1].Min), y<=ymax); i++) { if (widthHardFile,"(%s)",buf); if (i>100) break; /* if ymax-ymin is very large and step is specified */ } width+=sysCharWidth/2; if (hc) fprintf(gd->HardFile,"] 0.5 GPLMW\n"); gd->Slate.left+=width; } } if (gd->Axis[0].bScale || gd->Axis[0].bGrid) { /* horizontal */ if (gd->Axis[0].bScale) { sprintf(buf,"%g",gd->RAxis[0].Max); gd->Slate.right-=(StringWidth(buf)>>1)+(sysCharWidth/4); if (hc) fprintf(gd->HardFile," [(%s)] 0.25 GPRMW\n",buf); if (!gd->Axis[1].bScale) { sprintf(buf,"%g",gd->RAxis[0].Min); gd->Slate.left+=(StringWidth(buf)>>1)+(sysCharWidth/4); if (hc) fprintf(gd->HardFile," [(%s)] 0.25 GPLMW\n",buf); } else { gd->Slate.bottom-=0.5*sysLineHeight-sysDescent; if (hc) fprintf(gd->HardFile," 0.5 0 GPBMW\n"); } } xstep=gd->RAxis[0].Tick; if (xstep<=0 || xstep>gd->RAxis[0].Max-gd->RAxis[0].Min) xstep=ApplyArtificialIntellectX(gd->RAxis[0].Min,gd->RAxis[0].Max, gd->Slate.right-gd->Slate.left); gd->RAxis[0].Step=xstep; } gd->Slate.right--; gd->Slate.right+=HOFF; gd->Slate.bottom--; gd->Slate.bottom+=VOFF; /* Windows coordinates of drawing rectangle */ gd->ix_min=MathToWinX(gd->RAxis[0].Min,gd); gd->ix_max=MathToWinX(gd->RAxis[0].Max,gd); gd->iy_min=MathToWinY(gd->RAxis[1].Min,gd); gd->iy_max=MathToWinY(gd->RAxis[1].Max,gd); if (hc) { fprintf(gd->HardFile," } bind def\n/GP?M GP?MW def\n\n"); } } #undef HOFF #undef VOFF Local(void) lRefreshScale(WinComDataPtr wcd) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Select(gd->paPanel); /* Recalulate scales */ GetPosition(gd->paPanel,&gd->Slate); CalculateScales(wcd); /* Update panel */ Redraw(gd->paPanel); } /* Refresh scales after user pressed invisible DefaultButton */ Callback(void) RefreshScale(ButtoN b) { WinComDataPtr wcd=GetComDataC(b); lRefreshScale(wcd); UndoRecord(wcd); } Callback(void) ActProc(TexT t) { SetTitle(t,""); /* ignore everything */ } Callback(void) SelectProc(TexT t) { size_t l; l=TextLength(t); SelectText(t,(Int2)l,(Int2)l); } /* Limits SpeedBar common callback */ Callback(void) LimitsProc(TexT t) { WinComDataPtr wcd=GetComDataC(t); GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Int2 i,j; for (i=0; iteAxis); i++) for (j=0; jteAxis[i].teLimits); j++) if (t==gd->teAxis[i].teLimits[j]) { GetTitleAndSave(t,&gd->Axis[i].pText[j]); GetNumbers(wcd); return; } } /* Get rectangle surrounding axis's lable and draw it */ Local(void) DrawLabel(WinComDataPtr wcd, Int2 axis, RectPtr pr) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; #define MAXCHAR (Int2)50 RecT r; CharPtr p; Int2 width; Char c; Boolean hc=gd->Hardcopy; /* Hardcopy */ SelectFont(SystemFont); if (!pr) pr=&r; p=gd->Axis[axis].Funcs[gd->FuncCur].pFunc; width=(StrLen(p)<=MAXCHAR) ? StringWidth(p) : TextWidth(p,MAXCHAR); if (axis==0) { /* abs */ LoadRect(pr,gd->ix_max-width,gd->iy_min-sysLineHeight, gd->ix_max,gd->iy_min); OffsetRect(pr,-(sysCharWidth/2),-(sysLineHeight/2)+sysDescent); } else { /* ord */ LoadRect(pr,gd->ix_min,gd->iy_max, gd->ix_min+width,gd->iy_max+sysLineHeight); OffsetRect(pr,(sysCharWidth/2),sysDescent); } if (StrLen(p)>MAXCHAR) { c=p[MAXCHAR]; p[MAXCHAR]='\0'; } else c='\0'; ColorSet((gd->FuncNum?gd->Attr:gd->SaveAttr)[gd->FuncCur].Point.color); lString(pr->left,pr->bottom-sysDescent,p); if (hc) fprintf(gd->HardFile,"(%s) G%cL\n",p,"XY"[axis]); if (c) p[MAXCHAR]=c; #undef MAXCHAR } /* Redraws labels */ Local(void) RedrawLabels(WinComDataPtr wcd, Int2 incr) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; RecT rold[2],rnew; Int2 i; Select(gd->paPanel); for (i=0; i<2; i++) DrawLabel(wcd,i,rold+i); gd->FuncCur+=incr; for (i=0; i<2; i++) { DrawLabel(wcd,i,&rnew); UnionRect(&rnew,rold+i,&rnew); InvalRect(&rnew); } Update(); } /*----------------------------------------------*/ /* Palette SpeedBar support (in Graphic window) */ #if MYSWITCH Callback(void) PalNumProc(GraphiC sw, Int2 newval, Int2 oldval) { #else Callback(void) PalNumProc(SwitcH sw, Int2 newval, Int2 oldval) { #endif WinComDataPtr wcd=GetComDataC(sw); GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; RedrawLabels(wcd,newval-oldval); Redraw(gd->paSample); } /* Draw palette */ Callback(void) PalDrawProc(PaneL pnl) { RecT r; Int2 w,i,n; Select(pnl); GetPosition(pnl,&r); n=ColorNumber(); if (!(w=(r.right-r.left)/n)) w=1; for (i=0; iPrivate; FuncAttr Attr; RecT r; Color col; Select(pnl); GetPosition(pnl,&r); col=floor((pt.x-r.left)/((r.right-r.left)/ColorNumber())); Attr=gd->Attr[gd->FuncCur]; /* to simplify */ if (Attr.Trace.style>0 && Attr.Trace.color==Attr.Point.color) Attr.Trace.color=col; if (Attr.Path.style>0 && Attr.Path.color==Attr.Point.color) Attr.Path.color=col; Attr.Point.color=col; gd->Attr[gd->FuncCur]=Attr; Redraw(gd->paSample); } Callback(void) PalSampProc(PaneL pnl) { WinComDataPtr wcd=GetComDataC(pnl); GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; RecT r; Select(pnl); GetPosition(pnl,&r); ColorSet(gd->Attr[gd->FuncCur].Point.color); PaintRect(&r); } /*-----------------------------------------------------*/ /* Graphic panel callbacks: draw, click, drag, release */ Callback(void) DrawProc(PaneL panel) { WinComDataPtr wcd=GetComDataC(panel); GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; FloatHi x,y,xmax,ymax; DrawAttr attr; RecT r,rr; Int2 i,j,ix,iy,ix_min,ix_max,iy_min,iy_max; Boolean scale; Boolean hc; /* is hardcopy requested for this window */ Char buf[50]; Select(panel); #ifdef INENTRYX /* Always draw ==> never return! */ /* Were we asked to ignore? */ if (wcd->flags&WFL_DONT_REDRAW) { /* Yes, we were */ return; } #endif #if _WIN /* Windows NT: without this doesn't redraw the whole panel after resize */ if (wcd->flags&WFL_RESIZE) ResetClip(); #endif /* _WIN */ /* To block fetching and dispatching Expose events for other panels in the window caused by call to Disable/Enable made from GetNumbers() */ ProcessUpdatesFirst(FALSE); SelectFont(SystemFont); hc=gd->Hardcopy; scale=!(gd->flags&DONT_SCALE); if (scale) { GetPosition(panel,&gd->Slate); /* first GetNumbers&CalculateScales call does not take into account scales, if any */ GetNumbers(wcd); CalculateScales(wcd); GetNumbers(wcd); GetPosition(panel,&gd->Slate); CalculateScales(wcd); } ix_min=gd->ix_min; ix_max=gd->ix_max; iy_min=gd->iy_min; iy_max=gd->iy_max; /* Clear the panel */ ColorSet(wcd->Background); GetPosition(panel,&r); PaintRect(&r); InvertColors(); attr.width=1; attr.style=1; /* solid */ attr.color=wcd->Foreground; SetCurrentPen(&attr); /* Draw horizontal scale */ if (gd->Axis[0].bScale || gd->Axis[0].bGrid) { /* horizontal */ xmax=dtos(buf,"%g",gd->RAxis[0].Max); /* round it, if necessary */ j=iy_min+(gd->Axis[1].bScale ? 1.5*sysLineHeight-sysDescent : sysLineHeight); if (hc) { y=dtos(buf,"%g",gd->RAxis[1].Min); /* round it, if necessary */ } for (i=0; (x=dtos(buf,"%g",i*gd->RAxis[0].Step+gd->RAxis[0].Min),x<=xmax); i++) { ix=MathToWinX(x,gd); if (gd->Axis[0].bGrid && i) { if (hc) { fprintf(gd->HardFile,"%g GXG\n",x); } #if _UNIX SetPenDash(0,1,3); lLine(ix,iy_max,ix,iy_min); Solid(); #else LoadRect(&rr,ix,iy_max,ix+1,iy_min+1); #if _WIN /* Prevent CopyBits from crash */ if (iy_min>iy_max) #endif CopyBits(&rr,gd->GridVert); #endif } if (gd->Axis[0].bScale) { lString(ix-(StringWidth(buf)>>1),j,buf); lLine(ix,iy_min-(sysCharWidth/2),ix,iy_min); if (hc) { fprintf(gd->HardFile,gd->Axis[1].bScale ? "1.5 1" : " 1 1"); fprintf(gd->HardFile,"(%s) %g %g GXS\n",buf,x,y); } } if (i>100) break; /* if xmax-xmin is very large and step is specified */ } } /* Draw vertcial scale */ if (gd->Axis[1].bScale || gd->Axis[1].bGrid) { /* vertical */ GetPosition(panel,&r); ymax=dtos(buf,"%g",gd->RAxis[1].Max); /* round it, if necessary */ if (hc) { x=dtos(buf,"%g",gd->RAxis[0].Min); /* round it, if necessary */ } for (i=0; (y=dtos(buf,"%g",i*gd->RAxis[1].Step+gd->RAxis[1].Min),y<=ymax); i++) { iy=MathToWinY(y,gd); if (gd->Axis[1].bGrid && i) { if (hc) { fprintf(gd->HardFile,"%g GYG\n",y); } #if _UNIX SetPenDash(3,1,3); lLine(ix_min,iy,ix_max,iy); Solid(); #else LoadRect(&rr,ix_min,iy,ix_max+1,iy+1); #if _WIN /* Prevent CopyBits from crash */ if (ix_max>ix_min) #endif CopyBits(&rr,gd->GridHor); #endif } if (gd->Axis[1].bScale) { lString(gd->Slate.left-StringWidth(buf)-(sysCharWidth/4), iy+(sysAscent>>1),buf); lLine(ix_min,iy,ix_min+(sysCharWidth/2),iy); if (hc) { fprintf(gd->HardFile,"0.5 (%s) %g %g GYS\n",buf,x,y); } } if (i>100) break; /* if ymax-ymin is very large and step is specified */ } } /* Draw axes */ if (gd->Axis[0].bAxis) if (gd->RAxis[1].Min*gd->RAxis[1].Max<0) { i=MathToWinY(0,gd); lLine(ix_min,i,ix_max,i); if (hc) fprintf(gd->HardFile,"GXA\n"); } if (gd->Axis[1].bAxis) if (gd->RAxis[0].Min*gd->RAxis[0].Max<0) { j=MathToWinX(0,gd); lLine(j,iy_min,j,iy_max); if (hc) fprintf(gd->HardFile,"GYA\n"); } /* Draw frame */ FrameRect(&gd->Slate); if (hc) fprintf(gd->HardFile,"GFRAME\n\n"); /* Axes names for abs and ord */ for (i=0; iAxis); i++) if (gd->Axis[i].bFunc) DrawLabel(wcd,i,NULL); /* Draw the unit circle */ if (gd->Options.Flags&GWIN_CIRCLE) { ClipRect(&gd->Slate); LoadRect(&rr,MathToWinX(-1.0,gd),MathToWinY(-1.0,gd), MathToWinX(1.0,gd)+1,MathToWinY(1.0,gd)+1); FrameOval(&rr); if (hc) fprintf(gd->HardFile,"GUNITCIRCLE\n\n"); ResetClip(); } ProcessUpdatesFirst(TRUE); } Local(void) DrawMarqueeRect(PaneL panel) { WinComDataPtr wcd=GetComDataC(panel); GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; RecT r,mr; Select(panel); LoadRect(&r,gd->ptClick.x,gd->ptClick.y,gd->ptLast.x,gd->ptLast.y); SectRect(&r,&gd->Slate,&mr); ColorSet(wcd->Foreground); FrameRect(&mr); } Callback(void) ClickProc(PaneL panel, PoinT pt) { WinComDataPtr wcd=GetComDataC(panel); GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; if (ccd.Computing) { /* Computing is in progress - ignore */ gd->ptClick.x=-100; return; } if (PtInRect(pt,&gd->Slate)) { gd->ptClick=pt; gd->bDrag=FALSE; } else gd->ptClick.x=-100; } Callback(void) DragProc(PaneL panel, PoinT pt) { WinComDataPtr wcd=GetComDataC(panel); GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; FloatHi f[2]; Int2 i; Char buf[20]; if (gd->ptClick.x<0) return; /* This check ensures a call was made not due to activating the window by mouse (Windows: if another window is active then the first mouse click results to call to drag callback) */ if (EqualPt(pt,gd->ptClick)) return; InvertMode(); if (gd->bDrag) { DrawMarqueeRect(panel); f[0]=WinToMathX(pt.x,gd); f[1]=WinToMathY(pt.y,gd); for (i=0; i<2; i++) if (gd->Axis[i].bLimits) { sprintf(buf,"%g",f[i]); SetTitle(gd->teAxis[i].teLimits[1],buf); } } else { gd->bDrag=TRUE; f[0]=WinToMathX(gd->ptClick.x,gd); f[1]=WinToMathY(gd->ptClick.y,gd); for (i=0; i<2; i++) if (gd->Axis[i].bLimits) { sprintf(buf,"%g",f[i]); SetTitle(gd->teAxis[i].teLimits[0],buf); } } gd->ptLast=pt; DrawMarqueeRect(panel); } Callback(void) ReleaseProc(PaneL panel, PoinT pt) { WinComDataPtr wcd=GetComDataC(panel); GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; FloatHi mi,ma,x; FilePtr curvePtr; FloatHiPtr vp; Int2 spNum; PoinT spCoord; Int2 i,j; Uint2 id; Uint1 loc_class; Char buf[20]; Boolean goon; if (gd->ptClick.x<0) return; /* click was outside of drawing rectangle */ if (gd->bDrag) { /* Drag was called - change scales */ InvertMode(); DrawMarqueeRect(panel); if (PtInRect(pt,&gd->Slate) && gd->ptClick.x!=pt.x && gd->ptClick.y!=pt.y ) { /* Change limits */ if (gd->ptClick.x>pt.x) { i=pt.x; pt.x=gd->ptClick.x; gd->ptClick.x=i; } if (gd->ptClick.yptClick.y; gd->ptClick.y=i; } mi=WinToMathX(gd->ptClick.x,gd); ma=WinToMathX(pt.x,gd); gd->RAxis[0].Min=mi; gd->RAxis[0].Max=ma; mi=WinToMathY(gd->ptClick.y,gd); ma=WinToMathY(pt.y,gd); gd->RAxis[1].Min=mi; gd->RAxis[1].Max=ma; for (i=0; i<2; i++) { for (j=0; j<2; j++) { sprintf(buf,"%g",gd->RAxis[i].Limits[j]); MemFree(gd->Axis[i].pText[j]); gd->Axis[i].pText[j]=StringSave(buf); } if (gd->Axis[i].bLimits) for (j=0; j<2; j++) SetTitle(gd->teAxis[i].teLimits[j], gd->Axis[i].pText[j]); } RefreshScale(gd->buRefr); } else { /* Release outside the Slate, don't change */ for (i=0; i<2; i++) if (gd->Axis[i].bLimits) for (j=0; j<2; j++) SetTitle(gd->teAxis[i].teLimits[j], gd->Axis[i].pText[j]); } } else { /* Click-Hold-Release at the same place - select a point */ /* 1. Look if a special point was pointed out */ BSSeek(gd->SpecialPoints,0,SEEK_SET); goon=TRUE; while (goon && BSRead(gd->SpecialPoints,&curvePtr,sizeof(curvePtr))) { while (goon) { BSRead(gd->SpecialPoints,&spNum,sizeof(spNum)); if (spNum==-1) break; BSRead(gd->SpecialPoints,&spCoord,sizeof(spCoord)); if (PtNearSpecial(pt,spCoord)) goon=FALSE; } } BSSeek(gd->SpecialPoints,0,SEEK_END); if (!goon) { if (SetSpecialPoint(curvePtr,spNum)) return; } /* 2. Try to set coordinates of initial point */ if (FBStatus(-1) && gd->flags&MOUSE_PICK) if (gd->FuncNum==1) { goon=TRUE; for (i=0; iAxis); i++) if (gd->Axis[i].Funcs[0].FuncKind==0) { switch(i) { case 0: x=WinToMathX(pt.x,gd); break; case 1: x=WinToMathY(pt.y,gd); break; } /*** loc_class=ClassGlobToLoc(ClassPtr[gd->Axis[i].Funcs[0].Func.Simple.IndirectIndex].Id);***/ loc_class=0; if (GetClassNameAndId(gd->Axis[i].Funcs[0].Func.Simple.IndirectIndex,NULL,&id)) loc_class=ClassGlobToLoc(id); if (loc_class) { vp=GetLocalClassVector(loc_class); if (vp) { vp=(FloatHiPtr)((CharPtr)vp+gd->Axis[i].Funcs[0].Func.Simple.Offset); *vp=x; goon=FALSE; } } } if (!goon) { gd->ptClick.x=-1; /* WIN NT: prevent recursive call */ UpdateInitPoint(); InvalidateBifData(); LockMenus(); if (gd->flags&MOUSE_IMMF) Forward(0); if (gd->flags&MOUSE_IMMB) Backward(0); UnlockMenus(); return; } } Beep(); } } #if _UNIX #else /* Bitmaps for grids */ Local(void) BuildGrids(GraphicDataPtr gd) { Int2 i,len; /* Vibrant documentation requires width to be in multiples of 2 bytes, but 1 also works */ #define VIB_MULT 1 len=VIB_MULT*(screenRect.bottom-screenRect.top); gd->GridVert=MemNew(len); for (i=0; iGridVert[i]=0x80; #undef VIB_MULT len=(screenRect.right-screenRect.left)/BITSPERBYTE+1; gd->GridHor=MemNew(len); MemFill(gd->GridHor,0x11,len); /* the leftmost bit must be 0 */ } Local(void) FreeGrids(GraphicDataPtr gd) { MemFree(gd->GridVert); MemFree(gd->GridHor); } #endif /* _UNIX */ Local(void) SetCallbacks(GraphicDataPtr gd, Boolean set) { if (set) SetPanelClick(gd->paPanel,ClickProc,DragProc,NULL,ReleaseProc); else SetPanelClick(gd->paPanel,NULL,NULL,NULL,NULL); } ClassMember(void) CreateControls(WinComDataPtr wcd) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; WindoW w; TexT t; RecT r; PoinT pt,pt1; PaneL pnl; int numwidth; Int2 i,j,width,width1,panelw,panelh; w=wcd->Win; /* Create a button that refreshes scales and place it outside the panel */ /* Then create a DialogText to allow keyboard input during computations and in suspend mode (see GraphicGInt) */ GetNextPosition(w,&pt); LoadPt(&pt1,-100,-100); SetNextPosition(w,pt1); gd->buRefr=DefaultButton(w,"",RefreshScale); gd->teAct=HiddenText(w,"",1,ActProc,NULL,NULL); Hide(gd->teAct); #if _WIN #ifdef WIN32 pt.y++; #else pt.y--; #endif #endif SetNextPosition(w,pt); /* Sizes */ panelw=wcd->Width; panelh=wcd->Height; /* Create Limits SpeedBar */ for (i=0; iAxis); i++) { gd->teAxis[i].prompt=NULL; for (j=0; jteAxis[0].teLimits); j++) gd->teAxis[i].teLimits[j]=NULL; } if (gd->Axis[0].bLimits | gd->Axis[1].bLimits) { gd->grLimits=CreateHiddenGroup(w,20,0,0); SetGroupMargins(gd->grLimits,sysCharWidth/2,0); SetGroupSpacing(gd->grLimits,3,0); sscanf(GetParamString(SECTION,"NUMWIDTH"),"%i",&numwidth); for (i=0; iAxis); i++) if (gd->Axis[i].bLimits) { /* Width of Abs/Ord prompt. Load approp prompt and calc its len */ width=StringWidth(Text[ABS_P]); width1=StringWidth(Text[ORD_P]); width=MAX(width,width1); /* make a break if there is no room for ordinate's controls */ if (i) { GetPosition(gd->grLimits,&r); if (2*sysCharWidth+(r.right-r.left)+ width+ 2*numwidth*sysCharWidth+StringWidth("..")+ (gd->Axis[i].bTick ? StringWidth(":")+numwidth*sysCharWidth : 0) > panelw ) Break(gd->grLimits); } /* Abs/Ord prompt */ gd->teAxis[i].prompt= StaticPrompt(gd->grLimits,Text[i ? ORD_P : ABS_P],width,dialogTextHeight,NULL,'l'); /* Min */ t=DialogText(gd->grLimits,gd->Axis[i].pMin,numwidth,LimitsProc); SetTextSelect(t,SelectProc,NULL); gd->teAxis[i].teLimits[0]=t; /* .. */ StaticPrompt(gd->grLimits,"..",0,dialogTextHeight,NULL,'l'); /* Max */ t=DialogText(gd->grLimits,gd->Axis[i].pMax,numwidth,LimitsProc); SetTextSelect(t,SelectProc,NULL); gd->teAxis[i].teLimits[1]=t; /* NO func */ /* Tick */ if (gd->Axis[i].bTick) { /* : */ StaticPrompt(gd->grLimits,":",0,dialogTextHeight,NULL,'l'); t=DialogText(gd->grLimits,gd->Axis[i].pTick,numwidth,LimitsProc); SetTextSelect(t,SelectProc,NULL); gd->teAxis[i].teLimits[3]=t; } } GetPosition(gd->grLimits,&r); panelh-=r.bottom-r.top; } else gd->grLimits=NULL; /* Create Palette SpeedBar */ if (gd->Options.Flags&GWIN_PALETTE) { gd->grPalette=CreateHiddenGroup(w,20,0,0); SetGroupMargins(gd->grPalette,sysCharWidth/2,0); SetGroupSpacing(gd->grPalette,sysCharWidth/2,0); if (gd->FuncNum>1) { #if MYSWITCH gd->swNum=SwitchCreate(gd->grPalette,gd->FuncNum,PalNumProc); SwitchSetValue(gd->swNum,gd->FuncCur+1); Redraw(gd->swNum); #else gd->swNum=LeftRightSwitch(gd->grPalette,TRUE,PalNumProc); SetSwitchParams(gd->swNum,gd->FuncCur+1,gd->FuncNum); #endif GetPosition(gd->grPalette,&r); /* current width of the group */ } else LoadRect(&r,0,0,0,sysLineHeight); pnl=SimplePanel(gd->grPalette,panelw-(r.right-r.left)-2*sysCharWidth,r.bottom-r.top,PalDrawProc); Redraw(pnl); SetPanelClick(pnl,PalSelProc,NULL,NULL,NULL); gd->paSample=SimplePanel(gd->grPalette,sysCharWidth,r.bottom-r.top,PalSampProc); Redraw(gd->paSample); GetPosition(gd->grPalette,&r); panelh-=r.bottom-r.top+1; } else gd->grPalette=NULL; /* Compute dimensions of drawing rectangle in a panel (will be created later) */ GetNextPosition(w,&pt); LoadRect(&gd->Slate,pt.x,pt.y,pt.x+panelw-1,pt.y+panelh-1); #if _UNIX /* no bitmaps, SetPenDash is used */ #else BuildGrids(gd); #endif /* _UNIX */ /* Process Scale */ /* first GetNumbers&CalculateScales call does not take scales into account, if any */ r=gd->Slate; GetNumbers(wcd); CalculateScales(wcd); GetNumbers(wcd); gd->Slate=r; CalculateScales(wcd); /* Create panel for drawing */ gd->paPanel=SimplePanel(w,panelw,panelh,DrawProc); SetCallbacks(gd,TRUE); Redraw(gd->paPanel); gd->InitLevel=0; UndoRecord(wcd); } ClassMember(void) RemoveControls(WinComDataPtr wcd) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Hide(gd->grLimits); Hide(gd->grPalette); Remove(gd->buRefr); Remove(gd->teAct); Remove(gd->grLimits); Remove(gd->grPalette); Remove(gd->paPanel); #if _UNIX #else FreeGrids(gd); #endif } #if _WIN #pragma argsused #endif ClassMember(void) ManageControls(WinComDataPtr wcd, Boolean enable) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; (enable ? Enable : Disable)(gd->grLimits); (enable ? Enable : Disable)(gd->grPalette); /* Don't Enable/Disable gd->paPanel to avoid multiple redraws after Enable */ SetCallbacks(gd,enable); } ClassMember(void) BuildMenu(WinComDataPtr wcd) { MenuItemPtr ip; Int2 i; wcd->MenuDesc.Menu=ip=MemNew(sizeof(GraphicMenu)); wcd->MenuDesc.Num=DIM(GraphicMenu); wcd->MenuDesc.Lock=0; wcd->MenuDesc.Texts=Text; MemCopy(ip,GraphicMenu,sizeof(GraphicMenu)); for (i=0; iMenuDesc.Num; i++) { if (ip[i].Title==FORWARD_I) { ip[i].Action=Forward; ip[i].EnableDisable=FBStatus; continue; } if (ip[i].Title==BACKWARD_I) { ip[i].Action=Backward; ip[i].EnableDisable=FBStatus; continue; } if (ip[i].Title==EXTEND_I) { ip[i].Action=Extend; ip[i].EnableDisable=ExtendStatus; continue; } if (ip[i].Title==REDRAWD_I) { /*** ip[i].Action=RedrawDiagram;***/ ip[i].EnableDisable=RedrawDStatus; continue; } if (ip[i].Title==REDRAWC_I) { /*** ip[i].Action=RedrawCurve;***/ ip[i].EnableDisable=RedrawCStatus; continue; } if (ip[i].Title==FITD_I) { ip[i].EnableDisable=RedrawDStatus; continue; } if (ip[i].Title==FITC_I) { ip[i].EnableDisable=RedrawCStatus; continue; } if (ip[i].Title==HARDCOPY_I) { ip[i].EnableDisable=HardcopyStatus; continue; } if (ip[i].Title==HIDE_I) { ip[i].Action=HideWin; continue; } if (ip[i].Title==CURVEATR_I) { ip[i].EnableDisable=ExtendStatus; continue; } } } #if _WIN #pragma argsused #endif ClassMember(void) NewInitPoint(WinComDataPtr wcd) { /* nothing */ } ClassMember(void) ClearWindow(WinComDataPtr wcd) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Redraw(gd->paPanel); BSFree(gd->SpecialPoints); gd->SpecialPoints=BSNew(0); UndoRecord(wcd); } ClassMember(Boolean) SimpleFunctions(WinComDataPtr wcd) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Int2 i,j; Boolean res=TRUE,gdim1=TRUE; for (i=0; iAxis); i++) for (j=0; jFuncNum; j++) { if (res && !ParseName(gd->Axis[i].Funcs[j].pFunc,NULL,NULL)) res=FALSE; gd->Axis[i].Funcs[j].Gdim=GdimEq1(gd->Axis[i].Funcs[j].pFunc); if (!gd->Axis[i].Funcs[j].Gdim) gdim1=FALSE; } if (gdim1) wcd->flags|=WFL_GDIM1; else wcd->flags&=~WFL_GDIM1; return res; } Local(void) WinFuncName(CharPtr buf, int axis, int funcnum, Uint1 unique) { sprintf(buf,"_%c%i_%i","ao"[axis],funcnum,(int)unique); } ClassMember(void) PutFunctions(WinComDataPtr wcd, FILE PNTR Source, Int2Ptr LineNum) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; CharPtr p; int i,j; Char buf[15]; for (i=0; iAxis); i++) for (j=0; jFuncNum; j++) if (!ParseName(gd->Axis[i].Funcs[j].pFunc,NULL,NULL)) { WinFuncName(buf,i,j,wcd->Unique); SetParam("TMP","TMP",WIN_HEAD); /* Force replacement */ p=GetParamString("TMP","TMP"); /* of symbolical references */ p=(CharPtr)TSPrintf(p,buf); /* func name */ fputs(CountLinesAndErase_r(p,'\n',LineNum),Source); fputs(gd->Axis[i].Funcs[j].pFunc,Source); SetParam("TMP","TMP",WIN_TAIL); /* Force replacement */ p=GetParamString("TMP","TMP"); /* of symbolical references */ fputs(CountLinesAndErase_r(p,'\n',LineNum),Source); } } ClassMember(void) SetFunctions(WinComDataPtr wcd, LibHandle hWinLib) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; int i,j; Char buf[15]; for (i=0; iAxis); i++) for (j=0; jFuncNum; j++) if (ParseName(gd->Axis[i].Funcs[j].pFunc, &gd->Axis[i].Funcs[j].Func.Simple.IndirectIndex, &gd->Axis[i].Funcs[j].Func.Simple.Offset)) { gd->Axis[i].Funcs[j].FuncKind=0; } else { gd->Axis[i].Funcs[j].FuncKind=1; /*** sprintf(buf,"_%c%i_%i","ao"[i],j,(int)pwd->Unique);***/ WinFuncName(buf,i,j,wcd->Unique); gd->Axis[i].Funcs[j].Func.General.FloatFunc=hWinLib ? (WinFloatValue)LibraryFuncAddress(hWinLib,buf) : NULL; } } ClassMember(void) ExportDescription(WinComDataPtr wcd, DataLibPtr arch, FILE PNTR out) { GraphicDataPtr gd; Int2 i,j; ReadDescription(wcd,arch); /* also allocates private data area */ gd=(GraphicDataPtr)wcd->Private; fprintf(out," func=%i cur=%i\n",(int)gd->FuncNum,(int)gd->FuncCur); for (i=0; iAxis); i++) { for (j=0; jAxis[i].pText); j++) if (!FuncIndex(j)) fprintf(out," %s\n",gd->Axis[i].pText[j]); for (j=0; jFuncNum; j++) fprintf(out," %s\n", gd->Axis[i].Funcs[j].pFunc); fprintf(out," "); for (j=0; jAxis[i].Prop); j++) fprintf(out,"%i ",(int)gd->Axis[i].Prop[j]); fprintf(out,"\n"); } for (i=0; iFuncNum; i++) { fprintf(out," point=(%li,%i,%i) trace=(%li,%i,%i) path=(%li,%i,%i)\n", ColorOut(gd->Attr[i].Point.color),(int)gd->Attr[i].Point.width,(int)gd->Attr[i].Point.style, ColorOut(gd->Attr[i].Trace.color),(int)gd->Attr[i].Trace.width,(int)gd->Attr[i].Trace.style, ColorOut(gd->Attr[i].Path.color),(int)gd->Attr[i].Path.width,(int)gd->Attr[i].Path.style); } fprintf(out," options=(%li,%i,%i,%i,%i)\n", ColorOut(gd->Options.Shift.color), (int)gd->Options.Shift.width, (int)gd->Options.Shift.style, (int)gd->Options.Flags, (int)gd->Options.Reserve); fprintf(out," undo=%i\n",(int)gd->UndoNum); for (i=0; iUndoNum; i++) fprintf(out," %g %g %g %g\n",gd->UndoBuf[i].xMin,gd->UndoBuf[i].xMax, gd->UndoBuf[i].yMin,gd->UndoBuf[i].yMax); WriteDescription(wcd,NULL); /* free mem only */ MemFree(gd); } ClassMember(void) ImportDescription(WinComDataPtr wcd, DataLibPtr arch, FILE PNTR in) { GraphicData gd; long col1,col2,col3; int i1,i2,i3,j1,j2,j3,k2,k3; Int2 i,j; Char buf[PAR_BUF]; MemFill(&gd,0,sizeof(gd)); wcd->Private=&gd; fscanf(in," func=%i cur=%i\n",&i1,&i2); gd.FuncNum=(Int2)i1; gd.FuncCur=(Int2)i2; for (i=0; iPrivate; Int2 funcnum; Int2 i; DrawAttr Point,Trace,Path; if (from) BSRead(from,&funcnum,sizeof(funcnum)); else funcnum=gd->FuncNum; if (to) BSWrite(to,&funcnum,sizeof(funcnum)); else DataLibWrite(dgm,(CharPtr)&funcnum,sizeof(funcnum)); for (i=0; iAttr[i].Point; Trace=gd->Attr[i].Trace; Path=gd->Attr[i].Path; } if (to) { BSWrite(to,&Point,sizeof(Point)); BSWrite(to,&Trace,sizeof(Trace)); BSWrite(to,&Path,sizeof(Path)); } else { DataLibWrite(dgm,(CharPtr)&Point,sizeof(Point)); DataLibWrite(dgm,(CharPtr)&Trace,sizeof(Trace)); DataLibWrite(dgm,(CharPtr)&Path,sizeof(Path)); } } if (!from && freemem) { gd->Attr=MemFree(gd->Attr); gd->FuncNum=0; } } ClassMember(void) RestoreAttr(WinComDataPtr wcd, DataLibPtr dgm, ByteStorePtr from, ByteStorePtr to, Boolean skip) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; DrawAttr Point,Trace,Path; Int2 i,n; if (from) BSRead(from,&n,sizeof(gd->FuncNum)); else DataLibRead(dgm,(CharPtr)&n,sizeof(gd->FuncNum)); /* no of attr stored */ if (!skip && !to && !gd->FuncNum) { gd->Attr=MemNew(ARRAYSIZE(FuncAttr,n)); gd->FuncNum=n; } if (to) BSWrite(to,&n,sizeof(gd->FuncNum)); for (i=0; iFuncNum) { gd->Attr[i].Point=Point; if (gd->Attr[i].Trace.style<=0 && Trace.style>0) { /* Switching from "don't join" to "join" */ gd->joinpath=TRUE; } gd->Attr[i].Trace=Trace; if (gd->Attr[i].Path.style<=0 && Path.style>0) { /* Switching from "don't join" to "join" */ gd->Attr[i].flags|=PATH_CHANGE; gd->joinpath=TRUE; } gd->Attr[i].Path=Path; } } } #if _WIN #pragma argsused #endif ClassMember(void) ExportAttr(WinComDataPtr wcd, DataLibPtr dgm, FILE PNTR out) { DrawAttr Point,Trace,Path; Int2 i,n; DataLibRead(dgm,(CharPtr)&n,sizeof(n)); /* no of attr stored */ fprintf(out," %i:\n",(int)n); for (i=0; iPrivate; gd->SaveFuncNum=gd->FuncNum; gd->SaveAttr=MemNew(ARRAYSIZE(FuncAttr,gd->FuncNum)); MemCopy(gd->SaveAttr,gd->Attr,ARRAYSIZE(FuncAttr,gd->FuncNum)); if (freemem) { gd->Attr=MemFree(gd->Attr); gd->FuncNum=0; } } ClassMember(void) PopAttr(WinComDataPtr wcd) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; MemFree(gd->Attr); gd->FuncNum=gd->SaveFuncNum; gd->Attr=MemNew(ARRAYSIZE(FuncAttr,gd->FuncNum)); MemCopy(gd->Attr,gd->SaveAttr,ARRAYSIZE(FuncAttr,gd->FuncNum)); MemFree(gd->SaveAttr); } ClassMember(void) SpecialAction(WinComDataPtr wcd, VisualSpecAction vsa) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; FloatHi x[2]; Int2 i,j,ix,iy; RecT r; DrawAttr attr; Select(gd->paPanel); for (j=0; jFuncNum; j++) switch (vsa) { case VSA_RESET: gd->Axis[0].Funcs[j].Eip=gd->Axis[1].Funcs[j].Eip=0; break; case VSA_ERASE: if (gd->Axis[0].Funcs[j].Eip+gd->Axis[1].Funcs[j].Eip==0) break; ix=gd->Axis[0].Funcs[j].Eip; iy=gd->Axis[1].Funcs[j].Eip; gd->Axis[0].Funcs[j].Eip= gd->Axis[1].Funcs[j].Eip=0; goto draw; case VSA_DRAW: /* Compute functions along axes and convert their values to window coordinates */ for (i=0; iRAxis); i++) if (gd->Axis[i].Funcs[j].FuncKind) /* function */ x[i]=gd->Axis[i].Funcs[j].Func.General.FloatFunc(IndirectValues); else /* simple */ x[i]=*(FloatHiPtr)((CharPtr)*IndirectValues[gd->Axis[i].Funcs[j].Func.Simple.IndirectIndex]+ gd->Axis[i].Funcs[j].Func.Simple.Offset); ix=MathToWinX(x[0],gd); iy=MathToWinY(x[1],gd); gd->Axis[0].Funcs[j].Eip=ix; gd->Axis[1].Funcs[j].Eip=iy; draw:; InvertMode(); r=gd->Slate; InsetRect(&r,1,1); ClipRect(&r); attr.width=1; attr.style=1; /* solid */ attr.color=wcd->Foreground; SetCurrentPen(&attr); lLine(r.left,iy,r.right,iy); lLine(ix,r.top,ix,r.bottom); CopyMode(); ResetClip(); break; } } ClassMember(void) FreeCurveData(WinComDataPtr wcd, FilePtr curvefp) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Int4 pos,len; ByteStorePtr bp=gd->SpecialPoints; FilePtr fp; PoinT pt; Int2 pn; BSSeek(bp,0,SEEK_SET); while (pos=BSTell(bp), BSRead(bp,&fp,len=sizeof(fp))) { while (1) { BSRead(bp,&pn,sizeof(pn)); len+=sizeof(pn); if (pn==-1) break; BSRead(bp,&pt,sizeof(pt)); len+=sizeof(pt); } if (fp==curvefp) { BSSeek(bp,pos,SEEK_SET); BSDelete(bp,len); /* Don't break here: there is/are more if the curve was extended */ } } BSSeek(bp,0,SEEK_END); } ClassMember(void) GInit(WinComDataPtr wcd) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Int2 i,j; Boolean hc=gd->Hardcopy; if (gd->flags&FIT_IN_PROGRESS) return; gd->joinpath=FALSE; for (i=0; iFuncNum; i++) { if (gd->Attr[i].Path.style>0) gd->joinpath=TRUE; /* We must always allocate memory for PrevPath&CurPath because gd->Attr[i].Path.style may be changed at a special point during a pause or while redrawing */ gd->Attr[i].PrevPath=MemNew(sizeof(PoinT)); gd->Attr[i].CurPath=MemNew(sizeof(PoinT)); gd->Attr[i].PrevNum=gd->Attr[i].CurNum=1; if (hc) { gd->Attr[i].hcPrevPath=MemNew(sizeof(MathPoint)); gd->Attr[i].hcCurPath=MemNew(sizeof(MathPoint)); } } /* Mark beginning of curve */ if (CurCurve) BSWrite(gd->SpecialPoints,&ccd.CurrentCurvePtr,sizeof(ccd.CurrentCurvePtr)); /* Disable all speed bar controls */ if (!gd->InitLevel++) { for (i=0; iteAxis); i++) for (j=0; jteAxis[i].teLimits); j++) Disable(gd->teAxis[i].teLimits[j]); Show(gd->teAct); } if (hc) fprintf(gd->HardFile,"\n%%BeginCurve: %s\n",DiagramLib.DirName); } ClassMember(void) GTerm(WinComDataPtr wcd) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Int2 i,j; Boolean hc=gd->Hardcopy; if (gd->flags&FIT_IN_PROGRESS) return; for (i=0; iFuncNum; i++) { /* See the comment in GInit */ gd->Attr[i].PrevPath=MemFree(gd->Attr[i].PrevPath); gd->Attr[i].CurPath=MemFree(gd->Attr[i].CurPath); if (hc) { gd->Attr[i].hcPrevPath=MemFree(gd->Attr[i].hcPrevPath); gd->Attr[i].hcCurPath=MemFree(gd->Attr[i].hcCurPath); } } if (CurCurve) { Int2 m1=-1; BSWrite(gd->SpecialPoints,&m1,sizeof(m1)); } /* Enable all speed bar controls */ if (!--gd->InitLevel) { for (i=0; iteAxis); i++) for (j=0; jteAxis[i].teLimits); j++) Enable(gd->teAxis[i].teLimits[j]); Hide(gd->teAct); } if (hc) fprintf(gd->HardFile,"%%EndCurve: %s\n",DiagramLib.DirName); } Local(void) GraphicSwap(GraphicDataPtr gd, Int2 i) { Int2 n; PointPtr p; p=gd->Attr[i].PrevPath; n=gd->Attr[i].PrevNum; gd->Attr[i].PrevPath=gd->Attr[i].CurPath; gd->Attr[i].PrevNum=gd->Attr[i].CurNum; gd->Attr[i].CurPath=p; gd->Attr[i].CurNum=n; if (gd->Hardcopy) { MathPointPtr p; p=gd->Attr[i].hcPrevPath; gd->Attr[i].hcPrevPath=gd->Attr[i].hcCurPath; gd->Attr[i].hcCurPath=p; } } ClassMember(void) MInit(WinComDataPtr wcd) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; RecT r; div_t divt; Int2 i; if (gd->flags&FIT_IN_PROGRESS) return; if (gd->Options.Flags&GWIN_CLEAR) { UseWindow(wcd->Win); Select(gd->paPanel); Solid(); WidePen(1); /* just for Mac and Motif */ r=gd->Slate; InsetRect(&r,1,1); ClipRect(&r); gd->flags|=DONT_SCALE; DrawProc(gd->paPanel); gd->flags&=~DONT_SCALE; } if (gd->joinpath && !(wcd->flags&WFL_G1)) { if (ccd.curveDimG*ccd.curvePrevDimG) { divt=div(MAX(ccd.curveDimG,ccd.curvePrevDimG), MIN(ccd.curveDimG,ccd.curvePrevDimG)); gd->Q=divt.quot; gd->Qs=MIN(ccd.curveDimG,ccd.curvePrevDimG)-(gd->Q1s=divt.rem); } else wcd->flags|=WFL_G1; /* don't join (as for the first M-point) */ } for (i=0; iFuncNum; i++) { if (gd->Attr[i].flags&PATH_CHANGE) GraphicSwap(gd,i); if (gd->Attr[i].Path.style>0) { if (ccd.curveDimG>gd->Attr[i].CurNum) { gd->Attr[i].CurPath=MemMore(gd->Attr[i].CurPath,ARRAYSIZE(PoinT,ccd.curveDimG)); gd->Attr[i].CurNum=ccd.curveDimG; if (gd->Hardcopy) gd->Attr[i].hcCurPath=MemMore(gd->Attr[i].hcCurPath,ARRAYSIZE(MathPoint,ccd.curveDimG)); } } } /*** gd->flags&=~PATH_CHANGE;***/ } ClassMember(void) MTerm(WinComDataPtr wcd) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Int2 i; if (gd->flags&FIT_IN_PROGRESS) return; for (i=0; iFuncNum; i++) if (gd->Attr[i].Path.style>0) { GraphicSwap(gd,i); } } Local(GraphicDataPtr) Gd; /* used only by functions called by MProcess */ Local(Boolean) CheckJoinPoints(Int2 pointNum, Int2 joinNum, Int2Ptr curLeft) { Int2 i,j; Boolean rc=FALSE; for (i=0; i=ccd.curveDimG) { if (!--*curLeft) { Gd->JoinIndex=Gd->PrevNum-1; /* JoinIndex must be in [0..ccd.curvePrevDimG-1] */ Gd->JoinNum=joinNum; rc=TRUE; } } else Gd->PrevNum++; if (ccd.curvePrevDimG>=ccd.curveDimG) Gd->PrevNum+=joinNum; else for (j=0; jJoinIndex=Gd->PrevNum-2; /* JoinIndex must be in [0..ccd.curvePrevDimG-1] */ Gd->JoinNum=1; rc=TRUE; break; } } return rc; } /* There are Qs points where Q lines fork or merge and Q1s points where Q+1 lines fork or merge */ Local(Boolean) GetJoinParams(Int2 Qs, Int2 Q1s, Int2 side, Int2Ptr curLeft) { Int2 qa,qb; /* check terminal conditions */ if (Qs==0) return CheckJoinPoints(Q1s,Gd->Q+1,curLeft); if (Q1s==0) return CheckJoinPoints(Qs,Gd->Q,curLeft); qa=Qs>>1; qb=Q1s>>1; /* left part */ if (GetJoinParams(qa,qb,0,curLeft)) return TRUE; /* in between */ if (Qs&1) if (Q1s&1) { if (CheckJoinPoints(1,Gd->Q+side,curLeft)) return TRUE; if (CheckJoinPoints(1,Gd->Q+1-side,curLeft)) return TRUE; } else { if (CheckJoinPoints(1,Gd->Q,curLeft)) return TRUE; } else if (Q1s&1) if(CheckJoinPoints(1,Gd->Q+1,curLeft)) return TRUE; /* right part */ return GetJoinParams(qa,qb,1,curLeft); } Local(FloatHi) mpt[2]; Local(void) hcLine(FloatHiPtr ptprev, FloatHiPtr pt) { fprintf(Gd->HardFile,"%g %g %g %g LINE\n",pt[0],pt[1],ptprev[0],ptprev[1]); } Local(void) hcPoint(FloatHiPtr pt) { fprintf(Gd->HardFile,"%g %g POINT\n",pt[0],pt[1]); } ClassMember(void) MProcess(WinComDataPtr wcd) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; FloatHi x[2]; RecT r; Int2 ix,iy,i,j,curNum,ox,oy; Boolean hc=gd->Hardcopy; /* TRUE if Hardcopy is in progress */ Boolean hcm; Select(gd->paPanel); r=gd->Slate; InsetRect(&r,1,1); ClipRect(&r); Gd=gd; if ((gd->flags&FIT_IN_PROGRESS)==0) if (gd->joinpath && !(wcd->flags&WFL_G1)) if (ccd.curvePrevDimG==ccd.curveDimG) { gd->JoinIndex=curveCurNum-1; gd->JoinNum=1; } else { gd->PrevNum=1; curNum=curveCurNum; GetJoinParams(gd->Qs,gd->Q1s,0,&curNum); } for (j=0; jFuncNum; j++) { /* Compute functions along axes and convert their values to window coordinates */ for (i=0; iRAxis); i++) if (gd->Axis[i].Funcs[j].FuncKind) /* function */ x[i]=gd->Axis[i].Funcs[j].Func.General.FloatFunc(IndirectValues); else /* simple */ x[i]=*(FloatHiPtr)((CharPtr)*IndirectValues[gd->Axis[i].Funcs[j].Func.Simple.IndirectIndex]+ gd->Axis[i].Funcs[j].Func.Simple.Offset); if (gd->flags&FIT_IN_PROGRESS) { for (i=0; iRAxis); i++) { if (x[i]RAxis[i].FitMin) gd->RAxis[i].FitMin=x[i]; if (x[i]>gd->RAxis[i].FitMax) gd->RAxis[i].FitMax=x[i]; } continue; } if (x[0]==NOUPDATE || x[1]==NOUPDATE) continue; ix=MathToWinX(x[0],gd); iy=MathToWinY(x[1],gd); /* Join current point with previous one(s) along a path */ if (gd->Attr[j].Path.style>0) { if (!(wcd->flags&WFL_G1) && !(gd->Attr[j].flags&PATH_CHANGE)) for (i=0; iJoinNum; i++) { SetCurrentPen(&gd->Attr[j].Path); lLine(ix,iy,ox=gd->Attr[j].PrevPath[i+gd->JoinIndex].x, oy=gd->Attr[j].PrevPath[i+gd->JoinIndex].y); if (hc) { mpt[0]=gd->Attr[j].hcPrevPath[i+gd->JoinIndex].x; mpt[1]=gd->Attr[j].hcPrevPath[i+gd->JoinIndex].y; hcLine(mpt,x); } SetCurrentPen(&gd->Attr[j].Point); if (ccd.pointPrevType) { DrawSpecialPoint(ox,oy,ccd.pointPrevType,wcd->Background,FALSE); } else { lPoint(ox,oy); if (hc) hcPoint(mpt); } } else gd->Attr[j].flags&=~PATH_CHANGE; LoadPt(gd->Attr[j].CurPath+curveCurNum-1,ix,iy); if (hc) { gd->Attr[j].hcCurPath[curveCurNum-1].x=x[0]; gd->Attr[j].hcCurPath[curveCurNum-1].y=x[1]; } } /* Join current point with the previous one along a trace */ if (gd->Attr[j].Trace.style>0 && !(wcd->flags&WFL_M1)) { SetCurrentPen(&gd->Attr[j].Trace); lLine(ix,iy,ox=gd->Axis[0].Funcs[j].Wcoord, oy=gd->Axis[1].Funcs[j].Wcoord); if (hc) { mpt[0]=gd->Axis[0].Funcs[j].hcWcoord; mpt[1]=gd->Axis[1].Funcs[j].hcWcoord; hcLine(mpt,x); } SetCurrentPen(&gd->Attr[j].Point); if (ccd.pointType && !ccd.lastPoint) { DrawSpecialPoint(ox,oy,ccd.pointType,wcd->Background,FALSE); } else { lPoint(ox,oy); if (hc) hcPoint(mpt); } } /* Join current point with the previous one along a shift */ if (gd->Options.Shift.style>0 && j) { SetCurrentPen(&gd->Options.Shift); lLine(ix,iy,ox=gd->Axis[0].Funcs[j-1].Wcoord, oy=gd->Axis[1].Funcs[j-1].Wcoord); if (hc) { mpt[0]=gd->Axis[0].Funcs[j-1].hcWcoord; mpt[1]=gd->Axis[1].Funcs[j-1].hcWcoord; hcLine(mpt,x); } SetCurrentPen(&gd->Attr[j-1].Point); if (ccd.pointType && !ccd.lastPoint) { DrawSpecialPoint(ox,oy,ccd.pointType,wcd->Background,FALSE); } else { lPoint(ox,oy); if (hc) hcPoint(mpt); } } /* Plot the current point */ SetCurrentPen(&gd->Attr[j].Point); if (ccd.pointType && !ccd.lastPoint) { if ((gd->Axis[0].Funcs[j].Gdim && gd->Axis[1].Funcs[j].Gdim) || curveCurNum==(ccd.curveDimG>>1)) SpecialPointPrev(ix-gd->Axis[0].Funcs[j].Wcoord, iy-gd->Axis[1].Funcs[j].Wcoord, x[0]-gd->Axis[0].Funcs[j].hcWcoord, x[1]-gd->Axis[1].Funcs[j].hcWcoord, gd->DeltaX, gd->DeltaY ); if (hc) { MemCopy(mpt,x,sizeof(mpt)); hcm=IsMarker(ccd.pointType); if (hcm) fprintf(gd->HardFile,"/MARKER%i {newpath\n",(int)gd->hcMarkerNo); } DrawSpecialPoint(ix,iy,ccd.pointType,wcd->Background,TRUE); if (hc) { if (hcm) fprintf(gd->HardFile,"} bind def\nMARKER%i\n",(int)gd->hcMarkerNo++); } if (CurCurve) { PoinT pt; BSWrite(gd->SpecialPoints,&ccd.CurrentSpecialPoint,sizeof(ccd.CurrentSpecialPoint)); LoadPt(&pt,ix,iy); BSWrite(gd->SpecialPoints,&pt,sizeof(pt)); } } else { lPoint(ix,iy); if (hc) hcPoint(x); } /* Store previous coordinates */ gd->Axis[0].Funcs[j].Wcoord=ix; gd->Axis[1].Funcs[j].Wcoord=iy; gd->Axis[0].Funcs[j].hcWcoord=x[0]; /* Hardcopy + SpecialPointPrec */ gd->Axis[1].Funcs[j].hcWcoord=x[1]; } } Local(void) hcSetColor(FILE PNTR hcStream, CharPtr cmd) { Uint1 r,g,b; DecodeColor(GetColor(),&r,&g,&b); fprintf(hcStream,"%g %g %g %s",r/255.0,g/255.0,b/255.0,cmd); } ClassMember(void) hcPen(WinComDataPtr wcd, DrawAttrPtr attr) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; fprintf(gd->HardFile,"%i %i PEN\n",(int)attr->width,(int)attr->style); hcSetColor(gd->HardFile,"COLOR\n"); } ClassMember(void) hcString(WinComDataPtr wcd, CharPtr str, float PNTR hardcopy) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Int2 i; fprintf(gd->HardFile,"(%s)",str); for (i=0; i<6; ) fprintf(gd->HardFile," %g",hardcopy[i++]); fprintf(gd->HardFile," %g %g STRMARKER\n",mpt[0],mpt[1]); } ClassMember(void) hcPaintOval(WinComDataPtr wcd, RectPtr r) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; fprintf(gd->HardFile,"%g %g %g ",mpt[0],mpt[1],(r->right-r->left)/2.0); hcSetColor(gd->HardFile,"PAINTCIRCLE\n"); } ClassMember(void) hcFrameOval(WinComDataPtr wcd, RectPtr r) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; fprintf(gd->HardFile,"%g %g %g ",mpt[0],mpt[1],(r->right-r->left)/2.0); hcSetColor(gd->HardFile,"FRAMECIRCLE\n"); } Local(void) hcPoly(GraphicDataPtr gd, Int2 num, PointPtr poly, CharPtr oper) { Int2 i,wx,wy; for (i=num-1; i>=0; i--) { if (i) { wx=poly[i].x-poly[i-1].x; wy=-(poly[i].y-poly[i-1].y); } else { wx=poly[0].x-MathToWinX(mpt[0],gd); wy=-(poly[0].y-MathToWinY(mpt[1],gd)); } fprintf(gd->HardFile," %i %i",(int)wx,(int)wy); } fprintf(gd->HardFile," %i %g %g ",(int)num,mpt[0],mpt[1]); hcSetColor(gd->HardFile,oper); } ClassMember(void) hcPaintPoly(WinComDataPtr wcd, Int2 num, PointPtr poly) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; hcPoly(gd,num,poly,"PAINTPOLY\n"); } ClassMember(void) hcFramePoly(WinComDataPtr wcd, Int2 num, PointPtr poly) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; hcPoly(gd,num,poly,"FRAMEPOLY\n"); } /******************/ /* Menu callbacks */ /*---------------------------------------*/ /* Menu callback: Redraw current diagram */ #if _WIN #pragma argsused #endif Callback(void) lRedrawD(Int2 indx) { WinComDataPtr wcd=GetComDataI; DeactivateWindows(wcd); RedrawDiagram(0); ActivateWindows(); } /*-------------------------------------*/ /* Menu callback: Redraw current curve */ #if _WIN #pragma argsused #endif Callback(void) lRedrawC(Int2 indx) { WinComDataPtr wcd=GetComDataI; DeactivateWindows(wcd); RedrawCurve(0); ActivateWindows(); } /*---------------------------------*/ /* Menu callback: Clear the window */ #if _WIN #pragma argsused #endif Callback(void) lClear(Int2 indx) { ClearWindow(GetComDataI); } /*-----------------------------------*/ /* Menu callbacks: Fit diagram/curve */ #define PERCENT 2.5 /* of margins */ Local(void) Fit(Boolean diagram) { WinComDataPtr wcd=GetComDataI; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; TexT t; FloatHi d; Int2 i,j; MsgAnswer anstick; Boolean asktick=TRUE; Boolean change=FALSE; Char buf[30]; DeactivateWindows(wcd); /* freeze others */ for (i=0; iRAxis); i++) { gd->RAxis[i].FitMin=DBL_MAX; gd->RAxis[i].FitMax=-DBL_MAX; } gd->flags|=FIT_IN_PROGRESS; if (diagram) RedrawDiagram(0); else RedrawCurve(0); gd->flags^=FIT_IN_PROGRESS; UseWindow(wcd->Win); for (i=0; iRAxis); i++) if (gd->RAxis[i].FitMin!=DBL_MAX && gd->RAxis[i].FitMin!=gd->RAxis[i].FitMax) { change=TRUE; d=(gd->RAxis[i].FitMax-gd->RAxis[i].FitMin)/100*PERCENT; gd->RAxis[i].Min=gd->RAxis[i].FitMin-d; gd->RAxis[i].Max=gd->RAxis[i].FitMax+d; /* Update controls, see LimitsProc */ for (j=0; j<2; j++) { /* 0 - Min, 1 - Max */ sprintf(buf,"%g",gd->RAxis[i].Limits[j]); MemFree(gd->Axis[i].pText[j]); gd->Axis[i].pText[j]=StringSave(buf); t=gd->teAxis[i].teLimits[j]; if (t) SetTitle(t,buf); } /* Ticks */ if (gd->RAxis[i].Tick>0) { if (asktick) { asktick=FALSE; anstick=Message(MSG_YN, "Fit has found non-zero tick value.\n" "Set it to zero?\n" "(to allow Content to determine it)"); } if (anstick==ANS_YES) { gd->RAxis[i].Tick=0; MemFree(gd->Axis[i].pTick); gd->Axis[i].pTick=StringSave("0"); t=gd->teAxis[i].teLimits[3]; if (t) SetTitle(t,"0"); } } GetNumbers(wcd); } if (change) { lRefreshScale(wcd); ClearWindow(wcd); if (diagram) RedrawDiagram(0); else RedrawCurve(0); } ActivateWindows(); /* melt others */ } #undef PERCENT #if _WIN #pragma argsused #endif Callback(void) lFitDiagram(Int2 indx) { Fit(TRUE); } #if _WIN #pragma argsused #endif Callback(void) lFitCurve(Int2 indx) { Fit(FALSE); } /*---------------------------*/ /* Menu callback: Undo scale */ Local(void) UndoRecord(WinComDataPtr wcd) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Int2 i,n=gd->UndoNum; if (gd->UndoBuf) { if (gd->UndoBuf[n].xMin!=gd->RAxis[0].Min || gd->UndoBuf[n].xMax!=gd->RAxis[0].Max || gd->UndoBuf[n].yMin!=gd->RAxis[1].Min || gd->UndoBuf[n].yMax!=gd->RAxis[1].Max) { if (n==UNDODEPTH-1) for (i=0; iUndoBuf[i]=gd->UndoBuf[i+1]; else n++; } else return; } else { gd->UndoBuf=MemNew(ARRAYSIZE(UndoElem,UNDODEPTH)); n=0; } gd->UndoBuf[n].xMin=gd->RAxis[0].Min; gd->UndoBuf[n].xMax=gd->RAxis[0].Max; gd->UndoBuf[n].yMin=gd->RAxis[1].Min; gd->UndoBuf[n].yMax=gd->RAxis[1].Max; gd->UndoNum=n; SetStatusOfItems(&wcd->MenuDesc); } #if _WIN #pragma argsused #endif Callback(void) lUndoScale(Int2 index) { WinComDataPtr wcd=GetComDataI; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; UndoElem ue; Int2 i,j,n; Char b[20]; n=gd->UndoNum; /* n>0! see UndoScale_Status */ ue=gd->UndoBuf[n]; for (i=n; i; i--) gd->UndoBuf[i]=gd->UndoBuf[i-1]; gd->UndoBuf[0]=ue; gd->RAxis[0].Min=gd->UndoBuf[n].xMin; gd->RAxis[0].Max=gd->UndoBuf[n].xMax; gd->RAxis[1].Min=gd->UndoBuf[n].yMin; gd->RAxis[1].Max=gd->UndoBuf[n].yMax; for (i=0; i<2; i++) { for (j=0; j<2; j++) { sprintf(b,"%g",gd->RAxis[i].Limits[j]); MemFree(gd->Axis[i].pText[j]); gd->Axis[i].pText[j]=StringSave(b); } if (gd->Axis[i].bLimits) for (j=0; j<2; j++) SetTitle(gd->teAxis[i].teLimits[j],gd->Axis[i].pText[j]); } lRefreshScale(wcd); } #if _WIN #pragma argsused #endif Callback(Boolean) lUndoScale_Status(Int2 index) { WinComDataPtr wcd=GetComDataI; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; return gd->UndoNum>0; } /*----------------------------------*/ /* Menu callback: Layout dialog box */ typedef struct { WinComDataPtr Com; /* Common data for all classes of windows */ Color Colors[2]; /* colors */ struct { CharPtr PNTR pTrace; /* to array of ptrs to all V-functions along the axis */ Boolean Prop[6]; /* must be == to DIM(GraphicWindow.Axis.Prop) */ TexT teText[4]; #define teMin teText[0] /* Min */ #define teMax teText[1] /* Max */ #define teFunc teText[2] /* V-Func (currently available for editing) */ #define teTick teText[3] /* Tick */ ButtoN cbProp[6]; /* must be == to DIM(GraphicWindow.Axis.Prop) */ } Axis[2]; FuncAttrPtr Attr; /* to array of points,traces,paths atributes */ Int2 CurPair; /* current V-function pair */ Int2 NumPair; /* number of pairs */ TexT Title; /* WinTitle */ TexT teInsertTo; /* text for insertion */ ButtoN buDelFun; BaR scBar; /* scroll bar for V-func pair selection */ PrompT ptFuncNum; /* ordinal no of functions pair indicator */ GrouP grAttrOf; /* 'Set attributes of' group */ ButtoN buAttrOf[4]; /* 0-points, 1-paths, 2-traces, 3-shifts */ GrouP grStyle; /* Group for join: no/solid/dotted */ GrouP grWidth; /* Group for width: 0-9 */ ButtoN buColor; /* Button for set color */ ButtoN cbClear; /* 'Clear before each point' button */ ButtoN cbPalette; /* 'Show palette in window' */ ButtoN cbCircle; /* 'Draw unit circle in window' */ PaneL paSample; /* Panel to display a sample of window */ PaneL paLimits,paPalette,paDraw; /* and its superimposed parts */ /* Fields related to attributes of current curve */ #if MYSWITCH Switch swSegment; /* Current curve's attrs: 'segment numer' SwitcH */ #else SwitcH swSegment; /* Current curve's attrs: 'segment numer' SwitcH */ #endif PrompT prFrom; /* types of endpoints for current segment */ PrompT prTo; #if MYSWITCH Switch swAttr; /* current attributes (CurPair) */ #else SwitcH swAttr; /* current attributes (CurPair) */ #endif Int2 spnum,spcur; /* number of special points and current */ DataLibPosPtr splist; /* list of DataLib ptrs to special points */ ByteStorePtr PNTR spbs; /* ByteStorePtrs for attrs for all curve's segments */ /* End of fields related to attributes of current curve */ Int2 SampleHeight; ShowOptions Options; Uint1 Kind; /* options of: 0-current, 1-layout, 2-current curve */ Boolean Recompile; /* set to TRUE if a window function has been changed */ Uint1 Lock; /* to prevent recursion in SampleProc */ } LayoutData, PNTR LayoutDataPtr; #define GetLayoutData(h) ((LayoutDataPtr)GetWindowExtra(ParentWindow(h))) Local(Boolean) StdPrmt=TRUE; /* Creates a StaticPrompt */ Local(PrompT) CreatePrompt(GrouP g, Int2 key) { return StaticPrompt(g,key>=0 ? Text[key] : "",0,StdPrmt ? dialogTextHeight : 0,NULL,'l'); } /* The current V-function has been changed */ Callback(void) FuncChanged(TexT t) { LayoutDataPtr layout=GetLayoutData(t); Int2 i; layout->Recompile=TRUE; i=t==layout->Axis[0].teFunc ? 0 : 1; GetTitleAndSave(t,&layout->Axis[i].pTrace[layout->CurPair]); } Callback(void) NamesListProc(LisT l, Int2 var) { LayoutDataPtr layout=GetLayoutData(l); CharPtr p; CharPtr t; size_t len; Int2 b,e; if (layout->teInsertTo) { p=StringSave(((CharPtr PNTR)GetObjectExtra(l))[var-1]); len=TextLength(layout->teInsertTo)+StrLen(p)+1; t=MemNew(len); GetTitle(layout->teInsertTo,t,len); TextSelectionRange(layout->teInsertTo,&b,&e); StrCpy(t,p); b=0; SetTitle(layout->teInsertTo,t); len=b+StrLen(p); SelectText(layout->teInsertTo,(Int2)len,(Int2)len); MemFree(t); MemFree(p); FuncChanged(layout->teInsertTo); /* inform it text has been changed */ } } /* Just set teInsert for NamesListProc (see above)*/ Callback(void) MarkSelection(TexT t) { LayoutDataPtr layout=GetLayoutData(t); layout->teInsertTo=t; } Local(void) ShowGrAttributes(LayoutDataPtr layout, Int2 i) { DrawAttrPtr pda; switch (i) { case 0: pda=&layout->Attr[layout->CurPair].Point; break; case 1: pda=&layout->Attr[layout->CurPair].Path; break; case 2: pda=&layout->Attr[layout->CurPair].Trace; break; case 3: pda=&layout->Options.Shift; break; default: return; } SetValue(layout->grStyle,MAX(pda->style,0)+1); SetValue(layout->grWidth,pda->width+1); #if _WIN if (pda->width>1 && pda->style>1) { /* only solid in such cases */ pda->style=1; SetValue(layout->grStyle,pda->style+1); Beep(); } #endif /* _WIN */ if (i) Enable(layout->grStyle); else Disable(layout->grStyle); if (i==0 || pda->style>0) { Enable(layout->grWidth); Enable(layout->buColor); } else { Disable(layout->grWidth); Disable(layout->buColor); } } /* Show current curve's attributes */ Local(void) ShowAttributes(LayoutDataPtr layout, Boolean redraw) { Char buf[8]; Int2 i,j; switch (layout->Kind) { case 0: /* current */ case 2: /* curve */ if (layout->Kind==0) { /* current */ for (i=0; iAxis); i++) SetTitle(layout->Axis[i].teFunc,layout->Axis[i].pTrace[layout->CurPair]); } ShowGrAttributes(layout,GetValue(layout->grAttrOf)-1); if (layout->Kind==0) { /* current */ CorrectBarValue(layout->scBar,layout->CurPair); SelectText(layout->teInsertTo=layout->Axis[0].teFunc,0,0); (layout->NumPair>1 ? Enable : Disable)(layout->buAttrOf[3]); /* shifts */ SetStatus(layout->cbClear,(Boolean)(layout->Options.Flags&GWIN_CLEAR)); } else { #if MYSWITCH SwitchSetParams(layout->swAttr,layout->CurPair+1,layout->NumPair); #else SetSwitchParams(layout->swAttr,layout->CurPair+1,layout->NumPair); #endif } (layout->NumPair>1 && !ccd.Computing ? Enable : Disable)(layout->buDelFun); if (layout->NumPair>99) StrCpy(buf,"**/**"); else sprintf(buf,"%i/%i",layout->CurPair+1,layout->NumPair); SetTitle(layout->ptFuncNum,buf); break; case 1: /* axes */ for (i=0; iAxis); i++) { for (j=0; jAxis[i].Prop); j++) SetStatus(layout->Axis[i].cbProp[j],layout->Axis[i].Prop[j]); (layout->Axis[i].Prop[0] ? Enable : Disable)(layout->Axis[i].cbProp[1]); /* Tick depends on Limits */ } SetStatus(layout->cbPalette,(Boolean)(layout->Options.Flags&GWIN_PALETTE)); SetStatus(layout->cbCircle,(Boolean)(layout->Options.Flags&GWIN_CIRCLE)); break; } if (redraw) Redraw(layout->paSample); } /* Add/Del functions button callbacks */ Local(void) AddFunProc(ButtoN bu) { LayoutDataPtr layout=GetLayoutData(bu); WinComDataPtr wcd=layout->Com; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; DrawAttr dattr; Int2 i; for (i=0; iAxis); i++) { layout->Axis[i].pTrace=MemMore(layout->Axis[i].pTrace,ARRAYSIZE(CharPtr,layout->NumPair+1)); layout->Axis[i].pTrace[layout->NumPair]=StringSave("?"); } layout->Attr=MemMore(layout->Attr,ARRAYSIZE(FuncAttr,layout->NumPair+1)); dattr.color=wcd->Foreground; dattr.width=2; dattr.style=-1; layout->Attr[layout->NumPair].Point=dattr; layout->Attr[layout->NumPair].Trace=dattr; dattr.style=1; layout->Attr[layout->NumPair].Path=dattr; if (layout->Kind==0) { /* current */ layout->Recompile=TRUE; CorrectBarMax(layout->scBar,layout->NumPair); } else { /* curve */ gd->Attr=MemMore(gd->Attr,ARRAYSIZE(FuncAttr,layout->NumPair+1)); gd->FuncNum++; } layout->CurPair=layout->NumPair++; ShowAttributes(layout,TRUE); } Local(void) DelFunProc(ButtoN bu) { LayoutDataPtr layout=GetLayoutData(bu); WinComDataPtr wcd=layout->Com; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Int2 i; /* it is always layout->NumPair>1; otherwise the button is hidden */ if (layout->NumPair<=1) { /* It is quite possible (in UNIX at least): press AddFunction twice and then QUICKLY press DelFunction three times. */ return; } layout->NumPair--; for (i=0; iAxis); i++) { MemFree(layout->Axis[i].pTrace[layout->CurPair]); MemMove(&layout->Axis[i].pTrace[layout->CurPair], &layout->Axis[i].pTrace[layout->CurPair+1], ARRAYSIZE(CharPtr,layout->NumPair-layout->CurPair)); layout->Axis[i].pTrace=MemMore(layout->Axis[i].pTrace,ARRAYSIZE(CharPtr,layout->NumPair)); } MemMove(layout->Attr+layout->CurPair,layout->Attr+layout->CurPair+1, ARRAYSIZE(FuncAttr,layout->NumPair-layout->CurPair)); layout->Attr=MemMore(layout->Attr,ARRAYSIZE(FuncAttr,layout->NumPair)); if (layout->NumPair==layout->CurPair) layout->CurPair--; if (layout->Kind==0) { /* current */ layout->Recompile=TRUE; } else { /* curve */ gd->Attr=MemMore(gd->Attr,ARRAYSIZE(FuncAttr,layout->NumPair)); gd->FuncNum--; } ShowAttributes(layout,TRUE); if (layout->Kind==0) { /* current */ CorrectBarMax(layout->scBar,layout->NumPair-1); /* ShowAttributes() decreased scBar value */ } } #if _WIN #pragma argsused #endif /* V-func pair scroll bar callback */ Callback(void) SelFuncPairProc(BaR bar, GraphiC graphic, Int2 new, Int2 old) { LayoutDataPtr layout; if (new!=old) { layout=GetLayoutData(bar); layout->CurPair=new; ShowAttributes(layout,TRUE); } } /* Palette/Clear/Circle common callback */ Callback(void) PCCProc(ButtoN bu) { LayoutDataPtr layout=GetLayoutData(bu); Uint1 fl; if (bu==layout->cbPalette) fl=GWIN_PALETTE; if (bu==layout->cbClear) fl=GWIN_CLEAR; if (bu==layout->cbCircle) fl=GWIN_CIRCLE; if (GetStatus(bu)) layout->Options.Flags|=fl; else layout->Options.Flags&=~fl; Redraw(layout->paSample); } /* cbClear checkbox callback */ #define ClearProc PCCProc /* cbPalette checkbox callback */ #define ShowPaletteProc PCCProc /* cbCircle checkbox callback */ #define CircleProc PCCProc /* grAttrOf callback */ #if _WIN #pragma argsused #endif Callback(void) SetAttrOfProc(GrouP gr) { LayoutDataPtr layout=GetLayoutData(gr); ShowAttributes(layout,FALSE); } /* grWidth callback */ Callback(void) WidthProc(GrouP grWidth) { LayoutDataPtr layout=GetLayoutData(grWidth); Uint1 width; width=(Uint1)GetValue(grWidth)-1; switch (GetValue(layout->grAttrOf)) { case 1: /* Points */ layout->Attr[layout->CurPair].Point.width=width; break; case 2: /* Paths */ layout->Attr[layout->CurPair].Path.width=width; break; case 3: /* Traces */ layout->Attr[layout->CurPair].Trace.width=width; break; case 4: /* Shifts */ layout->Options.Shift.width=width; break; } ShowAttributes(layout,TRUE); } /* grStyle callback */ Callback(void) StyleProc(GrouP grStyle) { LayoutDataPtr layout=GetLayoutData(grStyle); Int1 style; style=(Int1)GetValue(grStyle)-1; switch (GetValue(layout->grAttrOf)) { case 1: /* Points - impossible */ break; case 2: /* Paths */ layout->Attr[layout->CurPair].Path.style=style; break; case 3: /* Traces */ layout->Attr[layout->CurPair].Trace.style=style; break; case 4: /* Shifts */ layout->Options.Shift.style=style; break; } ShowAttributes(layout,TRUE); } /* cbProp[1-5] callback */ Callback(void) PropProc(ButtoN bu) { LayoutDataPtr layout=GetLayoutData(bu); Int2 i,j; for (i=0; iAxis); i++) for (j=0; jAxis[i].Prop); j++) if (bu==layout->Axis[i].cbProp[j]) { layout->Axis[i].Prop[j]=GetStatus(bu); ShowAttributes(layout,TRUE); break; } } #define LimitProc PropProc /* Draw palette */ Local(void) PaletteProc(PaneL pnl) { RecT r; Int2 w,i,n; Select(pnl); GetPosition(pnl,&r); n=ColorNumber(); if (!(w=(r.right-r.left)/n)) w=1; for (i=0; iAxis); i++) { if (layout->Axis[i].bLimits) { r.left=off; off+=StringWidth(StrCpy(Buf,Text[i ? ORD_P : ABS_P]))+2; r.right=off; DrawString(&r,Buf,'l',FALSE); for (j=0; j<4; j++) { if (FuncIndex(j)) continue; if (j==3 && !layout->Axis[i].bTick) continue; r.left=off; off+=StringWidth(SampLims[i][j])+(sysCharWidth/4); r.right=off; DrawString(&r,SampLims[i][j],'c',FALSE); FrameRect(&r); off+=2; } } off+=sysCharWidth/2; } } #define SamplePaletteProc PaletteProc #define GPN 5 /* number of G-points */ #define MPN 10 /* number of M-points in the first G-point */ #define MPR 1.0/(GPN) /* radius of M-points in the first G-point */ #define MPRI 1.0/(GPN) /* increment of radius */ Local(Int2) Ox,Oy,Dx,Dy; #define GATHER 0 /* setting to 1 will create data file */ #if GATHER #include FILE *deb; #endif typedef struct {FloatLo cos,sin;} fPair; Local(fPair) Data[GPN][MPN+1]={ { {1,0}, {0.809204,0.587528}, {0.309623,0.950859}, {-0.308108,0.951351}, {-0.808267,0.588815}, {-0.999999,0.00159255}, {-0.810139,-0.586238}, {-0.311137,-0.950365}, {0.306593,-0.951841}, {0.807329,-0.590102}, {0.999995,-0.00318509} }, { {0.951106,0.308866}, {0.588172,0.808736}, {0.000796274,1}, {-0.586883,0.809672}, {-0.950613,0.31038}, {-0.951596,-0.30735}, {-0.589459,-0.807798}, {-0.00238894,-0.999997}, {0.585593,-0.810606}, {0.950117,-0.311893}, {0.952085,0.305834} }, { {0.809204,0.587528}, {0.309623,0.950859}, {-0.308108,0.951351}, {-0.808267,0.588815}, {-0.999999,0.00159255}, {-0.810139,-0.586238}, {-0.311137,-0.950365}, {0.306593,-0.951841}, {0.807329,-0.590102}, {0.999995,-0.00318509}, {0.811072,0.584947} }, { {0.588172,0.808736}, {0.000796274,1}, {-0.586883,0.809672}, {-0.950613,0.31038}, {-0.951596,-0.30735}, {-0.589459,-0.807798}, {-0.00238894,-0.999997}, {0.585593,-0.810606}, {0.950117,-0.311893}, {0.952085,0.305834}, {0.590745,0.806859} }, { {0.309623,0.950859}, {-0.308108,0.951351}, {-0.808267,0.588815}, {-0.999999,0.00159255}, {-0.810139,-0.586238}, {-0.311137,-0.950365}, {0.306593,-0.951841}, {0.807329,-0.590102}, {0.999995,-0.00318509}, {0.811072,0.584947}, {0.31265,0.949868} } }; Local(void) GetCoord(Int2 Gp, Int2 Mp, Int2Ptr x, Int2Ptr y) { #if GATHER FloatLo fi; fi=(1.57*Gp/GPN+6.28*Mp/MPN); *x=Ox+Dx*(MPR+Gp*MPRI)*cos(fi); *y=Oy+Dy*(MPR+Gp*MPRI)*sin(fi); fprintf(deb,"%2i %2i %g %g\n",Gp,Mp,cos(fi),sin(fi)); #else *x=Ox+Dx*(MPR+Gp*MPRI)*Data[Gp][Mp].cos; *y=Oy+Dy*(MPR+Gp*MPRI)*Data[Gp][Mp].sin; #endif } Local(void) CopyFromWork(WinComDataPtr wcd, LayoutDataPtr layout); Callback(void) SampleDrawProc(PaneL paDraw) { LayoutDataPtr layout=GetLayoutData(paDraw); WinComData foolwcd; GraphicData foolgd; DrawAttr flowers; WindoW attrwin=ParentWindow(paDraw); VoidPtr saveExtra=GetWindowExtra(attrwin); FuncAttr Attr; RecT r; Int2 Kind; Int2 i,j,ix,iy,ox,oy; Boolean Recompile; Select(paDraw); GetPosition(paDraw,&r); /* Use GraphDrawProc and VisualizerGPoint to draw the Sample */ /* 1. Fool GraphDrawProc before call */ MemFill(&foolwcd,0,sizeof(WinComData)); MemFill(&foolgd,0,sizeof(GraphicData)); #if _UNIX #else BuildGrids(&foolgd); #endif foolwcd.Private=&foolgd; /* 2. Fill in foolwcd from layout */ Recompile=layout->Recompile; layout->Recompile=TRUE; Kind=layout->Kind; layout->Kind=0; CopyFromWork(&foolwcd,layout); layout->Kind=Kind; layout->Recompile=Recompile; MemMove(&foolwcd.Colors,layout->Colors,sizeof(foolwcd.Colors)); for (i=0; i>1; Oy=(r.bottom+r.top)>>1; Dx=(r.right-r.left+1)>>1; Dy=(r.bottom-r.top+1)>>1; Attr=layout->Attr[layout->CurPair]; flowers.color=layout->Foreground; flowers.width=1; flowers.style=1; #if GATHER deb=fopen("deb","wt"); #endif for (j=0; jOptions.Flags&GWIN_CLEAR) { SetCurrentPen(&flowers); DrawProc(paDraw); } /* Join current point with the previous one along a trace */ if (Attr.Trace.style>0 && IsDimGMore1()) { SetCurrentPen(&Attr.Trace); ix=Dx*(MPR+j*MPRI); iy=Dy*(MPR+j*MPRI); LoadRect(&r,Ox-ix-1,Oy-iy-1,Ox+ix+1,Oy+iy+1); FrameOval(&r); } SetCurrentPen(&Attr.Point); for (i=0; i0) { if (j) { GetCoord(j-1,i,&ox,&oy); SetCurrentPen(&Attr.Path); lLine(ix,iy,ox,oy); SetCurrentPen(&Attr.Point); lPoint(ox,oy); } } /* It is not clear how to illustrate 'join along shift' */ /* Plot the current point */ lPoint(ix,iy); } } /* 5. Restore everything. This does not write but frees memory only */ #if _UNIX #else FreeGrids(&foolgd); #endif WriteDescription(&foolwcd,NULL); SetWindowExtra(attrwin,saveExtra,NULL); #if GATHER fclose(deb); #endif } Callback(void) SampleProc(PaneL sample) { LayoutDataPtr layout=GetLayoutData(sample); RecT r; Int2 y; Int2 j; if (layout->Lock) return; layout->Lock=1; Hide(layout->paDraw); Hide(layout->paPalette); Hide(layout->paLimits); GetPosition(sample,&r); y=r.top; j=layout->SampleHeight; /* Limits sample */ if (layout->Axis[0].bLimits || layout->Axis[1].bLimits) { GetPosition(layout->paLimits,&r); r.bottom+=y-r.top; r.top=y; SetPosition(layout->paLimits,&r); Show(layout->paLimits); j-=r.bottom-r.top; y+=r.bottom-r.top; } /* Palette sample */ if (layout->Options.Flags&GWIN_PALETTE) { GetPosition(layout->paPalette,&r); r.bottom+=y-r.top; r.top=y; SetPosition(layout->paPalette,&r); Show(layout->paPalette); j-=r.bottom-r.top; /*** y+=r.bottom-r.top;***/ } /* Draw sample */ GetPosition(layout->paDraw,&r); r.top=r.bottom-j; SetPosition(layout->paDraw,&r); Show(layout->paDraw); layout->Lock=0; } Callback(void) SetFGColor(ButtoN bt) { LayoutDataPtr layout=GetLayoutData(bt); layout->Foreground=ColorAsk(layout->Foreground); ShowAttributes(layout,TRUE); } Callback(void) SetBGColor(ButtoN bt) { LayoutDataPtr layout=GetLayoutData(bt); layout->Background=ColorAsk(layout->Background); ShowAttributes(layout,TRUE); } /* Activate/Deactivate segment (called be Copy To/From Work and switch callback). */ Local(void) ActivateSegment(LayoutDataPtr layout, Int2 s) { WinComDataPtr wcd=layout->Com; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Int2 i,k; Pointtype ptype; /* local code of the type of a special point */ layout->spcur=s; BSSeek(layout->spbs[s-1],0,SEEK_SET); RestoreVisualAttr(&DiagramLib,layout->spbs[s-1],NULL); if (!gd->FuncNum) { /* This window was created AFTER the active curve was stored/edited */ gd->FuncNum=gd->SaveFuncNum; gd->Attr=MemNew(ARRAYSIZE(FuncAttr,gd->FuncNum)); MemMove(gd->Attr,gd->SaveAttr,ARRAYSIZE(FuncAttr,gd->FuncNum)); } layout->NumPair=gd->FuncNum; layout->CurPair=0; /* Copy V-functions (for show sample only!) */ for (i=0; iAxis); i++) { layout->Axis[i].pTrace=MemNew(ARRAYSIZE(CharPtr,layout->NumPair)); for (k=0; kNumPair; k++) layout->Axis[i].pTrace[k]=StringSave(k>=gd->SaveFuncNum ? "?" : gd->Axis[i].Funcs[k].pFunc); } #if MYSWITCH SwitchSetParams(layout->swAttr,1,layout->NumPair); #else SetSwitchParams(layout->swAttr,1,layout->NumPair); #endif /* Copy attributes of V-functions */ layout->Attr=MemNew(ARRAYSIZE(FuncAttr,layout->NumPair)); MemMove(layout->Attr,gd->Attr,ARRAYSIZE(FuncAttr,layout->NumPair)); /* Show endpoints' type */ if (s==1) SetTitle(layout->prFrom,Text[FP_P]); else { DataLibSeek(&DiagramLib,layout->splist+s-2); DataLibRead(&DiagramLib,(CharPtr)&ptype,sizeof(ptype)); SetTitle(layout->prFrom,GetSPname(ptype,TRUE)); } if (s==layout->spnum) SetTitle(layout->prTo,Text[LP_P]); else { DataLibSeek(&DiagramLib,layout->splist+s-1); DataLibRead(&DiagramLib,(CharPtr)&ptype,sizeof(ptype)); SetTitle(layout->prTo,GetSPname(ptype,TRUE)); } } Local(void) DeactivateSegment(LayoutDataPtr layout, Int2 s) { WinComDataPtr wcd=layout->Com; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Int2 i,k; BSFree(layout->spbs[s-1]); layout->spbs[s-1]=BSNew(0); MemMove(gd->Attr,layout->Attr,ARRAYSIZE(FuncAttr,layout->NumPair)); for (i=0; iAxis); i++) if (layout->Axis[i].pTrace) { for (k=0; kNumPair; k++) MemFree(layout->Axis[i].pTrace[k]); layout->Axis[i].pTrace=MemFree(layout->Axis[i].pTrace); } layout->Attr=MemFree(layout->Attr); SaveVisualAttr(&DiagramLib,NULL,layout->spbs[s-1],FALSE); } /* Segment number callback */ #if MYSWITCH Callback(void) SegmentProc(GraphiC sw, Int2 new, Int2 old) { #else Callback(void) SegmentProc(SwitcH sw, Int2 new, Int2 old) { #endif LayoutDataPtr layout=GetLayoutData(sw); DeactivateSegment(layout,old); ActivateSegment(layout,new); ShowAttributes(layout,TRUE); } #define AddAttrProc AddFunProc #define DelAttrProc DelFunProc /* Attributes number callback */ #if _WIN #pragma argsused #endif #if MYSWITCH Local(void) AttrProc(GraphiC sw, Int2 new, Int2 old) { #else Local(void) AttrProc(SwitcH sw, Int2 new, Int2 old) { #endif LayoutDataPtr layout=GetLayoutData(sw); layout->CurPair=new-1; ShowAttributes(layout,TRUE); } /* Copy visual attributes to/from layout work area and free it */ Local(void) CopyToWork(LayoutDataPtr layout, WinComDataPtr wcd) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Int2 i,k; if (layout->Kind==2) { /* attribs of active curve */ PushVisualAttr(TRUE); /* will be restored in GraphicFreeAttributes */ DataLibSavePos(&DiagramLib); ReadSPList(&layout->spnum,&layout->splist); #if MYSWITCH SwitchSetParams(layout->swSegment,1,layout->spnum); #else SetSwitchParams(layout->swSegment,1,layout->spnum); #endif ReadVAList(layout->spnum+1,&layout->spbs); ActivateSegment(layout,1); } else { /* Get memory for local editable copies of attributes */ layout->NumPair=gd->FuncNum; layout->CurPair=gd->FuncCur; /* Copy attributes of V-functions */ layout->Attr=MemNew(ARRAYSIZE(FuncAttr,layout->NumPair)); MemMove(layout->Attr,gd->Attr,ARRAYSIZE(FuncAttr,layout->NumPair)); /* Copy V-functions */ for (i=0; iAxis); i++) { layout->Axis[i].pTrace=MemNew(ARRAYSIZE(CharPtr,layout->NumPair)); for (k=0; kNumPair; k++) layout->Axis[i].pTrace[k]=StringSave(gd->Axis[i].Funcs[k].pFunc); } } for (i=0; iAxis); i++) MemMove(layout->Axis[i].Prop,gd->Axis[i].Prop,sizeof(layout->Axis[i].Prop)); /* Copy general attributes */ MemMove(layout->Colors,wcd->Colors,sizeof(layout->Colors)); layout->Options=gd->Options; } Local(void) CopyFromWork(WinComDataPtr wcd, LayoutDataPtr layout) { GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; Int2 i,j,k; Char Buf[PAR_BUF]; if (layout->Kind==2) { /* attribs of active curve */ /* First save current segment's attributes to spbs[...] */ DeactivateSegment(layout,layout->spcur); /* Now save to DiagramLib */ WriteVAList(layout->spnum+1,layout->spbs); return; } if (layout->Recompile) { /* a func was changed */ /* free old pair descriptors */ for (i=0; iAxis); i++) { for (k=0; kFuncNum; k++) MemFree(gd->Axis[i].Funcs[k].pFunc); MemFree(gd->Axis[i].Funcs); } MemFree(gd->Attr); /* Create new ones */ gd->FuncNum=layout->NumPair; for (i=0; iAxis); i++) { gd->Axis[i].Funcs=MemNew(ARRAYSIZE(AxisFunc,gd->FuncNum)); for (k=0; kFuncNum; k++) { StrTrim(layout->Axis[i].pTrace[k]); if (StrLen(layout->Axis[i].pTrace[k])==0) { CharPtr name; Int2 dim; MemFree(layout->Axis[i].pTrace[k]); GetNameAndDim(0,1,&name,&dim); sprintf(Buf,"%s%s",name,dim==1 ? "" : "[0]"); layout->Axis[i].pTrace[k]=StringSave(Buf); Warning("VI_EMPTY",Buf); } gd->Axis[i].Funcs[k].pFunc=StringSave(layout->Axis[i].pTrace[k]); } } gd->Attr=MemNew(ARRAYSIZE(FuncAttr,gd->FuncNum)); } MemMove(gd->Attr,layout->Attr,ARRAYSIZE(FuncAttr,gd->FuncNum)); for (i=0; iAxis); i++) MemMove(gd->Axis[i].Prop,layout->Axis[i].Prop,sizeof(gd->Axis[i].Prop)); gd->FuncCur=layout->CurPair; switch (layout->Kind) { case 0: /* current */ case 2: /* curve */ break; case 1: /* axes */ GetTitleAndSave(layout->Title,&wcd->WinTitle); for (i=0; iAxis); i++) for (j=0; jAxis[i].pText); j++) if (!FuncIndex(j)) GetTitleAndSave(layout->Axis[i].teText[j],&gd->Axis[i].pText[j]); break; } /* Copy general attributes */ MemMove(wcd->Colors,layout->Colors,sizeof(wcd->Colors)); gd->Options=layout->Options; } Local(void) FreeWork(LayoutDataPtr layout) { Int2 i,k; if (layout->Kind==2) { FreeSPList(layout->spnum,layout->splist); FreeVAList(layout->spnum,layout->spbs); PopVisualAttr(); DataLibRestorePos(&DiagramLib); } for (i=0; iAxis); i++) if (layout->Axis[i].pTrace) { for (k=0; kNumPair; k++) MemFree(layout->Axis[i].pTrace[k]); MemFree(layout->Axis[i].pTrace); } MemFree(layout->Attr); } Local(void) CreateSampleGroup(GrouP parent, Int2 width, Int2 height) { LayoutDataPtr layout=GetLayoutData(parent); GrouP g; g=CreateNormalGroup(parent,0,0,Text[SAMPLE_WIN]); layout->SampleHeight=height; layout->paSample=SimplePanel(g,1,1,SampleProc); Hide(layout->paLimits=SimplePanel(g,width,sysLineHeight,SampleLimitsProc)); Hide(layout->paPalette=SimplePanel(g,width,sysLineHeight,SamplePaletteProc)); Hide(layout->paDraw=SimplePanel(g,width,height,SampleDrawProc)); } /* Cancel callback */ Callback(void) LayoutCancel(ButtoN bt) { LayoutDataPtr layout=GetLayoutData(bt); WinComDataPtr wcd=layout->Com; FreeWork(layout); PopContext(); MemFree(layout); Select(wcd->Win); Remove(ParentWindow(bt)); UnlockMenus(); } /* Ok callback */ Callback(void) LayoutOk(ButtoN bt) { LayoutDataPtr layout=GetLayoutData(bt); WinComDataPtr wcd=layout->Com; /* Remove old controls (they may depend on old options) */ RemoveControls(wcd); /* Get all attributes to wcd */ CopyFromWork(wcd,layout); /* wcd <== layout */ /* Rebuild all */ if (layout->Recompile) wcd->flags|=WFL_FUNC_EDITED; else wcd->flags&=~WFL_FUNC_EDITED; RecreateWindow(wcd); /* Clean up */ LayoutCancel(bt); } /* Help callback */ #if _WIN #pragma argsused #endif Callback(void) LayoutHelp(ButtoN bt) { Help(NULL); } /* Menu callback */ #if _WIN #pragma argsused #endif Callback(void) lLayout(Int2 indx) { WinComDataPtr wcd=GetComDataI; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; LayoutDataPtr layout; WindoW db; GrouP MainGroup,g,gT,gAxes,gAS,gA,gS,gColor,gFBSS,gFBS; RecT r; Int2 i,j; Char buf[50]; int numwidth,textwidth,lines,linelen; layout=MemNew(sizeof(LayoutData)); layout->Com=wcd; layout->Kind=1; /* Layout of graphic window */ sscanf(Text[SIZES],"%i,%i,(%i,%i)",&numwidth,&textwidth,&lines,&linelen); LockMenus(); /* will not wait */ PushContext(HK_LAYOUTWIN,NULL,Text[WAITATTR_C]); db=FixedWindow(-50,-50,-sysCharWidth,-sysLineHeight,Text[LAYOUT_T],NULL); SetWindowExtra(db,layout,NULL); MainGroup=InitLargeWindow(db); SetGroupSpacing(MainGroup,0,sysLineHeight/2); SetGroupMargins(MainGroup,0,0); g=CreateHiddenGroup(MainGroup,0,5,1); gT=CreateHiddenGroup(g,2,0,1); CreatePrompt(gT,WINTITLE_P); layout->Title=DialogText(gT,wcd->WinTitle,1,NULL); gAxes=CreateHiddenGroup(g,2,0,0); for (i=0; iAxis); i++) { gAS=CreateNormalGroup(gAxes,0,2,Text[i==0 ? ABS_P : ORD_P]); gA=CreateHiddenGroup(gAS,3,0,0); SetGroupSpacing(gA,GetGroupSM("nsx"),0); StdPrmt=FALSE; CreatePrompt(gA,MIN_P); CreatePrompt(gA,MAX_P); CreatePrompt(gA,TICK_P); StdPrmt=TRUE; for (j=0; jAxis[i].teText); j++) if (!FuncIndex(j)) layout->Axis[i].teText[j]=DialogText(gA,gd->Axis[i].pText[j],numwidth,NULL); gS=CreateNormalGroup(gAS,3,0,Text[SHOWOPT_P]); /* Show in window */ sprintf(buf,"%s..%s",Text[MIN_P],Text[MAX_P]); layout->Axis[i].cbProp[0]=CheckBox(gS,buf,LimitProc); layout->Axis[i].cbProp[1]=CheckBox(gS,Text[TICK_P],PropProc); layout->Axis[i].cbProp[2]=CheckBox(gS,Text[SCALE_P],PropProc); layout->Axis[i].cbProp[3]=CheckBox(gS,Text[FUNC_P],PropProc); layout->Axis[i].cbProp[4]=CheckBox(gS,Text[GRID_P],PropProc); layout->Axis[i].cbProp[5]=CheckBox(gS,Text[AXIS_P],PropProc); } gFBSS=CreateHiddenGroup(g,2,0,0); gColor=CreateHiddenGroup(gFBSS,0,2,2); SetGroupMargins(gColor,0,0); gFBS=CreateNormalGroup(gColor,0,-3,Text[COLORS_T]); PushButton(gFBS,Text[FG_P],SetFGColor); PushButton(gFBS,Text[BG_P],SetBGColor); layout->cbPalette=CheckBox(gFBS,Text[SHOWPAL_P],ShowPaletteProc); #if _WIN /* BC 5.1: does not work when calls to Parent are nested */ { Handle hg=(Handle)Parent(layout->Axis[0].teText[3]); HANDLE Hg=(HANDLE)Parent(hg); AlignObjects(ALIGN_RIGHT,(HANDLE)gFBS,Hg,NULL); } #else AlignObjects(ALIGN_RIGHT,(HANDLE)gFBS,(HANDLE)Parent(Parent(layout->Axis[0].teText[3])),NULL); #endif layout->cbCircle=CheckBox(gColor,Text[CIRCLE_P],CircleProc); GetPosition(gFBS,&r); CreateSampleGroup(gFBSS,1,5*(r.bottom-r.top)/3); AlignObjects(ALIGN_RIGHT, (HANDLE)Parent(layout->Axis[1].cbProp[2]), (HANDLE)layout->paLimits, (HANDLE)layout->paPalette, (HANDLE)layout->paDraw, (HANDLE)layout->Title, NULL); /* Create terminate buttons */ TerminalButtons((WindoW)MainGroup,MainGroup,LayoutOk,LayoutCancel,LayoutHelp); /* Fill in work area with temporary copies of options */ CopyToWork(layout,wcd); /* Show and activate */ ShowAttributes(layout,TRUE); ShowLargeWindow(MainGroup); } /*-----------------------------*/ /* Current attributes callback */ Callback(void) SetGraphicAttrColor(ButtoN bt) { LayoutDataPtr layout=GetLayoutData(bt); ColorPtr cp; switch(GetValue(layout->grAttrOf)) { case 1: /* Points */ cp=&layout->Attr[layout->CurPair].Point.color; break; case 2: /* Path */ cp=&layout->Attr[layout->CurPair].Path.color; break; case 3: /* Trace */ cp=&layout->Attr[layout->CurPair].Trace.color; break; case 4: /* Shift */ cp=&layout->Options.Shift.color; } *cp=ColorAsk(*cp); ShowAttributes(layout,TRUE); } Local(GrouP) OptionsGroup(LayoutDataPtr layout, GrouP parent) { GrouP g,gw; int i; Char b[5]; g=CreateNormalGroup(parent,0,4,Text[ATTR_T]); layout->grAttrOf=gw=CreateNormalGroup(g,2,0,Text[ATTROF_T]); SetAction(gw,(ActnProc)SetAttrOfProc); layout->buAttrOf[0]=RadioButton(gw,Text[POINTS_P]); layout->buAttrOf[1]=RadioButton(gw,Text[PATHS_P]); layout->buAttrOf[2]=RadioButton(gw,Text[TRACES_P]); if (!IsDimGMore1()) Disable(layout->buAttrOf[2]); /* Traces */ if (layout->Kind==0) layout->buAttrOf[3]=RadioButton(gw,Text[SHIFTS_P]); SetValue(gw,1); /* Points */ layout->grStyle=gw=CreateNormalGroup(g,3,0,Text[JOIN_T]); SetAction(gw,(ActnProc)StyleProc); RadioButton(gw,Text[NO_B]); RadioButton(gw,Text[SOLID_B]); RadioButton(gw,Text[DOTTED_B]); layout->grWidth=gw=CreateNormalGroup(g,5,0,Text[WIDTH_P]); SetAction(gw,(ActnProc)WidthProc); for (i=0; i<10; i++) { sprintf(b,"%i",i); RadioButton(gw,b); } PushButton(g,Text[COLOR_B],SetGraphicAttrColor); return g; } Callback(void) lCurrentAtr(Int2 indx) { WinComDataPtr wcd=GetComDataI; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; LayoutDataPtr layout; WindoW db; GrouP MainGroup,g,gA; GrouP gFunctions,gAJB,gB,gSWSC,gSWS,gOptions; ButtoN bu; LisT list=NULL; /* for Kind==2 */ RecT r,rr; CharPtr helpkey; Int2 i,ti; int numwidth,textwidth,lines,linelen; layout=MemNew(sizeof(LayoutData)); layout->Com=wcd; if (GraphicMenu[indx].Title==CURRENTATR_I) { layout->Kind=0; /* Current visual attributes */ helpkey=KH_CURRENTATTR; ti=DRAWATTR_T; } if (GraphicMenu[indx].Title==CURVEATR_I) { layout->Kind=2; /* Curve's visual attributes */ helpkey=KH_CURVEATTR; ti=CURVEATTR_T; } sscanf(Text[SIZES],"%i,%i,(%i,%i)",&numwidth,&textwidth,&lines,&linelen); LockMenus(); /* will not wait */ PushContext(helpkey,NULL,Text[WAITATTR_C]); db=FixedWindow(-50,-50,-sysCharWidth,-sysLineHeight,Text[ti],NULL); SetWindowExtra(db,layout,NULL); MainGroup=InitLargeWindow(db); SetGroupSpacing(MainGroup,0,sysLineHeight/2); SetGroupMargins(MainGroup,0,0); if (layout->Kind==2) { /* attribs of active curve */ Int2 wid; PrompT prm; wid=StringWidth(Text[SEG_P]); i=StringWidth(Text[SPF_P]); if (widswSegment=SwitchCreate(g,10,SegmentProc); #else StaticPrompt(g,Text[SEG_P],wid,0,NULL,'l'); layout->swSegment=LeftRightSwitch(g,TRUE,SegmentProc); #endif StaticPrompt(g,Text[SPF_P],wid,0,NULL,'l'); layout->prFrom=StaticPrompt(g,"",0,0,NULL,'l'); StaticPrompt(g,Text[SPT_P],wid,0,NULL,'l'); layout->prTo=StaticPrompt(g,"",0,0,NULL,'l'); g=CreateHiddenGroup(g,4,0,0); SetGroupMargins(g,0,0); #if MYSWITCH prm=StaticPrompt(g,Text[AN_P],wid,SwitchHeight(),NULL,'l'); layout->swAttr=SwitchCreate(g,10,AttrProc); #else StaticPrompt(g,Text[AN_P],wid,0,NULL,'l'); layout->swAttr=LeftRightSwitch(g,TRUE,AttrProc); #endif bu=PushButton(g,Text[AA_B],AddAttrProc); if (ccd.Computing) Hide(bu); layout->buDelFun=PushButton(g,Text[DA_B],DelAttrProc); GetPosition(bu,&rr); i=rr.bottom-rr.top; GetPosition(layout->swAttr,&r); i=(i-r.bottom+r.top)/2; if (i>0) { OffsetRect(&r,0,i-(r.top-rr.top)); SetPosition(layout->swAttr,&r); GetPosition(prm,&r); OffsetRect(&r,0,i-(r.top-rr.top)); SetPosition(prm,&r); } } else { /* V-functions group */ gFunctions=CreateNormalGroup(MainGroup,-2,0,Text[CURVES_P]); gAJB=CreateHiddenGroup(gFunctions,0,3,1); gA=CreateHiddenGroup(gAJB,3,0,0); SetGroupSpacing(gA,0,0); CreatePrompt(gA,ABS_P); layout->Axis[0].teFunc=DialogText(gA,"",textwidth,FuncChanged); SetTextSelect(layout->Axis[0].teFunc,MarkSelection,NULL); layout->scBar=ScrollBar(gA,0,1,SelFuncPairProc); CorrectBarMax(layout->scBar,gd->FuncNum-1); /* [0..FuncNum-1] */ CreatePrompt(gA,ORD_P); layout->Axis[1].teFunc=DialogText(gA,"",textwidth,FuncChanged); SetTextSelect(layout->Axis[1].teFunc,MarkSelection,NULL); gB=CreateHiddenGroup(gAJB,2,0,1); SetGroupMargins(gB,GetGroupSM("hmx"),4*GetGroupSM("nmy")); bu=PushButton(gB,Text[ADDFUN_B],AddFunProc); if (ccd.Computing) Hide(bu); layout->buDelFun=PushButton(gB,Text[DELFUN_B],DelFunProc); GetPosition(gAJB,&r); i=r.right-r.left; GetPosition(layout->buDelFun,&rr); i-=rr.right-rr.left; GetPosition(bu,&rr); i-=rr.right-rr.left; if (i>0) { i/=3; GetPosition(bu,&r); OffsetRect(&r,i-GetGroupSM("hmx"),0); SetPosition(bu,&r); GetPosition(layout->buDelFun,&r); OffsetRect(&r,2*i-GetGroupSM("hsx"),0); SetPosition(layout->buDelFun,&r); } layout->ptFuncNum=CreatePrompt(gAJB,FUNCNUM_P); GetPosition(gAJB,&r); i=r.bottom-r.top-sysLineHeight-2*GetGroupSM("nmy"); list=CreateNamesList(gFunctions,linelen,i/sysLineHeight,NamesListProc,NULL); } /* Graphic options and sample */ gSWSC=CreateHiddenGroup(MainGroup,2,0,0); gSWS=OptionsGroup(layout,gSWSC); GetPosition(Parent(gSWS),&r); i=r.bottom-r.top-2*GetGroupSM("nmy")-sysLineHeight; CreateSampleGroup(gSWSC,i,i); if (layout->Kind==0) { gOptions=CreateNormalGroup(MainGroup,0,2,Text[OPTIONS_P]); layout->cbClear=CheckBox(gOptions,Text[CLEAR_P],ClearProc); AlignObjects(ALIGN_RIGHT,(HANDLE)gFunctions,(HANDLE)gOptions,NULL); } else { AlignObjects(ALIGN_RIGHT,(HANDLE)layout->prFrom, (HANDLE)layout->prTo, (HANDLE)MainGroup, NULL); } AlignObjects(ALIGN_RIGHT,(HANDLE)layout->paLimits,(HANDLE)layout->paPalette,(HANDLE)layout->paDraw, (HANDLE)Parent(list), NULL); AlignObjects(ALIGN_LOWER,(HANDLE)layout->Axis[1].teFunc,(HANDLE)layout->scBar,NULL); /* Create terminate buttons */ TerminalButtons((WindoW)MainGroup,MainGroup,LayoutOk,LayoutCancel,LayoutHelp); /* Fill in work area with temporary copies of options */ CopyToWork(layout,wcd); /* Show and activate */ ShowAttributes(layout,TRUE); ShowLargeWindow(MainGroup); } /*-----------------------------*/ /* Curve's attributes callback */ Callback(void) lCurveAtr(Int2 indx) { lCurrentAtr(indx); } /*-------------------*/ /* Hardcopy callback */ typedef struct { WindoW wParent; TexT File; /* 'File name' prompt */ LisT Font; /* 'Font' list */ LisT Size; /* 'Size' list */ TexT Width_; TexT Height_; PopuP Unit; TexT LineWidthFactor; TexT CurveWidthFactor; TexT MarkerFactor; ButtoN Color; #if _UNIX ButtoN Preview; /* 'Preview' checkbox */ ButtoN Print; #endif Int2 oldunit; } hcOptData, PNTR hcOptDataPtr; #define MINSIZE 8 #define MAXSIZE 16 Callback(void) HardcopyCancel(ButtoN b) { WindoW optwin; hcOptDataPtr data; optwin=ParentWindow(b); data=(hcOptDataPtr)GetWindowExtra(optwin); Select(data->wParent); MemFree(data); Remove(optwin); UnlockMenus(); PopContext(); } Local(float) hcPageWidth, hcPageHeight; /* in Postscript's default units (1/72 of inch) */ Local(float) hcLineWidthFactor,hcCurveWidthFactor,hcMarkerFactor; Local(Int2) hcFontCur=1, hcFontSize=12; Local(Boolean) hcColor; /* whether to honor colors in hardcopy */ Local(float) hcUnitMult[]={72/25.4,72/2.54,72/1.0}; /* Hardcopy: PostScript */ Local(Char) hc_Header[]= "%%!PS-Adobe-3.0\n" "%%%%Creator: Content "VERSION"\n" "%%%%CreationDate: %s\n" "%%%%Pages:1\n" "%%%%BoundingBox: 0 0 %g %g\n" "%%%%EndComments\n\n" ; Local(Char) hc_ProcDef[]= "%%%%BeginProlog\n" "%%%%BeginResource: graphics\n\n" "%%margin[i]+=v: [lm rm tm bm] i v PUT4 [lm rm tm bm]\n" "/PUT4 {\n" " 3 -1 roll aload pop\n" " 4 6 index 1 add neg roll\n" " 4 index exch pop 4 6 index 1 add roll\n" " 4 array astore exch pop exch pop\n" " } bind def\n\n" "%% PageWidth: - GPW hcPageWidth\n" "/GPW %g def\n" "%% PageHeight: - GPH hcPageHeight\n" "/GPH %g def\n" "%% MathXmin&MathXmax\n" "/GMXMINW %g def\n/GMXMAXW %g def\n" "%% MathYmin&MathYmax\n" "/GMYMINW %g def\n/GMYMAXW %g def\n" "%% MathWidth: - GMW Xmax-Xmin\n" "/GMWW {GMXMAXW GMXMINW sub} def\n" "/GMW GMWW def\n" "%% MathHeight: - GMH Ymax-Ymin\n" "/GMHW {GMYMAXW GMYMINW sub} def\n" "/GMH GMHW def\n" "%% CurveWidth: devwidth GCWIDTH userwidth\n" "/GCWIDTH {%g mul dup idtransform pop} bind def\n" "%% LineWidth: devwidth GLWIDTH userwidth\n" "/GLWIDTH {%g mul dup idtransform pop} bind def\n" "%% MarkerScale: userscale GMSCALE userscale\n" "/GMSCALE {%g mul 2 div} bind def\n" "%% Colors\n" "/ISCOLORW {systemdict /setrgbcolor known %s and} bind def\n" "/ISCOLOR ISCOLORW def\n" "/BWCOLOR 0 def\n" "/BWSWAP {/BWCOLOR 1 BWCOLOR sub def} bind def\n\n" "%% SetMathSpace: - GSETMATH oldmatrix\n" "/GSETMATH {matrix currentmatrix\n" " [ GPW GPLM sub GPRM sub GMW div 0 0" " GPH GPTM sub GPBM sub GMH div" " 3 index 1 index\n" " GMYMINW mul neg GPBM add exch GMXMINW mul neg GPLM add exch] \n" " matrix currentmatrix matrix concatmatrix setmatrix\n" " } bind def\n" "%% PageLeftMargin: - GPLM plm\n" "/GPLM {GP?M 0 get} bind def\n" "%% PageRightMargin: - GPRM prm\n" "/GPRM {GP?M 1 get} bind def\n" "%% PageTopMargin: - GPTM ptm\n" "/GPTM {GP?M 2 get} bind def\n" "%% PageBottomMargin: - GPBM pbm\n" "/GPBM {GP?M 3 get} bind def\n" "%% stdLineHeight: - GSTDHD heigh descent\n" "/GSTDHD {gsave\n" " newpath 0 0 moveto (0) false charpath pathbbox" " exch pop exch sub exch pop\n" " newpath 0 0 moveto (0p) false charpath pathbbox" " exch pop exch sub exch pop 1 index sub\n" " grestore} bind def\n" "%% stdCharWidth: - GSTDW width\n" "/GSTDW {gsave\n" " newpath 0 0 moveto (W) false charpath pathbbox pop exch pop exch sub\n" " grestore} bind def\n" "%% a b c d GSPW a*c+b*d\n" "/GSPW {" " 2 index mul exch 3 index mul add exch pop exch pop" " } bind def\n" "%% incLeftMargin: [lm rm tm bm] [(s1)...] w GPLMW [lm rm tm bm]\n" "/GPLMW {\n" " GSTDW mul exch 0 exch\n" " {stringwidth pop 1 index 1 index lt {exch} if pop} forall\n" " add exch dup 0 get 3 -1 roll add 0 exch PUT4\n" " } bind def\n" "%% incRightMargin: [lm rm tm bm] [(s1)...] w GPRMW [lm rm tm bm]\n" "/GPRMW {" " GSTDW mul exch 0 exch\n" " {stringwidth pop 1 index 1 index lt {exch} if pop} forall\n" " add exch dup 1 get 3 -1 roll add 1 exch PUT4\n" " } bind def\n" "%% incTopMargin: [lm rm tm bm] h d GPTMW [lm rm tm bm]\n" "/GPTMW {\n" " GSTDHD GSPW exch dup 2 get 3 -1 roll add 2 exch PUT4" " } bind def\n" "%% incBottomMargin: [lm rm tm bm] h d GPBMW [lm rm tm bm]\n" "/GPBMW {\n" " GSTDHD GSPW exch dup 3 get 3 -1 roll add 3 exch PUT4\n" " } bind def\n\n" "%% xScale: HeighFactor DescentFactor (s) x y GXS\n" "/GXS {\n" " newpath 1 index 1 index GSETMATH 3 1 roll moveto setmatrix\n" " 0 GSTDW 2 div rlineto 1 GLWIDTH setlinewidth stroke\n" " newpath GSETMATH 3 1 roll moveto setmatrix\n" " 3 1 roll GSTDHD GSPW neg 1 index stringwidth pop 2 div neg exch rmoveto show\n" " stroke} bind def\n" "%% yScale: RelRightMargin (s) x y GYS\n" "/GYS {\n" " newpath 1 index 1 index GSETMATH 3 1 roll moveto setmatrix\n" " GSTDW 2 div 0 rlineto 1 GLWIDTH setlinewidth stroke\n" " newpath GSETMATH 3 1 roll moveto setmatrix\n" " exch GSTDW mul 1 index stringwidth pop add neg GSTDHD pop 2 div neg rmoveto show\n" " stroke} bind def\n" "%% xLabel: (label) GXL\n" "/GXL {\n" " GMXMAXW GMYMINW newpath GSETMATH 3 1 roll moveto setmatrix\n" " dup stringwidth pop GSTDW 2 div add neg GSTDHD pop 2 div rmoveto show stroke\n" " } bind def\n" "%% yLabel: (label) GYL\n" "/GYL {\n" " GMXMINW GMYMAXW newpath GSETMATH 3 1 roll moveto setmatrix\n" " GSTDW 2 div 1.5 0 GSTDHD GSPW neg rmoveto show stroke\n" " } bind def\n" "%% xAxis: GXA\n" "/GXA {\n" " newpath GSETMATH GMXMINW 0 moveto GMXMAXW 0 lineto setmatrix\n" " 1 GLWIDTH setlinewidth stroke\n" " } bind def\n" "%% yAxis: GYA\n" "/GYA {\n" " newpath GSETMATH 0 GMYMINW moveto 0 GMYMAXW lineto setmatrix\n" " 1 GLWIDTH setlinewidth stroke\n" " } bind def\n" "%% xGrid: x GXG\n" "/GXG {\n" " newpath GSETMATH exch dup GMYMINW moveto GMYMAXW lineto setmatrix\n" " gsave 1 GLWIDTH setlinewidth [GSTDW 32 div GSTDW 2 div] GSTDW 8 div setdash stroke grestore\n" " } bind def\n" "%% yGrid: y GYG\n" "/GYG {\n" " newpath GSETMATH exch dup GMXMINW exch moveto GMXMAXW exch lineto setmatrix\n" " gsave 1 GLWIDTH setlinewidth [GSTDW 32 div GSTDW 2 div] GSTDW 8 div setdash stroke grestore\n" " } bind def\n\n" "%% Frame: - GFRAME -\n" "/GFRAME {newpath\n" " GPLM GPBM moveto\n" " GPW GPRM sub GPBM lineto\n" " GPW GPRM sub GPH GPTM sub lineto\n" " GPLM GPH GPTM sub lineto\n" " closepath 1 GLWIDTH setlinewidth gsave stroke grestore clip} bind def\n" "%% UnitCircle: - GUNITCIRCLE -\n" "/GUNITCIRCLE {\n" "newpath GSETMATH 0 0 1 0 360 arc setmatrix\n" "1 GLWIDTH setlinewidth stroke\n" "} bind def\n\n" "%% SetPen: width style PEN -\n" "/PEN {\n" " 0 setlinecap\n" " dup 0 gt {dup 1 eq {[]}\n" " {dup 2 eq {[0 2 index GCWIDTH 6 mul] 1 setlinecap}\n" " {[1 index GCWIDTH dup 3 mul exch 4 mul]}\n" " ifelse\n" " } ifelse\n" " 0 setdash\n" " } if pop\n" " GCWIDTH setlinewidth\n" " } bind def\n" "%% Color: r g b COLOR -\n" "/COLOR {ISCOLOR {setrgbcolor}{pop pop pop BWCOLOR setgray} ifelse} bind def\n" "%% Point: x y POINT -\n" "/POINT {\n" " newpath GSETMATH 3 1 roll transform 3 -1 roll setmatrix itransform\n" " currentlinewidth 2 div 0 360 arc fill\n" " } bind def\n" "%% Line: x y xo yo LINE -\n" "/LINE {\n" " newpath GSETMATH 5 1 roll moveto lineto setmatrix stroke\n" " } bind def\n" "%%FRAME/PAINT CIRCLE: x y radius r g b ...CIRCLE -\n" "/CIRCLE {\n" " COLOR GMSCALE 3 1 roll GSETMATH 4 1 roll transform 4 -1 roll setmatrix itransform 3 -1 roll 0 360 arc} bind def\n" "/FRAMECIRCLE {\n" " CIRCLE 1 GLWIDTH setlinewidth stroke\n" " } bind def\n" "/PAINTCIRCLE {\n" " CIRCLE fill\n" " } bind def\n" "%%FRAME/PAINT POLYLINE: rxn ryn ... rx1 ry1 n x y r g b ...POLY -\n" "/POLY {\n" " COLOR GSETMATH 3 1 roll moveto setmatrix\n" " 1 1 3 -1 roll {3 1 roll GMSCALE exch GMSCALE exch 3 -1 roll 1 eq {rmoveto}{rlineto} ifelse} for\n" " } bind def\n" "/FRAMEPOLY {POLY closepath 1 GLWIDTH setlinewidth stroke} bind def\n" "/PAINTPOLY {POLY closepath fill} bind def\n" "%% STRMARKER: (s) ow oh mw mh ox oy x y STRMARKER -\n" "/STRMARKER {\n" " newpath GSETMATH 3 1 roll moveto\n" " setmatrix GMSCALE exch GMSCALE exch rmoveto\n" " GSTDHD pop mul exch 4 index stringwidth pop mul exch rmoveto\n" " GSTDHD pop mul exch GSTDW mul exch rmoveto\n" " show\n" " } bind def\n" "%%%%EndResource\n" "%%%%EndProlog\n\n" ; Local(Char) hc_DocSetup[]= "%%%%BeginSetup\n" " /%s findfont\n" " %i scalefont setfont\n" " 1 setlinecap\n" "%%lpr%% 72 72 translate\n" "%%%%EndSetup\n\n" ; /* Output Header, Procedure defenitions, Document setup */ Local(void) hcInit(GraphicDataPtr gd) { Char date[25]; /* see DayTimeStr in corelib */ /* Header */ DayTimeStr(date,TRUE,TRUE); /* get date and time */ fprintf(gd->HardFile,hc_Header,date,hcPageWidth, hcPageHeight); /* Procedure defenitions */ fprintf(gd->HardFile,hc_ProcDef,hcPageWidth,hcPageHeight, gd->RAxis[0].Min, gd->RAxis[0].Max, gd->RAxis[1].Min, gd->RAxis[1].Max, hcCurveWidthFactor, hcLineWidthFactor, hcMarkerFactor, hcColor ? "true" : "false" ); /* Document setup */ fprintf(gd->HardFile,hc_DocSetup,hcFontList[hcFontCur],(int)hcFontSize); gd->hcMarkerNo=0; } Local(Char) hc_Trailer[]= /*** "%%lpr%% showpage\n"***/ "showpage\n" "%%%%Trailer\n" "%%%%EOF\n" ; /* Output Document trailer */ Local(void) hcTerm(GraphicDataPtr gd) { int i; fprintf(gd->HardFile,"%%BeginMarkers:\n"); for (i=0; ihcMarkerNo; i++) fprintf(gd->HardFile,"MARKER%i\n",i); fprintf(gd->HardFile,"%%EndMarkers:\n"); fprintf(gd->HardFile,hc_Trailer); } Callback(void) HardcopyOk(ButtoN b) { WindoW optwin=ParentWindow(b); hcOptDataPtr data=(hcOptDataPtr)GetWindowExtra(optwin); WinComDataPtr wcd=(WinComDataPtr)GetWindowExtra(data->wParent); GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; #if _UNIX CharPtr p; Char Buf[PAR_BUF]; #endif float val; Int2 n; Char buf[PATH_MAX+100],num[20]; Hide(optwin); /* file name */ GetTitle(data->File,buf,PATH_MAX); gd->HardFile=fopen(buf,"wt"); if (!gd->HardFile) Warning("HC_OPEN",buf); /* Width, Height, unit */ n=GetValue(data->Unit); GetTitle(data->Width_,num,sizeof(num)); sscanf(num,"%g",&val); hcPageWidth=val*hcUnitMult[n-1]; GetTitle(data->Height_,num,sizeof(num)); sscanf(num,"%g",&val); hcPageHeight=val*hcUnitMult[n-1]; sprintf(buf+StrLen(buf)," %g %g %i",hcPageWidth,hcPageHeight,(int)n); /* Font */ hcFontCur=GetValue(data->Font); if (hcFontCur) hcFontCur--; sprintf(buf+StrLen(buf)," %s",hcFontList[hcFontCur]); /* Size */ n=GetValue(data->Size); hcFontSize=n ? n+MINSIZE-1 : MINSIZE; sprintf(buf+StrLen(buf)," %i",(int)hcFontSize); /* CurveWidthFactor */ GetTitle(data->CurveWidthFactor,num,sizeof(num)); sscanf(num,"%g",&hcCurveWidthFactor); sprintf(buf+StrLen(buf)," %g",hcCurveWidthFactor); /* LineWidthFactor */ GetTitle(data->LineWidthFactor,num,sizeof(num)); sscanf(num,"%g",&hcLineWidthFactor); sprintf(buf+StrLen(buf)," %g",hcLineWidthFactor); /* MarkerFactor */ GetTitle(data->MarkerFactor,num,sizeof(num)); sscanf(num,"%g",&hcMarkerFactor); sprintf(buf+StrLen(buf)," %g",hcMarkerFactor); /* Color toggle */ sprintf(buf+StrLen(buf)," %c","ft"[hcColor=GetStatus(data->Color)]); #if _UNIX /* Preview toggle */ sprintf(buf+StrLen(buf)," %c","ft"[GetStatus(data->Preview)]); /* Print toggle */ sprintf(buf+StrLen(buf)," %c","ft"[GetStatus(data->Print)]); #endif /* Save current settings */ SetParam(SECTION,"HARDCOPY",buf); /* Create PostScript file */ if (gd->HardFile) { gd->Hardcopy=TRUE; hcSetMode(wcd,gd->HardFile); hcInit(gd); RedrawDiagram(0); hcTerm(gd); gd->Hardcopy=FALSE; fclose(gd->HardFile); } #if _UNIX *StrChr(buf,' ')='\0'; /* filename */ if (GetStatus(data->Preview)) { p=GetParamString(SECTION_COM,"HCVIEWER"); sprintf(Buf,p,buf); system(Buf); } if (GetStatus(data->Print)) { FILE *in, *out; Char b[500]; CharPtr p; in=fopen(buf,"rt"); p=GetParamString(SFS_FILES,"TEMP"); out=fopen(p,"wt"); if (in && out) { while (fgets(b,sizeof(b),in)) { if (!StrNCmp(b,"%lpr%",5)) StrCpy(b,b+5); fputs(b,out); } } fclose(in); fclose(out); StrCpy(b,p); p=GetParamString(SECTION_COM,"HCPRINTER"); sprintf(Buf,p,b); system(Buf); } #endif HardcopyCancel(b); } #if _WIN #pragma argsused #endif Callback(void) HardcopyHelp(ButtoN b) { Help(NULL); } Callback(void) UnitCallback(PopuP Unit) { hcOptDataPtr data; float val; Char num[20]; Int2 unit=GetValue(Unit); data=(hcOptDataPtr)GetWindowExtra(ParentWindow(Unit)); GetTitle(data->Width_,num,sizeof(num)); sscanf(num,"%g",&val); hcPageWidth=val*hcUnitMult[data->oldunit-1]; sprintf(num,"%g",hcPageWidth/hcUnitMult[unit-1]); SetTitle(data->Width_,num); GetTitle(data->Height_,num,sizeof(num)); sscanf(num,"%g",&val); hcPageHeight=val*hcUnitMult[data->oldunit-1]; sprintf(num,"%g",hcPageHeight/hcUnitMult[unit-1]); SetTitle(data->Height_,num); data->oldunit=unit; } Callback(void) HardcopyOutFile(ButtoN b) { WindoW optwin; hcOptDataPtr data; Char def[PATH_MAX],file[PATH_MAX]; optwin=ParentWindow(b); data=(hcOptDataPtr)GetWindowExtra(optwin); GetTitle(data->File,def,sizeof(def)); *file='\0'; if (GetOutputFileName(file,sizeof(file),def)) SetTitle(data->File,file); } #if _WIN #pragma argsused #endif Callback(void) lHardcopy(Int2 index) { WindoW optwin; hcOptDataPtr data; GrouP g,gFile,gFont,gPicture,gOpt; CharPtr p; int pos,unit; Int2 i; Char b[50]; CharPtr Buf; data=MemNew(sizeof(hcOptData)); data->wParent=CurrentWindow(); LockMenus(); /* lock second time because otherwise it would be unlocked immediatedly after return */ optwin=FixedWindow(-50,-50,-sysCharWidth,-sysLineHeight, Text[HARDCOPY_T],NULL); SetWindowExtra(optwin,data,NULL); /* Create controls */ gFile=CreateNormalGroup(optwin,2,0,Text[HCFILE_G]); SetGroupSpacing(gFile,sysCharWidth,0); SetGroupMargins(gFile,sysCharWidth,sysLineHeight/2); data->File=DialogText(gFile,"",20,NULL); PushButton(gFile,Text[HCFILELIST_B],HardcopyOutFile); gPicture=CreateNormalGroup(optwin,3,0,Text[HCPIC_P]); SetGroupSpacing(gPicture,sysCharWidth,0); SetGroupMargins(gPicture,sysCharWidth,sysLineHeight/2); g=CreateHiddenGroup(gPicture,2,0,0); SetGroupSpacing(g,2,0); StaticPrompt(g,Text[HCWIDTH_P],0,dialogTextHeight,NULL,'l'); data->Width_=DialogText(g,"",5,NULL); g=CreateHiddenGroup(gPicture,2,0,0); SetGroupSpacing(g,2,0); StaticPrompt(g,Text[HCHEIGHT_P],0,dialogTextHeight,NULL,'l'); data->Height_=DialogText(g,"",5,NULL); data->Unit=PopupList(gPicture,FALSE,UnitCallback); StrCpy(b,Text[HCUNITS]); for (i=0; i<3; i++) { p=StrChr(b,' '); if (p) *p++='\0'; PopupItem(data->Unit,b); if (p) StrCpy(b,p); } gFont=CreateNormalGroup(optwin,2,0,Text[HCFONTG_P]); SetGroupSpacing(gFont,sysCharWidth,0); SetGroupMargins(gFont,sysCharWidth,sysLineHeight/2); data->Font=SingleList(gFont,15,5,NULL); data->Size=SingleList(gFont,4,5,NULL); gOpt=CreateNormalGroup(optwin,2,0,Text[HCOPT_P]); StaticPrompt(gOpt,Text[HCCWIDF_P],0,dialogTextHeight,NULL,'l'); data->CurveWidthFactor=DialogText(gOpt,"",2,NULL); StaticPrompt(gOpt,Text[HCLWIDF_P],0,dialogTextHeight,NULL,'l'); data->LineWidthFactor=DialogText(gOpt,"",2,NULL); StaticPrompt(gOpt,Text[HCMF_P],0,dialogTextHeight,NULL,'l'); data->MarkerFactor=DialogText(gOpt,"",2,NULL); data->Color=CheckBox(gOpt,Text[HCOPTCOL_P],NULL); Break(gOpt); #if _UNIX data->Preview=CheckBox(gOpt,Text[HCOPTPRE_P],NULL); data->Print=CheckBox(gOpt,Text[HCOPTPRI_P],NULL); #endif /* and set default values: */ Buf=GetParamString(SECTION,"HARDCOPY"); /* - file name */ StrTrim(Buf); p=StrChr(Buf,' '); if (p) *p++='\0'; SetTitle(data->File,Buf); StrCpy(Buf,p); /* - width, height, and unit */ sscanf(Buf," %g %g %i %n",&hcPageWidth,&hcPageHeight,&unit,&pos); data->oldunit=unit; sprintf(b,"%g",hcPageWidth/hcUnitMult[unit-1]); SetTitle(data->Width_,b); sprintf(b,"%g",hcPageHeight/hcUnitMult[unit-1]); SetTitle(data->Height_,b); SetValue(data->Unit,unit); StrCpy(Buf,Buf+pos); /* - font */ StrTrim(Buf); p=StrChr(Buf,' '); if (p) *p++='\0'; for (i=0; iFont,hcFontList[i]); if (!StrCmp(Buf,hcFontList[i])) { SetValue(data->Font,i+1); SetOffset(data->Font,0,i); } } StrCpy(Buf,p); /* - font size */ StrTrim(Buf); p=StrChr(Buf,' '); if (p) *p++='\0'; for (i=MINSIZE; i<=MAXSIZE; i++) { sprintf(b,"%i",(int)i); ListItem(data->Size,b); if (!StrCmp(Buf,b)) { SetValue(data->Size,i-MINSIZE+1); SetOffset(data->Size,0,i-MINSIZE); } } StrCpy(Buf,p); /* - curve width factor */ sscanf(Buf," %g %n",&hcCurveWidthFactor,&pos); sprintf(b,"%g",hcCurveWidthFactor); SetTitle(data->CurveWidthFactor,b); StrCpy(Buf,Buf+pos); /* - line width factor */ sscanf(Buf," %g %n",&hcLineWidthFactor,&pos); sprintf(b,"%g",hcLineWidthFactor); SetTitle(data->LineWidthFactor,b); StrCpy(Buf,Buf+pos); /* - marker factor */ sscanf(Buf," %g %n",&hcMarkerFactor,&pos); sprintf(b,"%g",hcMarkerFactor); SetTitle(data->MarkerFactor,b); StrCpy(Buf,Buf+pos); /* - color toggle */ StrTrim(Buf); SetStatus(data->Color,*Buf=='t'); StrCpy(Buf,Buf+1); #if _UNIX /* - preview toggle */ StrTrim(Buf); SetStatus(data->Preview,*Buf=='t'); StrCpy(Buf,Buf+1); /* - print toggle */ StrTrim(Buf); SetStatus(data->Print,*Buf=='t'); StrCpy(Buf,Buf+1); #endif /* Align */ AlignObjects(ALIGN_RIGHT,(HANDLE)gFile,(HANDLE)gFont,(HANDLE)gPicture,(HANDLE)gOpt,NULL); PushContext(HK_HARDCOPYWIN,NULL,Text[HARDCOPY_C]); TerminalButtons(optwin,gFile,HardcopyOk,HardcopyCancel,HardcopyHelp); Show(optwin); SelectText(data->File,0,0); } #undef MINSIZE #undef MAXSIZE /*---------------------------*/ /* Duplicate window callback */ #if _WIN #pragma argsused #endif Callback(void) lDuplicate(Int2 index) { WinComDataPtr wcd=GetComDataI; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; GraphicDataPtr cgd; /* new copy */ Int2 i,j; cgd=MemNew(sizeof(GraphicData)); if (cgd) { cgd->FuncNum=gd->FuncNum; cgd->FuncCur=gd->FuncCur; for (i=0; iAxis); i++) { cgd->Axis[i].pMin=StringSave(gd->Axis[i].pMin); cgd->Axis[i].pMax=StringSave(gd->Axis[i].pMax); cgd->Axis[i].Funcs=MemNew(ARRAYSIZE(AxisFunc,cgd->FuncNum)); for (j=0; jFuncNum; j++) { cgd->Axis[i].Funcs[j].pFunc=StringSave(gd->Axis[i].Funcs[j].pFunc); } cgd->Axis[i].pTick=StringSave(gd->Axis[i].pTick); MemCopy(cgd->Axis[i].Prop,gd->Axis[i].Prop,sizeof(cgd->Axis[i].Prop)); } cgd->Attr=MemNew(ARRAYSIZE(FuncAttr,cgd->FuncNum)); MemCopy(cgd->Attr,gd->Attr,ARRAYSIZE(FuncAttr,cgd->FuncNum)); MemCopy(&cgd->Options,&gd->Options,sizeof(cgd->Options)); cgd->flags=gd->flags; cgd->SpecialPoints=BSNew(0); if (DuplicateWindow(wcd,cgd)) { /* failure */ WinComData dwcd; dwcd.Private=cgd; WriteDescription(&dwcd,NULL); /* free cgd only */ } } } /*----------------------*/ /* Mouse menu callbacks */ #if _WIN #pragma argsused #endif Callback(void) lPickCoord(Int2 index) { WinComDataPtr wcd=GetComDataI; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; gd->flags^=MOUSE_PICK; if (!(gd->flags&MOUSE_PICK)) { gd->flags&=~(MOUSE_IMMB|MOUSE_IMMF); } } #if _WIN #pragma argsused #endif Callback(Boolean) lPickCoord_Status(Int2 index) { WinComDataPtr wcd=GetComDataI; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; return (gd->flags&MOUSE_PICK)!=0 && gd->FuncNum==1; } #if _WIN #pragma argsused #endif Callback(void) lImmedFComp(Int2 index) { WinComDataPtr wcd=GetComDataI; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; gd->flags^=MOUSE_IMMF; if (gd->flags&MOUSE_IMMF) { gd->flags&=~MOUSE_IMMB; gd->flags|=MOUSE_PICK; } } #if _WIN #pragma argsused #endif Callback(Boolean) lImmedFComp_Status(Int2 index) { WinComDataPtr wcd=GetComDataI; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; return (gd->flags&MOUSE_IMMF)!=0 && gd->FuncNum==1; } #if _WIN #pragma argsused #endif Callback(void) lImmedBComp(Int2 index) { WinComDataPtr wcd=GetComDataI; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; gd->flags^=MOUSE_IMMB; if (gd->flags&MOUSE_IMMB) { gd->flags&=~MOUSE_IMMF; gd->flags|=MOUSE_PICK; } } #if _WIN #pragma argsused #endif Callback(Boolean) lImmedBComp_Status(Int2 index) { WinComDataPtr wcd=GetComDataI; GraphicDataPtr gd=(GraphicDataPtr)wcd->Private; return (gd->flags&MOUSE_IMMB)!=0 && gd->FuncNum==1; } /*----------------*/ /* Help callbacks */ #if _WIN #pragma argsused #endif Callback(void) lHelp(Int2 indx) { Help(HK_2DWIN); } #if _WIN #pragma argsused #endif Callback(void) lHelpSearch(Int2 indx) { HelpSearch(HK_2DWIN); }