This month we add the second and final part of the Desktop Diary program, which allows entries to be made and edited, and saved to file for later recall. For a detailed account of how to use the complete program you should refer to last month's RISC User (Volume 2 Issue 9).
To add this month's coding to that for last month, type it in and save it under a suitable name. Then load part 1 of the program and use the APPEND command to add the rest. The whole program should be saved with the name !RunImage in the !Diary directory as described previously.
The Diary can be installed by double clicking on its icon in a directory viewer, while a single click on the menu bar will display the calendar for the current month, ready for entering data. Alternatively, if you have already created and saved a diary file, then you should load this by dragging its icon over the Diary icon on the menu bar.
Each diary entry requires 168 bytes of memory. The first three bytes hold the combined month and year, the next byte the day, and the remaining 164 bytes four lines of 41 characters. The maximum number of entries is set by the variable max_notes% in line 3280, and the command WimpSlot in the !Run file. This maximum is currently set to 270 entries, which requires 64K. If this is insufficient, change the WimpSlot command and adjust max_notes% accordingly - each 8K of memory gives another 48 entries.
Because there may be many hundreds of entries, three machine code routines are employed so that operations on the entries occur very quickly. find_entry is passed a date, and returns the address of the entry for that date, insert_entry is passed the address of an entry and creates a gap at which to insert the new entry, while delete_entry does just that on being passed the address of an entry.
The program may produce any of three error messages. The first occurs if the number of diary entries has reached the maximum set, and you click on an un-highlighted date. The second happens if you try to load a diary file with more entries than the current maximum. The last error can occur when attempting to merge a diary file. If a new entry would cause the maximum number of entries to be exceeded, then this is flagged, but the rest of the file is read in and existing entries overwritten, but all completely new entries will be ignored.
170 WHEN 7 : PROCdrag_done
180 WHEN 8 : PROCkey_press(!block%,block%!4,block%!8,block%!24)
270 IF W%<>w_diary% THEN
280 date%(FNget_note_num(W%))=-1
290 B%=FNaddr(W%)
300 IF del% OR (B%?4=13 AND B%?45=13 AND B%?86=13 AND B%?127=13) THEN
310 CALL delete_entry
320 PROCnew_month(0):PROCupdate_notes(FALSE)
330 ENDIF
340 ENDIF
430 WHEN 16,64 : PROCdrag_click
470 DEFPROCdrag_done
480 SYS "Wimp_GetPointerInfo",,block%
490 block%!20=64:block%!32=0
500 block%!36=1:block%!40=block%!12
510 block%!44=block%!16
520 block%!48=!block%
530 block%!52=block%!4
540 block%!56=!next-!first
550 block%!60=&FEF
560 $(block%+64)=FNleaf($file_name%)
570 SYS "Wimp_SendMessage",17,block%+2
0,block%!12,block%!16
580 ENDPROC
590 :
600 DEFPROCkey_press(W%,I%,X%,C%)
610 CASE C% OF
620 WHEN 13 : IF W%=w_save% PROCquick_save ELSE PROCcaret(W%,I%-(I%<3),0)
630 WHEN 30 : PROCcaret(W%,0,0)
640 WHEN &18E:PROCcaret(W%,I%-(I%<3),X%)
650 WHEN &18F:PROCcaret(W%,I%+(I%>0),X%)
660 OTHERWISE SYS "Wimp_ProcessKey",C%
670 ENDCASE
680 ENDPROC
690 :
760 WHEN 2 : PROCprint_entries(B%)
780 OTHERWISE : CASE A% OF
790 WHEN 0 : PROCclear_entry(mw%)
800 WHEN 1 : PROCclose_window(mw%,TRUE):stay%=FALSE
810 WHEN 2 : PROCprint_entries(FNaddr(mw%))
820 ENDCASE
900 WHEN 2 : PROCsave_notes(FNget_name(block%+44))
910 WHEN 3,5 : IF block%!12=0 AND block%!40=&FEF PROCload_merge(block%!20,FNget_name(block%+44))
980 WHEN w_save% : IF I%=i_ok% PROCquick_save
1020 OTHERWISE PROCdate_selected((month%<<8)+I%-3)
1120 OTHERWISE : PROCmaster_menu("Diary
note","Clear,Delete,Print,",X%,Y%)
1160 DEFPROCdrag_click
1170 SYS "Wimp_GetWindowState",,block%+
12
1180 X%=block%!16:Y%=block%!28
1190 block%!16=I%:SYS "Wimp_GetIconState",,block%+12
1200 block%!16=5
1210 block%!20+=X%-2:block%!24+=Y%-4
1220 block%!28+=X%+2:block%!32+=Y%+4
1230 block%!36=0:block%!40=0
1240 block%!44=&7FFFFFFF
1250 block%!48=&7FFFFFFF
1260 SYS "Wimp_DragBox",,block%+12
1270 ENDPROC
1280 :
1360 A%=!first:X%=8+FNday(y%,m%,1)*64:Y%=-152
1390 B%=FNicon(w_diary%,STR$D%,X%,Y%,44,44,&27003009-32*(E%=!USR search))
1470 DEFPROCdate_selected(E%)
1480 N%=0:WHILE N%<4 AND date%(N%)<>E% N%+=1:ENDWHILE
1490 IF date%(N%)=E% PROCtop(N%,FALSE):ENDPROC
1500 N%=0:WHILE N%<4 AND date%(N%)>0 N%+=1:ENDWHILE
1510 IF date%(N%)>0 ERROR 1,"Can't open
any more note windows."
1520 A%=USR find_entry
1530 IF !A%<>E% THEN
1540 IF !next=!max ERROR 1,"No memory for any more entries."
1550 CALL insert_entry
1560 !A%=E%:A%!4=13:A%!45=13:A%!86=13:A%!127=13
1570 PROCset_icon_state(w_diary%,I%,32,32)
1580 ENDIF
1590 PROCtop(N%,TRUE)
1600 ENDPROC
1610 :
1620 DEFPROCtop(N%,new%)
1630 PROCopen_window(w_note%(N%))
1640 IF new% date%(N%)=E%:$note_date%(N%)=FNdate_string(E%):PROCupdate_notes(FALSE)
1650 PROCcaret(w_note%(N%),0,0)
1660 ENDPROC
1670 :
1680 DEFPROCupdate_notes(show%)
1690 SYS "Wimp_GetCaretPosition",,block%+36
1700 FOR D%=0 TO 4:E%=date%(D%)
1710 IF E%>0 THEN
1720 !block%=w_note%(D%)
1730 P%=USR find_entry+4:Y%=-44
1740 FOR I%=0 TO 3
1750 block%!4=I%:SYS "Wimp_DeleteIcon",,block%
1760 A%=FNind_icon(w_note%(D%),P%,-1,41,"",0,Y%,652,44,&700F101)
1770 IF show% PROCset_icon_state(w_note%(D%),I%,0,0)
1780 Y%-=40:P%+=41:NEXT
1790 ENDIF
1800 NEXT
1810 SYS "Wimp_SetCaretPosition",block%!36,block%!40,block%!44,block%!48,block%!52,block%!56
1820 ENDPROC
1830 :
1840 DEFPROCclear_entry(W%)
1850 P%=FNaddr(W%)
1860 FORI%=0TO3:P%?(I%*41+4)=13
1870 PROCset_icon_state(W%,I%,0,0)
1880 NEXT
1890 PROCcaret(W%,0,0)
1900 ENDPROC
1910 :
1920 DEFPROCprint_entries(S%)
1930 IF !first=!next OR S%=-1 ENDPROC
1940 LOCAL ERROR
1950 ON ERROR LOCAL VDU3:OSCLI "fx 229,
1":ENDPROC
1960 SYS "OS_Byte",246,0,255 TO ,I%
1970 VDU2:*fx 229,0
1980 FORP%=!first TO !next-168 STEP 168
1990 M%=(!P%)>>8
2000 CASE S% OF
2010 WHEN 0 : IF month%=M% PROCprint_entry
2020 WHEN 1 : IF month% DIV12=M% DIV12 PROCprint_entry
2030 WHEN 2 : PROCprint_entry
2040 OTHERWISE : IF P%=S% PROCprint_entry
2050 ENDCASE
2060 NEXT
2070 VDU3:*fx 229,1
2080 ENDPROC
2090 :
2100 DEFPROCprint_entry
2110 PROCprint_line(FNdate_string(!P%))
2120 FORA%=4 TO 127 STEP 41
2130 PROCprint_line($(P%+A%))
2140 NEXT
2150 VDU1,13:IF I%<>10 VDU1,10
2160 ENDPROC
2170 :
2180 DEFPROCprint_line(A$)
2190 IF A$="" ENDPROC
2200 FORC%=1TOLEN(A$):VDU1,ASC(MID$(A$,C%,1)):NEXT
2210 VDU1,13:IF I%<>10 VDU1,10
2220 ENDPROC
2230 :
2280 DEFFNdate_string(M%)
2290 D%=M%AND255:Y%=(M%>>8)DIV12:M%=(M%>>8)MOD12
2300 =day$(FNday(Y%,M%,D%))+" "+STR$D%+" "+month$(M%)+" "+STR$Y%
2310 :
2320 DEFPROCload_merge(W%,A$)
2330 block%!12=block%!8
2340 block%!16=4:!block%=64
2350 SYS "Wimp_SendMessage",17,block%,block%!4
2360 CASE W% OF
2370 WHEN w_diary%:PROCmerge_notes(A$)
2380 OTHERWISE PROCload_notes(A$)
2390 ENDCASE
2400 ENDPROC
2410 :
2420 DEFPROCload_notes(A$)
2430 SYS "OS_File",5,A$ TO ,,,,L%
2440 IF !first+L%>!max ERROR 1,"Diary too big to be loaded."
2450 FOR N%=0 TO 4:!block%=w_note%(N%):SYS "Wimp_CloseWindow",,block%:NEXT
2460 date%()=-1:!next=!first+L%
2470 SYS "OS_File",&FF,A$,!first,0
2480 $file_name%=A$
2490 PROCnew_month(0)
2500 PROCopen_window(w_diary%)
2510 E%=today%:IF !USRfind_entry=E% PROCdate_selected(E%)
2520 ENDPROC
2530 :
2540 DEFPROCmerge_notes(A$)
2550 SYS "OS_File",5,A$ TO ,,,,L%
2560 err%=FALSE:H%=OPENIN A$
2570 FORP%=0 TO L%-168 STEP 168
2580 SYS "OS_GBPB",3,H%,buff,4,P%
2590 E%=!buff:A%=USR find_entry
2600 IF !A%<>E% AND !next<!max CALLinsert_entry:!A%=E%
2610 IF !A%<>E% AND !next=!max err%=TRUE
2620 IF !A%=E% SYS "OS_GBPB",4,H%,A%+4,
164
2630 NEXT
2640 CLOSE #H%
2650 PROCnew_month(0)
2660 PROCupdate_notes(TRUE)
2670 IF err% ERROR 1,"Ran out of memory
for new entries, excess new entries ignored."
2680 ENDPROC
2690 :
2700 DEFPROCsave_notes(A$)
2710 SYS "OS_File",10,A$,&FEF,,!first,!next
2720 SYS "Wimp_CreateMenu",-1
2730 $file_name%=A$
2740 block%!12=block%!8
2750 block%!16=3:!block%=64
2760 SYS "Wimp_SendMessage",17,block%,block%!20,block%!24
2770 ENDPROC
2780 :
2790 DEFPROCquick_save
2800 IF INSTR($file_name%,".")=0 ERROR
1,"To save, drag the icon to a directory
viewer."
2810 SYS "OS_File",10,$file_name%,&FEF,,!first,!next
2820 SYS "Wimp_CreateMenu",-1
2830 ENDPROC
2840 :
2850 DEFFNleaf(A$)
2860 WHILE INSTR(A$,".")>0
2870 A$=MID$(A$,INSTR(A$,".")+1)
2880 ENDWHILE
2890 =A$
2900 :
2910 DEFFNget_name(P%)
2920 A$=""
2930 WHILE ?P%<>0 AND ?P%<>13
2940 A$=A$+CHR$?P%:P%+=1
2950 ENDWHILE
2960 =A$
2970 :
3020 DEFPROCcaret(W%,I%,X%)
3030 SYS "Wimp_SetCaretPosition",W%,I%,X%,,-1,-1
3040 ENDPROC
3050 :
3060 DEFFNaddr(!block%)
3070 block%!4=0:SYS "Wimp_GetIconState",,block%
3080 =(block%!28)-4
3090 :
3100 DEFFNget_note_num(W%)
3110 N%=0
3120 WHILE w_note%(N%)<>W% N%+=1:ENDWHILE
3130 =N%
3140 :
3280 max_notes%=250:DIM notes% 168*max_notes%
3470 DIM w_note%(4),note_date%(4),date%(4):date%()=-1
3480 FORN%=0TO4
3490 w_note%(N%)=FNcreate_window("",note_date%(N%),30,999,884-N%*88,652,164,0,1
2,31)
3500 NEXT
3510 :
3520 w_save%=FNcreate_window("Save as:",A%,0,0,0,246,168,1,2,&93)
3530 A%=FNind_icon(w_save%,A%,1,9,"file_fef",88,-92,68,68,&6102)
3540 DIM t 3:$t="A~ "
3550 A%=FNind_icon(w_save%,file_name%,t,255,"DiaryFile",8,-160,180,48,&700F12D)
3560 i_ok%=FNicon(w_save%,"OK",194,-160,44,48,&C7019025)
3570 PROCassemble
3580 :
3590 SYS "OS_GetEnv" TO A$
3600 IF RIGHT$(A$,1)<>" " PROCload_notes(MID$(A$,INSTR(A$,""" ")+2))
4090 CASE $(I%+12) OF
4100 WHEN "Save notes" : I%!4=w_save%
4110 WHEN "Print notes" : I%!4=menu%+20
0
4120 PROCcreate_menu(I%!4,"Print notes","month's,year's,all,")
4130 ENDCASE
4180 :
4190 DEFPROCassemble
4200 DIM code% 128
4210 FORA%=0TO2STEP2:P%=code%
4220 [OPT A%
4230 .find_entry LDR R0,first
4250 .search:SUB R0,R0,#168
4270 LDR R1,next STR R0,[R1]
4290 .next_entry
4300 LDR R2,[R0,#168]!:TEQ R0,R1
4320 MOVEQ PC,R14:CMP R4,R2
4340 BHI next_entry:MOV PC,R14
4360 :
4370 .insert_entry
4380 LDR R1,next:ADD R2,R1,#168
4400 STR R2,next:.move_up
4420 TEQ R0,R1:MOVEQ PC,R14
4440 LDR R2,[R1,#-4]!:STR R2,[R1,#168]
4460 B move_up
4470 :
4480 .delete_entry
4490 LDR R0,next:SUB R2,R0,#168
4510 STR R2,next
4520 .move_down TEQ R0,R1
4540 MOVEQ PC,R14:LDR R2,[R1,#168]
4560 STR R2,[R1],#4:B move_down
4580 :
4590 .buff EQUD 0:.first EQUD notes%
4610 .next EQUD notes%
4620 .max EQUD notes%+168*max_notes%
4630 ]:NEXT
4640 ENDPROC