'====================== SIMPLE CALENDAR PRINTING ====================================== ' Made using Bill Haesslein's code for the calendar shell and his date routines ' John Paterson - Dec 2008 ' This program is designed to produce simple, clear, high-contrast, large-font ' print-outs of month-to-view calendars. It is aimed at persons who have very poor ' vision. No provision for images is made; just text with some space for writing ' your own, very limited, notes each day ' Extensive commenting of code may help beginners. Others can delete it if it annoys! ' Please amend and improve the code as you wish '====================================================================================== ' Previously called Jonz Calendar - I only renamed it 'cos I am called Brian, not Jon! ' Modified Dec 2019. Leap Year of 2020 was causing days to be printed out of order ' Checked with a calendar for 2019 and 2020 - all appears correct ' Added ability to print any month as required ' Using the Dates.txt file, ages for the printed year are calculated and printed ' Companion program Dates Editor can be used to create, delete, sort and save dates autodefine "off" $include "windowssdk.inc" $include "commctrl.inc" LVITEM lItem 'Calendar variables DIALOG d1 WINDOW w1,w2 INT colWidth,rowHeight INT xOrigin,yOrigin,l,x ISTRING year$[32] INT EasterMonth,EasterDay INT c,day,year,i,j,z 'Define variables for c=cell location, day=day number, year=year number, x=columns in table, y=rows in table ISTRING day$[32] 'Define variable to hold day number INT FirstDay 'Define variable to hold cell location for first day of month ISTRING m$[32] ISTRING iDate[32] STRING temp,tempp INT t,countRows,nState,clik,pages[13] FILE iFile ENUM day_names Monday Tuesday Wednesday Thursday Friday Saturday Sunday ENDENUM ENUM controls EditDate=100 staticYear lview CheckAll UncheckAll PrintCal Cancel ENDENUM CREATEDIALOG d1,0,0,292,296,0x80C80080,0,"Brian's Calendar",&d1_handler CONTROL d1,@EDIT,DATE$("yyyy"),16,16,70,20,0x50810000,EditDate CONTROL d1,@STATIC,"Enter the Year to be printed",99,20,141,20,0x5000010B,staticYear CONTROL d1,@LISTVIEW,"",16,56,130,226,0x5080000D,lview CONTROL d1,@SYSBUTTON,"Check All",160,56,114,20,0x50018000,CheckAll CONTROL d1,@SYSBUTTON,"Uncheck All",160,96,114,20,0x50018000,UncheckAll CONTROL d1,@SYSBUTTON,"Print",160,150,114,20,0x50018000,PrintCal CONTROL d1,@SYSBUTTON,"Cancel and Close",160,260,114,20,0x50018001,Cancel DOMODAL d1 WAITUNTIL w2=0 'Now set the number of days in each month, taking into account leap years 'Define an integer array to hold the max days in each month INT mo[12],v400,v100,v4 'Set max days in each month 'mnth:1 2 3 4 5 6 7 8 9 10 11 12 'indx:0 1 2 3 4 5 6 7 8 9 10 11 mo=31,28,31,30,31,30,31,31,30,31,30,31 'Check for leap year and, if so, adjust max days in Feb v400=year-(year/400)*400 IF v400=0 THEN mo[1]=29 v100=year-(year/100)*100 IF v100<>0 THEN mo[1]=29 ELSE mo[1]=28 v4=year-(year/4)*4 IF v4=0 THEN mo[1]=29 ELSE mo[1]=28 'This application was originally designed for a 1280 x 1024 pixel screen 'Automatic scaling has since been added, to cater for any size of screen 'So, first, measure screen size, then apply scaling factors later in code UINT screen_width,screen_height GETSCREENSIZE screen_width,screen_height 'Set calendar grid size CONST num_cols=7 CONST num_rows=7 'Define 3D integer array to map table with size: 7 rows x 7 columns x 2 (x & y) dimensions INT pixelxy[num_cols,num_rows,2],row,column 'Colour Constants UINT cFG=0 UINT cBG=0xFFFFFFFF 'Calculate column width and row height colWidth=10*INT(INT(screen_width/num_cols)/10) rowHeight=10*INT(INT(screen_height/num_rows)/10) 'calculate co-ordinates of top left corner of 7 x 7 grid xOrigin=(screen_width-(colWidth*num_cols))/2 yOrigin=(screen_height-(rowHeight*num_rows))/2 'calculate and store co-ordinates of top left corners of all cells FOR row=0 TO 6 FOR column=0 TO 6 pixelxy[column,row,0]=xOrigin+(column*colWidth) pixelxy[column,row,1]=yOrigin+(row*rowHeight) NEXT column NEXT row 'Determine Easter for chosen Year iDate=Easter(year) EasterMonth=VAL(MID$(iDate,6,2)) EasterDay=VAL(MID$(iDate,9,2)) 'Define variables for storing messages INT year_num,month_num,day_num,age STRING mess[13,32] 'String array for month, day, but only 1 message per day FOR i=0 TO 12 FOR j=0 TO 31 mess[i,j]="" NEXT j NEXT i 'Store permanent messages... 'Store New Year's Day mess[1,1]="-New Year" 'Store the message for Easter Sunday in the correct day mess[EasterMonth,EasterDay]="-Easter Day" 'Store Christmas & Boxing Day mess[12,25]="-Xmas Day" mess[12,26]="-Boxing Day" 'Load text file with dates and names ReadNames() 'List of month names DATABEGIN month_names DATA 1,"January" DATA 2,"February" DATA 3,"March" DATA 4,"April" DATA 5,"May" DATA 6,"June" DATA 7,"July" DATA 8,"August" DATA 9,"September" DATA 10,"October" DATA 11,"November" DATA 12,"December" DATAEND ISTRING month_name[32] INT month,max_day 'Display each month of the year in turn, complete with all day numbers aligned with correct days-of-the-week and showing any messages on the correct day 'Offers the ability to print the page or to cancel print dialog and move on to display next month RESTORE month_names FOR month=1 TO 12 GETDATA month_names,month_num GETDATA month_names,month_name 'Find the first day of this month FirstDay=DayOfWeek(year,month,01) IF FirstDay=0 THEN FirstDay=7 SETWINDOWCOLOR w1,cBG 'Sets the background color of a window FRONTPEN w1,cFG 'Sets the foreground colour for drawing OPENWINDOW w1,0,0,screen_width,screen_height,@MINBOX|@MAXBOX|@SIZE,0,"Brian's Calendar",&main IF pages[month-1]=1 'bkh 'draw month name rectangle across top of screen RECT w1,pixelxy[0,0,0],pixelxy[0,0,1],(num_cols*colWidth),rowHeight 'draw day rectangles across lower part of month rectangle FOR column=0 TO 6 RECT w1,pixelxy[column,0,0],pixelxy[column,0,1]+(0.6*rowHeight),colWidth,(rowHeight*0.4) NEXT column 'draw an array of 7 cols x 6 rows of rectangular cells on screen FOR row=1 to 6 FOR column=0 TO 6 RECT w1,pixelxy[column,row,0],pixelxy[column,row,1],colWidth,rowHeight NEXT column NEXT row 'Now print the month, year and day headings... SETFONT w1,"Tahoma",(48*screen_height/1024),900,0 'Sets the font of a window or control, ready to print the Month, Name & Year m$=month_name+STR$(year) z=LEN(m$) MOVE w1,(screen_width/2)-(17*z*screen_width/1280),12+(4*screen_height/1024) 'Move the pen position in the window, w1, to co-ordinates FRONTPEN w1,RGB(0,0,255) PRINT w1,m$ 'Print in window, w1, the Month Name & Year, at the location set by the line immediately above FRONTPEN w1,cFG 'Sets the foreground colour for drawing SETFONT w1,"Arial",(30*screen_height/1024),900,0 'Sets the font of a window or control, ready to print Day Names MOVE w1,pixelxy[0,0,0]+(0.25*colWidth),pixelxy[0,0,1]+(0.65*rowHeight) 'Move the pen in the window, w1, to co-ordinates PRINT w1,"MON" 'Print in window, w1, the text shown, at the location set by the line immediately above MOVE w1,pixelxy[1,0,0]+(0.25*colWidth),pixelxy[1,0,1]+(0.65*rowHeight) 'Move the pen in the window, w1, to co-ordinates PRINT w1,"TUE" 'Print in window, w1, the text shown, at the location set by the line immediately above MOVE w1,pixelxy[2,0,0]+(0.25*colWidth),pixelxy[2,0,1]+(0.65*rowHeight) 'Move the pen in the window, w1, to co-ordinates PRINT w1,"WED" 'Print in window, w1, the text shown, at the location set by the line immediately above MOVE w1,pixelxy[3,0,0]+(0.25*colWidth),pixelxy[3,0,1]+(0.65*rowHeight) 'Move the pen in the window, w1, to co-ordinates PRINT w1,"THU" 'Print in window, w1, the text shown, at the location set by the line immediately above MOVE w1,pixelxy[4,0,0]+(0.25*colWidth),pixelxy[4,0,1]+(0.65*rowHeight) 'Move the pen in the window, w1, to co-ordinates PRINT w1,"FRI" 'Print in window, w1, the text shown, at the location set by the line immediately above MOVE w1,pixelxy[5,0,0]+(0.25*colWidth),pixelxy[5,0,1]+(0.65*rowHeight) 'Move the pen in the window, w1, to co-ordinates PRINT w1,"SAT" 'Print in window, w1, the text shown, at the location set by the line immediately above MOVE w1,pixelxy[6,0,0]+(0.25*colWidth),pixelxy[6,0,1]+(0.65*rowHeight) 'Move the pen in the window, w1, to co-ordinates PRINT w1,"SUN" 'Print in window, w1, the text shown, at the location set by the line immediately above c=0 'Initialise cell-pointer c day=1 'Set the first day of the month as 1 max_day=mo[month-1] 'Set last day of month column=0 'Now print all the Day Numbers in the correct cells, and also print any messages in the appropriate cells FOR row=1 TO 6 WHILE day<=max_day c++ 'Increment cell pointer MOVE w1,pixelxy[column,row,0]+2,pixelxy[column,row,1]+2 'Move the pen position in the window, w1, to co-ordinates x=pxy[y,x,0], y=pxy[y,x,1] IF c>=FirstDay 'Check that the cell-pointer c points to a cell greater than the first day cell... day$=LTRIM$(STR$(day)) 'Convert the integer day number into a string ready for justified printing IF LEN(day$)<2 THEN day$=""+day$ 'Right-justify single-digit days, using an underline character SETFONT w1,"Tahoma",(45*screen_height/1024),900,0 'Set font for Day Numbers PRINT w1,day$, 'Print Day Number in each cell SETFONT w1,"Tahoma",(16*screen_height/1024),600,0 'Reduce font size to fit message into cell IF mess[month,day]<>"" 'only print messages if they are not null FRONTPEN w1,RGB(0,0,255) temp=mess[month,day] 'messagebox 0,STR$(month)+STR$(day)+mess[month,day],"info" l=INSTR(temp,",") x=0 MOVE w1,pixelxy[column,row,0]+80,pixelxy[column,row,1]+2+x WHILE l>0 tempp=mid$(temp,1,l-1) temp=mid$(temp,l+1) IF MID$(tempp,1,1) = "-" FRONTPEN w1,RGB(220,20,60) tempp = MID$(tempp,2) ENDIF PRINT w1,tempp 'Print any message for this cell x+=26 MOVE w1,pixelxy[column,row,0]+80,pixelxy[column,row,1]+2+x l=INSTR(temp,",") ENDWHILE IF MID$(temp,1,1) = "-" FRONTPEN w1,RGB(220,20,60) temp = MID$(temp,2) ENDIF PRINT w1,temp,"" FRONTPEN w1,cFG 'Sets the foreground colour for drawing ENDIF day++ 'Increment the day number ENDIF column++ 'Increment the column number ENDWHILE NEXT row SETCAPTION w1,m$ PRINTWINDOW w1 'Display print dialog, ready to send contents of window (scaled & sized for both portrait or landscape) to printer WAITUNTIL w1=0 'Wait until page has been printed or print cancelled ENDIF 'bkh CLOSEWINDOW w1 NEXT month END SUB main(),INT IF @MESSAGE=@IDCLOSEWINDOW CLOSEWINDOW w1 ENDIF RETURN 0 ENDSUB SUB Easter(y:INT),STRING INT century,g,k,i,j,l,EasterMonth,EasterDay century = y / 100 g = y - (y / 19) * 19 k = (century - 17) / 25 i = century - century / 4 - (century - k) / 3 + 19 * g + 15 i = i - (i / 30) * 30 i = i - (i / 28) * (1 - (i / 28) / (i + 1)) * ((21 - g) / 11) j = y + y / 4 + i + 2 - century + century / 4 j = j - (j / 7) * 7 l = i - j EasterMonth = 3 + (l + 40) / 44 EasterDay = l + 28 - 31 * (EasterMonth / 4) RETURN ISODate(y,EasterMonth,EasterDay) ENDSUB SUB ISODate(yyyy:INT,mm:INT,dd:INT),STRING RETURN USING("0####",yyyy) + "-" + USING("0##",mm)+ "-" + USING("0##",dd) ENDSUB SUB DayOfWeek(yyyy:INT,mm:INT,dd:INT),INT INT t[12],y t = 0,3,2,5,0,3,5,1,4,6,2,4 y = yyyy y -= (mm < 3) ? 1: 0 RETURN (y + y/4 - y/100 + y/400 + t[mm-1] + dd) % 7 ENDSUB SUB d1_handler(),INT SELECT @MESSAGE CASE @IDINITDIALOG CENTERWINDOW d1 SENDMESSAGE d1,LVM_SETEXTENDEDLISTVIEWSTYLE,0,LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT|LVS_EX_CHECKBOXES,lview SENDMESSAGE d1,0x1024,0,0x000000,lview SENDMESSAGE d1,0x1026,0,0xFFC078,lview SENDMESSAGE d1,0x1001,0,0xFFFFFF,lview CONTROLCMD d1,lview,@LVINSERTCOLUMN,0,"Set Months to Print" CONTROLCMD d1,lview,@LVSETCOLWIDTH,0,124 CONTROLCMD d1,lview,@LVINSERTITEM,0,"January" CONTROLCMD d1,lview,@LVINSERTITEM,1,"February" CONTROLCMD d1,lview,@LVINSERTITEM,2,"March" CONTROLCMD d1,lview,@LVINSERTITEM,3,"April" CONTROLCMD d1,lview,@LVINSERTITEM,4,"May" CONTROLCMD d1,lview,@LVINSERTITEM,5,"June" CONTROLCMD d1,lview,@LVINSERTITEM,6,"July" CONTROLCMD d1,lview,@LVINSERTITEM,7,"August" CONTROLCMD d1,lview,@LVINSERTITEM,8,"September" CONTROLCMD d1,lview,@LVINSERTITEM,9,"October" CONTROLCMD d1,lview,@LVINSERTITEM,10,"November" CONTROLCMD d1,lview,@LVINSERTITEM,11,"December" SENDMESSAGE(d1,LVM_SETBKCOLOR,0,0x12B0E0,lview) 'Set Background Colour SENDMESSAGE(d1,LVM_SETTEXTBKCOLOR,0,0x12B0E0,lview) 'Set Text Background Colour conLVSetCheckState(d1,lview,-1,1) SETFOCUS d1,EditDate CASE @IDCLOSEWINDOW w2=0 CLOSEDIALOG d1,@IDOK END CASE @IDCONTROL SELECT @CONTROLID CASE CheckAll 'Check all IF @NOTIFYCODE=0 conLVSetCheckState(d1,lview,-1,1) ENDIF CASE UncheckAll 'Uncheck all IF @NOTIFYCODE=0 conLVSetCheckState(d1,lview,-1,0) ENDIF CASE PrintCal 'Print IF @NOTIFYCODE=0 year$=GETCONTROLTEXT(d1,EditDate) year=VAL(year$) countRows=CONTROLCMD(d1,lview,@LVGETCOUNT) t=0 WHILE t"" THEN tempp+="," tempp+="("+LTRIM$(STR$(age))+") "+MID$(temp,12) mess[month_num,day_num]=tempp ENDWHILE CLOSEFILE iFile ENDIF FOR i=1 TO 12 FOR j=1 TO 31 IF mess[i,j]<>"" THEN PRINT i,j,mess[i,j] NEXT j NEXT i ENDSUB