THE RISC USER NOTEPAD (3)

David Spenser concludes this multi-tasking RISC OS application.

This month we add the remaining routines to the Notepad - namely the file transfer and printing options. We will also explain in more detail how specific parts of the program work.

ENTERING THE PROGRAM

The listing given here should be added to the !RunImage program from the previous two issues, making sure that the original has not been renumbered in any way. Note that a couple of lines overwrite existing ones. As a check, when the listing has been entered the line numbering should be in increments of ten, with the exception of lines 1710 and 1740 which are not present, and the addition of lines 2525 and 2526. The complete program should be saved back as !RunImage in the !Notepad directory, and the entire application can then be run from the Desktop.

Upon running the Notepad, the changes will not be immediately obvious. However, if you look at the menu option for save you will see that it now offers a submenu. Moving the pointer across to the submenu brings up a filing box like those used by ArcEdit etc. This can be used in exactly the same way as for the other applications. Hence, the name can be edited and the file icon dragged to a directory viewer. Once a notepad is saved, the title of the window changes to reflect the filename, and subsequent saves can be performed by bringing up the filing box and clicking on OK or pressing Return. You will notice that notepad files are identified by an icon representing a page of writing.

Loading a file is even easier. If the Notepad is already installed, then you can pick up a notepad file from a directory viewer and drag it to either the Notepad icon on the iconbar, or into the Notepad window itself. Alternatively, you can just double click on the notepad file. If the Notepad application is not currently installed, then double clicking on a notepad file will install the application and then load the data file. As well as loading notepad files, text files (such as those created using ArcEdit) can also be loaded. In this case, if the file is too long to fit in the eight page notepad then the text is truncated and a warning given. An imported text file is given the name 'Imported', rather than the actual filename.

The entire contents of the notepad can be printed by selecting the Print option from the main menu. The eight pages are printed out one after the other with two blank lines between each, except for the fourth and fifth. This ensures that on a printer set to the standard 66 lines per page, then the notepad fits exactly on two sheets.

HOW IT WORKS

Firstly, the print option. This is very straightforward and consists of the last two procedures in the program (lines 4760 onwards). The notepad is printed out on a character by character basis using VDU 1 to ensure that the output is only sent to the printer. The procedure PROCcr prints a carriage return, and an optional linefeed which depends on the Ignore character setting. You will notice that the Escape key is re-enabled, because the WIMP normally disables it. A local error handler is used to disable Escape and turn off the printer if an error occurs. As no calls are made to Wimp_Poll during the printing, all other tasks will freeze while the notepad is being printed.

The file saving and loading is much more involved. In order to fit into the multi-tasking environment, all file transfers are performed using a rigidly defined protocol. Fundamental to this is the ability to pass messages between tasks, where a message is a variable length block of memory. By defining the contents of the block, a message can be used to provide elaborate inter-task communication.

There is not sufficient space here to explain how messages are used in detail, but a brief explanation should help. A message is sent using the call "Wimp_SendMessage" which specifies who the recipient should be, the address in memory of the block of data making up the message, and a reason code which is sent to the recipient. A message can be sent to a particular task, or to the task owning a particular window, or to all active tasks, this latter case being called a broadcast. An example of a broadcast is the 'Shut down' message sent by the Task Manager when the user quits the Desktop. A message is received through Wimp_Poll by the recipient, with the reason code specified by the sender, and the message block copied into the receiver's parameter block. At the moment, we are only interested in messages with a reason code of 17 or 18 (general messages), in which case the 4-byte word at block!16 (assuming block points to Wimp_Poll's parameter block) is a further code or type. The procedure PROCreceive picks out these types, and there are six we are interested in. The values and meanings of these are:
0Shut down.
1Program wishes to save a file
2Ready to save a file.
3Load a file.
4File has been loaded
5A file has been double-clicked on.

We now need to consider all the possible options for loading and saving. Looking at saving first, the user can do one of two things:

1. Drag the file icon to a directory viewer.

2. Click on OK or press Return within the filing window to save the file using the current filename.

On the loading front, there are three possibilities:

3. The user drags a file icon to the Notepad window or the Notepad icon on the iconbar.

4. The user double-clicks on a notepad file when the Notepad is already installed.

5. As above, but without the Notepad installed.

We will now explain the steps involved for each of these possibilities. The text in brackets indicates the relevant parts of the program, and the numbers refer to the above list of options.

1. The Notepad initiates the icon drag (lines 1060 - 1220). The WIMP notifies the Notepad when the icon is dropped, and the Notepad then works out the window over which it was dropped, and sends a type one message to that window (PROCsave). This message includes the filename to be used. Assuming it was a directory viewer, the Filer returns a type two message which includes the full pathname under which to save the file. This causes the Notepad to save the file and send a type three message in acknowledgement (PROCdatasave). The Filer returns a type four message which is ignored by the Notepad.

2. In this case, the Notepad simply saves the file using the name it already has, and no messages are sent (PROCquicksave).

3. The Filer sends a type three message to the Notepad which causes it to load the file (PROCdataload). Depending on the file type of the file, it is loaded using one of the two procedures PROCload and PROCtextload. The Notepad then sends a type four message as acknowledgment (PROCackload).

4. The Filer sends a broadcast type five message. The Notepad picks this up, and assuming that the file in question is a notepad file, loads it as if it had been dragged into the notepad. When the type four message is sent back, the Filer takes this as an indication that no further action is needed.

5. In this case, no installed application will recognise the notepad file when it is doubled-clicked on, and the Filer will then attempt to *RUN the file. The Notepad's !Boot file sets up the alias:
Alias$@RunType_FEE Run <Obey$Dir>.!Run %%*0
This, in conjunction with the Notepad's !Run file and the alias set up to *RUN Basic programs, will ensure that *RUNing a notepad file will result in the command:
*BASIC -quit <Notepad pathname> <File pathname>
where Notepad pathname is the full pathname of the Notepad's !RunImage file, and File pathname is the full pathname of the notepad file which was run. If you don't believe this, try it out.

Lines 80 - 130 of the program pick out any filename supplied when the program is run, and if one is found, line 360 loads the file and opens the notepad window automatically.

The above explanation probably appears very complicated. However, with careful reading and following through the relevant sections of the program, it should begin to make sense.

This ends the RISC User Notepad, though I am sure that in the following months we will feature many more multi-tasking programs, and articles on different aspects of the multi-tasking WIMP system.

80 SYS "OS_GetEnv" TO c$
90 p=INSTR(c$,"""",INSTR(c$,"""")+1)
100 c$=MID$(c$,p+1)
110 WHILE LEFT$(c$,1)=" "
120 c$=MID$(c$,2)
130 ENDWHILE
270 file=FNcreate(0,0,268,164,&84000012,1,268,164,0,st)
310 fsave=FNspriteicon(file,100,-92,168,-24,&6102,1,"file_fee")
320 DIM t 2:$t="OK":ok=FNtexticon(file,214,-160,260,-112,&C701913D,t,-1,3)
330 DIM t 3:$t="A~ ":wr=FNtexticon(file,4,-160,210,-112,&700F12D,fi,t,255)
360 IF c$="" THEN open=FALSE ELSE PROCload(c$):open=TRUE:PROCretitle(main)
440 WHEN 7:PROCsave
570 WHEN 3,5:IF b!12=0 THEN PROCdataload(b)
1060 WHEN file
1070 IF (b!16=fsave) AND (b!8 AND &50)<>0 THEN
1080 !block=file
1090 SYS "Wimp_GetWindowState",,block
1100 wex=block!4-block!20
1110 wey=block!16-block!24
1120 block!4=fsave
1130 SYS "Wimp_GetIconState",,block
1140 !block=file:block!4=5
1150 block!8=block!8+wex
1160 block!12=block!12+wey
1170 block!16=block!16+wex
1180 block!20=block!20+wey
1190 block!24=0:block!28=0
1200 block!32=&7FFFFFFF:block!36=&7FFFFFFF
1210 SYS "Wimp_DragBox",,block
1220 ENDIF
1230 IF b!16=ok THEN
1240 PROCquicksave
1250 ENDIF
1770 ptr!-20=file
2525 ELSE
2526 IF !b=file AND b!4=wr AND b!24=&D THEN PROCquicksave
3020 IF data?((maxpage+1)*600-1)=ASC" "
THEN
3770 :
3780 DEF PROCsaveit(name$)
3790 SYS "OS_File",10,name$,&FEE,,data,data+600*(maxpage)+1
3800 mod=FALSE:$mt=name$
3810 SYS "Wimp_CreateMenu",,-1
3820 PROCretitle(main)
3830 ENDPROC
3840 :
3850 DEF FNleaf(path$)
3860 WHILE INSTR(path$,".")
3870 path$=MID$(path$,INSTR(path$,".")+1)
3880 ENDWHILE
3890 =path$
3900 :
3910 DEF PROCsave
3920 SYS "Wimp_GetPointerInfo",,block
3930 block!20=64:block!32=0
3940 block!36=1:block!40=block!12
3950 block!44=block!16
3960 block!48=!block
3970 block!52=block!4
3980 block!56=(maxpage+1)*600
3990 block!60=&FEE
4000 $(block+64)=FNleaf($fi)
4010 SYS "Wimp_SendMessage",17,block+20,block!12,block!16
4020 ENDPROC
4030 :
4040 DEF PROCdatasave(b)
4050 PROCsaveit(FNgname(b+44))
4060 $fi=FNgname(b+44)
4070 b!12=b!8:b!16=3:!b=64
4080 SYS "Wimp_SendMessage",17,b,b!20,b!24
4090 ENDPROC
4100 :
4110 DEF PROCdataload(b)
4120 CASE b!40 OF
4130 WHEN &FEE
4140 PROCload(FNgname(b+44))
4150 PROCackload(b)
4160 WHEN &FFF
4170 PROCtextload(FNgname(b+44))
4180 PROCackload(b)
4190 ENDCASE
4200 ENDPROC
4210 :
4220 DEF PROCload(name$)
4230 SYS "OS_File",&FF,name$,data
4240 $fi=name$:$mt=name$
4250 ENDPROC
4260 :
4270 DEF FNgname(ptr)
4280 f$=""
4290 WHILE ?ptr<>0 AND ?ptr<>13
4300 f$=f$+CHR$?ptr:ptr+=1
4310 ENDWHILE
4320 =f$
4330 :
4340 DEF PROCackload(b)
4350 mod=FALSE:tx=0:ty=0
4360 page=0:$pno="Page 1"
4370 b!12=b!8:b!16=4:!b=64
4380 SYS "Wimp_SendMessage",17,b,b!4
4390 PROCretitle(main)
4400 ENDPROC
4410 :
4420 DEF PROCtextload(name$)
4430 PROCwipe
4440 SYS "OS_Find",&48,name$ TO handle
4450 offset=0:last=0
4460 WHILE offset<(maxpage+1)*600 AND NOT EOF#handle
4470 char=BGET#handle
4480 IF char=13 AND last=10 OR char=10 AND last=13 THEN
4490 last=0
4500 ELSE
4510 last=char
4520 IF char<>10 AND char<>13 THEN
4530 data?offset=char:offset+=1
4540 ELSE
4550 offset=40*((offset+39) DIV 40)
4560 ENDIF
4570 ENDIF
4580 ENDWHILE
4590 IF NOT EOF#handle THEN
4600 $(block+64)=" Text has been truncated"
4610 SYS "Wimp_ReportError",block+64,1,"Note Pad"
4620 ENDIF
4630 CLOSE #handle
4640 $fi="Imported":$mt="Imported"
4650 ENDPROC
4660 :
4670 DEF PROCquicksave
4680 IF INSTR($fi,".") THEN
4690 PROCsaveit($fi)
4700 ELSE
4710 $block=" To save, drag the icon
to a directory viewer"
4720 SYS "Wimp_ReportError",block,1,"Note Pad"
4730 ENDIF
4740 ENDPROC
4750 :
4760 DEF PROCprint
4770 LOCAL ERROR
4780 ON ERROR LOCAL VDU 3:OSCLI "FX229 1":ENDPROC
4790 VDU 2:*FX 229
4800 FOR sheet=0 TO maxpage
4810 FOR line=0 TO 14
4820 FOR char=0 TO 39
4830 VDU 1,data?(sheet*600+line*40+char)
4840 NEXT
4850 PROCcr
4860 NEXT
4870 IF sheet<>2 THEN PROCcr:PROCcr
4880 NEXT
4890 VDU 3:*FX 299 1
4900 ENDPROC
4910 :
4920 DEF PROCcr
4930 VDU 1,13
4940 SYS "OS_Byte",246,0,255 TO ,ig
4950 IF ig<>10 THEN VDU 1,10
4960 ENDPROC