At the end of the last module, we asked where the variable quit% was changed to TRUE. In simple terms we could say in the 9th line of the procedure menuselect, but the intention was for you to work out why it happens here.
PROCmenuselect ensures that any click on any menu has the desired outcome. This is not entirely simple when you remember that the computer has to recognise which menu is open, whether a submenu also appears, and which item in the menu is being selected. Let's take these three steps and see how the program does this.
There is only one menu in our program so far. This is the iconbar menu, and it is set up in the 3 lines following the REM statement 'iconbar menu'. Every menu has to be stored in a location known to the operating system, and this is done using the DIM statement again. We have set up 76 bytes of memory at an address to be called barmenu%. A menu needs a specific amount of space in which the details are contained. It needs 28 bytes for the header information, and 24 bytes for each line in the menu. In our example, 28 + 24 + 24 = 76.
The process of creating the memory is hidden away in the Library, using the procedure make_menu, but the details are clearly seen in the DATA statement in the next line. DATA is another BASIC keyword indicating that the items that follow are data items, and the program will recognise these when it comes to a READ statement within the procedure. The data for a menu consists of a title, an indication of the number of headings in the menu, and then three items for each line of the menu.
For our iconbar menu, we have called the menu 'Secrets'. This will appear in the titlebar of the menu. Next we have said there will be 2 items. The first item has three parts: 0, info%, and Info. The zero effectively says that there is nothing special about this item. If we had put 1 in stead of 0, it would display a tick next to the item; a 2 would place a dotted line after the item, and so on. (You can try changing this to see the effect.)
The second item is used to indicate if the item leads to a submenu or another window. In our case, we want this item to lead to the Information window, the address of which is held at info%. The third element id the word to appear in the menu itself - Info.
The last three items of data do the same for the second item in the menu, but in this case we use &80 in the first position to indicate that this is the last item in the menu. We then use -1 to indicate there is no submenu, and Quit is the word that appears in the menu itself.
Any action taken in the desktop must be caught by the Wimp Poll routine, and selecting an item from a menu is no exception. When you click on anything to do with your program, whether it is a menu, a window, or the icon on the iconbar, the Poll Loop will record the fact and return a reason code of 6 to your program. Notice in the Poll Loop that the SYS call also uses the memory we set up at the address block%. It uses this memory to store information about the event that has just occurred.
The CASE routine in the Poll Loop directs the program to PROCclick, and also sends it information from the word at block%!12. We must digress a little to explain how we read the memory.
Data is generally thought of as being stored in memory in blocks of 4 bytes, 4 bytes being called a word. (Each byte is made up of 8 binary digits, or bits, and so a word is made up of 32 bits, and is not entirely divorced from the concept of 32-bit processors.) A byte has any value between 0 and 15, but 10 upwards are represented by the letters A, B, C ... F, and to indicate the hexadecimal number we use the ampersand &. Thus &E is equal to the number 14, and a large number such as &1AE3 has four bytes and is therefore equivalent to a word.
Because the computer often stores data in word blocks, there is a special way of extracting complete words using the ! operator. The value of !block% is the value of the word stored in the first 4 bytes of memory at block%, so when the program has sel1%=!block% it is taking the value of the number stored in the first four bytes and putting it in the variable sel1%.
How do we find the next word contained in the following 4 bytes? Unless we are reading the first word at the address, we put the ! (pronounced 'pling') after the address, and indicate with a number how much further forward in the memory we should look for the word. Thus block%!4 says 'read the word starting with the 5th byte from the address block%'. block%!8 will read the next word, and so on.
It follows that PROCclick(block%!12) is sending the procedure the word found starting at the 13th byte from block%. This word is a pointer to which ever window was clicked on, and in our case will contain the value -2 to say that it was the iconbar.
PROCclick is worked hard because it must interpret every click you make when using a program. The first step is to identify which window was clicked on, and so we receive the data passed from the Wimp Poll to the variable window%, and use a CASE structure to take the appropriate action. In our example we only have one possible outcome at the moment, which is the click on the iconbar when window%=-2.
Having got this far, we now need to know which mouse button was used, because we only want to open the menu if the middle menu button was pressed. This information is still present in block% at block%+8, and so, without giving it any special name, we set up a second CASE structure within the first to check for the menu button. Mouse clicks will return 4 for the select button, 2 for the menu, and 1 for adjust. We only need to check for the menu button, and when the value is 2 action must follow. The first part gives openmenu% a value for later identification. We have chosen 1 to represent the iconbar menu. It then calls a procedure contained in the Library to open the menu itself.
The menu has now opened, and as soon as you select an item in the menu, the Wimp_Poll routine will return a value of 9 to say a selection has been made from a menu, and calls PROCmenuselect. In our program, sel1% is set to the first word, sel2% is the second word, and sel3% is the third word. Now sel2% and sel3% are not used in our program. They have been put there for future use, but each of these variables represent the item selected in different levels of menus. sel1% will refer to the item selected in the main menu, sel2% will be that selected in the first submenu, sel3% the second level of submenus, and so on.
The procedure checks which menu is open using the CASE openmenu% OF construction. Remember that openmenu% was set to 1 in PROCclick, and the line WHEN 1 responds with the routine required for the iconbar menu.
Only one item is important at this stage, because the Wimp automatically looks after the appearance of the Info window without any further programming from us. The first item in a menu is always numbered 0, so the second item in number 1. This is the Quit option in our menu, so when sel1% is 1 we know that we have clicked on the Quit item, and so we must change quit% to TRUE. When the Wimp next goes to the Wimp_Poll loop quit% will be TRUE, the loop will not be followed, the Wimp will be closed down using SYS"Wimp_CloseDown", and the program ends.
Experienced programmers can often be quite scathing about the amateurs who fail to structure their programs clearly, and BASIC is often criticised as a language that does not lend itself to good habits. The BBC BASIC we all enjoy is much better than many other forms since it is not necessary to use line numbers as all. Line numbers encouraged use of GOTO statements, and following a program was like trying to unravel very tangled string. Even without line numbering, this can still happen.
Every programmer has his or her own ideas on this subject, but the important principles are that programs should be easy to follow, logically structured and well-commented. For me, this means that
In the last Module I suggested you might rearrange the program by adding a procedure PROCinit. This, to me, is part of keeping the structure tidy. If you did this in the way in which I would write it then you would have moved the 5th to 21st lines (from LIBRARY ... to ... -1,Quit) to the point after END and before PROCclick. You would have replaced them at line 5 with a call PROCinit, and added just before the LIBRARY line DEFPROCinit. You would have added ENDPROC after the DATA line.
The structure of a simple program then might be summarised as
Call an initialising procedure
Write the Poll loop
Add the close down routines
Now list the procedures needed
PROCinit
Essential routines including PROCclick, PROCmenuselect, etc
Load and Save routines
Printing routines
Any other utility functions not in the Library
Well, that is my structure, but don't be surprised if someone else has a different view! We still have a long way to go to get our program doing something useful, but that will have to follow in future modules.