/* User defined functions */ #include "common.h" #include "datalib.h" #include "function.h" #include "large.h" #include "archive.h" #include "file.h" #include "visual.h" #include "curve.h" #include "param.h" #include "help.h" #include "userfunc.h" extern Global(CharPtr PNTR) UserTxt; /* defined in text.c */ enum { /* see setup.c, init[], /userfunc */ WINTITLE, /* User functions */ ADD_B, DELETE_B, RENAME_B, DISABLE_B, ENABLE_B, LIST, /* 15 10 ! listwidth listheight */ EDITOR, /* 38 15 ! textwidth textheight */ LABEL, /* Label */ TITLE, /* Name */ CONTEXT_C, /* Compiling user defined functions, please wait... */ USERFUNC_C, /* editing user functions context */ ERROR_T /* Error messages */ } UserTxtIndex; /* PART_UDFLIB contains the name of dynamic library. PART_UDFUNC contains specification of user-defined funcs: 1) number of udf (n), 2) n pairs: 2.1) full name of a C function, 2.2) flag. 3) unique code for the next new function. 4) n tripples: 4.1) short name (label), 4.2) unique code,s 4.3) body of C function, If n==0 then 2) and 4) are omitted. */ #define UTF_PAR1 "_v" #define UTF_PAR2 "SeekPoint" #define UTF_PAR3 "Value" /* User-defined function, see also BuildHeader below */ typedef EntryPtr(int,UserFunc,(double * * * _v, int (* PointSeek)(int), double * Value)); typedef struct { CharPtr Label; /* short name used to identify points */ CharPtr Title; /* full name used to name function and C function */ CharPtr Text; /* function's body */ Uint4 Unique; /* unique code of this function */ Int2 line; /* number of first line of this func in C source */ Int1 flag; #define DISABLED 1 /* don't compile and show this func */ } TestFunc, PNTR TestFuncPtr; typedef struct { LisT list; PrompT prompt; TexT text; TexT label; TexT title; TestFuncPtr funcs; CharPtr curlabel; CharPtr curtitle; CharPtr lib; Uint4 NextUnique; /* unique code for next function */ Int2 num; /* number of functions */ Int2 cur; /* function currently operated on */ Int2 oldcur; /* prev function */ } OptData, PNTR OptDataPtr; Local(void) ListProc(LisT l); Local(Int2) NumOfActiveUDF(OptDataPtr data) { Int2 i,n; for (i=n=0; inum; i++) if (!(data->funcs[i].flag&DISABLED)) n++; return n; } Local(Boolean) GetTexts(OptDataPtr data, Boolean cur) { size_t lenl,lent; Int2 i; lenl=TextLength(data->label)+1; lent=TextLength(data->title)+1; data->curlabel=_MemNew(lenl); data->curtitle=_MemNew(lent); GetTitle(data->label,data->curlabel,lenl); GetTitle(data->title,data->curtitle,lent); StrTrim(data->curlabel); StrTrim(data->curtitle); if (!StrLen(data->curlabel) || !StrLen(data->curtitle)) { myWarning("UT_EMPTY"); goto error; } for (i=0; inum; i++) { if (!cur && i==data->cur) continue; if (!StrCmp(data->funcs[i].Label,data->curlabel) || !StrCmp(data->funcs[i].Title,data->curtitle)) { myWarning("UT_DUPLICATE"); goto error; } } return TRUE; error: _MemFree(data->curlabel); _MemFree(data->curtitle); return FALSE; } Local(void) FreeLib(DataLibPtr arch) { CharPtr lib; if (DataLibFind(arch,PART_UDFLIB)==0) { lib=DataLibReadVRecord(arch,NULL); unlink(lib); FreeFileName(lib); /* Free unique filename */ _MemFree(lib); DataLibDelete(arch); } } Local(void) ReadData(DataLibPtr arch, OptDataPtr data) { Int2 n; DataLibSeekDir(arch,arch->CurDirPtr); /* rewind */ DataLibRead(arch,(CharPtr)&data->num,sizeof(data->num)); if (data->num) data->funcs=_MemNew(ARRAYSIZE(TestFunc,data->num)); for (n=0; nnum; n++) { data->funcs[n].Title=DataLibReadVRecord(arch,NULL); DataLibRead(arch,(CharPtr)&data->funcs[n].flag,sizeof(data->funcs[n].flag)); } DataLibRead(arch,(CharPtr)&data->NextUnique,sizeof(data->NextUnique)); for (n=0; nnum; n++) { data->funcs[n].Label=DataLibReadVRecord(arch,NULL); DataLibRead(arch,(CharPtr)&data->funcs[n].Unique,sizeof(data->NextUnique)); data->funcs[n].Text=DataLibReadVRecord(arch,NULL); } } Local(void) FreeData(OptDataPtr data) { Int2 n; for (n=0; nnum; n++) { _MemFree(data->funcs[n].Label); _MemFree(data->funcs[n].Title); _MemFree(data->funcs[n].Text); } _MemFree(data->funcs); _MemFree(data->lib); _MemFree(data); } Local(Boolean) Errors=FALSE; /* during last compilation */ Local(ByteStorePtr) ErrorLines=NULL; Local(ByteStorePtr) StartLines=NULL; Local(Boolean) RecompileWindowFuncs=FALSE; Local(Boolean) CompErr=FALSE; /* called by the editor when the user pushed Ok or Cancel button */ Local(Int2) TerminateProc(CharPtr test) { WindoW win; OptDataPtr data; Int2 n; Boolean closed; if (Errors) { ErrorLines=BSFree(ErrorLines); Errors=FALSE; } win=CurrentWindow(); data=(OptDataPtr)GetWindowExtra(win); if (test) { /* Ok */ SetValue(data->list,0); ListProc(data->list); /* save text of current func */ } else FreeData(data); Remove(win); if (test) { closed=DataLibIsClosed(&ArchivesLib); if (closed) DataLibOpen(&ArchivesLib,ArchivesName); DeactivateUserFunc(&ArchivesLib); /* Save user's stuff */ DataLibDown(&ArchivesLib); /* Free lib to force its recreation */ FreeLib(&ArchivesLib); if (DataLibFind(&ArchivesLib,PART_UDFUNC)==0) DataLibDelete(&ArchivesLib); DataLibCreate(&ArchivesLib,PART_UDFUNC); DataLibWrite(&ArchivesLib,(CharPtr)&data->num,sizeof(data->num)); for (n=0; nnum; n++) { DataLibWriteVRecord(&ArchivesLib,NULL,data->funcs[n].Title,StrLen(data->funcs[n].Title)+1); DataLibWrite(&ArchivesLib,(CharPtr)&data->funcs[n].flag,sizeof(data->funcs[n].flag)); } DataLibWrite(&ArchivesLib,(CharPtr)&data->NextUnique,sizeof(data->NextUnique)); for (n=0; nnum; n++) { DataLibWriteVRecord(&ArchivesLib,NULL,data->funcs[n].Label,StrLen(data->funcs[n].Label)+1); DataLibWrite(&ArchivesLib,(CharPtr)&data->funcs[n].Unique,sizeof(data->NextUnique)); DataLibWriteVRecord(&ArchivesLib,NULL,data->funcs[n].Text,StrLen(data->funcs[n].Text)+1); } DataLibUp(&ArchivesLib); DataLibFlush(&ArchivesLib); FreeData(data); RecompileWindowFuncs=TRUE; ActivateUserFunc(&ArchivesLib); if (closed) DataLibClose(&ArchivesLib); } else CompErr=FALSE; UnlockAll(); return 0; /* editor will be terminated */ } Local(void) AddProc(Int2 index); Local(Boolean) AddProc_Status(Int2 index); Local(void) DeleteProc(Int2 index); Local(Boolean) DeleteProc_Status(Int2 index); Local(void) RenameProc(Int2 index); Local(Boolean) RenameProc_Status(Int2 index); Local(void) EnableProc(Int2 index); Local(Boolean) EnableProc_Status(Int2 index); Local(void) DisableProc(Int2 index); Local(Boolean) DisableProc_Status(Int2 index); Local(MenuItem) Buttons[]={ {ADD_B, AddProc, AddProc_Status}, {RENAME_B, RenameProc, RenameProc_Status}, {DELETE_B, DeleteProc, DeleteProc_Status}, {ENABLE_B, EnableProc, EnableProc_Status}, {DISABLE_B, DisableProc, DisableProc_Status} }; Local(MenuDesc) ShowButtons={Buttons,DIM(Buttons)}; /* Common callback for Buttons */ Local(void) ButtonAction(ButtoN b) { DoMenuAction(&ShowButtons,(IteM)b); } Local(OptDataPtr) GetOptDataPtr(Int2 index) { return GetWindowExtra(ParentWindow(Buttons[index].ItemId)); } Local(CharPtr) BuildListItem(TestFuncPtr tfp) { CharPtr p; p=_MemNew(1+StrLen(tfp->Label)+3+StrLen(tfp->Title)+1); sprintf(p,"%c%s (%s)",tfp->flag&DISABLED?'-':'+',tfp->Title,tfp->Label); return p; } Local(void) RecreateList(OptDataPtr data) { CharPtr p; Int2 i; Hide(data->list); Reset(data->list); for (i=0; inum; i++) { ListItem(data->list,p=BuildListItem(data->funcs+i)); _MemFree(p); } SetValue(data->list,data->cur+1); Show(data->list); } Local(Boolean) ManyFuncs(OptDataPtr data) { return NumOfActiveUDF(data)>=sizeof(Pointtype)*BITSPERBYTE-1 ? (myWarning("UF_MANY",(int)(sizeof(Pointtype)*BITSPERBYTE-1)),TRUE) : FALSE; } Local(void) AddProc(Int2 index) { OptDataPtr data=GetOptDataPtr(index); TestFuncPtr tfp; CharPtr p; if (GetTexts(data,TRUE)) { if (ManyFuncs(data)) return; if (data->num) data->funcs=_MemMore(data->funcs,ARRAYSIZE(TestFunc,data->num+1)); else data->funcs=_MemNew(ARRAYSIZE(TestFunc,1)); tfp=&data->funcs[data->num++]; tfp->Label=data->curlabel; tfp->Title=data->curtitle; tfp->Text= #if _WIN _StringSave(" *"UTF_PAR3"=?;\r\n return 0;\r\n"); #else _StringSave(" *"UTF_PAR3"=?;\n return 0;\n"); #endif tfp->flag=0; tfp->Unique=data->NextUnique++; p=BuildListItem(tfp); ListItem(data->list,p); _MemFree(p); SetValue(data->list,data->num); ListProc(data->list); Enable(data->text); SetStatusOfItems(&ShowButtons); } } Local(Boolean) AddProc_Status(Int2 index) { return GetOptDataPtr(index)->num<200; } Local(void) DeleteProc(Int2 index) { OptDataPtr data=GetOptDataPtr(index); Int2 cur=data->cur; SetValue(data->list,0); ListProc(data->list); /* save current */ _MemFree(data->funcs[cur].Label); _MemFree(data->funcs[cur].Title); _MemFree(data->funcs[cur].Text); if (data->num>1) { MemCopy(data->funcs+cur,data->funcs+cur+1, ARRAYSIZE(TestFunc,data->num-cur-1)); data->funcs=_MemMore(data->funcs,ARRAYSIZE(TestFunc,--data->num)); data->cur=cur>=data->num ? data->num-1 : cur; } else { data->funcs=_MemFree(data->funcs); data->num=0; data->cur=-1; Disable(data->text); } RecreateList(data); ListProc(data->list); SetStatusOfItems(&ShowButtons); } Local(Boolean) DeleteProc_Status(Int2 index) { return GetOptDataPtr(index)->num>0; } Local(void) RenameProc(Int2 index) { OptDataPtr data=GetOptDataPtr(index); TestFuncPtr tfp; if (GetTexts(data,FALSE)) { /* ignore current */ tfp=data->funcs+data->cur; _MemFree(tfp->Label); tfp->Label=data->curlabel; _MemFree(tfp->Title); tfp->Title=data->curtitle; RecreateList(data); ListProc(data->list); SetStatusOfItems(&ShowButtons); } } Local(Boolean) RenameProc_Status(Int2 index) { return GetOptDataPtr(index)->num>0; } Local(void) EnableProc(Int2 index) { OptDataPtr data=GetOptDataPtr(index); if (ManyFuncs(data)) return; data->funcs[data->cur].flag&=~DISABLED; RecreateList(data); ListProc(data->list); SetStatusOfItems(&ShowButtons); } Local(Boolean) EnableProc_Status(Int2 index) { OptDataPtr data=GetOptDataPtr(index); return data->cur<0 ? FALSE : data->funcs[data->cur].flag&DISABLED; } Local(void) DisableProc(Int2 index) { OptDataPtr data=GetOptDataPtr(index); data->funcs[data->cur].flag|=DISABLED; RecreateList(data); ListProc(data->list); SetStatusOfItems(&ShowButtons); } Local(Boolean) DisableProc_Status(Int2 index) { OptDataPtr data=GetOptDataPtr(index); return data->cur<0 ? FALSE : !(data->funcs[data->cur].flag&DISABLED); } /*-------------------------------------*/ /* Specify/Edit user-defined fucntions */ Local(void) BuildHeader(OptDataPtr data, Int2 n) { StrCpy(ParBuf,"int "); GetParamAppend(SFS_COMPILER,"RHSATTR"); sprintf(ParBuf+StrLen(ParBuf), " %s(double ***"UTF_PAR1", int (*"UTF_PAR2")(int), double *"UTF_PAR3")", data->funcs[n].Title); } /* User-defined func list callback */ Local(void) ListProc(LisT l) { OptDataPtr data=GetWindowExtra(ParentWindow(l)); size_t len; data->cur=GetValue(l)-1; if (data->oldcur>=0) { _MemFree(data->funcs[data->oldcur].Text); len=TextLength(data->text); data->funcs[data->oldcur].Text=_MemNew(len+1); GetTitle(data->text,data->funcs[data->oldcur].Text,len+1); } if (data->cur>=0) { SetTitle(data->label,data->funcs[data->cur].Label); SetTitle(data->title,data->funcs[data->cur].Title); SetTitle(data->text,data->funcs[data->cur].Text); BuildHeader(data,data->cur); SetTitle(data->prompt,ParBuf); (data->funcs[data->cur].flag&DISABLED ? Disable : Enable)(data->prompt); (data->funcs[data->cur].flag&DISABLED ? Disable : Enable)(data->text); } else { SetTitle(data->label,""); SetTitle(data->title,""); SetTitle(data->text,""); SetTitle(data->prompt,""); } data->oldcur=data->cur; SetStatusOfItems(&ShowButtons); } /* Error message list callback */ Local(void) ErrorListActn(LisT l) { OptDataPtr data=GetWindowExtra(ParentWindow(l)); CharPtr p,q; int line; Int2 n,i; line=GetValue(l)-1; BSSeek(ErrorLines,(Int4)(line*sizeof(line)),SEEK_SET); BSRead(ErrorLines,&line,sizeof(line)); for (n=data->num-1; n>=0; n--) { if (data->funcs[n].flag&DISABLED) continue; if (line>data->funcs[n].line) { SetValue(data->list,n+1); ListProc(data->list); p=data->funcs[n].Text; for (i=line-data->funcs[n].line-1; i; p=q+1,i--) { q=StrChr(p,'\n'); if (!q) break; } n=(Int2)(p-data->funcs[n].Text); SelectText(data->text,n,n); break; } } } Local(void) CheckLabelAndName(TexT t) { CharPtr p; size_t len; Int2 i,b,e; len=TextLength(t); p=_MemNew(len+1); GetTitle(t,p,len+1); if (*p) { TextSelectionRange(t,&b,&e); /* it is very probable lenlist=SingleList(gNames,w,h,ListProc); gButtons=HiddenGroup(gNames,0,5,NULL); GetPosition(data->list,&r); spacing=Spacing(r.bottom-r.top,FALSE,UserTxt[ADD_B], UserTxt[DELETE_B], UserTxt[RENAME_B], UserTxt[ENABLE_B], UserTxt[DISABLE_B],NULL); SetGroupMargins(gButtons,0,spacing); SetGroupSpacing(gButtons,0,spacing); for (n=0; nlabel=DialogText(gTitles,"",1,CheckLabelAndName); StaticPrompt(gTitles,UserTxt[TITLE],0,dialogTextHeight,NULL,'l'); data->title=DialogText(gTitles,"",1,CheckLabelAndName); sscanf(UserTxt[EDITOR],"%i %i",&w,&h); data->prompt=StaticPrompt(g,"",0,0,NULL,'l'); PushContext(HLP_USERFUNC,NULL,UserTxt[USERFUNC_C]); data->text=CreateEditor(g,"",w,h,TerminateProc,NULL); AlignObjects(ALIGN_LEFT,(HANDLE)data->list, (HANDLE)data->prompt, (HANDLE)data->text,NULL); AlignObjects(ALIGN_RIGHT,(HANDLE)data->label, (HANDLE)data->title, (HANDLE)data->prompt, (HANDLE)data->text,NULL); /* Restore user's stuff */ closed=DataLibIsClosed(&ArchivesLib); if (closed) DataLibOpen(&ArchivesLib,ArchivesName); DataLibDown(&ArchivesLib); if (DataLibFind(&ArchivesLib,PART_UDFUNC)==0) { ReadData(&ArchivesLib,data); RecreateList(data); } DataLibUp(&ArchivesLib); if (closed) DataLibClose(&ArchivesLib); data->oldcur=-1; if (data->num>0) { SetValue(data->list,data->cur=1); ListProc(data->list); } else { data->cur=-1; Disable(data->text); } if (Errors) { BSSeek(StartLines,0,SEEK_SET); for (n=0; nnum; n++) BSRead(StartLines,&data->funcs[n].line,sizeof(data->funcs[n].line)); StartLines=BSFree(StartLines); ErrorListActn(l); } /* Show */ SetStatusOfItems(&ShowButtons); ShowLargeWindow(gMain); } #if _WIN #pragma argsused #endif Global(Boolean) UserFuncProc_Status(Int2 index) { return FunctionsHandle!=NULL; /* functions are selected */ } /*-----------------------------------------------------------*/ /* Delete user function (a part of systems deletion process) */ Global(void) DeleteUserFunc(DataLibPtr arch) { CharPtr p; p=DataLibReadVRecord(arch,PART_UDFLIB); /* get user funcs lib file name */ if (p && *p) { unlink(p); FreeFileName(p); /* Free unique filename */ } _MemFree(p); DataLibDeletePartitions(arch,PART_UDFLIB,PART_UDFUNC,NULL); } /*--------------------------------------------*/ /* Activate/Deactivate user-defined functions */ Global(Int2) UserFuncNum=0; Local(UserFunc PNTR) UserFuncAddr=NULL; Local(LibHandle) UserFuncHandle=NULL; Global(FloatHiPtr) UserFuncValues=NULL; /* values of udfs */ Global(Uint4Ptr) UserFuncUnique=NULL; /* unique numbers of currently enabled udfs */ Local(CharPtr PNTR) UserLabel=NULL; Local(CharPtr PNTR) UserName=NULL; Global(Int2) UserFuncLookup(Uint4 unique) { Int2 i; for (i=0; i>=1) if (mask&1) { j=UserFuncLookup(udftable[i]); pn=j>=0 ? (full ? UserName : UserLabel)[i] : "u?"; if (l+StrLen(pn)lib); SetParam(SFS_LIBRARIES,"UDFLIB",ParBuf); UserFuncHandle=LibraryLock("UDFLIB"); UserFuncAddr=_MemNew(sizeof(UserFunc PNTR)*data->num); ClassAddVar(VCL_UDF,NULL); /* reset class */ for (n=UserFuncNum=0; nnum; n++) { if (data->funcs[n].flag&DISABLED) continue; UserFuncAddr[UserFuncNum++]= (UserFunc)LibraryFuncAddress(UserFuncHandle,data->funcs[n].Title); ClassAddVar(VCL_UDF,data->funcs[n].Title); } UserFuncValues=_MemNew(ARRAYSIZE(FloatHi,UserFuncNum)); UserFuncUnique=_MemNew(ARRAYSIZE(Uint4Ptr,UserFuncNum)); UserLabel=_MemNew(ARRAYSIZE(CharPtr,UserFuncNum)); UserName=_MemNew(ARRAYSIZE(CharPtr,UserFuncNum)); for (n=m=0; nnum; n++) { if (data->funcs[n].flag&DISABLED) continue; UserFuncUnique[m]=data->funcs[n].Unique; UserLabel[m]=_StringSave(data->funcs[n].Label); UserName[m]=_StringSave(data->funcs[n].Title); m++; } FreeData(data); if (RecompileWindowFuncs) ReinitAll(); } Local(OptDataPtr) Data; #if _WIN #pragma argsused #endif Local(Int2) ProcessUDFErrors(Boolean errors, CharPtr text, int linenum) { Int2 n; CompErr=errors; if (errors) { StartLines=BSNew(0); for (n=0; nnum; n++) { BSWrite(StartLines,&Data->funcs[n].line,sizeof(Data->funcs[n].line)); } FreeData(Data); Errors=TRUE; UserFuncProc(0); } else { /* MS Windows note. Compilation of udf is not complete up to return from this function (see utility.c). At the same time we should call LoadLib(Data) to load lib, etc. This would cause recompilation of windows function thus resulting to recursive call to ExecuteComand. To avoid this we postpone the call to LoadLib until the return from the Compile function. LoadLib(Data); */ } UnlockAll(); return errors ? 1 : 0; } Local(Int2) line,clas,var; Local(FILE PNTR) Source; #if _WIN #pragma argsused #endif Local(void) ProcVar(LisT dummy, CharPtr name, Int2 dim) { Int2 relcl; relcl=GetNthRelevantClass(clas); if (IsClassBasic(relcl)) { fprintf(Source,"#define %s %s(**("UTF_PAR1"+%i)+%i)%s\n", name,dim==1?"(*":"",relcl,var,dim==1?")":""); var+=dim; line++; } } #if _WIN #pragma argsused #endif Local(void) ProcClass(LisT dummy, CharPtr title, CharPtr name, Boolean defvis, Uint2 realId) { if (!StrCmp(name,VCL_UDF)) return; var=0; EnumVariables(0,GetNthRelevantClass(clas),ProcVar); clas++; /* don't do this in the prev. statement */ } Global(void) UserFuncDefineClass(DataLibPtr arch, CharPtr buf) { OptDataPtr data; Int2 i; *buf='\0'; DataLibDown(arch); if (DataLibFind(arch,PART_UDFUNC)==0) { data=_MemNew(sizeof(OptData)); ReadData(arch,data); for (i=0; inum; i++) { if (data->funcs[i].flag&DISABLED) continue; StrCat(buf,data->funcs[i].Title); StrCat(buf," "); } FreeData(data); } DataLibUp(arch); } Local(Boolean) CheckIncludes(struct stat *statbuf) { CharPtr p; int pos; Int2 n; Boolean res=FALSE; Char ifn[PATH_MAX]; for (n=0; nnum; n++) for (p=Data->funcs[n].Text; (p=StrChr(p,'#'),p); p+=pos) { pos=-1; if (sscanf(p,"# include \"%[^\"]\"%n",ifn,&pos)==1 && pos>0) res|=ProcessIncludeFile(ifn,statbuf); else pos=1; } return res; } Global(void) ActivateUserFunc(DataLibPtr arch) { OptDataPtr data; Int2 n; DataLibDown(arch); if (DataLibFind(arch,PART_UDFUNC)==0) { /*********** Don't erase PART_UDFUNC if number of udf becomes zero: NextUnique must be preserved. DataLibRead(arch,(CharPtr)&n,sizeof(n)); if (!n) { DataLibDelete(arch); FreeLib(arch); goto prem; } ***********/ data=_MemNew(sizeof(OptData)); /* filled by 0s by default */ ReadData(arch,data); if (NumOfActiveUDF(data)==0) { FreeLib(arch); FreeData(data); /*** prem: ***/ DataLibUp(arch); UserFuncValues=_MemNew(ARRAYSIZE(FloatHi,1)); if (RecompileWindowFuncs) ReinitAll(); return; } DataLibUp(arch); /* MustRecompile requires this */ Data=data; if (MustRecompile(arch,arch,PART_UDFLIB,FALSE,CheckIncludes)) { DataLibDown(arch); FreeLib(arch); AssignFileName(); SetParam(SFS_COMPILER,"TARGET",ParBuf); GetParamAppend(SFS_EXTENSIONS,"LIB"); /* Append the extension to it */ DataLibWriteVRecord(arch,PART_UDFLIB,ParBuf,StrLen(ParBuf)+1); data->lib=_StringSave(ParBuf); DataLibUp(arch); /* Create C source for user-defined functions */ LockAll(); SetParam(SFS_COMPILER,"SOURCE",GetParam(SFS_FILES,"UDF")); Source=FileOpen(GetParamAppend(SFS_EXTENSIONS,"C"),"wt"); line=0; CountLinesAndErase_r(BuildH(),'\n',&line); fputs(ParBuf,Source); clas=0; EnumClasses(0,ProcClass); /* defines for visible names */ for (n=0; nnum; n++) { if (data->funcs[n].flag&DISABLED) continue; BuildHeader(data,n); line+=2; /* number of \n before %s in following fprintf */ data->funcs[n].line=line; data->funcs[n].Text=CountLinesAndErase_r(data->funcs[n].Text,'\r',&line); fprintf(Source,"\n%s {\n%s\n}\n",ParBuf,data->funcs[n].Text); line+=2; /* number of \n after %s in above fprintf */ } FileClose(Source); PushContext(0,NULL,UserTxt[CONTEXT_C]); if (Compile("MAKERHS",ProcessUDFErrors)) while (CompErr) myProcessAnyEvent(); /* wait until successful compilation or 'Cancel' */ else { /* successful compilation */ LoadLib(Data); } } else { DataLibDown(arch); data->lib=DataLibReadVRecord(arch,PART_UDFLIB); DataLibUp(arch); LoadLib(data); } } else DataLibUp(arch); } #if _WIN #pragma argsused #endif Global(void) DeactivateUserFunc(DataLibPtr arch) { Int2 i; ClassAddVar(VCL_UDF,NULL); /* reset class */ UserFuncValues=_MemFree(UserFuncValues); UserFuncUnique=_MemFree(UserFuncUnique); UserFuncHandle=LibraryUnlock(UserFuncHandle); UserFuncAddr=_MemFree(UserFuncAddr); if (UserLabel) { for (i=0; i=0 && pointnum=UserFuncNum) return -12345; Gdim=Decoder(vector,DECODER_DIM); Decoder(vector,1); /* seek to the first/only M-point */ Vector=vector; rc=UserFuncAddr[num](IndirectValues,UserSeek,value); UserFuncValues[num]=*value; /* to visualize */ Epilog return rc; } /*-------------------------------------*/ /* Returns the name of a user function */ Global(CharPtr) UserFuncName(Int2 i) { CharPtr p; Prolog p=(i>=0 && inum); for (n=0; nnum; n++) fprintf(out," %s %i\n",data->funcs[n].Title,(int)data->funcs[n].flag); fprintf(out," %i\n",(int)data->NextUnique); for (n=0; nnum; n++) { fprintf(out," %s %i\n",data->funcs[n].Label,(int)data->funcs[n].Unique); fprintf(out,"%s\n"SECPRF" %i\n",data->funcs[n].Text,(int)n); } FreeData(data); } Global(void) UserFuncImport(DataLibPtr arch, FILE PNTR in) { /* This must correspond to ReadData */ CharPtr p; Uint4 unique; int w; Int2 n,num; Int1 flag; if (fscanf(in," %i ",&w)==1) { DataLibCreate(arch,PART_UDFUNC); num=(Int2)w; DataLibWrite(arch,(CharPtr)&num,sizeof(num)); for (n=0; n