// ttt.c // // by John D. de Boer #include "twist.h" #include "ttt.h" extern int PLACES,PEOPLE,EVENTS; extern Person ***People; extern Event ***Events; extern bool CheckingDelta; string FileName; // the name of the current .ttt file FSRef *FileRef; // a reference to the current file // Managing current file name static void SetCurrentFile(FSRef *F, const char *Path) { FileRef=F; old(FileName); FileName=copyof(Path); } void SetItemFileName(const void *V) { Person *P; Event *E; char *S; if (!V) return; if (VoidIsPers(V)) { P=(Person *)V; S=P->src; } else if (VoidIsEvent(V)) { E=(Event *)V; S=E->src; } else return; old(FileName); FileName=copyof(S); } // TTT Tasks static void CommonTTTTaskInit(TTTTask *T) { if (!T) return; T->begun=0; T->done=0; T->finished=0; T->next=NULL; T->num=0; T->did=0; T->path=NULL; setpath(&(T->file)); T->text=filetocharpointer(); closefile(&(T->file)); if (!T->text) { WarnOld(cat3(2,"File \"",filename(&(T->file)),"\" was empty or could not be read")); T->done=1; } T->p=T->text; } static void InitTTTSubTask(TTTTask *T, TTTTask *Sub) { real Frac; if (!T) return; CommonTTTTaskInit(Sub); Sub->pd=T->pd; Frac= T->f2 - T->f1; if (T->num>0) Frac/=T->num; Sub->f1= T->f1 + (Frac * T->did); Sub->f2= T->f1 + (Frac * (T->did + 1)); } static void OldTTTTask(TTTTask *T) { if (!T) return; old(T->text); old(T->path); old(T); } static void DoneTTTSubTask(TTTTask *T) { if (!T) return; OldTTTTask(T->next); T->next=NULL; T->did++; } // Opening .ttt files static filelist Files; // a record of files that have already been read static bool GoodFile(TTTTask *T) { if (!T) return 0; if (fileinlist(&Files,&(T->file.fsref))) { NoteOld(cat3(2,"Duplicate reference to file \"",filename(&(T->file)),"\"")); return 0; } addfiletolist(&Files,&(T->file.fsref)); return 1; } static int NumberOfSubFile(const char *P) { int NUM; if (!P) return 0; NUM=0; while (P) { P=position("#file",P); if (P) { NUM++; P++; } } return NUM; } static string NextOctothorp(const char *S) { char *P; bool Y; P=(char *)S; while (1) { P=firstocc('#',P); if (!P) return NULL; Y=1; if (P >= S + 3 && begins(P - 3,"htm")) Y=0; if (P >= S + 4 && begins(P - 4,"html")) Y=0; if (isdigit(P[1])) Y=0; if (Y) return P; P++; } } static string NextMarkup(TTTTask *T) { char *E; T->p=NextOctothorp(T->p); if (!T->p) return NULL; T->p++; if (!*(T->p)) return NULL; E=NextOctothorp(T->p); if (!E) { E=T->p; while (*E) E++; } return leftstr(T->p,E - T->p); } static bool OpenRelFile(const FSRef *FSR, const char *Name, file *F) { bool R; FSRef New; if (!FSR || !F) return 0; if (!Name) { Warning("filename not found after \"#file\" mark-up"); return 0; } R=relfsref(FSR,Name,&New); if (!R) { WarnOld(cat3(0,"Couldn't resolve file \"",(char *)Name,"\"")); return 0; } R=openfile(&New,F); if (!R) { WarnOld(cat3(0,"Couldn't open file \"",(char *)Name,"\"")); return 0; } return 1; } static string PathName(const char *P, const char *N) { char *L,*S; L=(char *)P; if (L && *L=='/') L++; S=L; L=lastocc('/',S); // doesn't handle "../" if (L) S=cat(1,leftstr(S,L - S + 1),(char *)N); else S=copyof(N); repover(S,":","/"); repover(S,"//","/"); return S; } static void ReadTTT(TTTTask *T) { if (!T || !T->text || T->done) return; if (!T->begun) { if (!GoodFile(T)) { T->done=1; return; } } SetCurrentFile(&(T->file.fsref),T->path); if (!T->begun) { removecomments(T->text); cleanwhitespace(T->text); if (!T->text || !*(T->text)) { T->done=1; return; } T->num=NumberOfSubFile(T->text); PostCurrentFile(T->path,T->f1); T->begun=1; } if (T->next) { ReadTTT(T->next); if (T->next->done) DoneTTTSubTask(T); return; } while (1) { char *S; S=NextMarkup(T); if (!S) break; if (begins(S,"ad")) T->pd.ad=1; else if (begins(S,"bc")) T->pd.ad=0; else if (begins(S,"file")) { char *N; TTTTask *Sub; bool R; T->next=pointer(sizeof(TTTTask)); Sub=T->next; N=GetTTTFileName(S); R=OpenRelFile(&(T->file.fsref),N,&(Sub->file)); if (!R) { old(Sub); T->next=NULL; old(N); return; } InitTTTSubTask(T,Sub); Sub->path=PathName(T->path,N); old(N); ReadTTT(Sub); if (Sub->done) DoneTTTSubTask(T); return; } // old(S)? else ParseElement(S,&(T->pd)); old(S); } T->done=1; } // Entry points void InitTTTTask(TTTTask *T) { int i; if (!T) return; WaitCursor(); CommonTTTTaskInit(T); T->pd.ad=1; T->pd.delta=0; T->f1=0.0; T->f2=0.65; for (i=0;i<4;i++) T->post[i]=0; } static real Denom; static void FinishTask0(TTTTask *T) { if (!T) return; OrderPlacesBySize(); OrderPeopleByDOB(); OrderEventsByDate(); Denom= (PEOPLE + EVENTS) / (1 - T->f2); PostMessage("Creating hyperlinks...",0.0); T->post[0]=-1; } static void FinishTask1(TTTTask *T) { int i,start,end; if (!T) return; start=T->post[1]; end=lsr(start + 50,PEOPLE); for (i=start;if2 + (end / Denom)); T->post[1]= (end>=PEOPLE) ? -1 : end; } static void FinishTask2(TTTTask *T) { int i,start,end; if (!T) return; start=T->post[2]; end=lsr(start + 50,EVENTS); for (i=start;if2 + ((PEOPLE + end) / Denom)); T->post[2]= (end>=EVENTS) ? -1 : end; } static void FinishTask3(TTTTask *T) { if (!T) return; SetUpOrder(); MakeMenus(); defaultcursor(); SaveDictionary(); T->post[3]=-1; } static void FinishTTTTask(TTTTask *T) { if (!T) return; if (T->post[0]>=0) { FinishTask0(T); return; } if (T->post[1]>=0) { FinishTask1(T); return; } if (T->post[2]>=0) { FinishTask2(T); return; } if (T->post[3]>=0) { FinishTask3(T); return; } // NoteOld(cat5(21,fig(PLACES),", ",fig(PEOPLE)," and ",fig(EVENTS))); // geo 1390 // people 2278 // events 3324 T->finished=1; } void DoTTTTask(TTTTask *T) { if (!T) return; if (!T->done) { ReadTTT(T); if (T->done) old(T->text); return; } if (!T->finished) { FinishTTTTask(T); if (T->finished) EndWait(); return; } } void Purge(void) { PurgeWarnings(); PurgeIcons(); PurgeSpheres(); PurgeGlobe(); PurgeWhich(); PurgeEvents(); PurgeTypes(); PurgePeople(); PurgeOccs(); PurgePlaces(); InitTimeBounds(); PurgeTTTFields(); purgefilelist(&Files); PurgeDictionary(); } bool CanDoDelta(void) { return PLACES>0 || PEOPLE>0 || EVENTS>0; } void DoDeltaTask(file *F) { TTTTask T; if (!F) return; T.file=*F; InitTTTTask(&T); T.pd.delta=1; CheckingDelta=1; while (!T.done) { ReadTTT(&T); if (T.done) old(T.text); } CheckingDelta=0; EndWait(); defaultcursor(); } void InitTTT(void) { InitWait(); InitDictionary(); InitTTTFields(); FileName=NULL; initfilelist(&Files); }