/* Visualizer */ #include #include "common.h" #include "datalib.h" #include "function.h" #include "file.h" #include "help.h" #include "diagram.h" #include "curve.h" #include "visual.h" #include "point.h" #include "userfunc.h" #include "param.h" #include "large.h" #define KERNEL #include "window.h" #undef KERNEL extern Global(CharPtr PNTR) VisualTxt; /* defined in setup.c */ enum { /* see setup.c, init[], /visual */ CONTEXT_C, /* Compiling, please wait... */ HIDDEN_C, /* Waiting for selection of window */ LIST_P, SHW_T, /* Select window to show */ D_U_M_M_Y } VisualTxtIndex; Local(Boolean) ParseName(CharPtr func, Int2Ptr p_index, Uint2Ptr p_offset); Global(FloatHiPtr PNTR PNTR) IndirectValues=NULL; /* Ptr to array of ptrs to vectors of values */ Local(void) SetWindowsFunctions(void); /*----------------------------------------*/ /* Data and vars related to visible names */ /* Descriptor of potentially visible variable */ typedef struct { CharPtr Name; /* Name of variable */ Uint2 Dim; /* Dimension (1 for simple) */ Uint2 Offset; /* Offset in class value vector */ Uint2 Mult; /* Multiplier for index */ } VisVar, PNTR VisVarPtr; /* Descriptor of a class of potentially visible variables */ typedef struct { CharPtr Name; /* Name of class (short name) */ CharPtr Title; /* Title of class (full name) */ VisVarPtr Variables; /* Ptr to an array of variables */ Uint2 Id; /* Unique id of class */ Uint2 Num; /* Number of variables in the class */ Int2 Dim; /* Dimension (number of components) of the class */ Uchar Flags; #define VN_RELEVANT 1 /* set for classes relevant to current curve type */ #define VN_DEFVIS 2 /* visible by default (see .con file) */ #define VN_BASIC 4 /* this class is either basic or derived from a basic one */ #define VN_DIMG 8 /* G-dim of the class > 1 */ } VisClass, PNTR VisClassPtr; /* Number of classes and ptr to their descriptor */ Local(Uint2) ClassNumber=0,ClassNumberAll; /* including those with codes >200 */ Local(VisClassPtr) ClassPtr=NULL; /*************/ /* I. Colors */ /*************/ /* SGI: Avoid calling of SelectColor for each point in each window */ typedef struct { #if _UNIX Uint4 rgb; Uint1 flag; #endif Uint1 r,g,b; } ColorRGB, PNTR ColorRGBPtr; Local(ColorRGBPtr) Palette=NULL; Local(Int2) PaletteSize=0; Local(Boolean) PaletteHasBeenChanged=FALSE; Global(Color) BlackIndex; Global(Color) WhiteIndex; Global(Uint4) defForeground; Global(Uint4) defBackground; #define defFgIndex -1000 #define defBgIndex -1001 Global(void) ReadPalette(void) { FILE PNTR stream; Int2 i; int r,g,b; FloatLo d,d_min,d_max; stream=FileOpen(GetParam(SFS_FILES,"PALETTE"),"rt"); if (stream) { for (PaletteSize=0; fscanf(stream,"%i %i %i",&r,&g,&b)==3; PaletteSize++); if (PaletteSize) { rewind(stream); Palette=_MemNew(ARRAYSIZE(ColorRGB,PaletteSize)); BlackIndex=WhiteIndex=0; d_min=255*sqrt(3); /* (255,255,255) */ d_max=0; /* (0,0,0) */ for (i=0; id) { BlackIndex=i; d_min=d; } if (d_max<=d) { WhiteIndex=i; d_max=d; } } } else myWarning("VI_PAL",ParBuf); FileClose(stream); } else myWarning("VI_OPEN",ParBuf); } Global(Int2) ColorNumber(void) { return PaletteSize; } Global(void) ColorSet(Color i) { switch (i) { case defFgIndex: defcol:; SetColor(defForeground); break; case defBgIndex: SetColor(defBackground); break; default: if (i>=0 && i long rgb */ Global(long) ColorOut(Color i) { long rgb; if (i>=0 && i Color index */ Global(Color) ColorIn(long rgb) { FloatLo d,d_min; FloatLo r,g,b; Int2 i; Color j; if (rgb<0) j=(Color)rgb; else { b=rgb%256; g=(rgb/256)%256; r=rgb/256/256; for (i=j=0,d_min=512; i=0 && InitColorNext) if (pwd->ComData.Win==win) return pwd; return NULL; } /* Deactivate/Activate windows. Called by individual window's to freeze all windows except the window itself. Example: redraw during Fit curve should not disturb other windows. */ Local(void) DeactivateWindows(WinComDataPtr wcd) { WindowPtr pwd; for (pwd=Windows; pwd; pwd=pwd->Next) { if (wcd==&pwd->ComData) continue; if (pwd->ComData.flags&(WFL_HIDDEN|WFL_FROZEN)) continue; pwd->ComData.flags|=WFL_HIDDEN|WFL_NOTACTIVE; } } Local(void) ActivateWindows(void) { WindowPtr pwd; for (pwd=Windows; pwd; pwd=pwd->Next) if (pwd->ComData.flags&WFL_NOTACTIVE) pwd->ComData.flags&=~(WFL_HIDDEN|WFL_NOTACTIVE); } /* Hardcopy stuff */ Local(WindowPtr) CurPwd; /* currently updated window's descriptor */ Local(WindowPtr) hcPwd; /* hardcopy window's descriptor */ Local(Boolean) hcFlag=FALSE; /* TRUE when redraw in hard copy mode */ Local(FILE PNTR) hcStream; /* hard copy output file */ Local(void) hcSetMode(WinComDataPtr wcd, FILE PNTR Stream) { WindowPtr pwd; hcPwd=NULL; hcStream=NULL; hcFlag=FALSE; if (Stream) for (pwd=Windows; pwd; pwd=pwd->Next) if (&pwd->ComData==wcd) { hcPwd=pwd; hcStream=Stream; hcFlag=TRUE; break; } } /* Utilities passed to windows class functions */ Local(Boolean) GdimEq1(CharPtr expr); Local(void) CheckWindowsFunctions(WindowPtr pwd); Local(void) RecreateWindow(WinComDataPtr wcd); Local(Boolean) HardCopyProc_Status(Int2 index); Local(GrouP) CreateNormalGroup(GrouP parent, Int2 x, Int2 y, CharPtr title); Local(GrouP) CreateHiddenGroup(GrouP parent, Int2 x, Int2 y, Int2 vspace); Local(Int2) GetGroupSM(CharPtr SMCode); Local(void) HideProc(Int2 index); Local(CharPtr PNTR) hcFontList=NULL; Local(Int2) hcFontNum=0; Local(Boolean) DuplicateWin(WinComDataPtr wcd, VoidPtr private); Local(Util) UtilList={ /* DataLib and Co */ &DiagramLib, &DataLibLastVRecLen, DataLibReadVRecord,DataLibWriteVRecord, DataLibRead,DataLibWrite, DataLibSavePos, DataLibRestorePos, DataLibSeek, /* Menu items and Co */ ForwardProc, BackwardProc, FBProc_Status, ContinueProc, ContinueProc_Status, RedrawDiagram, SelectCurve_Status, RedrawCurveProc, ContinueProc_Status, ClearAllWindows, HardCopyProc_Status, HideProc, /* Help */ Help, HelpSearch, /* Visible names */ GetNthRelevantClass, GetClassNameAndId,GetClassDim, GetNameAndDim, IsClassRelevant, EnumClasses,EnumVariables, ClassGlobToLoc, GetLocalClassVector, UpdateInitPoint, /* Colors */ ColorNumber,ColorSet, &BlackIndex,&WhiteIndex, ColorIn,ColorOut, ColorAsk, /* Draw */ SetCurrentPen, /* Special points */ PtNearSpecial, SetSpecialPoint, DrawSpecialPoint, SpecialPointPrev, IsMarker, ReadSPList, FreeSPList, GetSPAttr, GetSPname, /* Misc */ RecreateWindow, PushContext, PopContext, GdimEq1, IsDimGMore1, LockAll, UnlockAll, RefreshMenus, SetStatusOfItems, CreateNormalGroup,CreateHiddenGroup,GetGroupSM, TermButtons, CreateNamesList,MultiNamesList, GetTitleAndSave, CountLinesAndErase_r, LibraryFuncAddress, &ccd, &IndirectValues, &curveCurNum, &CurCurve, ComputeExpr, ParseName, InvalidateBifData, hcSetMode, &hcFontList, &hcFontNum, ReadVAList, WriteVAList, FreeVAList, PushVisualAttr, PopVisualAttr, SaveVisualAttr, RestoreVisualAttr, DuplicateWin, &FunctionsEntry, /* Critical intervals */ StartCR, EndCR, /* Windows */ DeactivateWindows,ActivateWindows, NULL }; /* Dynamically defined any window border's height and width */ Local(Int2) BorderHeight=-1,BorderWidth=-1; Local(Int2) WindowsNum=0; Local(Int4) WindowsMask=0; #define ALLMASK 0x7fffffffL /* Handle of windows' library (its name in PART_WINLIB) */ Local(LibHandle) hWinLib=NULL; Global(void) lInvertColors(void) { InvertColors(); if (hcFlag && CurPwd==hcPwd) fprintf(hcStream,"BWSWAP\n"); } Global(void) llString(Int2 x, Int2 y, CharPtr str, float PNTR hardcopy) { lString(x,y,str); if (hcFlag) if (CurPwd==hcPwd) hcPwd->Member->hcString(&hcPwd->ComData,str,hardcopy); } Global(void) lPaintOval(RectPtr r) { PaintOval(r); if (hcFlag) if (CurPwd==hcPwd) hcPwd->Member->hcPaintOval(&hcPwd->ComData,r); } Global(void) lFrameOval(RectPtr r) { FrameOval(r); if (hcFlag) if (CurPwd==hcPwd) hcPwd->Member->hcFrameOval(&hcPwd->ComData,r); } Global(void) lPaintRect(RectPtr r) { PaintRect(r); } Global(void) lFrameRect(RectPtr r) { FrameRect(r); } Global(void) lPaintPoly(Int2 num, PointPtr poly) { if (hcFlag) if (CurPwd==hcPwd) hcPwd->Member->hcPaintPoly(&hcPwd->ComData,num,poly); PaintPoly(num,poly); } Global(void) lFramePoly(Int2 num, PointPtr poly) { if (hcFlag) if (CurPwd==hcPwd) hcPwd->Member->hcFramePoly(&hcPwd->ComData,num,poly); FramePoly(num,poly); } /* Own Point and Line */ Local(Uint1) Penwidth,Penwidthd; Global(void) lMoveTo(Int2 x, Int2 y) { MoveTo(x,y); } Global(void) lPoint(Int2 x, Int2 y) { #if _WIN RecT r; Int2 lu,rb; if (Penwidth<=3) { if (Penwidth==3) { WidePen(1); MoveTo(x-1,y); LineTo(x+2,y); MoveTo(x,y-1); LineTo(x,y+2); WidePen(Penwidth); } else { WidePen(2); /* cannot find other way around: points with w=0,1 are invisible! */ MoveTo(x,y); LineTo(x,y); } } else { lu=rb=(Penwidth>>1); rb+=(Penwidth&1); LoadRect(&r,x-lu,y-lu,x+rb,y+rb); WidePen(1); PaintOval(&r); WidePen(Penwidth); } #endif /* _WIN */ #if _UNIX RecT r; Int2 lu,rb; if (Penwidth>=2) { lu=rb=(Penwidth>>1); rb+=(Penwidth&1); LoadRect(&r,x-lu,y-lu,x+rb,y+rb); WidePen(1); PaintOval(&r); WidePen(Penwidth); } else { WidePen(0); MoveTo(x,y); LineTo(x,y); } #endif /* _UNIX */ #if _MAC #error Point() is undefined #endif /* _MAK */ } Global(void) lLine(Int2 x1, Int2 y1, Int2 x2, Int2 y2) { #if _WIN MoveTo(x1,y1); LineTo(x2,y2); #endif #if _UNIX if (x1==x2) if (y1>y2) y1++; else y2++; MoveTo(x1,y1); LineTo(x2,y2); #endif #if _MAC #error lLine() is undefined #endif } Global(void) lString(Int2 x, Int2 y, CharPtr str) { MoveTo(x,y); SelectFont(SystemFont); PaintString(str); } /*-------------------------------------------------*/ /* Does an expression use only names with Gdim==1? */ /* G-dim of a visible name>1 if it is prefixed with '*' in a .con file (section /names), 1 otherwise. */ Local(Boolean) GdimEq1(CharPtr expr) { CharPtr p; Int2 i,j,l; if (IsDimGMore1() && expr) for (i=0; iNext; pwdw=pwdw->Next); pwdw->Next=pwd; } else Windows=pwd; WindowsNum++; pwd->WinClass=winclass; } else { myWarning("VI_MANY"); pwd=NULL; } return pwd; } Local(WindowPtr) CreateAndFillWindowDesc(Int2 winclass) { WindowPtr pwd; Int4 mask; Int1 i; pwd=CreateWindowDescriptor(winclass); if (pwd) { for (mask=1,i=0; WindowsMask&mask; mask<<=1,i++); pwd->ComData.Unique=i; WindowsMask|=mask; pwd->ComData.Left=pwd->ComData.Top=-50; /* centrate */ #if _WIN pwd->ComData.Width=2*(screenRect.right-screenRect.left)/3; #else pwd->ComData.Width=(screenRect.right-screenRect.left)/2; #endif pwd->ComData.Height=(screenRect.bottom-screenRect.top)/2; pwd->ComData.Foreground=defFgIndex; /* default */ pwd->ComData.Background=defBgIndex; /* default */ pwd->ComData.BorderWidth=BorderWidth; pwd->ComData.BorderHeight=BorderHeight; } return pwd; } Local(void) DeleteWindowDescriptor(WindowPtr pwind) { WindowPtr pwd; if (Windows==pwind) Windows=pwind->Next; else { for (pwd=Windows; pwd->Next!=pwind; pwd=pwd->Next); pwd->Next=pwind->Next; } _MemFree(pwind); WindowsNum--; } /*-----------------*/ /* LockAll and Co. */ Global(void) LockAll(void) { WindowPtr pwd; Lock(&MainMenu); Lock(&TypeMenuDesc); Lock(&ClassMenuDesc); Lock(&WindowMenuDesc); for (pwd=Windows; pwd; pwd=pwd->Next) { Lock(&pwd->ComData.MenuDesc); pwd->Member->ManageControls(&pwd->ComData,FALSE); } ParamLock(TRUE); } Global(void) UnlockAll(void) { WindowPtr pwd; for (pwd=Windows; pwd; pwd=pwd->Next) if (MainMenu.Lock<=pwd->ComData.MenuDesc.Lock) { /* to coordinate with main menu */ if (Unlock(&pwd->ComData.MenuDesc)==0) pwd->Member->ManageControls(&pwd->ComData,(Boolean)!(pwd->ComData.flags&WFL_FROZEN)); } Unlock(&MainMenu); Unlock(&TypeMenuDesc); Unlock(&ClassMenuDesc); Unlock(&WindowMenuDesc); ParamLock(FALSE); } Global(void) RefreshMenus(void) { WindowPtr pwd; for (pwd=Windows; pwd; pwd=pwd->Next) SetStatusOfItems(&pwd->ComData.MenuDesc); SetStatusOfItems(&MainMenu); SetStatusOfItems(&TypeMenuDesc); SetStatusOfItems(&ClassMenuDesc); SetStatusOfItems(&WindowMenuDesc); } Global(void) PauseItemsAll(Boolean enable) { WindowPtr pwd; for (pwd=Windows; pwd; pwd=pwd->Next) PauseItems(&pwd->ComData.MenuDesc,enable); PauseItems(&MainMenu,enable); } /* Returns TRUE if there is incompleted action during suspend mode */ Global(Boolean) IncompleteAction(void) { return MainMenu.Lock>1; } /*-------------------------------------------------------*/ /* Generic Create/Delete/Resize/Options/Clear/Hide/Close */ /* Reset position for controls in a window */ Local(void) SetInitialPosition(WindoW w) { PoinT p; LoadPt(&p,WHM,WVM); SetNextPosition(w,p); } /* Redraw an object */ Global(void) Redraw(PaneL p) { RecT r; if (p) { /* p may be 0 for Scrollable text window */ Select(p); GetPosition(p,&r); InvalRect(&r); Update(); } } /* Show window and calculate its borders */ Local(void) ShowWin(WindoW w) { Show(w); } /* Deletes a window */ Local(void) DeleteWin(WindowPtr pwd) { Hide(pwd->ComData.Win); /* avoid redraw */ pwd->Member->RemoveControls(&pwd->ComData); Remove(pwd->ComData.Win); pwd->ComData.Win=0; pwd->ComData.MenuDesc.Menu=_MemFree(pwd->ComData.MenuDesc.Menu); pwd->ComData.WinTitle=_MemFree(pwd->ComData.WinTitle); pwd->ComData.Private=_MemFree(pwd->ComData.Private); } #if _WIN #pragma argsused #endif /* Hide the window */ Local(void) HideProc(Int2 index) { WindowPtr pwd; pwd=GetWindowData(CurrentWindow()); Hide(pwd->ComData.Win); pwd->ComData.flags|=WFL_HIDDEN; RefreshMenus(); } Local(void) ResizeProc(WindoW w) { WindowPtr pwd; RecT r; Int2 width,height; /* Get ptr to window's descriptor */ pwd=GetWindowData(w); /* Should we ignore? */ if (pwd->ComData.flags&WFL_DONT_RESIZE) { /* Called immediately after DocumentWindow */ pwd->ComData.flags&=~WFL_DONT_RESIZE; /* Hide was moved here from CreateWin because it does not work there under Motif */ if (pwd->ComData.flags&WFL_HIDDEN) Hide(w); return; } GetPosition(w,&r); width=(r.right-r.left+1)-pwd->ComData.BorderWidth; height=(r.bottom-r.top+1)-pwd->ComData.BorderHeight; /* Try to avoid flikering caused by multiple resize issued by Motif */ if (pwd->ComData.Width==width && pwd->ComData.Height==height) return; /* Tell DrawProc ignore draw requests untill we recreate conrtols */ pwd->ComData.flags|=WFL_DONT_REDRAW|WFL_RESIZE; /* Remove controls that fit old dimensions of window */ pwd->Member->RemoveControls(&pwd->ComData); /* Determine new dimensions of client rectangle (internal area) */ pwd->ComData.Width=width; pwd->ComData.Height=height; /* Clear window (between controls esp.) */ LoadRect(&r,0,0,pwd->ComData.Width,pwd->ComData.Height); /* GetPosition(w,&r) returns screen coords! */ InvalRect(&r); Update(); /* Recreate controls */ SetInitialPosition(pwd->ComData.Win); pwd->Member->CreateControls(&pwd->ComData); /* Recreation has been completed */ pwd->ComData.flags^=WFL_DONT_REDRAW|WFL_RESIZE; /* Manage controls if resize has been done during incomplete action e.g opened dialog box */ if (pwd->ComData.MenuDesc.Lock) pwd->Member->ManageControls(&pwd->ComData,FALSE); } Local(void) CloseProc(WindoW w) { WindowPtr pwd; pwd=GetWindowData(w); if (!Locked(&pwd->ComData.MenuDesc)) { WindowsMask^=1<ComData.Unique; pwd->Member->WriteDescription(&pwd->ComData,NULL); /* just free memory and don't write */ DeleteWin(pwd); UnloadWindowClassLib(GetWinClassIndex(pwd->WinClass)); DeleteWindowDescriptor(pwd); /* pwd is no longer valid */ } } /* Common umbrella for window's menu */ Local(void) UmbrellaProc(IteM item) { WindowPtr pwd; pwd=GetWindowData(ParentWindow(item)); DoMenuAction(&pwd->ComData.MenuDesc,item); } /* Creates new window */ Local(void) CreateWin(WindowPtr pwd) { WindoW w; /* Create menu descriptor and window title */ pwd->Member->BuildMenu(&pwd->ComData); w=DocumentWindow(pwd->ComData.Left,pwd->ComData.Top, -WHM,-WVM, pwd->ComData.WinTitle, CloseProc,ResizeProc); SetWindowExtra(w,&pwd->ComData,NULL); pwd->ComData.Win=w; CreateMenu(w,NULL,&pwd->ComData.MenuDesc,UmbrellaProc); /* Create Class-specific controls */ pwd->ComData.BorderWidth=BorderWidth; pwd->ComData.BorderHeight=BorderHeight; SetInitialPosition(pwd->ComData.Win); pwd->Member->CreateControls(&pwd->ComData); pwd->ComData.flags|=WFL_DONT_RESIZE; /* let ResizeProc know this is after-creation-call */ RealizeWindow(w); /* Now Show or Hide */ if (!(pwd->ComData.flags&WFL_HIDDEN)) ShowWin(w); pwd->ComData.flags&=~WFL_DONT_RESIZE; /* just in a case resize callback is no longer called */ } /* Duplicates window; may be called by a window class's member only */ Local(Boolean) DuplicateWin(WinComDataPtr wcd, VoidPtr private) { WindowPtr tpwd,spwd; int winclassind; spwd=GetWindowData(wcd->Win); winclassind=GetWinClassIndex(spwd->WinClass); LoadWindowClassLib(winclassind); /* increase usage count */ tpwd=CreateAndFillWindowDesc(spwd->WinClass); if (tpwd) { tpwd->Member=WindowClasses[winclassind].GetClass(&UtilList); tpwd->ComData.Private=private; /* Attach private data */ /* Copy common fields */ tpwd->ComData.WinTitle=_StringSave(spwd->ComData.WinTitle); tpwd->ComData.Position=spwd->ComData.Position; tpwd->ComData.Left+=spwd->ComData.BorderWidth; tpwd->ComData.Top+=spwd->ComData.BorderHeight; /* shift it a little bit */ tpwd->ComData.Colors[0]=spwd->ComData.Colors[0]; tpwd->ComData.Colors[1]=spwd->ComData.Colors[1]; tpwd->ComData.flags=spwd->ComData.flags; tpwd->ComData.BorderHeight=spwd->ComData.BorderHeight; tpwd->ComData.BorderWidth=spwd->ComData.BorderWidth; CreateWin(tpwd); /* Create at last */ CheckWindowsFunctions(tpwd); /* Set up window's function(s) */ } else { UnloadWindowClassLib(GetWinClassIndex(spwd->WinClass)); return TRUE; } return FALSE; /* no error(s) */ } /*----------------------------------------------------------*/ /* Show previously hidden window. Called from the Main menu */ Local(LisT) list; /* used by Show hidden window Procs */ Local(void) HWCancelProc(ButtoN bu) { UnlockAll(); Remove(ParentWindow(bu)); PopContext(); } Local(void) HWShowProc(ButtoN bu) { WindowPtr pwd; Int2 n; n=GetValue(list); for (pwd=Windows; pwd; pwd=pwd->Next) if (pwd->ComData.flags&WFL_HIDDEN) if (n==1) { ShowWin(pwd->ComData.Win); pwd->ComData.flags&=~WFL_HIDDEN; break; } else n--; HWCancelProc(bu); } Local(void) HWListProc(LisT list) { if (dblClick) HWShowProc((ButtoN) list); } #if _WIN #pragma argsused #endif Local(void) HWHelpProc(ButtoN b) { Help(NULL); } #if _WIN #pragma argsused #endif Global(void) ShowHiddenWindows(Int2 index) { WindowPtr pwd; WindoW win; GrouP group; LockAll(); win=FixedWindow(-50,-50,-sysCharWidth,-sysCharWidth, VisualTxt[SHW_T],NULL); group=HiddenGroup(win,1,0,NULL); list=SingleList(group,20,10,HWListProc); for (pwd=Windows; pwd; pwd=pwd->Next) if (pwd->ComData.flags&WFL_HIDDEN) ListItem(list,pwd->ComData.WinTitle); SetValue(list,1); PushContext(HLP_HIDDEN,NULL,VisualTxt[HIDDEN_C]); TermButtons(win,(GrouP)list,HWShowProc,HWCancelProc,HWHelpProc); Show(win); } #if _WIN #pragma argsused #endif Global(Boolean) ShowHiddenWindow_Status(Int2 index) { WindowPtr pwd; Boolean bhw=FALSE; for (pwd=Windows; pwd; pwd=pwd->Next) bhw|=pwd->ComData.flags&WFL_HIDDEN; return bhw; } /* Spacing and Margins for normal and hidden groups in Options windows */ #define nMX (sysCharWidth2) #define nMY (sysLineHeight4) #define nSX (sysCharWidth) #define nSY (sysLineHeight4) #define hMX 0 #define hMY 0 #define hSX (sysCharWidth2) #define hSY (sysLineHeight4) Local(GrouP) CreateNormalGroup(GrouP parent, Int2 x, Int2 y, CharPtr title) { GrouP g; g=NormalGroup(parent,x,y,title,SystemFont,NULL); SetGroupMargins(g,nMX,nMY); SetGroupSpacing(g,nSX,nSY); return g; } Local(GrouP) CreateHiddenGroup(GrouP parent, Int2 x, Int2 y, Int2 vspace) { GrouP g; g=HiddenGroup(parent,x,y,NULL); SetGroupMargins(g,hMX,hMY); SetGroupSpacing(g,hSX,hSY*vspace); return g; } Local(Int2) GetGroupSM(CharPtr SMCode) { if (SMCode[0]=='n') if (SMCode[1]=='m') return SMCode[2]=='x' ? nMX : nMY; else return SMCode[2]=='x' ? nSX : nSY; else if (SMCode[1]=='m') return SMCode[2]=='x' ? hMX : hMY; else return SMCode[2]=='x' ? hSX : hSY; } Local(Boolean) ErrorsInFunctions=FALSE; /* Called from class function to recreate window after options have been changed (e.g. layout ) */ Local(void) RecreateWindow(WinComDataPtr wcd) { WindoW w,ow=CurrentWindow(); WindowPtr pwd; w=wcd->Win; pwd=GetWindowData(w); UseWindow(w); SetTitle(wcd->Win,wcd->WinTitle); /* Recreate controls */ wcd->flags|=WFL_DONT_REDRAW; SetInitialPosition(wcd->Win); pwd->Member->CreateControls(wcd); wcd->flags^=WFL_DONT_REDRAW; /* Have we recompile? */ if (wcd->flags&WFL_FUNC_EDITED || ErrorsInFunctions) { /* a window function has been changed or error(s) found during previous compilation - must be checked again */ CheckWindowsFunctions(pwd); } UseWindow(ow); } /*-----------------*/ /* Windows library */ Local(Char) WinLibName[20]; /* (Short) name of windows library */ /* Check window function(s) and recompile it(them) if necessary */ Local(void) CheckWindowsFunctions(WindowPtr pwd) { if (!ErrorsInFunctions && pwd->Member->SimpleFunctions(&pwd->ComData)) { pwd->Member->SetFunctions(&pwd->ComData,hWinLib); } else { /* is(are) not simple */ if (hWinLib) hWinLib=LibraryUnlock(hWinLib); else { AssignFileName(); /* Assign unique filename */ GetParamAppend(SFS_EXTENSIONS,"LIB"); /* Append the extension to it */ StrCpy(WinLibName,ParBuf); } CompileWindowsFunctions(FALSE); } } /*---------*/ /* Palette */ /* Draw palette */ Global(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; icolor); switch (attr->style) { case 2: WidePen(Penwidth=attr->width); Dotted(); break; case 3: WidePen(Penwidth=attr->width); Dashed(); break; case 1: default: Solid(); WidePen(Penwidth=attr->width); } Penwidthd=Penwidth ? ((Penwidth-1)>>1) : 0; if (hcFlag && CurPwd==hcPwd) hcPwd->Member->hcPen(&hcPwd->ComData,attr); } /*----------------------------*/ /* Hard copy output functions */ /* Definitions of hcFont* variables were moved upwards */ /* Read a list of PostScript fonts */ Global(void) ReadPsFonts(Int2 num) { Int2 i; Char b[80]; if (num>0) { hcFontNum=num; hcFontList=_MemNew(ARRAYSIZE(CharPtr,num)); for (i=0; iNext) { if (CurPwd->ComData.flags&WFL_HIDDEN) continue; /* voor frozen windows ook */ UseWindow(CurPwd->ComData.Win); CurPwd->Member->ClearWindow(&CurPwd->ComData); } } #if _WIN #pragma argsused #endif Global(Boolean) CreateWindow_Status(Int2 index) { return FunctionsHandle!=NULL; /* functions are selected */ } Global(void) NotifyAboutNewInitPoint(void) { UpdateInfoInMainWindow(MWI_MESSAGE,""); for (CurPwd=Windows; CurPwd; CurPwd=CurPwd->Next) if (!(CurPwd->ComData.flags&(WFL_HIDDEN|WFL_FROZEN))) { UseWindow(CurPwd->ComData.Win); CurPwd->Member->NewInitPoint(&CurPwd->ComData); } } /*---------------------------*/ /* Compile Windows Functions */ /* Set windows functions */ Local(void) SetWindowsFunctions(void) { WindowPtr pwd; for (pwd=Windows; pwd; pwd=pwd->Next) { pwd->Member->SetFunctions(&pwd->ComData,hWinLib); } } /* Shows compiler/linker error messages */ Local(void) ShowErrFile(GrouP g) { DoC doc; RecT r; Int2 width; SelectFont(ProgramFont); /* for FileLineMaxWidth */ width=FileLineMaxWidth(ParBuf); if (!width) { GetPosition(g,&r); width=r.right-r.left; } doc=DocumentPanel(g,width,10*LineHeight()); /* ParBuf contains error file name */ DisplayFancy(doc,ParBuf,NULL,NULL,ProgramFont,8); } /* Process errors (if any) and set windows functions */ Local(Int2) ProcessFuncErrors(Boolean errors, CharPtr text, int linenum) { WindowPtr pwd,pwd1; ErrorsInFunctions=errors; if (errors) { myMessageSetUser(ShowErrFile); GetParam(SFS_COMPILER,"LOGFILE"); myWarning("VI_WFE",text); myMessageSetUser(NULL); if (linenum>0) { for (pwd=NULL, pwd1=Windows; pwd1; pwd1=pwd1->Next) if (pwd1->LineNumComData.Win); } } } else { GetParam(SFS_CURRENTS,"DIRECTORY"); StrCat(ParBuf,WinLibName); SetParam(SFS_LIBRARIES,"WINLIB",ParBuf); hWinLib=LibraryLock("WINLIB"); SetWindowsFunctions(); } UnlockAll(); return 0; } Local(void) CreateWinHeading(void); /* Create source text and run compiler */ Global(void) CompileWindowsFunctions(Boolean UnlockOld) { FILE PNTR Source; WindowPtr pwd; CharPtr p; Int2 LineNum; Char c; Boolean all_funcs_are_simple=TRUE; if (UnlockOld) if (hWinLib) hWinLib=LibraryUnlock(hWinLib); for (pwd=Windows; pwd; pwd=pwd->Next) { all_funcs_are_simple&=pwd->Member->SimpleFunctions(&pwd->ComData); } if (all_funcs_are_simple) { ErrorsInFunctions=FALSE; SetWindowsFunctions(); return; } LockAll(); CreateWinHeading(); SetParam(SFS_COMPILER,"SOURCE",GetParam(SFS_FILES,"WIN")); if (*WinLibName==0) { /* user funcs may call CompileWindowsFunctions */ AssignFileName(); /* Assign unique filename */ GetParamAppend(SFS_EXTENSIONS,"LIB"); /* Append the extension to it */ StrCpy(WinLibName,ParBuf); } p=StrStr(WinLibName,GetParam(SFS_EXTENSIONS,"LIB")); if (p) {c=*p; *p='\0';} SetParam(SFS_COMPILER,"TARGET",WinLibName); if (p) *p=c; Source=FileOpen((GetParam(SFS_COMPILER,"SOURCE"), GetParamAppend(SFS_EXTENSIONS,"C") ),"wt"); fputs(BuildH(),Source); fputs(GetParam(SFS_VISUAL,"INCLUDE"),Source); LineNum=3; for (pwd=Windows; pwd; pwd=pwd->Next) { pwd->LineNum=LineNum; pwd->Member->PutFunctions(&pwd->ComData,Source,&LineNum); } FileClose(Source); ErrorsInFunctions=FALSE; PushContext(0,NULL,VisualTxt[CONTEXT_C]); Compile("MAKERHS",ProcessFuncErrors); } /*----------------------------------*/ /* Save/Restore window descriptions */ typedef struct { Int2 lx,ly; } ScreenDim; /* Read window descriptions */ Local (void) ReadWindowsDescription(DataLibPtr arch) { WindowPtr pwd; int winclassind; CharPtr p; ScreenDim scr; Int2 i,n; Boolean all_funcs_are_simple=TRUE; DataLibDown(arch); if (DataLibFind(arch,PART_WIN)==0) { DataLibRead(arch,(CharPtr)&n,sizeof(n)); DataLibRead(arch,(CharPtr)&WindowsMask,sizeof(WindowsMask)); for (i=0; iComData.flags,sizeof(pwd->ComData.flags)); pwd->ComData.WinTitle=DataLibReadVRecord(arch,NULL); DataLibRead(arch,(CharPtr)&pwd->ComData.Position,sizeof(pwd->ComData.Position)); DataLibRead(arch,(CharPtr)&scr,sizeof(scr)); DataLibRead(arch,(CharPtr)&pwd->ComData.Colors,sizeof(pwd->ComData.Colors)); DataLibRead(arch,(CharPtr)&pwd->WinClass,sizeof(pwd->WinClass)); DataLibRead(arch,(CharPtr)&pwd->ComData.Unique,sizeof(pwd->ComData.Unique)); winclassind=GetWinClassIndex(pwd->WinClass); if (winclassind<0 || winclassind>=WindowMenuDesc.Num) { DeleteWindowDescriptor(pwd); return; } if (LoadWindowClassLib(winclassind)) { DeleteWindowDescriptor(pwd); return; } pwd->Member=WindowClasses[winclassind].GetClass(&UtilList); /* translate position of a window and dimensions of its client area */ pwd->ComData.Left=(FloatHi)pwd->ComData.Left*(screenRect.right-screenRect.left)/scr.lx; pwd->ComData.Top=(FloatHi)pwd->ComData.Top*(screenRect.bottom-screenRect.top)/scr.ly; pwd->ComData.Width=(FloatHi)pwd->ComData.Width*(screenRect.right-screenRect.left)/scr.lx; pwd->ComData.Height=(FloatHi)pwd->ComData.Height*(screenRect.bottom-screenRect.top)/scr.ly; /* Class specific fields */ pwd->Member->ReadDescription(&pwd->ComData,arch); /* Create window */ CreateWin(pwd); /* Disable it when needed */ if (pwd->ComData.flags&WFL_FROZEN) pwd->Member->ManageControls(&pwd->ComData,FALSE); /* Check whether functions are simple, i.e. need not to be compiled */ all_funcs_are_simple&=pwd->Member->SimpleFunctions(&pwd->ComData); } } /* Process windows library */ ErrorsInFunctions=FALSE; /* no error(s) yet */ if (DataLibFind(arch,PART_WINLIB)==0) { function: GetParam(SFS_CURRENTS,"DIRECTORY"); p=DataLibReadVRecord(arch,NULL); StrCpy(WinLibName,p); StrCat(ParBuf,p); _MemFree(p); /* OK, WINLIB partition does exist. But are there non-simple functions? */ if (all_funcs_are_simple) { /* All are simple */ unlink(ParBuf); FreeFileName(WinLibName); /* Free unique filename */ DataLibDeletePartitions(arch,PART_WINLIB,NULL); goto simple; } SetParam(SFS_LIBRARIES,"WINLIB",ParBuf); DataLibUp(arch); /* for MustRecompile */ if (access(ParBuf,0)==0 && !MustRecompile(arch,arch,PART_WINLIB,FALSE,NULL)) { /* exists and need not be recompiled */ hWinLib=LibraryLock("WINLIB"); SetWindowsFunctions(); } else CompileWindowsFunctions(FALSE); } else { if (all_funcs_are_simple) { /* All are simple */ simple: *WinLibName='\0'; SetWindowsFunctions(); DataLibUp(arch); } else { /* This may happen next time after the user edited phase/par/time descriptions. In such a case simple variable may formally become a function because it does not match any (updated) name (e.g. x[3] ==> xx) */ AssignFileName(); /* Assign unique filename */ GetParamAppend(SFS_EXTENSIONS,"LIB"); /* Append the extension to it */ DataLibWriteVRecord(arch,PART_WINLIB,ParBuf,StrLen(ParBuf)+1); DataLibFind(arch,PART_WINLIB); goto function; } } } /* Write window descriptions */ Local(void) WriteWindowsDescription(DataLibPtr arch) { WindowPtr pwd; RecT r; ScreenDim scr; DataLibDown(arch); if (DataLibFind(arch,PART_WIN)==0) DataLibDelete(arch); DataLibCreate(arch,PART_WIN); DataLibWrite(arch,(CharPtr)&WindowsNum,sizeof(WindowsNum)); DataLibWrite(arch,(CharPtr)&WindowsMask,sizeof(WindowsMask)); scr.lx=screenRect.right-screenRect.left; scr.ly=screenRect.bottom-screenRect.top; while (Windows) { pwd=Windows; GetPosition(pwd->ComData.Win,&r); pwd->ComData.Left=r.left; pwd->ComData.Top=r.top; /* Width and Height are updated by ResizeProc */ /* Write common fields */ DataLibWrite(arch,(CharPtr)&pwd->ComData.flags,sizeof(pwd->ComData.flags)); DataLibWriteVRecord(arch,NULL,pwd->ComData.WinTitle,StringLen(pwd->ComData.WinTitle)+1); DataLibWrite(arch,(CharPtr)&pwd->ComData.Position,sizeof(pwd->ComData.Position)); DataLibWrite(arch,(CharPtr)&scr,sizeof(scr)); DataLibWrite(arch,(CharPtr)&pwd->ComData.Colors,sizeof(pwd->ComData.Colors)); DataLibWrite(arch,(CharPtr)&pwd->WinClass,sizeof(pwd->WinClass)); DataLibWrite(arch,(CharPtr)&pwd->ComData.Unique,sizeof(pwd->ComData.Unique)); /* Class specific fields */ pwd->Member->WriteDescription(&pwd->ComData,arch); DeleteWin(pwd); DeleteWindowDescriptor(pwd); } if (hWinLib) { hWinLib=LibraryUnlock(hWinLib); DataLibWriteVRecord(arch,PART_WINLIB,WinLibName,StrLen(WinLibName)+1); } DataLibUp(arch); } /*----------------------------------*/ /* Export/Import window description */ Global(void) WindowsExport(DataLibPtr arch, FILE PNTR out) { /* Must correspond to ReadWindowsDescription */ Window wd; Int2 winclindex; CharPtr p; ScreenDim scr; Int2 i,n; DataLibRead(arch,(CharPtr)&n,sizeof(n)); DataLibRead(arch,(CharPtr)&WindowsMask,sizeof(WindowsMask)); fprintf(out,"num=%i mask=%li\n",(int)n,(long)WindowsMask); for (i=0; iExportDescription(&wd.ComData,arch,out); /* Class specific fields */ UnloadWindowClassLib(winclindex); } } Global(void) WindowsImport(DataLibPtr arch, FILE PNTR in) { Window wd; Int2 winclindex; ScreenDim scr; long l,col1,col2; int i1,i2,i3,i4,s1,s2; Int2 i; DataLibCreate(arch,PART_WIN); fscanf(in,"num=%i mask=%li\n",&i1,&l); WindowsNum=(Int2)i1; WindowsMask=(Int4)l; DataLibWrite(arch,(CharPtr)&WindowsNum,sizeof(WindowsNum)); DataLibWrite(arch,(CharPtr)&WindowsMask,sizeof(WindowsMask)); for (i=0; iImportDescription(&wd.ComData,arch,in); /* Class specific fields */ UnloadWindowClassLib(winclindex); } WindowsNum=0; WindowsMask=0; } /*------------------------------------*/ /* Export/Inport of visual attributes */ Global(void) ExportVisualAttr(DataLibPtr dgm, FILE PNTR out) { Window wd; Int2 winclindex; Int2 i,n; Int1 ClassUnique[2]; DataLibRead(dgm,(CharPtr)&n,sizeof(n)); fprintf(out," %i\n",(int)n); for (i=0; iExportAttr(&wd.ComData,dgm,out); UnloadWindowClassLib(winclindex); } } Global(void) ImportVisualAttr(DataLibPtr dgm, FILE PNTR in) { Window wd; Int2 winclindex; int c,u,k; Int2 i,n; Int1 ClassUnique[2]; fscanf(in," %i\n",&k); n=(Int2)k; DataLibWrite(dgm,(CharPtr)&n,sizeof(n)); for (i=0; iImportAttr(&wd.ComData,dgm,in); UnloadWindowClassLib(winclindex); } } /*---------------------------------*/ /* Delete all windows' description */ Global(void) DeleteWindows(DataLibPtr arch) { CharPtr p; p=DataLibReadVRecord(arch,PART_WINLIB); /* get window lib file name */ if (p && *p) { unlink(p); FreeFileName(p); /* Free unique filename */ } _MemFree(p); DataLibDeletePartitions(arch,PART_WIN,PART_WINLIB,NULL); } /* Save visualizer's attributes and Restore them */ /* Int2 - number of following elements. Each elements: Int1 - window's class, Int1 - window's unique numer, ... - window's specific data. */ Global(void) SaveVisualAttr(DataLibPtr dl, ByteStorePtr from, ByteStorePtr to, Boolean freemem) { WindowPtr pwd; Int2 n; Int1 ClassUnique[2]; if (from) BSRead(from,&n,sizeof(n)); else for (n=0, pwd=Windows; pwd; pwd=pwd->Next) n++; if (to) BSWrite(to,&n,sizeof(n)); else DataLibWrite(dl,(CharPtr)&n,sizeof(n)); if (from) for (; n; n--) { BSRead(from,ClassUnique,sizeof(ClassUnique)); for (pwd=Windows; pwd; pwd=pwd->Next) if (ClassUnique[0]==pwd->WinClass && ClassUnique[1]==pwd->ComData.Unique) { if (to) BSWrite(to,ClassUnique,sizeof(ClassUnique)); else DataLibWrite(dl,(CharPtr)ClassUnique,sizeof(ClassUnique)); pwd->Member->SaveAttr(&pwd->ComData,dl,from,to,freemem); break; } } else for (pwd=Windows; pwd; pwd=pwd->Next) if (pwd->Member->SaveAttr) { ClassUnique[0]=pwd->WinClass; ClassUnique[1]=pwd->ComData.Unique; if (to) BSWrite(to,ClassUnique,sizeof(ClassUnique)); else DataLibWrite(dl,(CharPtr)ClassUnique,sizeof(ClassUnique)); pwd->Member->SaveAttr(&pwd->ComData,dl,from,to,freemem); } } Global(void) RestoreVisualAttr(DataLibPtr dl, ByteStorePtr from, ByteStorePtr to) { WindowPtr pwd; Int4 bspos; Int2 i,n,n1; Int1 ClassUnique[2]; if (from) BSRead(from,&n,sizeof(n)); else DataLibRead(dl,(CharPtr)&n,sizeof(n)); if (to) { bspos=BSTell(to); BSWrite(to,&n,sizeof(n)); } for (i=n1=0; iNext) if (pwd->WinClass==ClassUnique[0] && pwd->ComData.Unique==ClassUnique[1]) { if (to) BSWrite(to,ClassUnique,sizeof(ClassUnique)); pwd->Member->RestoreAttr(&pwd->ComData,dl,from,to,FALSE); break; } if (!pwd) { /* window was destroyed, skip */ Window wd; Int2 winclindex=GetWinClassIndex(ClassUnique[0]); MemFill(&wd,0,sizeof(wd)); LoadWindowClassLib(winclindex); wd.Member=WindowClasses[winclindex].GetClass(&UtilList); wd.Member->RestoreAttr(&wd.ComData,dl,from,to,TRUE); UnloadWindowClassLib(winclindex); n1++; } } if (n1 && to) { n-=n1; BSSeek(to,bspos,SEEK_SET); BSWrite(to,&n,sizeof(n)); BSSeek(to,0,SEEK_END); } } /* Push/pop attribute (just to store them temporary) */ Global(void) PushVisualAttr(Boolean freemem) { WindowPtr pwd; for (pwd=Windows; pwd; pwd=pwd->Next) pwd->Member->PushAttr(&pwd->ComData,freemem); } Global(void) PopVisualAttr(void) { WindowPtr pwd; for (pwd=Windows; pwd; pwd=pwd->Next) pwd->Member->PopAttr(&pwd->ComData); } /*--------------*/ /* Windows list */ Local(Boolean) LoadWindowClassLib(Int2 indx) { if (WindowClasses[indx].Count++==0) { #if LINKIN switch (WindowClasses[indx].WinClass) { #if LINKIN_2D case 1: WindowClasses[indx].GetClass=g2d_GetClassTable; break; #endif #if LINKIN_NUM case 2: WindowClasses[indx].GetClass=num_GetClassTable; break; #endif #if LINKIN_TAB case 3: WindowClasses[indx].GetClass=tab_GetClassTable; break; #endif #if LINKIN_1S case 4: WindowClasses[indx].GetClass=s1d_GetClassTable; break; #endif #if LINKIN_3D case 5: WindowClasses[indx].GetClass=g3d_GetClassTable; break; #endif } #else /* regular way */ SetParam(SFS_LIBRARIES,"WINCLASSLIB",WindowClasses[indx].LibName); WindowClasses[indx].Lib=LibraryLock("WINCLASSLIB"); if (WindowClasses[indx].Lib==NULL) { myMessage(MSG_OK,"Cannot load window class library.\n ClassId=%i\nFile %s", indx,WindowClasses[indx].LibName); return TRUE; /* no lib - no win */ } WindowClasses[indx].GetClass=(EntryPtr(ClassFuncPtr,,())) LibraryFuncAddress(WindowClasses[indx].Lib, WindowClasses[indx].FuncName); if (!WindowClasses[indx].GetClass) { myMessage(MSG_OK,"Cannot locate entry point of window class library.\n ClassId=%i\nName %s", indx,WindowClasses[indx].FuncName); return TRUE; } #endif HelpAddFile(WindowClasses[indx].HelpFile); } return FALSE; /* ok */ } Local(void) UnloadWindowClassLib(Int2 indx) { if (--WindowClasses[indx].Count==0) { #if LINKIN #else WindowClasses[indx].Lib=LibraryUnlock(WindowClasses[indx].Lib); #endif HelpRemFile(WindowClasses[indx].HelpFile); } } /* Open a window */ Local(void) WindowAction(Int2 indx) { WindowPtr pwd; /* Assert: WindowClassess[indx] describes desired window class */ if (LoadWindowClassLib(indx)) return; pwd=CreateAndFillWindowDesc(WindowClasses[indx].WinClass); if (pwd) { pwd->Member=WindowClasses[indx].GetClass(&UtilList); pwd->Member->BuildDefaultDescription(&pwd->ComData); CreateWin(pwd); /* Set up window's function(s) */ CheckWindowsFunctions(pwd); } } Local(Boolean) WindowStatus(Int2 indx) { FloatHi ed; Boolean res=FALSE; if (FunctionsHandle) { /* functions are selected */ if (StrCmp(WindowClasses[indx].Status,"1")==0) res=TRUE; else if (ComputeExpr(WindowClasses[indx].Status,&ed)==0 && ed) res=TRUE; } return res; } Local(void) WindowCallback(IteM it) { DoMenuAction(&WindowMenuDesc,it); SetStatusOfItems(&MainMenu); } Local(Int2) MainMenuIndex; /* To access Windows submenu */ Local(Int2) WinDescStackTop; Local(Int2) WinDescStack[5]; Global(void) BuildWindowsList(Int2 index) { int i,lib_s,lib_e,func_s,func_e,item_s,item_e,help_s,help_e,ed_s,ed_e; if (index) { /* top-level list of windows (universal windows) */ GetParam(SFS_VISUAL,"WINFILE"); if (!DescOpen(ParBuf)) { myWarning("CT_OPEN",ParBuf); return; /* cannot find/open file */ } MainMenuIndex=index; WinDescStack[WinDescStackTop=0]=0; WindowMenuDesc.Num=CountLines(); WindowMenuDesc.Menu=_MemNew(ARRAYSIZE(MenuItem,WindowMenuDesc.Num)); WindowClasses=_MemNew(ARRAYSIZE(WinClass,WindowMenuDesc.Num)); WindowText=_MemNew(ARRAYSIZE(CharPtr,WindowMenuDesc.Num)); } else { Int2 old=WindowMenuDesc.Num; Reset(MainMenu.Menu[MainMenuIndex].ItemId); WinDescStack[++WinDescStackTop]=WindowMenuDesc.Num; WindowMenuDesc.Num+=CountLines(); WindowMenuDesc.Menu=_MemExtend(WindowMenuDesc.Menu, ARRAYSIZE(MenuItem,WindowMenuDesc.Num), ARRAYSIZE(MenuItem,old)); WindowClasses=_MemExtend(WindowClasses, ARRAYSIZE(WinClass,WindowMenuDesc.Num), ARRAYSIZE(WinClass,old)); WindowText=_MemExtend(WindowText, ARRAYSIZE(CharPtr,WindowMenuDesc.Num), ARRAYSIZE(CharPtr,old)); } for (i=WinDescStack[WinDescStackTop]; i1 */ #define PRES_PRE '\\' /* \class is replaced by class to postpone replacement of $class etc. in inner loops: $\class --> $class */ #define EXPR_PRE "@(" /* calculate expr: @(expr) */ /* VisVar and VisClass structures are defined above as well as ClassPtr and ClassNumber variables. */ Global(Boolean) IsClassBasic(Int2 Class) { return (Boolean)(ClassPtr[Class].Flags&VN_BASIC); } /* Enumerate all relevant classes */ Global(void) EnumClasses(LisT List, ProcClassPtr proc) { Uint2Ptr realIds; Int2 i,j,num; num=GetLocalClasses(&realIds); if (num==0) { /* point &/| curve type are/is not choosen */ for (i=0; i=ClassNumber) return FALSE; if (name) *name=ClassPtr[Class].Title; if (id) *id=ClassPtr[Class].Id; return TRUE; } Global(Int2) IsClassRelevant(Uint2 realId) { Int2 i; for (i=0; i1) { pos=-1; sscanf(p+1,"%i]%n",&n,&pos); if (pos<0 || *(p+1+pos)) return FALSE; if (p_offset) *p_offset+=ClassPtr[i].Variables[j].Mult*n; return TRUE; } return (!p && ClassPtr[i].Variables[j].Dim==1) ? TRUE : FALSE; } if (p) *p='['; return FALSE; } Global(void) ClassAddVar(CharPtr clas, CharPtr var) { VisClassPtr cp; VisVarPtr vp; Int2 i,j; for (i=0; iVariables=cp->Num>0 ? _MemMore(cp->Variables,ARRAYSIZE(VisVar,cp->Num+1)) : _MemNew(ARRAYSIZE(VisVar,1)); vp=cp->Variables+cp->Num; vp->Name=_StringSave(var); vp->Dim=1; vp->Offset=(Uint2)(cp->Dim*sizeof(FloatHi)); vp->Mult=sizeof(FloatHi); cp->Num++; cp->Dim++; } else { if (cp->Variables) for (j=0; jNum; j++) _MemFree(cp->Variables[j].Name); cp->Variables=_MemFree(cp->Variables); cp->Num=cp->Dim=0; } break; } } /*-------------------------------------*/ /* Management of list of visible names */ /*-------------------------------------*/ Local(Boolean) ZeroLevel; Local(Boolean) Multi; Global(Int2) ListCurrentClass; /* abs index (counting irrelevant classes) */ Global(Int2) ListCurrentItem; /* rel index (ignoring irrelevant classes) */ Local(Int2) LstWidth; Local(LstNotifyProc) CallersNotifyProc; Local(LstCountSelProc) CountSelectedProc; /* Fill list in with class names (ZeroLevel=TRUE) */ #if _WIN #pragma argsused #endif Local(void) AddClassTitle(LisT List, CharPtr ClassTitle, CharPtr ClassName, Boolean defvis, Uint2 RealId) { Int2 n=CountItems(List); Char buf[BL]; if (Multi) { SelectFont(systemFont); sprintf(buf,"%s %i/%i",ClassTitle,CountSelectedProc(n),(int)*GetClassDim(ClassName)); ListItem(List,buf); } else ListItem(List,ClassTitle); } Local(void) FreeNameList(GraphiC list, VoidPtr ptr) { Int2 i,n=CountItems((LisT)list)-1; /* ignore ".." item */ if (ptr) { for (i=0; i=1: the first is ".." */ CharPtr p; CharPtr PNTR lp=(CharPtr PNTR)GetObjectExtra(List); lp=lp ? _MemMore(lp,ARRAYSIZE(CharPtr,n-1+Dim)) : _MemNew(ARRAYSIZE(CharPtr,n-1+Dim)); if (Dim>1) { p=_MemNew(StrLen(VarName)+5+8+1); for (i=0; i::={{ [[ ]] [[ @class { } ]] }} ::=any text not containing '@' Note: @class&{...} is a loop throught all components (not names) of the class. In such a case the only psudo-name allowed in the body of the loop is &class which denotes ordinal numbers of components (it varies from 0 to DIM(class)-1). */ #define LOOPMAX 10 /* max number of loops per text */ /***#define REPMAX 10***/ /* max number of replaceable units per loop */ #define REPN 10 /* init and incr of number of replaceable units per loop */ Local(Char) ExpandPrefix[]={NAME_PRE,NUM_PRE,ORD_PRE,INDIR_PRE,PRES_PRE}; Local(Int2) Digits(Int2 n, ExpandOp ExpandArrays) { switch (ExpandArrays) { case EA_DONT: if (n<10) return 1; if (n<100) return 2; if (n<1000) return 3; if (n<10000) return 4; return 5; case EA_DO: if (n<10) return n+1; if (n<100) return 2*n-8; /* 2*(n-9)+1*10 */ if (n<1000) return 3*n-107; /* 3*(n-99)+2*90+1*10 */ if (n<10000) return 4*n-1106; /* 4*(n-999)+3*900+2*90+1*10 */ return 5*n; } return 0; } Local(int) ExpandCmp(const void PNTR key, const void PNTR elem) { if (*(Int2Ptr)key<*(Int2Ptr)elem) return -1; if (*(Int2Ptr)key>*(Int2Ptr)elem) return 1; return 0; } Local(CharPtr) ExpandText(CharPtr text, ExpandOp ExpandArrays) { CharPtr q,replace; int pos; Int2 partn,cumlen; Int2 level; Char clas[50]; struct { CharPtr replace; /* NULL for */ Int2 from; /* the *text */ Int2 len; } part[LOOPMAX+1]; CharPtr r; VisVarPtr pVar; Int2 repn,i,j,k,l,m,l0,claslen,clasnum,ordnum,replen,replen1,replacelen; /*** Int2 rep[REPMAX+1];***/ /* len is always StrLen(clas) */ Int2Ptr rep; /* len is always StrLen(clas) */ Int2 rep_n; /* number of allocated REPN-blocks */ Boolean ordloop; partn=0; cumlen=0; /* len of processed text */ rep=_MemNew(ARRAYSIZE(Int2,REPN)); rep_n=1; /* Partition text to and replaceable parts */ while (text[cumlen]) { /* Find 's position */ q=StrChr(text+cumlen,LOOP_PRE); if (q) { if (q[1]==PRES_PRE) { cumlen++; continue; /* don't expand @\clas */ } cumlen=(Int2)(q-text); } else { cumlen+=StrLen(text+cumlen); break; } /* Find replaceable unit's position */ part[partn].from=cumlen; sscanf(text+cumlen,"%c%[a-zA-Z0-9&] {%n",clas,clas+1,&pos); l=StrLen(clas)-1; if (clas[l]=='&') { clas[l]='\0'; ordloop=TRUE; } else ordloop=FALSE; cumlen+=pos; /* right after { */ for (level=1; text[cumlen]; cumlen++) { if (text[cumlen]=='{') {level++; continue;} if (text[cumlen]=='}') {level--; if (level==0) break;} } part[partn].len=cumlen+1-part[partn].from; text[cumlen]='\0'; replace=ExpandText(text+part[partn].from+pos,ExpandArrays); text[cumlen++]='}'; /* Replicate replaced body and substitute names according to class clas */ for (i=0; i=REPMAX) { myWarning("VI_EXPAND","REPMAX",repn); return text; } ***/ if (repn>=REPN*rep_n) { rep_n++; rep=_MemMore(rep,ARRAYSIZE(Int2,REPN*rep_n)); } rep[repn++]=(Int2)(r-replace); } } rep[repn]=StrLen(replace); /* NOT rep[repn++]! */ qsort(rep,repn,sizeof(Int2),ExpandCmp); replacelen=StrLen(replace); if (ordloop) { replen=(replacelen-repn*claslen)*ClassPtr[i].Dim; for (ordnum=0; ordnumDim, j++) { { replen1=0; for (k=0; kName); break; case NUM_PRE: replen1+=Digits(j+1,EA_DONT); break; case ORD_PRE: replen1+=Digits(ordnum,EA_DONT); break; case INDIR_PRE: replen1++; /* '*' or ' ' */ break; case PRES_PRE: replen1+=claslen; break; } } if (pVar->Dim>1 && ExpandArrays!=EA_NO) { replen1+=Digits(pVar->Dim,ExpandArrays)+2; if (ExpandArrays==EA_DO) replen1+=(2+replacelen-repn*claslen+replen1)*(pVar->Dim-1); } replen+=replen1; } } /* replicate replace */ r=_MemGet(replen+1,FALSE); if (ordloop) for (l=ordnum=0; ordnumDim, j++) { l0=l; #if defined(COMP_GNU) && defined(OS_UNIX_SUN) sprintf(r+l,"%.*s",rep[0],replace); l+=StrLen(r+l); #else l+=sprintf(r+l,"%.*s",rep[0],replace); #endif /* defined(COMP_GNU) && defined(OS_UNIX_SUN) */ for (k=0; kName); l+=StrLen(r+l); #else l+=sprintf(r+l,"%s",pVar->Name); #endif /* defined(COMP_GNU) && defined(OS_UNIX_SUN) */ break; case NUM_PRE: #if defined(COMP_GNU) && defined(OS_UNIX_SUN) sprintf(r+l,"%i",(int)j+1); l+=StrLen(r+l); #else l+=sprintf(r+l,"%i",(int)j+1); #endif /* defined(COMP_GNU) && defined(OS_UNIX_SUN) */ break; case ORD_PRE: #if defined(COMP_GNU) && defined(OS_UNIX_SUN) sprintf(r+l,"%i",(int)ordnum); l+=StrLen(r+l); #else l+=sprintf(r+l,"%i",(int)ordnum); #endif /* defined(COMP_GNU) && defined(OS_UNIX_SUN) */ break; case INDIR_PRE: #if defined(COMP_GNU) && defined(OS_UNIX_SUN) sprintf(r+l,pVar->Dim==1 ? "*" : " "); l+=StrLen(r+l); #else l+=sprintf(r+l,pVar->Dim==1 ? "*" : " "); #endif /* defined(COMP_GNU) && defined(OS_UNIX_SUN) */ break; case PRES_PRE: l+=sprintf(r+l,"%s",clas+1); break; } #if defined(COMP_GNU) && defined(OS_UNIX_SUN) sprintf(r+l,"%.*s",(int)(rep[k+1]-rep[k]-claslen),replace+rep[k]+claslen); l+=StrLen(r+l); #else l+=sprintf(r+l,"%.*s",(int)(rep[k+1]-rep[k]-claslen),replace+rep[k]+claslen); #endif /* defined(COMP_GNU) && defined(OS_UNIX_SUN) */ } if (pVar->Dim>1) switch (ExpandArrays) { case EA_DONT: #if defined(COMP_GNU) && defined(OS_UNIX_SUN) sprintf(r+l,"[%i]",(int)pVar->Dim); l+=StrLen(r+l); #else l+=sprintf(r+l,"[%i]",(int)pVar->Dim); #endif /* defined(COMP_GNU) && defined(OS_UNIX_SUN) */ break; case EA_DO: replen=l-l0; #if defined(COMP_GNU) && defined(OS_UNIX_SUN) sprintf(r+l,"[0]"); l+=StrLen(r+l); #else l+=sprintf(r+l,"[0]"); #endif /* defined(COMP_GNU) && defined(OS_UNIX_SUN) */ for (m=1; mDim; m++) #if defined(COMP_GNU) && defined(OS_UNIX_SUN) sprintf(r+l,"%.*s[%i]",(int)replen,r+l0,(int)m); l+=StrLen(r+l); #else l+=sprintf(r+l,"%.*s[%i]",(int)replen,r+l0,(int)m); #endif /* defined(COMP_GNU) && defined(OS_UNIX_SUN) */ break; } } break; } if (i==ClassNumber) { myWarning("VI_CLASS",clas+1); return text; } if (partn>=LOOPMAX) { myWarning("VI_EXPAND","LOOPMAX",partn); return text; } part[partn++].replace=r; _MemFree(replace); } /* while */ _MemFree(rep); part[partn].from=cumlen; /* DON'T increase partn here! */ for (replen=cumlen, i=0; i's position */ q=StrStr(text+cumlen,EXPR_PRE); if (q) cumlen=(Int2)(q-text); else { part[partn].from=StrLen(text); break; } /* Find replaceable unit's position */ part[partn].from=cumlen; for (level=0; TRUE; cumlen++) { if (text[cumlen]=='(') {level++; continue;} if (text[cumlen]==')') {level--; if (level==0) break;} } part[partn].len=cumlen+1-part[partn].from; text[cumlen]='\0'; ComputeExpr(text+part[partn].from+StrLen(EXPR_PRE),&e); part[partn].replace=(int)e; sprintf(buf,"%i",(int)e); part[partn].replen=StrLen(buf); text[cumlen++]=')'; partn++; } for (newlen=StrLen(text), i=0; i |%s|\n",text,r);***/ return r; } Global(CharPtr) ExpandClassDef(CharPtr p, ExpandOp ExpandArrays) { CharPtr r; if (StringChr(p,LOOP_PRE)) { /* p may be NULL */ if (StrStr(p,EXPR_PRE)) { r=ComputeExprs(p); _MemFree(p); p=r; } r=ExpandText(p,ExpandArrays); _MemFree(p); p=r; } return p; } #undef LOOPMAX /***#undef REPMAX***/ #undef REPN /* Tests conditions optionally associated with names */ Local(void) TestConditions(CharPtr text) { FloatHi val; CharPtr p; int pos,pos1,posw,i; Int2 ce; Char name[BL]; for (pos=0; pos1=0,sscanf(text+pos," %n%s%n",&posw,name,&pos1)==1; ) { p=StrChr(name,'('); if (p) { ce=ComputeExpr(p,&val); while (*p) *p++=' '; /* erase (expr) */ MemCopy(text+pos+posw,name,StrLen(name)); if (ce==0 && val<0) for (i=0; iId=*(Int2Ptr)p; pCurClass->Name=_StringSave((CharPtr)((Int2Ptr)p+1)); pCurClass->Title=_StringSave(cllib->DirName); pCurClass->Num=iVisVar; pCurClass->Dim=iVisDim; pCurClass->Variables=pVisVar; /* Until a curve type has been selected treat EACH class as a relevant one. Otherwise any reference to a variable from non-standard class (e.g. Re0 made from a window) will be considered as an error. */ /*** pCurClass->Flags=iVisVar ? (VN_RELEVANT|VN_DEFVIS) : 0; ***/ /* NB: iVisVar==0 for UserFunc class initially; this class is created dynamically by userfunc.c */ if (pCurClass->Name[0]=='*') { StrCpy(pCurClass->Name,pCurClass->Name+1); flag|=VN_DIMG; SetDimGMore1(TRUE); } pCurClass->Flags=(VN_RELEVANT|VN_DEFVIS)|flag; if (pCurClass->Name[StrLen(pCurClass->Name)-1]=='-') { pCurClass->Name[StrLen(pCurClass->Name)-1]='\0'; pCurClass->Flags&=~VN_DEFVIS; } _MemFree(p); return 0; } /* Create heading file for windows' functions */ Local(void) CreateWinHeading(void) { FILE PNTR out; Int2 i,j; Par("WINHEADER"); out=FileOpen(ParBuf,"wt"); if (out) { for (i=0; i1 ? "WINDEFA" : "WINDEFS", ClassPtr[i].Variables[j].Name,(int)i,(unsigned int)ClassPtr[i].Variables[j].Offset); if (FilePuts(ParBuf,out)==EOF) myWarning("VI_WRITE",Par("WINHEADER")); } FileClose(out); } else myWarning("VI_OPEN",ParBuf); } Global(Boolean) VisFull=TRUE; Global(void) ActivateVisualizer(DataLibPtr arch) { DataLibVar(cllib); WindoW curwin; Int2 i; Char buf[BL]; GetParam(SFS_FILES,"VN"); if (VisFull) { curwin=CurrentWindow(); unlink(ParBuf); } if (DataLibOpen(&cllib,ParBuf)) return; /* Create additional standard classes (0 code must be present in any case) */ for (i=VCnum-1; i>VCsep; i--) CreateStdClass(NULL,NULL,&cllib,i); /* Create three classes */ for (i=VCsep-1; i>=0; i--) { *buf=HIDDEN_CHAR; sscanf(VCptr[i],"%*i %s",buf+1); CreateStdClass(arch,buf,&cllib,i); } /* Build tables for all the classes */ SetDimGMore1(FALSE); DataLibEnum(&cllib,BuildClassTable,FALSE); DataLibClose(&cllib); /* 'Hide' classes with codes>200 */ ClassNumberAll=ClassNumber; for (; ClassPtr[ClassNumber-1].Id>200; ClassNumber--); /* Memory for values */ IndirectValues=_MemNew(ARRAYSIZE(FloatHiPtr,ClassNumber)); if (VisFull) { /* Window's width and height */ WindoW w; RecT r; w=DocumentWindow(-50,-50,-WHM,-WVM,"?",NULL,NULL); PulldownMenu(w,"?"); SimplePanel(w,100,100,NULL); RealizeWindow(w); GetPosition(w,&r); BorderWidth=(r.right-r.left+1)-100; BorderHeight=(r.bottom-r.top+1)-100; Remove(w); /* Read windows' description */ ReadWindowsDescription(arch); /* That's all */ Select(curwin); } } /*-----------------------*/ /* Deactivate Visualizer */ /*-----------------------*/ Local(void) DeleteStdClass(DataLibPtr cllib, Int2 indx) { int pos,pose; StrCpy(ParBuf,VCptr[indx]); sscanf(ParBuf," %*i %*s %n%*[^\n]%n",&pos,&pose); *(ParBuf+pose)='\0'; if (DataLibFind(cllib,ParBuf+pos)==0) { DataLibDown(cllib); DataLibFind(cllib,PART_VCLASSDEF); DataLibDelete(cllib); DataLibUp(cllib); DataLibDelete(cllib); } } Global(void) DeactivateVisualizer(DataLibPtr arch) { DataLibVar(cllib); Int2 i,j; if (DataLibOpen(&cllib,GetParam(SFS_FILES,"VN"))) return; /* Delete standard classes */ for (i=0; iNext) { if (!(CurPwd->ComData.flags&(WFL_HIDDEN|WFL_FROZEN))) { UseWindow(CurPwd->ComData.Win); CurPwd->ComData.flags|=WFL_G1; CurPwd->Member->GInit(&CurPwd->ComData); } } } /* G-curve termination */ Global(void) VisualizerTermGCurve(void) { for (CurPwd=Windows; CurPwd; CurPwd=CurPwd->Next) if (!(CurPwd->ComData.flags&(WFL_HIDDEN|WFL_FROZEN))) { UseWindow(CurPwd->ComData.Win); CurPwd->Member->GTerm(&CurPwd->ComData); CurPwd->ComData.flags&=~WFL_G1; } } /*--------------------*/ /* M-curve processing */ /* M-curve initialization */ Global(void) VisualizerInitMCurve(void) { for (CurPwd=Windows; CurPwd; CurPwd=CurPwd->Next) if (!(CurPwd->ComData.flags&(WFL_HIDDEN|WFL_FROZEN))) { CurPwd->ComData.flags|=WFL_M1; CurPwd->Member->MInit(&CurPwd->ComData); } } /* M-curve termination */ Global(void) VisualizerTermMCurve(void) { for (CurPwd=Windows; CurPwd; CurPwd=CurPwd->Next) if (!(CurPwd->ComData.flags&(WFL_HIDDEN|WFL_FROZEN))) { CurPwd->Member->MTerm(&CurPwd->ComData); CurPwd->ComData.flags&=~WFL_G1; } } /* M-point processing */ Global(void) VisualizerProcMPoint(void) { if (ErrorsInFunctions) return; /* error(s) in function(s) */ for (CurPwd=Windows; CurPwd; CurPwd=CurPwd->Next) if (!(CurPwd->ComData.flags&(WFL_HIDDEN|WFL_FROZEN))) { if (curveCurNum>1 && CurPwd->ComData.flags&WFL_GDIM1) goto cont; UseWindow(CurPwd->ComData.Win); CurPwd->Member->MProcess(&CurPwd->ComData); cont:; CurPwd->ComData.flags&=~WFL_M1; } } /* Free data related to a curve and associated with windows */ Global(void) VisualizerFreeCurve(FilePtr fp) { WindowPtr pwd; for (pwd=Windows; pwd; pwd=pwd->Next) if (!(pwd->ComData.flags&(WFL_HIDDEN|WFL_FROZEN))) { pwd->Member->FreeCurveData(&pwd->ComData,(long)fp); } } /********/ /* Misc */ Local(void) ManageMenu(WindowPtr pwd) { Int2 i; Boolean enable=(pwd->ComData.flags&WFL_FROZEN)==0; pwd->Member->ManageControls(&pwd->ComData,enable); for (i=0; iComData.MenuDesc.Num; i++) if (pwd->ComData.MenuDesc.Menu[i].Kind==MENU_PULLDOWN) (enable ? Enable : Disable)(pwd->ComData.MenuDesc.Menu[i].ItemId); } /* Called after loading starter and generator. 1. Re-evaluates G-dimensions after loading starter and generator. Example: for ODEs Phase and Time are not multi-dim in general (in class's .con file). But: for limit cycles they are (in type's .con file). Windows are initailized before LoadGen. 2. Sets/resets WFL_FROZEN flag for windows and manage menus appropriately. */ Global(void) VisualizerReevalGDim(void) { for (CurPwd=Windows; CurPwd; CurPwd=CurPwd->Next) { /* WFL_FROZEN and menus */ if (WindowStatus(GetWinClassIndex(CurPwd->WinClass))) { if (CurPwd->ComData.flags&WFL_FROZEN) { CurPwd->ComData.flags&=~WFL_FROZEN; ManageMenu(CurPwd); } } else { if (!(CurPwd->ComData.flags&WFL_FROZEN)) { CurPwd->ComData.flags|=WFL_FROZEN; ManageMenu(CurPwd); } } /*** ManageMenu(CurPwd); ***/ /* Set functions; this should be done for hidden windows as well */ CurPwd->Member->SimpleFunctions(&CurPwd->ComData); } } /* Special actions */ Global(void) VisualizerSpecial(VisualSpecAction vsa) { WindowPtr pwd; for (pwd=Windows; pwd; pwd=pwd->Next) if (!(pwd->ComData.flags&(WFL_HIDDEN|WFL_FROZEN))) { UseWindow(pwd->ComData.Win); pwd->Member->SpecialAction(&pwd->ComData,vsa); } }