// drawyear.c // // This file draws the year/month/day scale in the timeline window. // // by John D. de Boer #include "twist.h" #include "twindow.h" extern TimeGlobs Time; extern StepGlobs Step; extern GlobalOpts Opt; //extern bool /*Mono,RecordingPicture;*/ extern float Centre,Scale; extern int MAPWINDS; //extern Rect Page; extern void *Sel; extern const int BIGWIND; float TopRoom; // vertical coordinate of bottom of date line(s) static int DaysInMonth[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; static char *MonthLetter[12] = { "J","F","M","A","M","J","J","A","S","O","N","D" }; enum { monthNot=0,monthLetter,month3Letters,monthFull }; static int YEARS, // resolution of year lines MONTHS; // month drawing detail; see above enumeration static float DateHeight, // pixels per legend row TextBase, // base line of text from top of legend row FScale; // determines what accuracy of dates there is space for static bool Days, // whether days lines & numbers are drawn Wrinkle; // whether the month is October, 1582 // Utility static float Midnight(long JD) { float L; L= Centre + ((JD - Time.jd - 0.5) * Scale); return fbetween(L,-BIGWIND,BIGWIND); } // Year, month & day lines in time-line windows static void centreif(window *W, char *S, int ROW, float L, float R) { float V,Width; bool Ch; rect Page; if (!W || !S) return; Page=W->page; if (Rright(Page) || Rright(Page)) { R=right(Page); Ch=1; } Width=textwidth(W,S); if (Ch && R - L < Width + 6) return; V= (ROW * DateHeight) + TextBase; drawtext(W,((L + R - Width) / 2) + 1,top(Page) - V,S); } static void DrawDay(window *W, int YEAR, int MONTH, int DATE) { float L,R; long JD; char *S; bool Sabbath; rect Page; if (!W) return; Page=W->page; if (Wrinkle && DATE>=4 && DATE<14) return; JD=datetojd(YEAR,MONTH,DATE); L=Midnight(JD); R= L + Scale; if (Rright(Page)) return; penindex(W,beige); beginpath(W); moveto(W,L,top(Page) - (2 * DateHeight)); lineto(W,L,bottom(Page)); stroke(W); Sabbath=(dayofweek(JD)==6); fillindex(W,Sabbath ? brickred : brown); S=fig(DATE + 1); centreif(W,S,2,L,R); old(S); } static void DrawMonth(window *W, int YEAR, int MONTH, float L, float R) { int i,D; char *S; rect Page; if (!W) return; Page=W->page; if (Rright(Page)) return; if (Days) { Wrinkle=(YEAR==1582 && MONTH==9); D=DaysInMonth[MONTH]; if (MONTH==monthLetter && leapyear(YEAR,YEAR>1582)) D=29; for (i=0;ipage) - TextBase,fig(abso(YEAR))); } static void DrawYearNumber(window *W, int YEAR, int L, int R) { char *S; S=fig(abso(YEAR)); if (FScale>2.0) { if (YEAR<0) S=cat(1,S," B.C."); else S=cat(2,"A.D. ",S); } centreif(W,S,0,L,R); old(S); } static void DrawYear(window *W, int YEAR) { int i,YPO,Mo[13]; bool LineOnly; rect Page; if (!W) return; Page=W->page; LineOnly=(YEAR>=Time.year2 && YEARS==1); YPO= YEAR + 1; if (YPO==0) YPO=1; Mo[0]=Midnight(datetojd(YEAR,0,0)); Mo[12]=Midnight(datetojd(YPO,0,0)); if (MONTHS!=monthNot && !LineOnly) { for (i=1;i<12;i++) Mo[i]=Midnight(datetojd(YEAR,i,0)); for (i=0;i<12;i++) DrawMonth(W,YEAR,i,Mo[i],Mo[i + 1]); } penindex(W,medbrown); beginpath(W); moveto(W,Mo[0],top(Page)); lineto(W,Mo[0],bottom(Page)); stroke(W); if (LineOnly) return; fillindex(W,brown); if (YEARS>1) DrawYearSpan(W,YEAR,Mo[0]); else DrawYearNumber(W,YEAR,Mo[0],Mo[12]); } static int YearSpacing(void) { if (FScale < 0.0025) return 1000; if (FScale < 0.0050) return 500; if (FScale < 0.0125) return 200; if (FScale < 0.025) return 100; if (FScale < 0.050) return 50; if (FScale < 0.125) return 20; if (FScale < 0.25) return 10; if (FScale < 0.50) return 5; if (FScale < 1.25) return 2; return 1; } static int MonthResolution(void) { if (FScale< 4.0) return monthNot; if (FScale< 7.0) return monthLetter; if (FScale<30.0) return month3Letters; return monthFull; } // The grey box covering the interval static void FrameStepRect(window *W) { Span *S; float T; rect R; colour Grey; if (!W) return; S=&(Step.intv); if (S->start.kind!=timeJD || S->start.kind!=timeJD) return; T= top(W->page) - DateHeight; if (MONTHS!=monthNot) T-=DateHeight; if (Days) T-=DateHeight; setlbrt(&R,Midnight(S->start.jd),bottom(W->page),Midnight(S->end.jd + 1),T); greyshade(&Grey,0.88); fillcolour(W,&Grey); fillrect(W,R); fillindex(W,black); } // Calendar comparison text static string julstr(long JD) { string S; Date D; D.jd=JD; jdtojul(&D); if (!D.good) return copyof("error"); S=fig(abso(D.year)); if (D.year<0) S=cat(1,S," B.C."); S=cat3(1,S," ",monthname(D.month)); return cat3(5,S," ",fig(D.date + 1)); } static string gregstr(long JD) { string S; Date D; int YEAR; D.jd=JD; jdtogreg(&D); if (!D.good) return copyof("error"); YEAR=D.year; if (YEAR<0) YEAR++; S=fig(YEAR); S=cat3(1,S," ",monthname(D.month)); return cat3(5,S," ",fig(D.date + 1)); } static string hebstr(long JD) { string S; Date D; D.jd=JD; jdtoheb(&D); if (!D.good) return copyof("error"); S=fig(D.year); S=cat3(1,S," ",hebmonthname(D.month)); return cat3(5,S," ",fig(D.date + 1)); } static void DrawCalendComparison(window *W) { float H,V; H= Midnight(Time.jd) + 5; V= TopRoom + 5; drawtext(W,H,V - (1 * DateHeight),dayname(dayofweek(Time.jd))); drawtext(W,H,V - (2 * DateHeight),"J.D. at noon: "); textint(W,Time.jd); text(W,".0"); drawtext(W,H,V - (3 * DateHeight),"Julian: "); textold(W,julstr(Time.jd)); drawtext(W,H,V - (4 * DateHeight),"Gregorian: "); textold(W,gregstr(Time.jd)); drawtext(W,H,V - (5 * DateHeight),"Hebrew: "); textold(W,hebstr(Time.jd)); } // Entry routine void DrawTimeCoordinates(window *W, int PAGES, bool Printing) { int i; short START,END; bool Current; rect Page; float T; if (!W) return; Page=W->page; Current=(/*!Mono && */!Printing /*&& !RecordingPicture*/); FScale= 100.0 * Scale / Opt.size; DateHeight= Opt.size + 4; TextBase= Opt.size + 1; if (Opt.size>=18) TextBase--; if (Opt.size>=24) TextBase--; YEARS=YearSpacing(); MONTHS=MonthResolution(); Days=(FScale>150.0); if (Current && MAPWINDS>0) FrameStepRect(W); jdtodate(Time.jd - Time.dt,&START,NULL,NULL); START-=mod(START,YEARS); if (YEARS>1 && START>=0) START++; START=gtr(START,Time.year1); jdtodate(Time.jd + (Time.dt * ((PAGES * 2) - 1)),&END,NULL,NULL); END=lsr(END,Time.year2); for (i=START;i<=END && i<0;i+=YEARS) DrawYear(W,i); for (i=gtr(START,1);i<=END;i+=YEARS) DrawYear(W,i); penindex(W,medbrown); beginpath(W); if (W->printing) { moveto(W,left(Page),top(Page)); lineto(W,right(Page),top(Page)); moveto(W,left(Page),bottom(Page)); lineto(W,right(Page),bottom(Page)); } T= top(Page) - DateHeight; moveto(W,left(Page),T); lineto(W,right(Page),T); if (MONTHS!=monthNot) { T-=DateHeight; moveto(W,left(Page),T); lineto(W,right(Page),T); } if (Days) { T-=DateHeight; moveto(W,left(Page),T); lineto(W,right(Page),T); } stroke(W); if (Current) { penindex(W,red); beginpath(W); moveto(W,Midnight(Time.jd),T + 1.0); lineto(W,Midnight(Time.jd),bottom(Page)); stroke(W); } penindex(W,black); TopRoom= T - 5.0; if (Days) DrawCalendComparison(W); }